OSDN Git Service

Add file_offset parameter to android_extinfo
authorDmitriy Ivanov <dimitry@google.com>
Sat, 4 Oct 2014 00:52:44 +0000 (17:52 -0700)
committerDmitriy Ivanov <dimitry@google.com>
Mon, 6 Oct 2014 17:02:34 +0000 (10:02 -0700)
Bug: 17762003
Change-Id: I8fb267a3155acef3dba534038cf5d1ef00d7154b

libc/include/android/dlext.h
linker/dlfcn.cpp
linker/linker.cpp
linker/linker.h
linker/linker_phdr.cpp
linker/linker_phdr.h
tests/dlext_test.cpp
tests/libs/Android.build.dlext_testzip.mk [new file with mode: 0644]
tests/libs/Android.mk

index 5c3a206..f81ec70 100644 (file)
@@ -54,12 +54,19 @@ enum {
    */
   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 */
   ANDROID_DLEXT_VALID_FLAG_BITS       = ANDROID_DLEXT_RESERVED_ADDRESS |
                                         ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
                                         ANDROID_DLEXT_WRITE_RELRO |
                                         ANDROID_DLEXT_USE_RELRO |
-                                        ANDROID_DLEXT_USE_LIBRARY_FD,
+                                        ANDROID_DLEXT_USE_LIBRARY_FD |
+                                        ANDROID_DLEXT_USE_LIBRARY_OFFSET,
 };
 
 typedef struct {
@@ -68,6 +75,7 @@ typedef struct {
   size_t  reserved_size;
   int     relro_fd;
   int     library_fd;
+  off64_t library_offset;
 } android_dlextinfo;
 
 extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);
index 98931c7..367179d 100644 (file)
@@ -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 };
 #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.
 soinfo* get_libdl_info() {
index a8c2b1e..be2b45a 100644 (file)
@@ -282,13 +282,13 @@ static void protect_data(int 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) {
     DL_ERR("library name \"%s\" too long", name);
     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 = si;
@@ -452,7 +452,7 @@ static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name)
   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));
 
   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;
 
   if (file_stat != nullptr) {
-    set_st_dev(file_stat->st_dev);
-    set_st_ino(file_stat->st_ino);
+    this->st_dev = file_stat->st_dev;
+    this->st_ino = file_stat->st_ino;
+    this->file_offset = file_offset;
   }
 
   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) {
   int fd = -1;
+  off64_t file_offset = 0;
   ScopedFd file_guard(-1);
 
   if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
     fd = extinfo->library_fd;
+    if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_OFFSET) != 0) {
+      file_offset = extinfo->library_offset;
+    }
   } else {
     // Open the file.
     fd = open_library(name);
@@ -796,6 +801,11 @@ static soinfo* load_library(LoadTaskList& load_tasks, const char* name, int rtld
     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;
   if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
     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 &&
         si->get_st_ino() != 0 &&
         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);
       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.
-  ElfReader elf_reader(name, fd);
+  ElfReader elf_reader(name, fd, file_offset);
   if (!elf_reader.Load(extinfo)) {
     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) {
     return nullptr;
   }
@@ -1043,9 +1054,16 @@ soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo)
     DL_ERR("invalid flags to dlopen: %x", flags);
     return nullptr;
   }
-  if (extinfo != nullptr && ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0)) {
-    DL_ERR("invalid extended flags to android_dlopen_ext: %" PRIx64, extinfo->flags);
-    return nullptr;
+  if (extinfo != nullptr) {
+    if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
+      DL_ERR("invalid extended flags to android_dlopen_ext: 0x%" PRIx64, extinfo->flags);
+      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);
   soinfo* si = find_library(name, flags, extinfo);
@@ -1727,18 +1745,6 @@ void soinfo::remove_all_links() {
   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() {
   if (has_min_version(0)) {
     return st_dev;
@@ -1755,6 +1761,14 @@ ino_t soinfo::get_st_ino() {
   return 0;
 }
 
+off64_t soinfo::get_file_offset() {
+  if (has_min_version(1)) {
+    return file_offset;
+  }
+
+  return 0;
+}
+
 int soinfo::get_rtld_flags() {
   if (has_min_version(1)) {
     return rtld_flags;
@@ -2242,7 +2256,7 @@ static void add_vdso(KernelArgumentBlock& args __unused) {
     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->phnum = ehdr_vdso->e_phnum;
@@ -2263,7 +2277,7 @@ static void add_vdso(KernelArgumentBlock& args __unused) {
 #else
 #define LINKER_PATH "/system/bin/linker"
 #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.
  * 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 ]");
 
-  soinfo* si = soinfo_alloc(args.argv[0], nullptr, RTLD_GLOBAL);
+  soinfo* si = soinfo_alloc(args.argv[0], nullptr, 0, RTLD_GLOBAL);
   if (si == nullptr) {
     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(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
   // _start. Which means that the linker is running as an executable and
index c8e5c68..08dd625 100644 (file)
@@ -201,7 +201,7 @@ struct soinfo {
 #endif
   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 CallDestructors();
@@ -212,10 +212,9 @@ struct soinfo {
   void add_child(soinfo* child);
   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();
   dev_t get_st_dev();
+  off64_t get_file_offset();
 
   int get_rtld_flags();
 
@@ -254,6 +253,7 @@ struct soinfo {
   soinfo_list_t parents;
 
   // version >= 1
+  off64_t file_offset;
   int rtld_flags;
   size_t strtab_size;
 
index 44c8e9e..e0d6d0e 100644 (file)
                                       MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
                                       MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
 
-ElfReader::ElfReader(const char* name, int fd)
-    : name_(name), fd_(fd),
+ElfReader::ElfReader(const char* name, int fd, off64_t file_offset)
+    : name_(name), fd_(fd), file_offset_(file_offset),
       phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0),
       load_start_(nullptr), load_size_(0), load_bias_(0),
       loaded_phdr_(nullptr) {
@@ -142,6 +142,13 @@ bool ElfReader::Load(const android_dlextinfo* extinfo) {
 }
 
 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_)));
   if (rc < 0) {
     DL_ERR("can't read file \"%s\": %s", name_, strerror(errno));
@@ -225,7 +232,7 @@ bool ElfReader::ReadProgramHeader() {
 
   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) {
     DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
     return false;
@@ -356,12 +363,12 @@ bool ElfReader::LoadSegments() {
     ElfW(Addr) file_length = file_end - file_page_start;
 
     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,
                             PFLAGS_TO_PROT(phdr->p_flags),
                             MAP_FIXED|MAP_PRIVATE,
                             fd_,
-                            file_page_start);
+                            file_offset_ + file_page_start);
       if (seg_addr == MAP_FAILED) {
         DL_ERR("couldn't map \"%s\" segment %zd: %s", name_, i, strerror(errno));
         return false;
index 593fb5a..65d302c 100644 (file)
@@ -39,7 +39,7 @@
 
 class ElfReader {
  public:
-  ElfReader(const char* name, int fd);
+  ElfReader(const char* name, int fd, off64_t file_offset);
   ~ElfReader();
 
   bool Load(const android_dlextinfo* extinfo);
@@ -61,6 +61,7 @@ class ElfReader {
 
   const char* name_;
   int fd_;
+  off64_t file_offset_;
 
   ElfW(Ehdr) header_;
   size_t phdr_num_;
index 7bd59c8..7585e9b 100644 (file)
@@ -31,7 +31,7 @@
 
 
 #define ASSERT_DL_NOTNULL(ptr) \
-    ASSERT_TRUE(ptr != NULL) << "dlerror: " << dlerror()
+    ASSERT_TRUE(ptr != nullptr) << "dlerror: " << dlerror()
 
 #define ASSERT_DL_ZERO(i) \
     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
 
 #if defined(__LP64__)
-#define LIBPATH "%s/nativetest64/libdlext_test_fd/libdlext_test_fd.so"
+#define LIBPATH_PREFIX "%s/nativetest64/libdlext_test_fd/"
 #else
-#define LIBPATH "%s/nativetest/libdlext_test_fd/libdlext_test_fd.so"
+#define LIBPATH_PREFIX "%s/nativetest/libdlext_test_fd/"
 #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 {
 protected:
   virtual void SetUp() {
-    handle_ = NULL;
+    handle_ = nullptr;
     // 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
-    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() {
-    if (handle_ != NULL) {
+    if (handle_ != nullptr) {
       ASSERT_DL_ZERO(dlclose(handle_));
     }
   }
@@ -71,7 +79,7 @@ protected:
 };
 
 TEST_F(DlExtTest, ExtInfoNull) {
-  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, NULL);
+  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, nullptr);
   ASSERT_DL_NOTNULL(handle_);
   fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
   ASSERT_DL_NOTNULL(f);
@@ -90,7 +98,7 @@ TEST_F(DlExtTest, ExtInfoNoFlags) {
 
 TEST_F(DlExtTest, ExtInfoUseFd) {
   const char* android_data = getenv("ANDROID_DATA");
-  ASSERT_TRUE(android_data != NULL);
+  ASSERT_TRUE(android_data != nullptr);
   char lib_path[PATH_MAX];
   snprintf(lib_path, sizeof(lib_path), LIBPATH, android_data);
 
@@ -105,8 +113,55 @@ TEST_F(DlExtTest, ExtInfoUseFd) {
   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) {
-  void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+  void* start = mmap(nullptr, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
                      -1, 0);
   ASSERT_TRUE(start != MAP_FAILED);
   android_dlextinfo extinfo;
@@ -124,7 +179,7 @@ TEST_F(DlExtTest, Reserved) {
 }
 
 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);
   ASSERT_TRUE(start != MAP_FAILED);
   android_dlextinfo extinfo;
@@ -132,11 +187,11 @@ TEST_F(DlExtTest, ReservedTooSmall) {
   extinfo.reserved_addr = start;
   extinfo.reserved_size = PAGE_SIZE;
   handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
-  EXPECT_EQ(NULL, handle_);
+  EXPECT_EQ(nullptr, handle_);
 }
 
 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);
   ASSERT_TRUE(start != MAP_FAILED);
   android_dlextinfo extinfo;
@@ -154,7 +209,7 @@ TEST_F(DlExtTest, ReservedHint) {
 }
 
 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);
   ASSERT_TRUE(start != MAP_FAILED);
   android_dlextinfo extinfo;
@@ -175,7 +230,7 @@ class DlExtRelroSharingTest : public DlExtTest {
 protected:
   virtual void 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);
     ASSERT_TRUE(start != MAP_FAILED);
     extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
@@ -184,7 +239,7 @@ protected:
     extinfo_.relro_fd = -1;
 
     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);
   }
 
@@ -205,7 +260,7 @@ protected:
       extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
       extinfo_.relro_fd = relro_fd;
       void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
-      if (handle == NULL) {
+      if (handle == nullptr) {
         fprintf(stderr, "in child: %s\n", dlerror());
         exit(1);
       }
@@ -333,7 +388,7 @@ void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, bool sha
       } else {
         handle = dlopen(lib, RTLD_NOW);
       }
-      if (handle == NULL) {
+      if (handle == nullptr) {
         fprintf(stderr, "in child: %s\n", dlerror());
         exit(1);
       }
diff --git a/tests/libs/Android.build.dlext_testzip.mk b/tests/libs/Android.build.dlext_testzip.mk
new file mode 100644 (file)
index 0000000..e672091
--- /dev/null
@@ -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) $< $@
+
index c98fea8..0cff660 100644 (file)
@@ -95,6 +95,17 @@ build_target := SHARED_LIBRARY
 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
 # -----------------------------------------------------------------------------
 libtest_simple_src_files := \
@@ -338,4 +349,8 @@ libtest_dlsym_weak_func_src_files := \
 module := libtest_dlsym_weak_func
 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