Merge "loader: stop relying on AT_BASE"

This commit is contained in:
Treehugger Robot 2017-03-24 02:03:57 +00:00 committed by Gerrit Code Review
commit ad8dcd6023
2 changed files with 21 additions and 20 deletions

View file

@ -39,35 +39,29 @@ cc_binary {
srcs: ["arch/arm/begin.S"],
cflags: ["-D__work_around_b_24465209__"],
ldflags: ["-Wl,-dynamic-linker,/system/bin/linker"],
},
arm64: {
srcs: ["arch/arm64/begin.S"],
ldflags: ["-Wl,-dynamic-linker,/system/bin/linker64"],
},
x86: {
srcs: ["arch/x86/begin.c"],
cflags: ["-D__work_around_b_24465209__"],
ldflags: ["-Wl,-dynamic-linker,/system/bin/linker"],
},
x86_64: {
srcs: ["arch/x86_64/begin.S"],
ldflags: ["-Wl,-dynamic-linker,/system/bin/linker64"],
},
mips: {
srcs: [
"arch/mips/begin.S",
"linker_mips.cpp",
],
ldflags: ["-Wl,-dynamic-linker,/system/bin/linker"],
},
mips64: {
srcs: [
"arch/mips64/begin.S",
"linker_mips.cpp",
],
ldflags: ["-Wl,-dynamic-linker,/system/bin/linker64"],
},
},

View file

@ -481,26 +481,20 @@ static void __linker_cannot_link(const char* argv0) {
extern "C" ElfW(Addr) __linker_init(void* raw_args) {
KernelArgumentBlock args(raw_args);
ElfW(Addr) linker_addr = args.getauxval(AT_BASE);
// AT_BASE is set to 0 in the case when linker is run by iself
// so in order to link the linker it needs to calcuate AT_BASE
// using information at hand. The trick below takes advantage
// of the fact that the value of linktime_addr before relocations
// are run is an offset and this can be used to calculate AT_BASE.
static uintptr_t linktime_addr = reinterpret_cast<uintptr_t>(&linktime_addr);
ElfW(Addr) linker_addr = reinterpret_cast<uintptr_t>(&linktime_addr) - linktime_addr;
ElfW(Addr) entry_point = args.getauxval(AT_ENTRY);
ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);
soinfo linker_so(nullptr, nullptr, nullptr, 0, 0);
// If the linker is not acting as PT_INTERP entry_point is equal to
// _start. Which means that the linker is running as an executable and
// already linked by PT_INTERP.
//
// This happens when user tries to run 'adb shell /system/bin/linker'
// see also https://code.google.com/p/android/issues/detail?id=63174
if (reinterpret_cast<ElfW(Addr)>(&_start) == entry_point) {
__libc_format_fd(STDOUT_FILENO,
"This is %s, the helper program for dynamic executables.\n",
args.argv[0]);
exit(0);
}
linker_so.base = linker_addr;
linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum);
linker_so.load_bias = get_elf_exec_load_bias(elf_hdr);
@ -547,6 +541,19 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) {
// Initialize the linker's own global variables
linker_so.call_constructors();
// If the linker is not acting as PT_INTERP entry_point is equal to
// _start. Which means that the linker is running as an executable and
// already linked by PT_INTERP.
//
// This happens when user tries to run 'adb shell /system/bin/linker'
// see also https://code.google.com/p/android/issues/detail?id=63174
if (reinterpret_cast<ElfW(Addr)>(&_start) == entry_point) {
__libc_format_fd(STDOUT_FILENO,
"This is %s, the helper program for dynamic executables.\n",
args.argv[0]);
exit(0);
}
// Initialize static variables. Note that in order to
// get correct libdl_info we need to call constructors
// before get_libdl_info().