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 <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include "Zip.h"
|
||||
|
||||
/* Android headers don't define RUSAGE_THREAD */
|
||||
#ifndef RUSAGE_THREAD
|
||||
#define RUSAGE_THREAD 1
|
||||
#endif
|
||||
|
||||
/* compression methods */
|
||||
#define STORE 0
|
||||
#define DEFLATE 8
|
||||
#define LZMA 14
|
||||
|
||||
enum StartupEvent {
|
||||
#define mozilla_StartupTimeline_Event(ev, z) ev,
|
||||
#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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
NS_EXPORT const struct mapping_info *
|
||||
@ -164,52 +108,6 @@ createAshmem(size_t bytes, const char *name)
|
||||
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) \
|
||||
typedef void (*name ## _t)(JNIEnv *, jclass); \
|
||||
static name ## _t f_ ## name; \
|
||||
@ -310,9 +208,9 @@ extern "C" int extractLibs = 0;
|
||||
#endif
|
||||
|
||||
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;
|
||||
if (!stat(path, &status) &&
|
||||
@ -341,8 +239,8 @@ extractFile(const char * path, const struct cdir_entry *entry, void * data)
|
||||
}
|
||||
|
||||
z_stream strm = {
|
||||
next_in: (Bytef *)data,
|
||||
avail_in: letoh32(entry->compressed_size),
|
||||
next_in: (Bytef *)s.GetBuffer(),
|
||||
avail_in: s.GetSize(),
|
||||
total_in: 0,
|
||||
|
||||
next_out: (Bytef *)buf,
|
||||
@ -375,15 +273,15 @@ extractFile(const char * path, const struct cdir_entry *entry, void * data)
|
||||
}
|
||||
|
||||
static void
|
||||
extractLib(const struct cdir_entry *entry, void * data, void * dest)
|
||||
extractLib(Zip::Stream &s, void * dest)
|
||||
{
|
||||
z_stream strm = {
|
||||
next_in: (Bytef *)data,
|
||||
avail_in: letoh32(entry->compressed_size),
|
||||
next_in: (Bytef *)s.GetBuffer(),
|
||||
avail_in: s.GetSize(),
|
||||
total_in: 0,
|
||||
|
||||
next_out: (Bytef *)dest,
|
||||
avail_out: letoh32(entry->uncompressed_size),
|
||||
avail_out: s.GetUncompressedSize(),
|
||||
total_out: 0
|
||||
};
|
||||
|
||||
@ -400,8 +298,8 @@ extractLib(const struct cdir_entry *entry, void * data, void * dest)
|
||||
if (ret != Z_OK)
|
||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateEnd failed: %s", strm.msg);
|
||||
|
||||
if (strm.total_out != letoh32(entry->uncompressed_size))
|
||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "File not fully uncompressed! %d / %d", 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, s.GetUncompressedSize());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void * mozload(const char * path, void *zip,
|
||||
struct cdir_entry *cdir_start, uint16_t cdir_entries)
|
||||
static void * mozload(const char * path, Zip *zip)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
struct timeval t0, t1;
|
||||
gettimeofday(&t0, 0);
|
||||
#endif
|
||||
|
||||
struct cdir_entry *entry = find_cdir_entry(cdir_start, cdir_entries, path);
|
||||
struct local_file_header *file = (struct local_file_header *)((char *)zip + letoh32(entry->offset));
|
||||
void * data = ((char *)&file->data) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
|
||||
void * handle;
|
||||
void *handle;
|
||||
Zip::Stream s;
|
||||
if (!zip->GetStream(path, &s))
|
||||
return NULL;
|
||||
|
||||
if (extractLibs) {
|
||||
char fullpath[PATH_MAX];
|
||||
snprintf(fullpath, PATH_MAX, "%s/%s", getenv("CACHE_PATH"), path);
|
||||
__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);
|
||||
if (!handle)
|
||||
__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;
|
||||
}
|
||||
|
||||
size_t offset = letoh32(entry->offset) + sizeof(*file) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
|
||||
bool skipLibCache = false;
|
||||
int fd = zip_fd;
|
||||
int fd;
|
||||
void * buf = NULL;
|
||||
uint32_t lib_size = letoh32(entry->uncompressed_size);
|
||||
uint32_t lib_size = s.GetUncompressedSize();
|
||||
int cache_fd = 0;
|
||||
if (letoh16(file->compression) == DEFLATE) {
|
||||
if (s.GetType() == Zip::Stream::DEFLATE) {
|
||||
cache_fd = lookupLibCacheFd(path);
|
||||
fd = cache_fd;
|
||||
if (fd < 0)
|
||||
@ -540,30 +436,27 @@ static void * mozload(const char * path, void *zip,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
|
||||
if (cache_fd < 0) {
|
||||
extractLib(entry, data, buf);
|
||||
extractLib(s, buf);
|
||||
#ifdef ANDROID_ARM_LINKER
|
||||
/* We just extracted data that is going to be executed in the future.
|
||||
* 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
|
||||
addLibCacheFd(path, fd, lib_size, buf);
|
||||
}
|
||||
|
||||
// preload libxul, to avoid slowly demand-paging it
|
||||
if (!strcmp(path, "libxul.so"))
|
||||
madvise(buf, entry->uncompressed_size, MADV_WILLNEED);
|
||||
data = buf;
|
||||
madvise(buf, s.GetUncompressedSize(), MADV_WILLNEED);
|
||||
}
|
||||
|
||||
#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);
|
||||
#endif
|
||||
|
||||
handle = moz_mapped_dlopen(path, RTLD_LAZY, fd, data,
|
||||
lib_size, offset);
|
||||
handle = moz_mapped_dlopen(path, RTLD_LAZY, fd, buf,
|
||||
lib_size, 0);
|
||||
if (!handle)
|
||||
__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 *
|
||||
extractBuf(const char * path, void *zip,
|
||||
struct cdir_entry *cdir_start, uint16_t cdir_entries)
|
||||
extractBuf(const char * path, Zip *zip)
|
||||
{
|
||||
struct cdir_entry *entry = find_cdir_entry(cdir_start, cdir_entries, path);
|
||||
struct local_file_header *file = (struct local_file_header *)((char *)zip + letoh32(entry->offset));
|
||||
void * data = ((char *)&file->data) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
|
||||
Zip::Stream s;
|
||||
if (!zip->GetStream(path, &s))
|
||||
return NULL;
|
||||
|
||||
void * buf = malloc(letoh32(entry->uncompressed_size));
|
||||
void * buf = malloc(s.GetUncompressedSize());
|
||||
if (buf == (void *)-1) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't alloc decompression buffer for %s", path);
|
||||
return NULL;
|
||||
}
|
||||
if (letoh16(file->compression) == DEFLATE)
|
||||
extractLib(entry, data, buf);
|
||||
if (s.GetType() == Zip::Stream::DEFLATE)
|
||||
extractLib(s, buf);
|
||||
else
|
||||
memcpy(buf, data, letoh32(entry->uncompressed_size));
|
||||
memcpy(buf, s.GetBuffer(), s.GetUncompressedSize());
|
||||
|
||||
return buf;
|
||||
}
|
||||
@ -640,27 +532,14 @@ loadLibs(const char *apkName)
|
||||
struct rusage usage1;
|
||||
getrusage(RUSAGE_THREAD, &usage1);
|
||||
|
||||
void *zip = map_file(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);
|
||||
Zip *zip = new Zip(apkName);
|
||||
|
||||
lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping));
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
file_ids = (char *)extractBuf("lib.id", zip, cdir_start, cdir_entries);
|
||||
file_ids = (char *)extractBuf("lib.id", zip);
|
||||
#endif
|
||||
|
||||
#define MOZLOAD(name) mozload("lib" name ".so", zip, cdir_start, cdir_entries)
|
||||
#define MOZLOAD(name) mozload("lib" name ".so", zip)
|
||||
MOZLOAD("mozalloc");
|
||||
MOZLOAD("nspr4");
|
||||
MOZLOAD("plc4");
|
||||
@ -677,7 +556,7 @@ loadLibs(const char *apkName)
|
||||
MOZLOAD("softokn3");
|
||||
#undef MOZLOAD
|
||||
|
||||
close(zip_fd);
|
||||
delete zip;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
free(file_ids);
|
||||
|
@ -55,6 +55,7 @@ CPPSRCS = \
|
||||
APKOpen.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES += -I$(srcdir)/../linker
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/startup
|
||||
ifdef MOZ_OLD_LINKER
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/other-licenses/android
|
||||
|
@ -265,17 +265,14 @@ include $(topsrcdir)/config/android-common.mk
|
||||
|
||||
JARSIGNER ?= echo
|
||||
|
||||
DIST_FILES = \
|
||||
resources.arsc \
|
||||
AndroidManifest.xml \
|
||||
chrome \
|
||||
components \
|
||||
defaults \
|
||||
modules \
|
||||
hyphenation \
|
||||
res \
|
||||
lib \
|
||||
lib.id \
|
||||
DIST_FILES =
|
||||
|
||||
# Place the files in the order they are going to be opened by the linker
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
DIST_FILES += lib.id
|
||||
endif
|
||||
|
||||
DIST_FILES += \
|
||||
libmozalloc.so \
|
||||
libnspr4.so \
|
||||
libplc4.so \
|
||||
@ -290,6 +287,15 @@ DIST_FILES = \
|
||||
libnssckbi.so \
|
||||
libfreebl3.so \
|
||||
libsoftokn3.so \
|
||||
resources.arsc \
|
||||
AndroidManifest.xml \
|
||||
chrome \
|
||||
components \
|
||||
defaults \
|
||||
modules \
|
||||
hyphenation \
|
||||
res \
|
||||
lib \
|
||||
extensions \
|
||||
application.ini \
|
||||
package-name.txt \
|
||||
|
Loading…
Reference in New Issue
Block a user