mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 683127 part 4 - Use the new ELF linker Zip reader in the old linker. r=tglek
This commit is contained in:
parent
402ad20521
commit
86663af6ae
@ -61,17 +61,13 @@
|
|||||||
#include "APKOpen.h"
|
#include "APKOpen.h"
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include "Zip.h"
|
||||||
|
|
||||||
/* Android headers don't define RUSAGE_THREAD */
|
/* Android headers don't define RUSAGE_THREAD */
|
||||||
#ifndef RUSAGE_THREAD
|
#ifndef RUSAGE_THREAD
|
||||||
#define RUSAGE_THREAD 1
|
#define RUSAGE_THREAD 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* compression methods */
|
|
||||||
#define STORE 0
|
|
||||||
#define DEFLATE 8
|
|
||||||
#define LZMA 14
|
|
||||||
|
|
||||||
enum StartupEvent {
|
enum StartupEvent {
|
||||||
#define mozilla_StartupTimeline_Event(ev, z) ev,
|
#define mozilla_StartupTimeline_Event(ev, z) ev,
|
||||||
#include "StartupTimeline.h"
|
#include "StartupTimeline.h"
|
||||||
@ -85,58 +81,6 @@ void StartupTimeline_Record(StartupEvent ev, struct timeval *tm)
|
|||||||
sStartupTimeline[ev] = (((uint64_t)tm->tv_sec * 1000000LL) + (uint64_t)tm->tv_usec);
|
sStartupTimeline[ev] = (((uint64_t)tm->tv_sec * 1000000LL) + (uint64_t)tm->tv_usec);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct local_file_header {
|
|
||||||
uint32_t signature;
|
|
||||||
uint16_t min_version;
|
|
||||||
uint16_t general_flag;
|
|
||||||
uint16_t compression;
|
|
||||||
uint16_t lastmod_time;
|
|
||||||
uint16_t lastmod_date;
|
|
||||||
uint32_t crc32;
|
|
||||||
uint32_t compressed_size;
|
|
||||||
uint32_t uncompressed_size;
|
|
||||||
uint16_t filename_size;
|
|
||||||
uint16_t extra_field_size;
|
|
||||||
char data[0];
|
|
||||||
} __attribute__((__packed__));
|
|
||||||
|
|
||||||
struct cdir_entry {
|
|
||||||
uint32_t signature;
|
|
||||||
uint16_t creator_version;
|
|
||||||
uint16_t min_version;
|
|
||||||
uint16_t general_flag;
|
|
||||||
uint16_t compression;
|
|
||||||
uint16_t lastmod_time;
|
|
||||||
uint16_t lastmod_date;
|
|
||||||
uint32_t crc32;
|
|
||||||
uint32_t compressed_size;
|
|
||||||
uint32_t uncompressed_size;
|
|
||||||
uint16_t filename_size;
|
|
||||||
uint16_t extra_field_size;
|
|
||||||
uint16_t file_comment_size;
|
|
||||||
uint16_t disk_num;
|
|
||||||
uint16_t internal_attr;
|
|
||||||
uint32_t external_attr;
|
|
||||||
uint32_t offset;
|
|
||||||
char data[0];
|
|
||||||
} __attribute__((__packed__));
|
|
||||||
|
|
||||||
#define CDIR_END_SIG 0x06054b50
|
|
||||||
|
|
||||||
struct cdir_end {
|
|
||||||
uint32_t signature;
|
|
||||||
uint16_t disk_num;
|
|
||||||
uint16_t cdir_disk;
|
|
||||||
uint16_t disk_entries;
|
|
||||||
uint16_t cdir_entries;
|
|
||||||
uint32_t cdir_size;
|
|
||||||
uint32_t cdir_offset;
|
|
||||||
uint16_t comment_size;
|
|
||||||
char comment[0];
|
|
||||||
} __attribute__((__packed__));
|
|
||||||
|
|
||||||
static size_t zip_size;
|
|
||||||
static int zip_fd;
|
|
||||||
static struct mapping_info * lib_mapping = NULL;
|
static struct mapping_info * lib_mapping = NULL;
|
||||||
|
|
||||||
NS_EXPORT const struct mapping_info *
|
NS_EXPORT const struct mapping_info *
|
||||||
@ -164,52 +108,6 @@ createAshmem(size_t bytes, const char *name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void * map_file (const char *file)
|
|
||||||
{
|
|
||||||
int fd = open(file, O_RDONLY);
|
|
||||||
if (fd == -1) {
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoMapFile", "map_file open %s", strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_fd = fd;
|
|
||||||
struct stat s;
|
|
||||||
if (fstat(fd, &s) == -1) {
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoMapFile", "map_file fstat %s", strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_size = s.st_size;
|
|
||||||
void *addr = mmap(NULL, zip_size, PROT_READ, MAP_SHARED, fd, 0);
|
|
||||||
if (addr == MAP_FAILED) {
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoMapFile", "map_file mmap %s", strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t cdir_entry_size (struct cdir_entry *entry)
|
|
||||||
{
|
|
||||||
return sizeof(*entry) +
|
|
||||||
letoh16(entry->filename_size) +
|
|
||||||
letoh16(entry->extra_field_size) +
|
|
||||||
letoh16(entry->file_comment_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct cdir_entry *
|
|
||||||
find_cdir_entry (struct cdir_entry *entry, int count, const char *name)
|
|
||||||
{
|
|
||||||
size_t name_size = strlen(name);
|
|
||||||
while (count--) {
|
|
||||||
if (letoh16(entry->filename_size) == name_size &&
|
|
||||||
!memcmp(entry->data, name, name_size))
|
|
||||||
return entry;
|
|
||||||
entry = (struct cdir_entry *)((char *)entry + cdir_entry_size(entry));
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SHELL_WRAPPER0(name) \
|
#define SHELL_WRAPPER0(name) \
|
||||||
typedef void (*name ## _t)(JNIEnv *, jclass); \
|
typedef void (*name ## _t)(JNIEnv *, jclass); \
|
||||||
static name ## _t f_ ## name; \
|
static name ## _t f_ ## name; \
|
||||||
@ -310,9 +208,9 @@ extern "C" int extractLibs = 0;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
extractFile(const char * path, const struct cdir_entry *entry, void * data)
|
extractFile(const char * path, Zip::Stream &s)
|
||||||
{
|
{
|
||||||
uint32_t size = letoh32(entry->uncompressed_size);
|
uint32_t size = s.GetUncompressedSize();
|
||||||
|
|
||||||
struct stat status;
|
struct stat status;
|
||||||
if (!stat(path, &status) &&
|
if (!stat(path, &status) &&
|
||||||
@ -341,8 +239,8 @@ extractFile(const char * path, const struct cdir_entry *entry, void * data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
z_stream strm = {
|
z_stream strm = {
|
||||||
next_in: (Bytef *)data,
|
next_in: (Bytef *)s.GetBuffer(),
|
||||||
avail_in: letoh32(entry->compressed_size),
|
avail_in: s.GetSize(),
|
||||||
total_in: 0,
|
total_in: 0,
|
||||||
|
|
||||||
next_out: (Bytef *)buf,
|
next_out: (Bytef *)buf,
|
||||||
@ -375,15 +273,15 @@ extractFile(const char * path, const struct cdir_entry *entry, void * data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
extractLib(const struct cdir_entry *entry, void * data, void * dest)
|
extractLib(Zip::Stream &s, void * dest)
|
||||||
{
|
{
|
||||||
z_stream strm = {
|
z_stream strm = {
|
||||||
next_in: (Bytef *)data,
|
next_in: (Bytef *)s.GetBuffer(),
|
||||||
avail_in: letoh32(entry->compressed_size),
|
avail_in: s.GetSize(),
|
||||||
total_in: 0,
|
total_in: 0,
|
||||||
|
|
||||||
next_out: (Bytef *)dest,
|
next_out: (Bytef *)dest,
|
||||||
avail_out: letoh32(entry->uncompressed_size),
|
avail_out: s.GetUncompressedSize(),
|
||||||
total_out: 0
|
total_out: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -400,8 +298,8 @@ extractLib(const struct cdir_entry *entry, void * data, void * dest)
|
|||||||
if (ret != Z_OK)
|
if (ret != Z_OK)
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateEnd failed: %s", strm.msg);
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateEnd failed: %s", strm.msg);
|
||||||
|
|
||||||
if (strm.total_out != letoh32(entry->uncompressed_size))
|
if (strm.total_out != s.GetUncompressedSize())
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "File not fully uncompressed! %d / %d", strm.total_out, letoh32(entry->uncompressed_size));
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "File not fully uncompressed! %d / %d", strm.total_out, s.GetUncompressedSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cache_count = 0;
|
static int cache_count = 0;
|
||||||
@ -480,24 +378,23 @@ addLibCacheFd(const char *libName, int fd, uint32_t lib_size = 0, void* buffer =
|
|||||||
info->buffer = buffer;
|
info->buffer = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void * mozload(const char * path, void *zip,
|
static void * mozload(const char * path, Zip *zip)
|
||||||
struct cdir_entry *cdir_start, uint16_t cdir_entries)
|
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
struct timeval t0, t1;
|
struct timeval t0, t1;
|
||||||
gettimeofday(&t0, 0);
|
gettimeofday(&t0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct cdir_entry *entry = find_cdir_entry(cdir_start, cdir_entries, path);
|
void *handle;
|
||||||
struct local_file_header *file = (struct local_file_header *)((char *)zip + letoh32(entry->offset));
|
Zip::Stream s;
|
||||||
void * data = ((char *)&file->data) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
|
if (!zip->GetStream(path, &s))
|
||||||
void * handle;
|
return NULL;
|
||||||
|
|
||||||
if (extractLibs) {
|
if (extractLibs) {
|
||||||
char fullpath[PATH_MAX];
|
char fullpath[PATH_MAX];
|
||||||
snprintf(fullpath, PATH_MAX, "%s/%s", getenv("CACHE_PATH"), path);
|
snprintf(fullpath, PATH_MAX, "%s/%s", getenv("CACHE_PATH"), path);
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "resolved %s to %s", path, fullpath);
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "resolved %s to %s", path, fullpath);
|
||||||
extractFile(fullpath, entry, data);
|
extractFile(fullpath, s);
|
||||||
handle = __wrap_dlopen(fullpath, RTLD_LAZY);
|
handle = __wrap_dlopen(fullpath, RTLD_LAZY);
|
||||||
if (!handle)
|
if (!handle)
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", fullpath, __wrap_dlerror());
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", fullpath, __wrap_dlerror());
|
||||||
@ -512,13 +409,12 @@ static void * mozload(const char * path, void *zip,
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t offset = letoh32(entry->offset) + sizeof(*file) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
|
|
||||||
bool skipLibCache = false;
|
bool skipLibCache = false;
|
||||||
int fd = zip_fd;
|
int fd;
|
||||||
void * buf = NULL;
|
void * buf = NULL;
|
||||||
uint32_t lib_size = letoh32(entry->uncompressed_size);
|
uint32_t lib_size = s.GetUncompressedSize();
|
||||||
int cache_fd = 0;
|
int cache_fd = 0;
|
||||||
if (letoh16(file->compression) == DEFLATE) {
|
if (s.GetType() == Zip::Stream::DEFLATE) {
|
||||||
cache_fd = lookupLibCacheFd(path);
|
cache_fd = lookupLibCacheFd(path);
|
||||||
fd = cache_fd;
|
fd = cache_fd;
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
@ -540,30 +436,27 @@ static void * mozload(const char * path, void *zip,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
|
|
||||||
if (cache_fd < 0) {
|
if (cache_fd < 0) {
|
||||||
extractLib(entry, data, buf);
|
extractLib(s, buf);
|
||||||
#ifdef ANDROID_ARM_LINKER
|
#ifdef ANDROID_ARM_LINKER
|
||||||
/* We just extracted data that is going to be executed in the future.
|
/* We just extracted data that is going to be executed in the future.
|
||||||
* We thus need to ensure Instruction and Data cache coherency. */
|
* We thus need to ensure Instruction and Data cache coherency. */
|
||||||
cacheflush((unsigned) buf, (unsigned) buf + entry->uncompressed_size, 0);
|
cacheflush((unsigned) buf, (unsigned) buf + s.GetUncompressedSize(), 0);
|
||||||
#endif
|
#endif
|
||||||
addLibCacheFd(path, fd, lib_size, buf);
|
addLibCacheFd(path, fd, lib_size, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// preload libxul, to avoid slowly demand-paging it
|
// preload libxul, to avoid slowly demand-paging it
|
||||||
if (!strcmp(path, "libxul.so"))
|
if (!strcmp(path, "libxul.so"))
|
||||||
madvise(buf, entry->uncompressed_size, MADV_WILLNEED);
|
madvise(buf, s.GetUncompressedSize(), MADV_WILLNEED);
|
||||||
data = buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d (0x%08x) and offset %d (0x%08x)", path, lib_size, lib_size, offset, offset);
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d (0x%08x) and offset %d (0x%08x)", path, lib_size, lib_size, offset, offset);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
handle = moz_mapped_dlopen(path, RTLD_LAZY, fd, data,
|
handle = moz_mapped_dlopen(path, RTLD_LAZY, fd, buf,
|
||||||
lib_size, offset);
|
lib_size, 0);
|
||||||
if (!handle)
|
if (!handle)
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", path, __wrap_dlerror());
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", path, __wrap_dlerror());
|
||||||
|
|
||||||
@ -580,22 +473,21 @@ static void * mozload(const char * path, void *zip,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
extractBuf(const char * path, void *zip,
|
extractBuf(const char * path, Zip *zip)
|
||||||
struct cdir_entry *cdir_start, uint16_t cdir_entries)
|
|
||||||
{
|
{
|
||||||
struct cdir_entry *entry = find_cdir_entry(cdir_start, cdir_entries, path);
|
Zip::Stream s;
|
||||||
struct local_file_header *file = (struct local_file_header *)((char *)zip + letoh32(entry->offset));
|
if (!zip->GetStream(path, &s))
|
||||||
void * data = ((char *)&file->data) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
|
return NULL;
|
||||||
|
|
||||||
void * buf = malloc(letoh32(entry->uncompressed_size));
|
void * buf = malloc(s.GetUncompressedSize());
|
||||||
if (buf == (void *)-1) {
|
if (buf == (void *)-1) {
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't alloc decompression buffer for %s", path);
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't alloc decompression buffer for %s", path);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (letoh16(file->compression) == DEFLATE)
|
if (s.GetType() == Zip::Stream::DEFLATE)
|
||||||
extractLib(entry, data, buf);
|
extractLib(s, buf);
|
||||||
else
|
else
|
||||||
memcpy(buf, data, letoh32(entry->uncompressed_size));
|
memcpy(buf, s.GetBuffer(), s.GetUncompressedSize());
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@ -640,27 +532,14 @@ loadLibs(const char *apkName)
|
|||||||
struct rusage usage1;
|
struct rusage usage1;
|
||||||
getrusage(RUSAGE_THREAD, &usage1);
|
getrusage(RUSAGE_THREAD, &usage1);
|
||||||
|
|
||||||
void *zip = map_file(apkName);
|
Zip *zip = new Zip(apkName);
|
||||||
struct cdir_end *dirend = (struct cdir_end *)((char *)zip + zip_size - sizeof(*dirend));
|
|
||||||
while ((void *)dirend > zip &&
|
|
||||||
letoh32(dirend->signature) != CDIR_END_SIG)
|
|
||||||
dirend = (struct cdir_end *)((char *)dirend - 1);
|
|
||||||
if (letoh32(dirend->signature) != CDIR_END_SIG) {
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't find end of central directory record");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t cdir_offset = letoh32(dirend->cdir_offset);
|
|
||||||
uint16_t cdir_entries = letoh16(dirend->cdir_entries);
|
|
||||||
|
|
||||||
struct cdir_entry *cdir_start = (struct cdir_entry *)((char *)zip + cdir_offset);
|
|
||||||
|
|
||||||
lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping));
|
lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping));
|
||||||
#ifdef MOZ_CRASHREPORTER
|
#ifdef MOZ_CRASHREPORTER
|
||||||
file_ids = (char *)extractBuf("lib.id", zip, cdir_start, cdir_entries);
|
file_ids = (char *)extractBuf("lib.id", zip);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MOZLOAD(name) mozload("lib" name ".so", zip, cdir_start, cdir_entries)
|
#define MOZLOAD(name) mozload("lib" name ".so", zip)
|
||||||
MOZLOAD("mozalloc");
|
MOZLOAD("mozalloc");
|
||||||
MOZLOAD("nspr4");
|
MOZLOAD("nspr4");
|
||||||
MOZLOAD("plc4");
|
MOZLOAD("plc4");
|
||||||
@ -677,7 +556,7 @@ loadLibs(const char *apkName)
|
|||||||
MOZLOAD("softokn3");
|
MOZLOAD("softokn3");
|
||||||
#undef MOZLOAD
|
#undef MOZLOAD
|
||||||
|
|
||||||
close(zip_fd);
|
delete zip;
|
||||||
|
|
||||||
#ifdef MOZ_CRASHREPORTER
|
#ifdef MOZ_CRASHREPORTER
|
||||||
free(file_ids);
|
free(file_ids);
|
||||||
|
@ -55,6 +55,7 @@ CPPSRCS = \
|
|||||||
APKOpen.cpp \
|
APKOpen.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
LOCAL_INCLUDES += -I$(srcdir)/../linker
|
||||||
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/startup
|
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/startup
|
||||||
ifdef MOZ_OLD_LINKER
|
ifdef MOZ_OLD_LINKER
|
||||||
LOCAL_INCLUDES += -I$(topsrcdir)/other-licenses/android
|
LOCAL_INCLUDES += -I$(topsrcdir)/other-licenses/android
|
||||||
|
@ -265,17 +265,14 @@ include $(topsrcdir)/config/android-common.mk
|
|||||||
|
|
||||||
JARSIGNER ?= echo
|
JARSIGNER ?= echo
|
||||||
|
|
||||||
DIST_FILES = \
|
DIST_FILES =
|
||||||
resources.arsc \
|
|
||||||
AndroidManifest.xml \
|
# Place the files in the order they are going to be opened by the linker
|
||||||
chrome \
|
ifdef MOZ_CRASHREPORTER
|
||||||
components \
|
DIST_FILES += lib.id
|
||||||
defaults \
|
endif
|
||||||
modules \
|
|
||||||
hyphenation \
|
DIST_FILES += \
|
||||||
res \
|
|
||||||
lib \
|
|
||||||
lib.id \
|
|
||||||
libmozalloc.so \
|
libmozalloc.so \
|
||||||
libnspr4.so \
|
libnspr4.so \
|
||||||
libplc4.so \
|
libplc4.so \
|
||||||
@ -290,6 +287,15 @@ DIST_FILES = \
|
|||||||
libnssckbi.so \
|
libnssckbi.so \
|
||||||
libfreebl3.so \
|
libfreebl3.so \
|
||||||
libsoftokn3.so \
|
libsoftokn3.so \
|
||||||
|
resources.arsc \
|
||||||
|
AndroidManifest.xml \
|
||||||
|
chrome \
|
||||||
|
components \
|
||||||
|
defaults \
|
||||||
|
modules \
|
||||||
|
hyphenation \
|
||||||
|
res \
|
||||||
|
lib \
|
||||||
extensions \
|
extensions \
|
||||||
application.ini \
|
application.ini \
|
||||||
package-name.txt \
|
package-name.txt \
|
||||||
|
Loading…
Reference in New Issue
Block a user