Bug 1350501 - Find absolute paths for system libraries on Android. r?glandium draft
authorMarkus Stange <mstange@themasta.com>
Wed, 10 May 2017 16:59:57 -0400 (2017-05-10)
changeset 575780 0b19326cb7c45b3c3f561e42bc5722ecdfec1c08
parent 575779 81b3327241c778fbdc1b5cf9903015281073d31d
child 575782 cb9739e2b1c50d579b7620c7d59c34fd3c62f3b4
push id58163
push userbmo:mstange@themasta.com
push dateWed, 10 May 2017 21:01:02 +0000 (2017-05-10)
reviewersglandium
bugs1350501
milestone55.0a1
Bug 1350501 - Find absolute paths for system libraries on Android. r?glandium MozReview-Commit-ID: C7l1jj2tPyt
mozglue/linker/ElfLoader.cpp
--- a/mozglue/linker/ElfLoader.cpp
+++ b/mozglue/linker/ElfLoader.cpp
@@ -12,16 +12,18 @@
 #include <algorithm>
 #include <fcntl.h>
 #include "ElfLoader.h"
 #include "BaseElf.h"
 #include "CustomElf.h"
 #include "Mappable.h"
 #include "Logging.h"
 #include <inttypes.h>
+#include "mozilla/Sprintf.h"
+#include "mozilla/ArrayUtils.h"
 
 #if defined(ANDROID)
 #include <sys/syscall.h>
 
 #include <android/api-level.h>
 #if __ANDROID_API__ < 8
 /* Android API < 8 doesn't provide sigaltstack */
 
@@ -39,18 +41,16 @@ inline int sigaltstack(const stack_t *ss
 extern "C" MOZ_EXPORT const void *
 __gnu_Unwind_Find_exidx(void *pc, int *pcount) __attribute__((weak));
 #endif
 
 /* Pointer to the PT_DYNAMIC section of the executable or library
  * containing this code. */
 extern "C" Elf::Dyn _DYNAMIC[];
 
-using namespace mozilla;
-
 /**
  * dlfcn.h replacements functions
  */
 
 void *
 __wrap_dlopen(const char *path, int flags)
 {
   RefPtr<LibHandle> handle = ElfLoader::Singleton.Load(path, flags);
@@ -99,32 +99,64 @@ int
   if (!handle) {
     return dladdr(addr, info);
   }
   info->dli_fname = handle->GetPath();
   info->dli_fbase = handle->GetBase();
   return 1;
 }
 
+static const char* const sSOPaths[] = {
+    "/vendor/lib",
+    "/vendor/lib/egl",
+    "/system/lib",
+    "/system/lib/hw"
+};
+
+static std::string
+GetFullLibPath(const char* name)
+{
+    DEBUG_LOG("GetFullLibPath(%s)\n", name);
+    if (!name || strlen(name) > 256 || name[0] == '/') {
+        return name;
+    }
+
+    // Try out the hardcoded system library prefixes in sSOPaths.
+    for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sSOPaths); i++) {
+        std::string fullPath = sSOPaths[i];
+        fullPath += "/";
+        fullPath += name;
+
+        AutoCloseFD fd(access(fullPath.c_str(), O_RDONLY));
+        if (fd >= 0) {
+          return fullPath;
+        }
+        DEBUG_LOG("%s does not exist: %s", fullPath.c_str(), strerror(errno));
+    }
+
+    return name;
+}
+
 int
 __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data)
 {
   if (!ElfLoader::Singleton.dbg)
     return -1;
 
   int pipefd[2];
   bool valid_pipe = (pipe(pipefd) == 0);
   AutoCloseFD read_fd(pipefd[0]);
   AutoCloseFD write_fd(pipefd[1]);
 
   for (ElfLoader::DebuggerHelper::iterator it = ElfLoader::Singleton.dbg.begin();
        it < ElfLoader::Singleton.dbg.end(); ++it) {
+    std::string fullPath = GetFullLibPath(it->l_name);
     dl_phdr_info info;
     info.dlpi_addr = reinterpret_cast<Elf::Addr>(it->l_addr);
-    info.dlpi_name = it->l_name;
+    info.dlpi_name = fullPath.c_str();
     info.dlpi_phdr = nullptr;
     info.dlpi_phnum = 0;
 
     // Assuming l_addr points to Elf headers (in most cases, this is true),
     // get the Phdr location from there.
     // Unfortunately, when l_addr doesn't point to Elf headers, it may point
     // to unmapped memory, or worse, unreadable memory. The only way to detect
     // the latter without causing a SIGSEGV is to use the pointer in a system
@@ -344,24 +376,18 @@ SystemElf::GetSymbolPtr(const char *symb
 
 Mappable *
 SystemElf::GetMappable() const
 {
   const char *path = GetPath();
   if (!path)
     return nullptr;
 #ifdef ANDROID
-  /* On Android, if we don't have the full path, try in /system/lib */
-  const char *name = LeafName(path);
-  std::string systemPath;
-  if (name == path) {
-    systemPath = "/system/lib/";
-    systemPath += path;
-    path = systemPath.c_str();
-  }
+  std::string systemPath = GetFullLibPath(path);
+  path = systemPath.c_str();
 #endif
 
   return MappableFile::Create(path);
 }
 
 #ifdef __ARM_EABI__
 const void *
 SystemElf::FindExidx(int *pcount) const
@@ -469,16 +495,17 @@ ElfLoader::GetHandleByPtr(void *addr)
     }
   }
   return nullptr;
 }
 
 Mappable *
 ElfLoader::GetMappableFromPath(const char *path)
 {
+  DEBUG_LOG("ElfLoader::GetMappableFromPath(%s)\n", path);
   const char *name = LeafName(path);
   Mappable *mappable = nullptr;
   RefPtr<Zip> zip;
   const char *subpath;
   if ((subpath = strchr(path, '!'))) {
     char *zip_path = strndup(path, subpath - path);
     while (*(++subpath) == '/') { }
     zip = ZipCollection::GetZip(zip_path);