summaryrefslogtreecommitdiff
path: root/linker/linker.cpp
diff options
context:
space:
mode:
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);