linker: Fallback to argv[0] to get the executable info
Enable linking on a system without /proc mounted by falling back to
reading the executable paths from argv[0] when /proc/exe/self can't be
found.
Bug: 254835242
Change-Id: I0735e873fa4e2f439688722c4a846fb70ff398a5
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index f0e7b1b..833157e 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -203,35 +203,29 @@
ElfW(Addr) entry_point;
};
-static ExecutableInfo get_executable_info() {
+static ExecutableInfo get_executable_info(const char* arg_path) {
ExecutableInfo result = {};
+ char const* exe_path = "/proc/self/exe";
- if (is_first_stage_init()) {
- // /proc fs is not mounted when first stage init starts. Therefore we can't
- // use /proc/self/exe for init.
- stat("/init", &result.file_stat);
-
- // /init may be a symlink, so try to read it as such.
- char path[PATH_MAX];
- ssize_t path_len = readlink("/init", path, sizeof(path));
- if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) {
- result.path = "/init";
- } else {
- result.path = std::string(path, path_len);
+ // Stat "/proc/self/exe" instead of executable_path because
+ // the executable could be unlinked by this point and it should
+ // not cause a crash (see http://b/31084669)
+ if (TEMP_FAILURE_RETRY(stat(exe_path, &result.file_stat) == -1)) {
+ // Fallback to argv[0] for the case where /proc isn't available
+ if (TEMP_FAILURE_RETRY(stat(arg_path, &result.file_stat) == -1)) {
+ async_safe_fatal("unable to stat either \"/proc/self/exe\" or \"%s\": %s",
+ arg_path, strerror(errno));
}
+ exe_path = arg_path;
+ }
+
+ // Path might be a symlink
+ char sym_path[PATH_MAX];
+ ssize_t sym_path_len = readlink(exe_path, sym_path, sizeof(sym_path));
+ if (sym_path_len > 0 && sym_path_len < static_cast<ssize_t>(sizeof(sym_path))) {
+ result.path = std::string(sym_path, sym_path_len);
} else {
- // Stat "/proc/self/exe" instead of executable_path because
- // the executable could be unlinked by this point and it should
- // not cause a crash (see http://b/31084669)
- if (TEMP_FAILURE_RETRY(stat("/proc/self/exe", &result.file_stat)) != 0) {
- async_safe_fatal("unable to stat \"/proc/self/exe\": %s", strerror(errno));
- }
- 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))) {
- async_safe_fatal("readlink('/proc/self/exe') failed: %s", strerror(errno));
- }
- result.path = std::string(path, path_len);
+ result.path = std::string(exe_path, strlen(exe_path));
}
result.phdr = reinterpret_cast<const ElfW(Phdr)*>(getauxval(AT_PHDR));
@@ -359,7 +353,7 @@
}
const ExecutableInfo exe_info = exe_to_load ? load_executable(exe_to_load) :
- get_executable_info();
+ get_executable_info(args.argv[0]);
INFO("[ Linking executable \"%s\" ]", exe_info.path.c_str());