static void * extractBuf(const char * path, Zip *zip) { Zip::Stream s; if (!zip->GetStream(path, &s)) return NULL; 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 (s.GetType() == Zip::Stream::DEFLATE) extractLib(s, buf); else memcpy(buf, s.GetBuffer(), s.GetUncompressedSize()); return buf; }
static void * extractBuf(const char * path, Zip *zip) { Zip::Stream s; if (!zip->GetStream(path, &s)) return NULL; // allocate space for a trailing null byte void * buf = malloc(s.GetUncompressedSize() + 1); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't alloc decompression buffer for %s", path); return NULL; } if (s.GetType() == Zip::Stream::DEFLATE) extractLib(s, buf); else memcpy(buf, s.GetBuffer(), s.GetUncompressedSize()); // null terminate it ((unsigned char*) buf)[s.GetUncompressedSize()] = 0; return buf; }
static void * mozload(const char * path, Zip *zip) { #ifdef DEBUG struct timeval t0, t1; gettimeofday(&t0, 0); #endif 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("MOZ_LINKER_CACHE"), path); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "resolved %s to %s", path, fullpath); 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()); #ifdef DEBUG gettimeofday(&t1, 0); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: spent %d", path, (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec)); #endif return handle; } int fd; void * buf = NULL; uint32_t lib_size = s.GetUncompressedSize(); int cache_fd = 0; if (s.GetType() == Zip::Stream::DEFLATE) { cache_fd = lookupLibCacheFd(path); fd = cache_fd; if (fd < 0) fd = createAshmem(lib_size, path); #ifdef DEBUG else __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s from cache", path); #endif if (fd < 0) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't open " ASHMEM_NAME_DEF ", Error %d, %s, bailing out", errno, strerror(errno)); return NULL; } buf = mmap(NULL, lib_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer"); close(fd); return NULL; } if (cache_fd < 0) { 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 + 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, s.GetUncompressedSize(), MADV_WILLNEED); } #ifdef DEBUG __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d (0x%08x)", path, lib_size, lib_size); #endif 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()); if (buf) munmap(buf, lib_size); #ifdef DEBUG gettimeofday(&t1, 0); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: spent %d", path, (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec)); #endif return handle; }
static void extractFile(const char * path, Zip::Stream &s) { uint32_t size = s.GetUncompressedSize(); struct stat status; if (!stat(path, &status) && status.st_size == size && apk_mtime < status.st_mtime) return; int fd = open(path, O_CREAT | O_NOATIME | O_TRUNC | O_RDWR, S_IRWXU); if (fd == -1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't open %s to decompress library", path); return; } if (ftruncate(fd, size) == -1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't ftruncate %s to decompress library", path); close(fd); return; } void * buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer"); close(fd); return; } z_stream strm = { next_in: (Bytef *)s.GetBuffer(), avail_in: s.GetSize(), total_in: 0, next_out: (Bytef *)buf, avail_out: size, total_out: 0 }; int ret; ret = inflateInit2(&strm, -MAX_WBITS); if (ret != Z_OK) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateInit failed: %s", strm.msg); if (inflate(&strm, Z_FINISH) != Z_STREAM_END) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflate failed: %s", strm.msg); if (strm.total_out != size) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "extracted %d, expected %d!", strm.total_out, size); ret = inflateEnd(&strm); if (ret != Z_OK) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateEnd failed: %s", strm.msg); close(fd); #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 + size, 0); #endif munmap(buf, size); }