summaryrefslogtreecommitdiff
path: root/linker/linker.cpp
diff options
context:
space:
mode:
authorDimitry Ivanov <dimitry@google.com>2016-05-17 13:29:37 -0700
committerDimitry Ivanov <dimitry@google.com>2016-05-17 15:31:05 -0700
commitdcaef3710df817db5652a1f3ab4646f43f5cd3ee (patch)
tree3aa1bd5e9f1c8040189ef2abb01228938e2fd9d9 /linker/linker.cpp
parentd120719e250d3f112b1c71ae775cab09c70191cd (diff)
Fix dlopen of main executable by absolute path
This CL adds initialization of inode for the main executable which enables linker to resolve the correct soinfo when application calls dlopen with absolute path to the main executable. Bug: http://b/28420266 Change-Id: I102e07bde454bd44c6e46075e3faeeb5092830d8 (cherry picked from commit 2ba1cf39ae6087249a839ec7b3793d4d4fa75438)
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r--linker/linker.cpp24
1 files changed, 22 insertions, 2 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index d21625edb..799ec50ef 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -4142,6 +4142,20 @@ static void init_default_namespace() {
extern "C" int __system_properties_init(void);
+static const char* get_executable_path() {
+ static std::string executable_path;
+ if (executable_path.empty()) {
+ char path[PATH_MAX];
+ ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
+ if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) {
+ __libc_fatal("readlink('/proc/self/exe') failed: %s", strerror(errno));
+ }
+ executable_path = std::string(path, path_len);
+ }
+
+ return executable_path.c_str();
+}
+
/*
* This code is called after the linker has linked itself and
* fixed it's own GOT. It is safe to make references to externs
@@ -4188,7 +4202,13 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
}
}
- soinfo* si = soinfo_alloc(&g_default_namespace, args.argv[0], nullptr, 0, RTLD_GLOBAL);
+ const char* executable_path = get_executable_path();
+ struct stat file_stat;
+ if (TEMP_FAILURE_RETRY(stat(executable_path, &file_stat)) != 0) {
+ __libc_fatal("unable to stat file for the executable \"%s\": %s", executable_path, strerror(errno));
+ }
+
+ soinfo* si = soinfo_alloc(&g_default_namespace, executable_path, &file_stat, 0, RTLD_GLOBAL);
if (si == nullptr) {
__libc_fatal("Couldn't allocate soinfo: out of memory?");
}
@@ -4201,7 +4221,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
// gdb aware of them before loading the rest of the dependency
// tree.
map->l_addr = 0;
- map->l_name = args.argv[0];
+ map->l_name = const_cast<char*>(executable_path);
insert_link_map_into_debug_map(map);
init_linker_info_for_gdb(linker_base);