am 6d569b92: Merge "Add file_offset parameter to android_extinfo"
				
					
				
			* commit '6d569b92012543a297dccf2dfeaa648d07b3c133': Add file_offset parameter to android_extinfo
This commit is contained in:
		@@ -54,12 +54,19 @@ enum {
 | 
				
			|||||||
   */
 | 
					   */
 | 
				
			||||||
  ANDROID_DLEXT_USE_LIBRARY_FD        = 0x10,
 | 
					  ANDROID_DLEXT_USE_LIBRARY_FD        = 0x10,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* When opening library using library_fd read it starting with library_offset
 | 
				
			||||||
 | 
					   * This flag is only valid when ANDROID_DLEXT_USE_LIBRARY_FD is set.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ANDROID_DLEXT_USE_LIBRARY_OFFSET    = 0x20,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Mask of valid bits */
 | 
					  /* Mask of valid bits */
 | 
				
			||||||
  ANDROID_DLEXT_VALID_FLAG_BITS       = ANDROID_DLEXT_RESERVED_ADDRESS |
 | 
					  ANDROID_DLEXT_VALID_FLAG_BITS       = ANDROID_DLEXT_RESERVED_ADDRESS |
 | 
				
			||||||
                                        ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
 | 
					                                        ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
 | 
				
			||||||
                                        ANDROID_DLEXT_WRITE_RELRO |
 | 
					                                        ANDROID_DLEXT_WRITE_RELRO |
 | 
				
			||||||
                                        ANDROID_DLEXT_USE_RELRO |
 | 
					                                        ANDROID_DLEXT_USE_RELRO |
 | 
				
			||||||
                                        ANDROID_DLEXT_USE_LIBRARY_FD,
 | 
					                                        ANDROID_DLEXT_USE_LIBRARY_FD |
 | 
				
			||||||
 | 
					                                        ANDROID_DLEXT_USE_LIBRARY_OFFSET,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@@ -68,6 +75,7 @@ typedef struct {
 | 
				
			|||||||
  size_t  reserved_size;
 | 
					  size_t  reserved_size;
 | 
				
			||||||
  int     relro_fd;
 | 
					  int     relro_fd;
 | 
				
			||||||
  int     library_fd;
 | 
					  int     library_fd;
 | 
				
			||||||
 | 
					  off64_t library_offset;
 | 
				
			||||||
} android_dlextinfo;
 | 
					} android_dlextinfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);
 | 
					extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -232,7 +232,7 @@ static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 };
 | 
				
			|||||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
 | 
					static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static soinfo __libdl_info("libdl.so", nullptr, RTLD_GLOBAL);
 | 
					static soinfo __libdl_info("libdl.so", nullptr, 0, RTLD_GLOBAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This is used by the dynamic linker. Every process gets these symbols for free.
 | 
					// This is used by the dynamic linker. Every process gets these symbols for free.
 | 
				
			||||||
soinfo* get_libdl_info() {
 | 
					soinfo* get_libdl_info() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -282,13 +282,13 @@ static void protect_data(int protection) {
 | 
				
			|||||||
  g_soinfo_links_allocator.protect_all(protection);
 | 
					  g_soinfo_links_allocator.protect_all(protection);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static soinfo* soinfo_alloc(const char* name, struct stat* file_stat, int rtld_flags) {
 | 
					static soinfo* soinfo_alloc(const char* name, struct stat* file_stat, off64_t file_offset, int rtld_flags) {
 | 
				
			||||||
  if (strlen(name) >= SOINFO_NAME_LEN) {
 | 
					  if (strlen(name) >= SOINFO_NAME_LEN) {
 | 
				
			||||||
    DL_ERR("library name \"%s\" too long", name);
 | 
					    DL_ERR("library name \"%s\" too long", name);
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(name, file_stat, rtld_flags);
 | 
					  soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(name, file_stat, file_offset, rtld_flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  sonext->next = si;
 | 
					  sonext->next = si;
 | 
				
			||||||
  sonext = si;
 | 
					  sonext = si;
 | 
				
			||||||
@@ -452,7 +452,7 @@ static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name)
 | 
				
			|||||||
  return nullptr;
 | 
					  return nullptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
soinfo::soinfo(const char* name, const struct stat* file_stat, int rtld_flags) {
 | 
					soinfo::soinfo(const char* name, const struct stat* file_stat, off64_t file_offset, int rtld_flags) {
 | 
				
			||||||
  memset(this, 0, sizeof(*this));
 | 
					  memset(this, 0, sizeof(*this));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  strlcpy(this->name, name, sizeof(this->name));
 | 
					  strlcpy(this->name, name, sizeof(this->name));
 | 
				
			||||||
@@ -460,8 +460,9 @@ soinfo::soinfo(const char* name, const struct stat* file_stat, int rtld_flags) {
 | 
				
			|||||||
  version = SOINFO_VERSION;
 | 
					  version = SOINFO_VERSION;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (file_stat != nullptr) {
 | 
					  if (file_stat != nullptr) {
 | 
				
			||||||
    set_st_dev(file_stat->st_dev);
 | 
					    this->st_dev = file_stat->st_dev;
 | 
				
			||||||
    set_st_ino(file_stat->st_ino);
 | 
					    this->st_ino = file_stat->st_ino;
 | 
				
			||||||
 | 
					    this->file_offset = file_offset;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  this->rtld_flags = rtld_flags;
 | 
					  this->rtld_flags = rtld_flags;
 | 
				
			||||||
@@ -781,10 +782,14 @@ static void for_each_dt_needed(const soinfo* si, F action) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static soinfo* load_library(LoadTaskList& load_tasks, const char* name, int rtld_flags, const android_dlextinfo* extinfo) {
 | 
					static soinfo* load_library(LoadTaskList& load_tasks, const char* name, int rtld_flags, const android_dlextinfo* extinfo) {
 | 
				
			||||||
  int fd = -1;
 | 
					  int fd = -1;
 | 
				
			||||||
 | 
					  off64_t file_offset = 0;
 | 
				
			||||||
  ScopedFd file_guard(-1);
 | 
					  ScopedFd file_guard(-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
 | 
					  if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
 | 
				
			||||||
    fd = extinfo->library_fd;
 | 
					    fd = extinfo->library_fd;
 | 
				
			||||||
 | 
					    if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_OFFSET) != 0) {
 | 
				
			||||||
 | 
					      file_offset = extinfo->library_offset;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    // Open the file.
 | 
					    // Open the file.
 | 
				
			||||||
    fd = open_library(name);
 | 
					    fd = open_library(name);
 | 
				
			||||||
@@ -796,6 +801,11 @@ static soinfo* load_library(LoadTaskList& load_tasks, const char* name, int rtld
 | 
				
			|||||||
    file_guard.reset(fd);
 | 
					    file_guard.reset(fd);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((file_offset % PAGE_SIZE) != 0) {
 | 
				
			||||||
 | 
					    DL_ERR("file offset for the library %s is not page-aligned: %" PRId64, name, file_offset);
 | 
				
			||||||
 | 
					    return nullptr;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  struct stat file_stat;
 | 
					  struct stat file_stat;
 | 
				
			||||||
  if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
 | 
					  if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
 | 
				
			||||||
    DL_ERR("unable to stat file for the library %s: %s", name, strerror(errno));
 | 
					    DL_ERR("unable to stat file for the library %s: %s", name, strerror(errno));
 | 
				
			||||||
@@ -808,7 +818,8 @@ static soinfo* load_library(LoadTaskList& load_tasks, const char* name, int rtld
 | 
				
			|||||||
    if (si->get_st_dev() != 0 &&
 | 
					    if (si->get_st_dev() != 0 &&
 | 
				
			||||||
        si->get_st_ino() != 0 &&
 | 
					        si->get_st_ino() != 0 &&
 | 
				
			||||||
        si->get_st_dev() == file_stat.st_dev &&
 | 
					        si->get_st_dev() == file_stat.st_dev &&
 | 
				
			||||||
        si->get_st_ino() == file_stat.st_ino) {
 | 
					        si->get_st_ino() == file_stat.st_ino &&
 | 
				
			||||||
 | 
					        si->get_file_offset() == file_offset) {
 | 
				
			||||||
      TRACE("library \"%s\" is already loaded under different name/path \"%s\" - will return existing soinfo", name, si->name);
 | 
					      TRACE("library \"%s\" is already loaded under different name/path \"%s\" - will return existing soinfo", name, si->name);
 | 
				
			||||||
      return si;
 | 
					      return si;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -820,12 +831,12 @@ static soinfo* load_library(LoadTaskList& load_tasks, const char* name, int rtld
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Read the ELF header and load the segments.
 | 
					  // Read the ELF header and load the segments.
 | 
				
			||||||
  ElfReader elf_reader(name, fd);
 | 
					  ElfReader elf_reader(name, fd, file_offset);
 | 
				
			||||||
  if (!elf_reader.Load(extinfo)) {
 | 
					  if (!elf_reader.Load(extinfo)) {
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  soinfo* si = soinfo_alloc(SEARCH_NAME(name), &file_stat, rtld_flags);
 | 
					  soinfo* si = soinfo_alloc(SEARCH_NAME(name), &file_stat, file_offset, rtld_flags);
 | 
				
			||||||
  if (si == nullptr) {
 | 
					  if (si == nullptr) {
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1043,10 +1054,17 @@ soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo)
 | 
				
			|||||||
    DL_ERR("invalid flags to dlopen: %x", flags);
 | 
					    DL_ERR("invalid flags to dlopen: %x", flags);
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (extinfo != nullptr && ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0)) {
 | 
					  if (extinfo != nullptr) {
 | 
				
			||||||
    DL_ERR("invalid extended flags to android_dlopen_ext: %" PRIx64, extinfo->flags);
 | 
					    if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
 | 
				
			||||||
 | 
					      DL_ERR("invalid extended flags to android_dlopen_ext: 0x%" PRIx64, extinfo->flags);
 | 
				
			||||||
      return nullptr;
 | 
					      return nullptr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&
 | 
				
			||||||
 | 
					        (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_OFFSET) != 0) {
 | 
				
			||||||
 | 
					      DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);
 | 
				
			||||||
 | 
					      return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  protect_data(PROT_READ | PROT_WRITE);
 | 
					  protect_data(PROT_READ | PROT_WRITE);
 | 
				
			||||||
  soinfo* si = find_library(name, flags, extinfo);
 | 
					  soinfo* si = find_library(name, flags, extinfo);
 | 
				
			||||||
  if (si != nullptr) {
 | 
					  if (si != nullptr) {
 | 
				
			||||||
@@ -1727,18 +1745,6 @@ void soinfo::remove_all_links() {
 | 
				
			|||||||
  children.clear();
 | 
					  children.clear();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void soinfo::set_st_dev(dev_t dev) {
 | 
					 | 
				
			||||||
  if (has_min_version(0)) {
 | 
					 | 
				
			||||||
    st_dev = dev;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void soinfo::set_st_ino(ino_t ino) {
 | 
					 | 
				
			||||||
  if (has_min_version(0)) {
 | 
					 | 
				
			||||||
    st_ino = ino;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
dev_t soinfo::get_st_dev() {
 | 
					dev_t soinfo::get_st_dev() {
 | 
				
			||||||
  if (has_min_version(0)) {
 | 
					  if (has_min_version(0)) {
 | 
				
			||||||
    return st_dev;
 | 
					    return st_dev;
 | 
				
			||||||
@@ -1755,6 +1761,14 @@ ino_t soinfo::get_st_ino() {
 | 
				
			|||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					off64_t soinfo::get_file_offset() {
 | 
				
			||||||
 | 
					  if (has_min_version(1)) {
 | 
				
			||||||
 | 
					    return file_offset;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int soinfo::get_rtld_flags() {
 | 
					int soinfo::get_rtld_flags() {
 | 
				
			||||||
  if (has_min_version(1)) {
 | 
					  if (has_min_version(1)) {
 | 
				
			||||||
    return rtld_flags;
 | 
					    return rtld_flags;
 | 
				
			||||||
@@ -2242,7 +2256,7 @@ static void add_vdso(KernelArgumentBlock& args __unused) {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  soinfo* si = soinfo_alloc("[vdso]", nullptr, 0);
 | 
					  soinfo* si = soinfo_alloc("[vdso]", nullptr, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  si->phdr = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(ehdr_vdso) + ehdr_vdso->e_phoff);
 | 
					  si->phdr = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(ehdr_vdso) + ehdr_vdso->e_phoff);
 | 
				
			||||||
  si->phnum = ehdr_vdso->e_phnum;
 | 
					  si->phnum = ehdr_vdso->e_phnum;
 | 
				
			||||||
@@ -2263,7 +2277,7 @@ static void add_vdso(KernelArgumentBlock& args __unused) {
 | 
				
			|||||||
#else
 | 
					#else
 | 
				
			||||||
#define LINKER_PATH "/system/bin/linker"
 | 
					#define LINKER_PATH "/system/bin/linker"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
static soinfo linker_soinfo_for_gdb(LINKER_PATH, nullptr, 0);
 | 
					static soinfo linker_soinfo_for_gdb(LINKER_PATH, nullptr, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* gdb expects the linker to be in the debug shared object list.
 | 
					/* gdb expects the linker to be in the debug shared object list.
 | 
				
			||||||
 * Without this, gdb has trouble locating the linker's ".text"
 | 
					 * Without this, gdb has trouble locating the linker's ".text"
 | 
				
			||||||
@@ -2327,7 +2341,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  INFO("[ android linker & debugger ]");
 | 
					  INFO("[ android linker & debugger ]");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  soinfo* si = soinfo_alloc(args.argv[0], nullptr, RTLD_GLOBAL);
 | 
					  soinfo* si = soinfo_alloc(args.argv[0], nullptr, 0, RTLD_GLOBAL);
 | 
				
			||||||
  if (si == nullptr) {
 | 
					  if (si == nullptr) {
 | 
				
			||||||
    exit(EXIT_FAILURE);
 | 
					    exit(EXIT_FAILURE);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -2515,7 +2529,7 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) {
 | 
				
			|||||||
  ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
 | 
					  ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
 | 
				
			||||||
  ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);
 | 
					  ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  soinfo linker_so("[dynamic linker]", nullptr, 0);
 | 
					  soinfo linker_so("[dynamic linker]", nullptr, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If the linker is not acting as PT_INTERP entry_point is equal to
 | 
					  // If the linker is not acting as PT_INTERP entry_point is equal to
 | 
				
			||||||
  // _start. Which means that the linker is running as an executable and
 | 
					  // _start. Which means that the linker is running as an executable and
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -201,7 +201,7 @@ struct soinfo {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
  bool has_DT_SYMBOLIC;
 | 
					  bool has_DT_SYMBOLIC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  soinfo(const char* name, const struct stat* file_stat, int rtld_flags);
 | 
					  soinfo(const char* name, const struct stat* file_stat, off64_t file_offset, int rtld_flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void CallConstructors();
 | 
					  void CallConstructors();
 | 
				
			||||||
  void CallDestructors();
 | 
					  void CallDestructors();
 | 
				
			||||||
@@ -212,10 +212,9 @@ struct soinfo {
 | 
				
			|||||||
  void add_child(soinfo* child);
 | 
					  void add_child(soinfo* child);
 | 
				
			||||||
  void remove_all_links();
 | 
					  void remove_all_links();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void set_st_dev(dev_t st_dev);
 | 
					 | 
				
			||||||
  void set_st_ino(ino_t st_ino);
 | 
					 | 
				
			||||||
  ino_t get_st_ino();
 | 
					  ino_t get_st_ino();
 | 
				
			||||||
  dev_t get_st_dev();
 | 
					  dev_t get_st_dev();
 | 
				
			||||||
 | 
					  off64_t get_file_offset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int get_rtld_flags();
 | 
					  int get_rtld_flags();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -254,6 +253,7 @@ struct soinfo {
 | 
				
			|||||||
  soinfo_list_t parents;
 | 
					  soinfo_list_t parents;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // version >= 1
 | 
					  // version >= 1
 | 
				
			||||||
 | 
					  off64_t file_offset;
 | 
				
			||||||
  int rtld_flags;
 | 
					  int rtld_flags;
 | 
				
			||||||
  size_t strtab_size;
 | 
					  size_t strtab_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -119,8 +119,8 @@
 | 
				
			|||||||
                                      MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
 | 
					                                      MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
 | 
				
			||||||
                                      MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
 | 
					                                      MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ElfReader::ElfReader(const char* name, int fd)
 | 
					ElfReader::ElfReader(const char* name, int fd, off64_t file_offset)
 | 
				
			||||||
    : name_(name), fd_(fd),
 | 
					    : name_(name), fd_(fd), file_offset_(file_offset),
 | 
				
			||||||
      phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0),
 | 
					      phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0),
 | 
				
			||||||
      load_start_(nullptr), load_size_(0), load_bias_(0),
 | 
					      load_start_(nullptr), load_size_(0), load_bias_(0),
 | 
				
			||||||
      loaded_phdr_(nullptr) {
 | 
					      loaded_phdr_(nullptr) {
 | 
				
			||||||
@@ -142,6 +142,13 @@ bool ElfReader::Load(const android_dlextinfo* extinfo) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ElfReader::ReadElfHeader() {
 | 
					bool ElfReader::ReadElfHeader() {
 | 
				
			||||||
 | 
					  off64_t actual_offset = lseek64(fd_, file_offset_, SEEK_SET);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (actual_offset != file_offset_) {
 | 
				
			||||||
 | 
					    DL_ERR("seek to %" PRId64 " failed: %s", file_offset_, strerror(errno));
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ssize_t rc = TEMP_FAILURE_RETRY(read(fd_, &header_, sizeof(header_)));
 | 
					  ssize_t rc = TEMP_FAILURE_RETRY(read(fd_, &header_, sizeof(header_)));
 | 
				
			||||||
  if (rc < 0) {
 | 
					  if (rc < 0) {
 | 
				
			||||||
    DL_ERR("can't read file \"%s\": %s", name_, strerror(errno));
 | 
					    DL_ERR("can't read file \"%s\": %s", name_, strerror(errno));
 | 
				
			||||||
@@ -225,7 +232,7 @@ bool ElfReader::ReadProgramHeader() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  phdr_size_ = page_max - page_min;
 | 
					  phdr_size_ = page_max - page_min;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void* mmap_result = mmap(nullptr, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, page_min);
 | 
					  void* mmap_result = mmap64(nullptr, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, file_offset_ + page_min);
 | 
				
			||||||
  if (mmap_result == MAP_FAILED) {
 | 
					  if (mmap_result == MAP_FAILED) {
 | 
				
			||||||
    DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
 | 
					    DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
@@ -356,12 +363,12 @@ bool ElfReader::LoadSegments() {
 | 
				
			|||||||
    ElfW(Addr) file_length = file_end - file_page_start;
 | 
					    ElfW(Addr) file_length = file_end - file_page_start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (file_length != 0) {
 | 
					    if (file_length != 0) {
 | 
				
			||||||
      void* seg_addr = mmap(reinterpret_cast<void*>(seg_page_start),
 | 
					      void* seg_addr = mmap64(reinterpret_cast<void*>(seg_page_start),
 | 
				
			||||||
                            file_length,
 | 
					                            file_length,
 | 
				
			||||||
                            PFLAGS_TO_PROT(phdr->p_flags),
 | 
					                            PFLAGS_TO_PROT(phdr->p_flags),
 | 
				
			||||||
                            MAP_FIXED|MAP_PRIVATE,
 | 
					                            MAP_FIXED|MAP_PRIVATE,
 | 
				
			||||||
                            fd_,
 | 
					                            fd_,
 | 
				
			||||||
                            file_page_start);
 | 
					                            file_offset_ + file_page_start);
 | 
				
			||||||
      if (seg_addr == MAP_FAILED) {
 | 
					      if (seg_addr == MAP_FAILED) {
 | 
				
			||||||
        DL_ERR("couldn't map \"%s\" segment %zd: %s", name_, i, strerror(errno));
 | 
					        DL_ERR("couldn't map \"%s\" segment %zd: %s", name_, i, strerror(errno));
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ElfReader {
 | 
					class ElfReader {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  ElfReader(const char* name, int fd);
 | 
					  ElfReader(const char* name, int fd, off64_t file_offset);
 | 
				
			||||||
  ~ElfReader();
 | 
					  ~ElfReader();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool Load(const android_dlextinfo* extinfo);
 | 
					  bool Load(const android_dlextinfo* extinfo);
 | 
				
			||||||
@@ -61,6 +61,7 @@ class ElfReader {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const char* name_;
 | 
					  const char* name_;
 | 
				
			||||||
  int fd_;
 | 
					  int fd_;
 | 
				
			||||||
 | 
					  off64_t file_offset_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ElfW(Ehdr) header_;
 | 
					  ElfW(Ehdr) header_;
 | 
				
			||||||
  size_t phdr_num_;
 | 
					  size_t phdr_num_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,7 +31,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ASSERT_DL_NOTNULL(ptr) \
 | 
					#define ASSERT_DL_NOTNULL(ptr) \
 | 
				
			||||||
    ASSERT_TRUE(ptr != NULL) << "dlerror: " << dlerror()
 | 
					    ASSERT_TRUE(ptr != nullptr) << "dlerror: " << dlerror()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ASSERT_DL_ZERO(i) \
 | 
					#define ASSERT_DL_ZERO(i) \
 | 
				
			||||||
    ASSERT_EQ(0, i) << "dlerror: " << dlerror()
 | 
					    ASSERT_EQ(0, i) << "dlerror: " << dlerror()
 | 
				
			||||||
@@ -46,23 +46,31 @@ typedef int (*fn)(void);
 | 
				
			|||||||
#define LIBSIZE 1024*1024 // how much address space to reserve for it
 | 
					#define LIBSIZE 1024*1024 // how much address space to reserve for it
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__LP64__)
 | 
					#if defined(__LP64__)
 | 
				
			||||||
#define LIBPATH "%s/nativetest64/libdlext_test_fd/libdlext_test_fd.so"
 | 
					#define LIBPATH_PREFIX "%s/nativetest64/libdlext_test_fd/"
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#define LIBPATH "%s/nativetest/libdlext_test_fd/libdlext_test_fd.so"
 | 
					#define LIBPATH_PREFIX "%s/nativetest/libdlext_test_fd/"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LIBPATH LIBPATH_PREFIX "libdlext_test_fd.so"
 | 
				
			||||||
 | 
					#define LIBZIPPATH LIBPATH_PREFIX "dlext_test.zip"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LIBZIP_OFFSET 2*PAGE_SIZE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DlExtTest : public ::testing::Test {
 | 
					class DlExtTest : public ::testing::Test {
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
  virtual void SetUp() {
 | 
					  virtual void SetUp() {
 | 
				
			||||||
    handle_ = NULL;
 | 
					    handle_ = nullptr;
 | 
				
			||||||
    // verify that we don't have the library loaded already
 | 
					    // verify that we don't have the library loaded already
 | 
				
			||||||
    ASSERT_EQ(NULL, dlsym(RTLD_DEFAULT, "getRandomNumber"));
 | 
					    void* h = dlopen(LIBNAME, RTLD_NOW | RTLD_NOLOAD);
 | 
				
			||||||
 | 
					    ASSERT_TRUE(h == nullptr);
 | 
				
			||||||
 | 
					    h = dlopen(LIBNAME_NORELRO, RTLD_NOW | RTLD_NOLOAD);
 | 
				
			||||||
 | 
					    ASSERT_TRUE(h == nullptr);
 | 
				
			||||||
    // call dlerror() to swallow the error, and check it was the one we wanted
 | 
					    // call dlerror() to swallow the error, and check it was the one we wanted
 | 
				
			||||||
    ASSERT_STREQ("undefined symbol: getRandomNumber", dlerror());
 | 
					    ASSERT_STREQ("dlopen failed: library \"" LIBNAME_NORELRO "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  virtual void TearDown() {
 | 
					  virtual void TearDown() {
 | 
				
			||||||
    if (handle_ != NULL) {
 | 
					    if (handle_ != nullptr) {
 | 
				
			||||||
      ASSERT_DL_ZERO(dlclose(handle_));
 | 
					      ASSERT_DL_ZERO(dlclose(handle_));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -71,7 +79,7 @@ protected:
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_F(DlExtTest, ExtInfoNull) {
 | 
					TEST_F(DlExtTest, ExtInfoNull) {
 | 
				
			||||||
  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, NULL);
 | 
					  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, nullptr);
 | 
				
			||||||
  ASSERT_DL_NOTNULL(handle_);
 | 
					  ASSERT_DL_NOTNULL(handle_);
 | 
				
			||||||
  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
 | 
					  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
 | 
				
			||||||
  ASSERT_DL_NOTNULL(f);
 | 
					  ASSERT_DL_NOTNULL(f);
 | 
				
			||||||
@@ -90,7 +98,7 @@ TEST_F(DlExtTest, ExtInfoNoFlags) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
TEST_F(DlExtTest, ExtInfoUseFd) {
 | 
					TEST_F(DlExtTest, ExtInfoUseFd) {
 | 
				
			||||||
  const char* android_data = getenv("ANDROID_DATA");
 | 
					  const char* android_data = getenv("ANDROID_DATA");
 | 
				
			||||||
  ASSERT_TRUE(android_data != NULL);
 | 
					  ASSERT_TRUE(android_data != nullptr);
 | 
				
			||||||
  char lib_path[PATH_MAX];
 | 
					  char lib_path[PATH_MAX];
 | 
				
			||||||
  snprintf(lib_path, sizeof(lib_path), LIBPATH, android_data);
 | 
					  snprintf(lib_path, sizeof(lib_path), LIBPATH, android_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -105,8 +113,55 @@ TEST_F(DlExtTest, ExtInfoUseFd) {
 | 
				
			|||||||
  EXPECT_EQ(4, f());
 | 
					  EXPECT_EQ(4, f());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_F(DlExtTest, ExtInfoUseFdWithOffset) {
 | 
				
			||||||
 | 
					  const char* android_data = getenv("ANDROID_DATA");
 | 
				
			||||||
 | 
					  ASSERT_TRUE(android_data != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  char lib_path[PATH_MAX];
 | 
				
			||||||
 | 
					  snprintf(lib_path, sizeof(lib_path), LIBZIPPATH, android_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  android_dlextinfo extinfo;
 | 
				
			||||||
 | 
					  extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_OFFSET;
 | 
				
			||||||
 | 
					  extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path, O_RDONLY | O_CLOEXEC));
 | 
				
			||||||
 | 
					  extinfo.library_offset = LIBZIP_OFFSET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handle_ = android_dlopen_ext(lib_path, RTLD_NOW, &extinfo);
 | 
				
			||||||
 | 
					  ASSERT_DL_NOTNULL(handle_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
 | 
				
			||||||
 | 
					  ASSERT_DL_NOTNULL(f);
 | 
				
			||||||
 | 
					  EXPECT_EQ(4, f());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
 | 
				
			||||||
 | 
					  const char* android_data = getenv("ANDROID_DATA");
 | 
				
			||||||
 | 
					  ASSERT_TRUE(android_data != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  char lib_path[PATH_MAX];
 | 
				
			||||||
 | 
					  snprintf(lib_path, sizeof(lib_path), LIBZIPPATH, android_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  android_dlextinfo extinfo;
 | 
				
			||||||
 | 
					  extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_OFFSET;
 | 
				
			||||||
 | 
					  extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path, O_RDONLY | O_CLOEXEC));
 | 
				
			||||||
 | 
					  extinfo.library_offset = 17;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(handle_ == nullptr);
 | 
				
			||||||
 | 
					  ASSERT_STREQ("dlopen failed: file offset for the library libname_placeholder is not page-aligned: 17", dlerror());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_F(DlExtTest, ExtInfoUseOffsetWihtoutFd) {
 | 
				
			||||||
 | 
					  android_dlextinfo extinfo;
 | 
				
			||||||
 | 
					  extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_OFFSET;
 | 
				
			||||||
 | 
					  extinfo.library_offset = LIBZIP_OFFSET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(handle_ == nullptr);
 | 
				
			||||||
 | 
					  ASSERT_STREQ("dlopen failed: invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x20", dlerror());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_F(DlExtTest, Reserved) {
 | 
					TEST_F(DlExtTest, Reserved) {
 | 
				
			||||||
  void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
 | 
					  void* start = mmap(nullptr, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
 | 
				
			||||||
                     -1, 0);
 | 
					                     -1, 0);
 | 
				
			||||||
  ASSERT_TRUE(start != MAP_FAILED);
 | 
					  ASSERT_TRUE(start != MAP_FAILED);
 | 
				
			||||||
  android_dlextinfo extinfo;
 | 
					  android_dlextinfo extinfo;
 | 
				
			||||||
@@ -124,7 +179,7 @@ TEST_F(DlExtTest, Reserved) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_F(DlExtTest, ReservedTooSmall) {
 | 
					TEST_F(DlExtTest, ReservedTooSmall) {
 | 
				
			||||||
  void* start = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
 | 
					  void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
 | 
				
			||||||
                     -1, 0);
 | 
					                     -1, 0);
 | 
				
			||||||
  ASSERT_TRUE(start != MAP_FAILED);
 | 
					  ASSERT_TRUE(start != MAP_FAILED);
 | 
				
			||||||
  android_dlextinfo extinfo;
 | 
					  android_dlextinfo extinfo;
 | 
				
			||||||
@@ -132,11 +187,11 @@ TEST_F(DlExtTest, ReservedTooSmall) {
 | 
				
			|||||||
  extinfo.reserved_addr = start;
 | 
					  extinfo.reserved_addr = start;
 | 
				
			||||||
  extinfo.reserved_size = PAGE_SIZE;
 | 
					  extinfo.reserved_size = PAGE_SIZE;
 | 
				
			||||||
  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
 | 
					  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
 | 
				
			||||||
  EXPECT_EQ(NULL, handle_);
 | 
					  EXPECT_EQ(nullptr, handle_);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_F(DlExtTest, ReservedHint) {
 | 
					TEST_F(DlExtTest, ReservedHint) {
 | 
				
			||||||
  void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
 | 
					  void* start = mmap(nullptr, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
 | 
				
			||||||
                     -1, 0);
 | 
					                     -1, 0);
 | 
				
			||||||
  ASSERT_TRUE(start != MAP_FAILED);
 | 
					  ASSERT_TRUE(start != MAP_FAILED);
 | 
				
			||||||
  android_dlextinfo extinfo;
 | 
					  android_dlextinfo extinfo;
 | 
				
			||||||
@@ -154,7 +209,7 @@ TEST_F(DlExtTest, ReservedHint) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_F(DlExtTest, ReservedHintTooSmall) {
 | 
					TEST_F(DlExtTest, ReservedHintTooSmall) {
 | 
				
			||||||
  void* start = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
 | 
					  void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
 | 
				
			||||||
                     -1, 0);
 | 
					                     -1, 0);
 | 
				
			||||||
  ASSERT_TRUE(start != MAP_FAILED);
 | 
					  ASSERT_TRUE(start != MAP_FAILED);
 | 
				
			||||||
  android_dlextinfo extinfo;
 | 
					  android_dlextinfo extinfo;
 | 
				
			||||||
@@ -175,7 +230,7 @@ class DlExtRelroSharingTest : public DlExtTest {
 | 
				
			|||||||
protected:
 | 
					protected:
 | 
				
			||||||
  virtual void SetUp() {
 | 
					  virtual void SetUp() {
 | 
				
			||||||
    DlExtTest::SetUp();
 | 
					    DlExtTest::SetUp();
 | 
				
			||||||
    void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
 | 
					    void* start = mmap(nullptr, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
 | 
				
			||||||
                       -1, 0);
 | 
					                       -1, 0);
 | 
				
			||||||
    ASSERT_TRUE(start != MAP_FAILED);
 | 
					    ASSERT_TRUE(start != MAP_FAILED);
 | 
				
			||||||
    extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
 | 
					    extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
 | 
				
			||||||
@@ -184,7 +239,7 @@ protected:
 | 
				
			|||||||
    extinfo_.relro_fd = -1;
 | 
					    extinfo_.relro_fd = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const char* android_data = getenv("ANDROID_DATA");
 | 
					    const char* android_data = getenv("ANDROID_DATA");
 | 
				
			||||||
    ASSERT_TRUE(android_data != NULL);
 | 
					    ASSERT_TRUE(android_data != nullptr);
 | 
				
			||||||
    snprintf(relro_file_, sizeof(relro_file_), "%s/local/tmp/libdlext_test.relro", android_data);
 | 
					    snprintf(relro_file_, sizeof(relro_file_), "%s/local/tmp/libdlext_test.relro", android_data);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -205,7 +260,7 @@ protected:
 | 
				
			|||||||
      extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
 | 
					      extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
 | 
				
			||||||
      extinfo_.relro_fd = relro_fd;
 | 
					      extinfo_.relro_fd = relro_fd;
 | 
				
			||||||
      void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
 | 
					      void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
 | 
				
			||||||
      if (handle == NULL) {
 | 
					      if (handle == nullptr) {
 | 
				
			||||||
        fprintf(stderr, "in child: %s\n", dlerror());
 | 
					        fprintf(stderr, "in child: %s\n", dlerror());
 | 
				
			||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -333,7 +388,7 @@ void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, bool sha
 | 
				
			|||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        handle = dlopen(lib, RTLD_NOW);
 | 
					        handle = dlopen(lib, RTLD_NOW);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (handle == NULL) {
 | 
					      if (handle == nullptr) {
 | 
				
			||||||
        fprintf(stderr, "in child: %s\n", dlerror());
 | 
					        fprintf(stderr, "in child: %s\n", dlerror());
 | 
				
			||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										48
									
								
								tests/libs/Android.build.dlext_testzip.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								tests/libs/Android.build.dlext_testzip.mk
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (C) 2014 The Android Open Source Project
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Library used by dlext tests - zipped and aligned
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO: It there simple way to do this?
 | 
				
			||||||
 | 
					$(bionic_2nd_arch_prefix)bionic_dlext_test_zip := \
 | 
				
			||||||
 | 
					    $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATES)/libdlext_test_fd/dlext_test_origin.zip
 | 
				
			||||||
 | 
					$(bionic_2nd_arch_prefix)bionic_dlext_test_zip_aligned := \
 | 
				
			||||||
 | 
					    $($(bionic_2nd_arch_prefix)TARGET_OUT_DATA_NATIVE_TESTS)/libdlext_test_fd/dlext_test.zip
 | 
				
			||||||
 | 
					ALL_MODULES += $($(bionic_2nd_arch_prefix)bionic_dlext_test_zip_aligned)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(bionic_2nd_arch_prefix)bionic_dlext_built_shared_libraries := \
 | 
				
			||||||
 | 
					    $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libdlext_test_fd.so
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bionic_dlext_test_zip_alignment := 4096 # PAGE_SIZE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(bionic_2nd_arch_prefix)bionic_dlext_test_zip_tmpdir := $(dir $($(bionic_2nd_arch_prefix)bionic_dlext_test_zip))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$($(bionic_2nd_arch_prefix)bionic_dlext_test_zip)_prepare: $($(bionic_2nd_arch_prefix)bionic_dlext_built_shared_libraries)
 | 
				
			||||||
 | 
						$(hide) mkdir -p $(dir $@)
 | 
				
			||||||
 | 
						$(hide) cp -p $< $(dir $@)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$($(bionic_2nd_arch_prefix)bionic_dlext_test_zip): $($(bionic_2nd_arch_prefix)bionic_dlext_test_zip)_prepare
 | 
				
			||||||
 | 
						@echo "Zip: $@"
 | 
				
			||||||
 | 
						$(hide) (cd $(dir $@) && touch empty_file.txt && zip -rD0 $(notdir $@) empty_file.txt libdlext_test_fd.so)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$($(bionic_2nd_arch_prefix)bionic_dlext_test_zip_aligned): $($(bionic_2nd_arch_prefix)bionic_dlext_test_zip) | $(ZIPALIGN)
 | 
				
			||||||
 | 
						$(hide) rm -rf $@
 | 
				
			||||||
 | 
						$(hide) mkdir -p $(dir $@)
 | 
				
			||||||
 | 
						@echo "Zipalign $(bionic_dlext_test_zip_alignment): $@"
 | 
				
			||||||
 | 
						$(hide) zipalign $(bionic_dlext_test_zip_alignment) $< $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -94,6 +94,17 @@ build_type := target
 | 
				
			|||||||
build_target := SHARED_LIBRARY
 | 
					build_target := SHARED_LIBRARY
 | 
				
			||||||
include $(TEST_PATH)/Android.build.mk
 | 
					include $(TEST_PATH)/Android.build.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Library used by dlext tests - zipped and aligned
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					include $(CLEAR_VARS)
 | 
				
			||||||
 | 
					bionic_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.dlext_testzip.mk
 | 
				
			||||||
 | 
					ifneq ($(TARGET_2ND_ARCH),)
 | 
				
			||||||
 | 
					  bionic_2nd_arch_prefix :=
 | 
				
			||||||
 | 
					  include $(LOCAL_PATH)/Android.build.dlext_testzip.mk
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# -----------------------------------------------------------------------------
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
# Library used by dlfcn tests
 | 
					# Library used by dlfcn tests
 | 
				
			||||||
# -----------------------------------------------------------------------------
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
@@ -338,4 +349,8 @@ libtest_dlsym_weak_func_src_files := \
 | 
				
			|||||||
module := libtest_dlsym_weak_func
 | 
					module := libtest_dlsym_weak_func
 | 
				
			||||||
include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/Android.build.testlib.mk $(TEST_PATH)/Android.build.mk
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := \
 | 
				
			||||||
 | 
					    $(LOCAL_PATH)/Android.mk \
 | 
				
			||||||
 | 
					    $(LOCAL_PATH)/Android.build.dlext_testzip.mk \
 | 
				
			||||||
 | 
					    $(LOCAL_PATH)/Android.build.testlib.mk \
 | 
				
			||||||
 | 
					    $(TEST_PATH)/Android.build.mk
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user