diff options
| author | Elliott Hughes <enh@google.com> | 2013-10-25 17:38:02 -0700 |
|---|---|---|
| committer | Elliott Hughes <enh@google.com> | 2013-10-28 11:02:49 -0700 |
| commit | 4eeb1f12a8b63afc0d0ad4d466b16fbffb21cd5a (patch) | |
| tree | 618c8b7133f3602880e0a4c8285c34e7552a0a45 /linker/linker.cpp | |
| parent | 93fcfeee2b4de4c65fc766bf10601397592341d7 (diff) | |
| download | bionic-4eeb1f12a8b63afc0d0ad4d466b16fbffb21cd5a.zip bionic-4eeb1f12a8b63afc0d0ad4d466b16fbffb21cd5a.tar.gz bionic-4eeb1f12a8b63afc0d0ad4d466b16fbffb21cd5a.tar.bz2 | |
Clean up linker architecture macros.
We don't need our own architecture macros; the standard ones will do.
This patch also fixes some __x86_64__ tests to be USE_RELA tests instead,
because they're not actually x86_64-specific.
I've cleaned up architecture-specific code slightly so where possible
all the code corresponding to a particular architecture is together.
This patch also fixes a bug in LP64 DT_PLTGOT handling, which should be
an error rather than falling through into DT_DEBUG! There was another #ifdef
bug where we'd only report unexpected DT_ entries on MIPS.
Change-Id: Id1d04e372611f641c1aa278a18e379f28af9eaf5
Diffstat (limited to 'linker/linker.cpp')
| -rwxr-xr-x | linker/linker.cpp | 215 |
1 files changed, 97 insertions, 118 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp index 4f05c7a..5a4f20f 100755 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -90,7 +90,7 @@ static soinfo* sonext = &libdl_info; static soinfo* somain; /* main process, always the one after libdl_info */ static const char* const gSoPaths[] = { -#if __LP64__ +#if defined(__LP64__) "/vendor/lib64", "/system/lib64", #else @@ -393,7 +393,7 @@ static void parse_LD_PRELOAD(const char* path) { gLdPreloadsBuffer, sizeof(gLdPreloadsBuffer), LDPRELOAD_MAX); } -#ifdef ANDROID_ARM_LINKER +#if defined(__arm__) /* For a given PC, find the .so that it belongs to. * Returns the base address of the .ARM.exidx section @@ -521,7 +521,7 @@ static Elf_Sym* soinfo_do_lookup(soinfo* si, const char* name, soinfo** lsi, soi } /* Look for symbols in the local scope (the object who is - * searching). This happens with C++ templates on i386 for some + * searching). This happens with C++ templates on x86 for some * reason. * * Notes on weak symbols: @@ -845,7 +845,7 @@ int do_dlclose(soinfo* si) { return result; } -#if defined(ANDROID_X86_64_LINKER) +#if defined(USE_RELA) static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* needed[]) { Elf_Sym* symtab = si->symtab; const char* strtab = si->strtab; @@ -888,16 +888,17 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* */ switch (type) { +#if defined(__x86_64__) case R_X86_64_JUMP_SLOT: case R_X86_64_GLOB_DAT: case R_X86_64_32: case R_X86_64_RELATIVE: // No need to do anything. break; - case R_X86_64_PC32: sym_addr = reloc; break; +#endif default: DL_ERR("unknown weak reloc type %d @ %p (%d)", type, rela, (int) (rela - start)); @@ -913,6 +914,7 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* } switch (type) { +#if defined(__x86_64__) case R_X86_64_JUMP_SLOT: count_relocation(kRelocAbsolute); MARK(rela->r_offset); @@ -938,7 +940,6 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* static_cast<size_t>(si->base)); *reinterpret_cast<Elf_Addr*>(reloc) = si->base + rela->r_addend; break; - case R_X86_64_32: count_relocation(kRelocRelative); MARK(rela->r_offset); @@ -946,7 +947,6 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* static_cast<size_t>(sym_addr), sym_name); *reinterpret_cast<Elf_Addr*>(reloc) = sym_addr + rela->r_addend; break; - case R_X86_64_64: count_relocation(kRelocRelative); MARK(rela->r_offset); @@ -954,7 +954,6 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* static_cast<size_t>(sym_addr), sym_name); *reinterpret_cast<Elf_Addr*>(reloc) = sym_addr + rela->r_addend; break; - case R_X86_64_PC32: count_relocation(kRelocRelative); MARK(rela->r_offset); @@ -963,6 +962,7 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* static_cast<size_t>(sym_addr), static_cast<size_t>(reloc), sym_name); *reinterpret_cast<Elf_Addr*>(reloc) = sym_addr + rela->r_addend - reloc; break; +#endif default: DL_ERR("unknown reloc type %d @ %p (%d)", type, rela, (int) (rela - start)); return -1; @@ -996,8 +996,7 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, sym_name = (char *)(strtab + symtab[sym].st_name); s = soinfo_do_lookup(si, sym_name, &lsi, needed); if (s == NULL) { - /* We only allow an undefined symbol if this is a weak - reference.. */ + // We only allow an undefined symbol if this is a weak reference... s = &symtab[sym]; if (ELF_ST_BIND(s->st_info) != STB_WEAK) { DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, si->name); @@ -1018,48 +1017,39 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, */ switch (type) { -#if defined(ANDROID_ARM_LINKER) +#if defined(__arm__) case R_ARM_JUMP_SLOT: case R_ARM_GLOB_DAT: case R_ARM_ABS32: case R_ARM_RELATIVE: /* Don't care. */ -#elif defined(ANDROID_X86_LINKER) + // sym_addr was initialized to be zero above or relocation + // code below does not care about value of sym_addr. + // No need to do anything. + break; +#elif defined(__i386__) case R_386_JMP_SLOT: case R_386_GLOB_DAT: case R_386_32: case R_386_RELATIVE: /* Don't care. */ -#endif /* ANDROID_*_LINKER */ - /* sym_addr was initialized to be zero above or relocation - code below does not care about value of sym_addr. - No need to do anything. */ + // sym_addr was initialized to be zero above or relocation + // code below does not care about value of sym_addr. + // No need to do anything. break; - -#if defined(ANDROID_X86_LINKER) case R_386_PC32: sym_addr = reloc; break; -#endif /* ANDROID_X86_LINKER */ +#endif -#if defined(ANDROID_ARM_LINKER) +#if defined(__arm__) case R_ARM_COPY: - /* Fall through. Can't really copy if weak symbol is - not found in run-time. */ -#endif /* ANDROID_ARM_LINKER */ + // Fall through. Can't really copy if weak symbol is not found at run-time. +#endif default: - DL_ERR("unknown weak reloc type %d @ %p (%d)", - type, rel, (int) (rel - start)); + DL_ERR("unknown weak reloc type %d @ %p (%d)", type, rel, (int) (rel - start)); return -1; } } else { - /* We got a definition. */ -#if 0 - if ((base == 0) && (si->base != 0)) { - /* linking from libraries to main image is bad */ - DL_ERR("cannot locate \"%s\"...", - strtab + symtab[sym].st_name); - return -1; - } -#endif + // We got a definition. sym_addr = static_cast<Elf_Addr>(s->st_value + lsi->load_bias); } count_relocation(kRelocSymbol); @@ -1067,11 +1057,8 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, s = NULL; } -/* TODO: This is ugly. Split up the relocations by arch into - * different files. - */ switch (type) { -#if defined(ANDROID_ARM_LINKER) +#if defined(__arm__) case R_ARM_JUMP_SLOT: count_relocation(kRelocAbsolute); MARK(rel->r_offset); @@ -1097,68 +1084,6 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, reloc, sym_addr, rel->r_offset, sym_name); *reinterpret_cast<Elf_Addr*>(reloc) += sym_addr - rel->r_offset; break; -#elif defined(ANDROID_X86_LINKER) - case R_386_JMP_SLOT: - count_relocation(kRelocAbsolute); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO JMP_SLOT %08x <- %08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast<Elf_Addr*>(reloc) = sym_addr; - break; - case R_386_GLOB_DAT: - count_relocation(kRelocAbsolute); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO GLOB_DAT %08x <- %08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast<Elf_Addr*>(reloc) = sym_addr; - break; -#elif defined(ANDROID_MIPS_LINKER) - case R_MIPS_REL32: - count_relocation(kRelocAbsolute); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x %s", - reloc, sym_addr, (sym_name) ? sym_name : "*SECTIONHDR*"); - if (s) { - *reinterpret_cast<Elf_Addr*>(reloc) += sym_addr; - } else { - *reinterpret_cast<Elf_Addr*>(reloc) += si->base; - } - break; -#endif /* ANDROID_*_LINKER */ - -#if defined(ANDROID_ARM_LINKER) - case R_ARM_RELATIVE: -#elif defined(ANDROID_X86_LINKER) - case R_386_RELATIVE: -#endif /* ANDROID_*_LINKER */ - count_relocation(kRelocRelative); - MARK(rel->r_offset); - if (sym) { - DL_ERR("odd RELATIVE form..."); - return -1; - } - TRACE_TYPE(RELO, "RELO RELATIVE %p <- +%p", - reinterpret_cast<void*>(reloc), reinterpret_cast<void*>(si->base)); - *reinterpret_cast<Elf_Addr*>(reloc) += si->base; - break; - -#if defined(ANDROID_X86_LINKER) - case R_386_32: - count_relocation(kRelocRelative); - MARK(rel->r_offset); - - TRACE_TYPE(RELO, "RELO R_386_32 %08x <- +%08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast<Elf_Addr*>(reloc) += sym_addr; - break; - - case R_386_PC32: - count_relocation(kRelocRelative); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO R_386_PC32 %08x <- +%08x (%08x - %08x) %s", - reloc, (sym_addr - reloc), sym_addr, reloc, sym_name); - *reinterpret_cast<Elf_Addr*>(reloc) += (sym_addr - reloc); - break; -#endif /* ANDROID_X86_LINKER */ - -#ifdef ANDROID_ARM_LINKER case R_ARM_COPY: if ((si->flags & FLAG_EXE) == 0) { /* @@ -1201,11 +1126,64 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, return -1; } break; -#endif /* ANDROID_ARM_LINKER */ +#elif defined(__i386__) + case R_386_JMP_SLOT: + count_relocation(kRelocAbsolute); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "RELO JMP_SLOT %08x <- %08x %s", reloc, sym_addr, sym_name); + *reinterpret_cast<Elf_Addr*>(reloc) = sym_addr; + break; + case R_386_GLOB_DAT: + count_relocation(kRelocAbsolute); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "RELO GLOB_DAT %08x <- %08x %s", reloc, sym_addr, sym_name); + *reinterpret_cast<Elf_Addr*>(reloc) = sym_addr; + break; + case R_386_32: + count_relocation(kRelocRelative); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "RELO R_386_32 %08x <- +%08x %s", reloc, sym_addr, sym_name); + *reinterpret_cast<Elf_Addr*>(reloc) += sym_addr; + break; + case R_386_PC32: + count_relocation(kRelocRelative); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "RELO R_386_PC32 %08x <- +%08x (%08x - %08x) %s", + reloc, (sym_addr - reloc), sym_addr, reloc, sym_name); + *reinterpret_cast<Elf_Addr*>(reloc) += (sym_addr - reloc); + break; +#elif defined(__mips__) + case R_MIPS_REL32: + count_relocation(kRelocAbsolute); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x %s", + reloc, sym_addr, (sym_name) ? sym_name : "*SECTIONHDR*"); + if (s) { + *reinterpret_cast<Elf_Addr*>(reloc) += sym_addr; + } else { + *reinterpret_cast<Elf_Addr*>(reloc) += si->base; + } + break; +#endif + +#if defined(__arm__) + case R_ARM_RELATIVE: +#elif defined(__i386__) + case R_386_RELATIVE: +#endif + count_relocation(kRelocRelative); + MARK(rel->r_offset); + if (sym) { + DL_ERR("odd RELATIVE form..."); + return -1; + } + TRACE_TYPE(RELO, "RELO RELATIVE %p <- +%p", + reinterpret_cast<void*>(reloc), reinterpret_cast<void*>(si->base)); + *reinterpret_cast<Elf_Addr*>(reloc) += si->base; + break; default: - DL_ERR("unknown reloc type %d @ %p (%d)", - type, rel, (int) (rel - start)); + DL_ERR("unknown reloc type %d @ %p (%d)", type, rel, (int) (rel - start)); return -1; } } @@ -1213,7 +1191,7 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, } #endif -#ifdef ANDROID_MIPS_LINKER +#if defined(__mips__) static bool mips_relocate_got(soinfo* si, soinfo* needed[]) { unsigned* got = si->plt_got; if (got == NULL) { @@ -1458,7 +1436,7 @@ static bool soinfo_link_image(soinfo* si) { } } -#ifdef ANDROID_ARM_LINKER +#if defined(__arm__) (void) phdr_table_get_arm_exidx(phdr, phnum, base, &si->ARM_exidx, &si->ARM_exidx_count); #endif @@ -1481,7 +1459,7 @@ static bool soinfo_link_image(soinfo* si) { case DT_SYMTAB: si->symtab = (Elf_Sym *) (base + d->d_un.d_ptr); break; -#if !defined(ANDROID_X86_64_LINKER) +#if !defined(__LP64__) case DT_PLTREL: if (d->d_un.d_val != DT_REL) { DL_ERR("unsupported DT_RELA in \"%s\"", si->name); @@ -1490,22 +1468,22 @@ static bool soinfo_link_image(soinfo* si) { break; #endif case DT_JMPREL: -#if defined(ANDROID_X86_64_LINKER) +#if defined(USE_RELA) si->plt_rela = (Elf_Rela*) (base + d->d_un.d_ptr); #else si->plt_rel = (Elf_Rel*) (base + d->d_un.d_ptr); #endif break; case DT_PLTRELSZ: -#if defined(ANDROID_X86_64_LINKER) +#if defined(USE_RELA) si->plt_rela_count = d->d_un.d_val / sizeof(Elf_Rela); #else si->plt_rel_count = d->d_un.d_val / sizeof(Elf_Rel); #endif break; +#if !defined(__LP64__) case DT_PLTGOT: -#if !defined(ANDROID_X86_64_LINKER) - /* Save this in case we decide to do lazy binding. We don't yet. */ + // Used by 32-bit MIPS. si->plt_got = (unsigned *)(base + d->d_un.d_ptr); break; #endif @@ -1516,7 +1494,7 @@ static bool soinfo_link_image(soinfo* si) { d->d_un.d_val = reinterpret_cast<uintptr_t>(&_r_debug); } break; -#if defined(ANDROID_X86_64_LINKER) +#if defined(USE_RELA) case DT_RELA: si->rela = (Elf_Rela*) (base + d->d_un.d_ptr); break; @@ -1589,7 +1567,7 @@ static bool soinfo_link_image(soinfo* si) { } break; #endif -#if defined(ANDROID_MIPS_LINKER) +#if defined(__mips__) case DT_STRSZ: case DT_SYMENT: case DT_RELENT: @@ -1618,11 +1596,12 @@ static bool soinfo_link_image(soinfo* si) { case DT_MIPS_GOTSYM: si->mips_gotsym = d->d_un.d_val; break; +#endif default: - DEBUG("Unused DT entry: type 0x%08x arg 0x%08x", d->d_tag, d->d_un.d_val); + DEBUG("Unused DT entry: type %p arg %p", + reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val)); break; -#endif } } @@ -1697,7 +1676,7 @@ static bool soinfo_link_image(soinfo* si) { } } -#if defined(ANDROID_X86_64_LINKER) +#if defined(USE_RELA) if (si->plt_rela != NULL) { DEBUG("[ relocating %s plt ]\n", si->name ); if (soinfo_relocate_a(si, si->plt_rela, si->plt_rela_count, needed)) { @@ -1725,7 +1704,7 @@ static bool soinfo_link_image(soinfo* si) { } #endif -#ifdef ANDROID_MIPS_LINKER +#if defined(__mips__) if (!mips_relocate_got(si, needed)) { return false; } @@ -1761,7 +1740,7 @@ static bool soinfo_link_image(soinfo* si) { * Also, it makes bionic more like glibc. */ static void add_vdso(KernelArgumentBlock& args UNUSED) { -#ifdef AT_SYSINFO_EHDR +#if defined(AT_SYSINFO_EHDR) Elf_Ehdr* ehdr_vdso = reinterpret_cast<Elf_Ehdr*>(args.getauxval(AT_SYSINFO_EHDR)); soinfo* si = soinfo_alloc("[vdso]"); @@ -1852,7 +1831,7 @@ static Elf_Addr __linker_init_post_relocation(KernelArgumentBlock& args, Elf_Add */ { static soinfo linker_soinfo; -#ifdef __LP64__ +#if defined(__LP64__) strlcpy(linker_soinfo.name, "/system/bin/linker64", sizeof(linker_soinfo.name)); #else strlcpy(linker_soinfo.name, "/system/bin/linker", sizeof(linker_soinfo.name)); |
