Bug 1350501 - Find absolute paths for system libraries on Android. r?glandium
MozReview-Commit-ID: C7l1jj2tPyt
--- 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);