linker: support ldd(1)-like behavior via --list.
Given that we have both linker and linker64, I didn't really want to have
to have ldd and ldd64, so this change just adds the --list option to the
linkers and a shell script wrapper "ldd" that calls the appropriate
linker behind the scenes.
Test: adb shell linker --list `which app_process32`
Test: adb shell linker64 --list `which date`
Test: adb shell ldd `which app_process32`
Test: adb shell ldd `which date`
Change-Id: I33494bda1cc3cafee54e091f97c0f2ae52d1f74b
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index f6e4f67..f576023 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -117,6 +117,7 @@
return vdso;
}
+bool g_is_ldd;
int g_ld_debug_verbosity;
static std::vector<std::string> g_ld_preload_names;
@@ -397,7 +398,7 @@
"\"%s\": error: Android 5.0 and later only support "
"position-independent executables (-fPIE).\n",
g_argv[0]);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
// Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
@@ -660,22 +661,29 @@
// linker's _start.
const char* exe_to_load = nullptr;
if (getauxval(AT_ENTRY) == reinterpret_cast<uintptr_t>(&_start)) {
- if (args.argc <= 1 || !strcmp(args.argv[1], "--help")) {
+ if (args.argc == 3 && !strcmp(args.argv[1], "--list")) {
+ // We're being asked to behave like ldd(1).
+ g_is_ldd = true;
+ exe_to_load = args.argv[2];
+ } else if (args.argc <= 1 || !strcmp(args.argv[1], "--help")) {
async_safe_format_fd(STDOUT_FILENO,
- "Usage: %s program [arguments...]\n"
- " %s path.zip!/program [arguments...]\n"
+ "Usage: %s [--list] PROGRAM [ARGS-FOR-PROGRAM...]\n"
+ " %s [--list] path.zip!/PROGRAM [ARGS-FOR-PROGRAM...]\n"
"\n"
"A helper program for linking dynamic executables. Typically, the kernel loads\n"
"this program because it's the PT_INTERP of a dynamic executable.\n"
"\n"
"This program can also be run directly to load and run a dynamic executable. The\n"
"executable can be inside a zip file if it's stored uncompressed and at a\n"
- "page-aligned offset.\n",
+ "page-aligned offset.\n"
+ "\n"
+ "The --list option gives behavior equivalent to ldd(1) on other systems.\n",
args.argv[0], args.argv[0]);
- exit(0);
+ _exit(EXIT_SUCCESS);
+ } else {
+ exe_to_load = args.argv[1];
+ __libc_shared_globals()->initial_linker_arg_count = 1;
}
- exe_to_load = args.argv[1];
- __libc_shared_globals()->initial_linker_arg_count = 1;
}
// store argc/argv/envp to use them for calling constructors
@@ -693,6 +701,8 @@
ElfW(Addr) start_address = linker_main(args, exe_to_load);
+ if (g_is_ldd) _exit(EXIT_SUCCESS);
+
INFO("[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address));
// Return the address that the calling assembly stub should jump to.