Example #1
0
static void * mozload(const char * path, void *zip,
                      struct cdir_entry *cdir_start, uint16_t cdir_entries)
{
#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;

  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);
    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;
  }

  size_t offset = letoh32(entry->offset) + sizeof(*file) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
  bool skipLibCache = false;
  int fd = zip_fd;
  void * buf = NULL;
  uint32_t lib_size = letoh32(entry->uncompressed_size);
  int cache_fd = 0;
  if (letoh16(file->compression) == 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;
    }

    offset = 0;

    if (cache_fd < 0) {
      extractLib(entry, data, 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);
#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;
  }

#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);
  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;
}
Example #2
0
static void * mozload(const char * path, void *zip,
                      struct cdir_entry *cdir_start, uint16_t cdir_entries)
{
#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;

  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);
    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;
  }

  size_t offset = letoh32(entry->offset) + sizeof(*file) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
  bool skipLibCache = false;
  int fd = zip_fd;
  void * buf = NULL;
  uint32_t lib_size = letoh32(entry->uncompressed_size);
  int cache_fd = 0;
  if (letoh16(file->compression) == DEFLATE) {
    cache_fd = lookupLibCacheFd(path);
    fd = cache_fd;
    if (fd < 0) {
      char fullpath[PATH_MAX];
      snprintf(fullpath, PATH_MAX, "%s/%s", getenv("CACHE_PATH"), path);
      fd = open(fullpath, O_RDWR);
      struct stat status;
      if (stat(fullpath, &status) ||
          status.st_size != lib_size ||
          apk_mtime > status.st_mtime) {
        unlink(fullpath);
        fd = -1;
      } else {
        cache_fd = fd;
        addLibCacheFd(path, 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, using a file", errno, strerror(errno));
      char fullpath[PATH_MAX];
      snprintf(fullpath, PATH_MAX, "%s/%s", getenv("CACHE_PATH"), path);
      fd = open(fullpath, O_RDWR | O_CREAT);
      if (fd < 0) {
        __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't create a file either, giving up");
        return NULL;
      }
      // we'd like to use fallocate here, but it doesn't exist currently?
      if (lseek(fd, lib_size - 1, SEEK_SET) == (off_t) - 1) {
         __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "seeking file failed");
        close(fd);
        return NULL;
      }
      if (write(fd, "", 1) != 1) {
        __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "writting one byte to the file failed");
        close(fd);
        return NULL;
      }
      skipLibCache = true;
      addLibCacheFd(path, fd);
    }
    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;
    }

    offset = 0;

    if (cache_fd < 0) {
      extractLib(entry, data, 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);
#endif
      if (!skipLibCache)
        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;
  }

#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);
  if (!handle)
    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", path, __wrap_dlerror());

  // if we're extracting the libs to disk and cache_fd is not valid then 
  // keep this buffer around so it can be used to write to disk
  if (buf && (!extractLibs || cache_fd >= 0))
    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;
}