diff options
-rw-r--r-- | trunk/ChangeLog.cross | 26 | ||||
-rw-r--r-- | trunk/src/arch-mips.c | 121 | ||||
-rw-r--r-- | trunk/src/dso-readonly.c | 2 | ||||
-rw-r--r-- | trunk/src/dso.c | 2 | ||||
-rw-r--r-- | trunk/src/ld-do-lookup.h | 5 | ||||
-rw-r--r-- | trunk/src/ld-libs.c | 16 | ||||
-rw-r--r-- | trunk/src/prelink.h | 15 |
7 files changed, 173 insertions, 14 deletions
diff --git a/trunk/ChangeLog.cross b/trunk/ChangeLog.cross index 4dca3d0..00fbadf 100644 --- a/trunk/ChangeLog.cross +++ b/trunk/ChangeLog.cross @@ -2,6 +2,32 @@ * Integrate prelinker/cross-prelinking patches + 2008-03-06 Daniel Jacobowitz <dan@codesourcery.com> + + * src/ld-do-lookup.h: Check for STO_MIPS_PLT on MIPS. + * src/ld-libs.c (reloc_type_class): Handle copy and PLT relocs. + * src/prelink.h (R_MIPS_TLS_DTPMOD32, R_MIPS_TLS_DTPREL32) + (R_MIPS_TLS_TPREL32, R_MIPS_GLOB_DAT): Remove duplicate definitions. + (R_MIPS_COPY, R_MIPS_JUMP_SLOT, STO_MIPS_PLT, DT_MIPS_PLTGOT) + (DT_MIPS_PLTNO, DT_MIPS_RWPLT): Define. + (DSO): Add info_DT_MIPS_PLTGOT. + * src/arch-mips.c (mips_prelink_reloc): Handle R_MIPS_JUMP_SLOT and + R_MIPS_COPY. + (mips_prelink_conflict_reloc): Handle R_MIPS_COPY. + (mips_apply_conflict_rela): Handle R_MIPS_JUMP_SLOT. + (mips_apply_reloc): Handle R_MIPS_JUMP_SLOT and R_MIPS_COPY. + (mips_rel_to_rela, mips_rela_to_rel): Handle R_MIPS_COPY. + (mips_need_rel_to_rela): Handle R_MIPS_COPY and R_MIPS_JUMP_SLOT. + Correct error message. + (mips_reloc_class): Handle R_MIPS_COPY and R_MIPS_JUMP_SLOT. Use + RTYPE_CLASS_VALID by default. + (mips_arch_prelink): Save .plt in gotplt[1]. + (mips_arch_undo_prelink): Clear gotplt[1]. + (mips_undo_prelink_rel): Undo R_MIPS_JUMP_SLOT relocations. + (PL_ARCH): Set R_COPY and R_JMP_SLOT. + * src/dso.c (read_dynamic): Save DT_MIPS_PLTGOT. + * src/dso-readonly.c (read_dynamic): ditto + 2007-07-09 Daniel Jacobowitz <dan@codesourcery.com> Issue #1816 diff --git a/trunk/src/arch-mips.c b/trunk/src/arch-mips.c index a57b6c8..cf583aa 100644 --- a/trunk/src/arch-mips.c +++ b/trunk/src/arch-mips.c @@ -454,6 +454,10 @@ mips_prelink_reloc (struct prelink_info *info, GElf_Addr r_offset, write_ne32 (dso, r_offset, info->resolve (info, r_sym, r_type)); break; + case R_MIPS_JUMP_SLOT: + write_ne32 (dso, r_offset, info->resolve (info, r_sym, r_type)); + break; + case R_MIPS_TLS_DTPMOD32: if (dso->ehdr.e_type == ET_EXEC) { @@ -481,6 +485,13 @@ mips_prelink_reloc (struct prelink_info *info, GElf_Addr r_offset, } break; + case R_MIPS_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_MIPS_COPY reloc in shared library?", dso->filename); + return 1; + default: error (0, 0, "%s: Unknown MIPS relocation type %d", dso->filename, (int) GELF_R_TYPE (r_info)); @@ -596,6 +607,10 @@ mips_prelink_conflict_reloc (DSO *dso, struct prelink_info *info, case R_MIPS_GLOB_DAT: break; + case R_MIPS_COPY: + error (0, 0, "R_MIPS_COPY should not be present in shared libraries"); + return 1; + case R_MIPS_TLS_DTPMOD32: if (conflict != NULL && mips_get_tls (dso, conflict, &tls) == 1) return 1; @@ -693,6 +708,10 @@ mips_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, buf_write_ne32 (info->dso, buf, rela->r_addend); break; + case R_MIPS_JUMP_SLOT: + buf_write_ne32 (info->dso, buf, rela->r_addend); + break; + default: abort (); } @@ -727,6 +746,15 @@ mips_apply_reloc (struct prelink_info *info, GElf_Xword r_info, case R_MIPS_NONE: break; + case R_MIPS_JUMP_SLOT: + buf_write_ne32 (info->dso, buf, + info->resolve (info, GELF_R_SYM (r_info), + GELF_R_TYPE (r_info))); + break; + + case R_MIPS_COPY: + abort (); + case R_MIPS_REL32: mips_apply_adjustment (dso, rela, buf, info->resolve (info, GELF_R_SYM (r_info), @@ -766,6 +794,7 @@ mips_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) break; case R_MIPS_NONE: + case R_MIPS_COPY: case R_MIPS_GLOB_DAT: case R_MIPS_TLS_DTPMOD32: /* These relocations have no addend. */ @@ -788,6 +817,7 @@ mips_rela_to_rel (DSO *dso, GElf_Rela *rela, GElf_Rel *rel) switch (GELF_R_TYPE (rela->r_info)) { case R_MIPS_NONE: + case R_MIPS_COPY: break; case R_MIPS_REL32: @@ -831,6 +861,8 @@ mips_need_rel_to_rela (DSO *dso, int first, int last) switch (ELF32_R_TYPE (rel->r_info)) { case R_MIPS_NONE: + case R_MIPS_COPY: + case R_MIPS_JUMP_SLOT: break; case R_MIPS_REL32: @@ -871,8 +903,8 @@ mips_need_rel_to_rela (DSO *dso, int first, int last) default: error (0, 0, "%s: Unknown MIPS relocation type %d", - dso->filename, (int) GELF_R_TYPE (rel->r_info)); - return 1; + dso->filename, (int) GELF_R_TYPE (rel->r_info)); + return 1; } } } @@ -890,14 +922,16 @@ mips_reloc_class (int reloc_type) { switch (reloc_type) { + case R_MIPS_COPY: + return RTYPE_CLASS_COPY; + case R_MIPS_JUMP_SLOT: + return RTYPE_CLASS_PLT; case R_MIPS_TLS_DTPMOD32: case R_MIPS_TLS_DTPREL32: case R_MIPS_TLS_TPREL32: return RTYPE_CLASS_TLS; default: - /* MIPS lazy resolution stubs are local to the containing object, - so SHN_UNDEF symbols never participate in symbol lookup. */ - return RTYPE_CLASS_PLT; + return RTYPE_CLASS_VALID; } } @@ -907,8 +941,31 @@ mips_arch_prelink (struct prelink_info *info) struct mips_global_got_iterator ggi; DSO *dso; GElf_Addr value; + int i; dso = info->dso; + if (dso->info_DT_MIPS_PLTGOT) + { + /* Write address of .plt into gotplt[1]. This is in each + normal gotplt entry unless prelinking. */ + int sec = addr_to_sec (dso, dso->info_DT_MIPS_PLTGOT); + Elf32_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + if (i == dso->ehdr.e_shnum) + return 0; + data = dso->shdr[i].sh_addr; + write_ne32 (dso, dso->info_DT_MIPS_PLTGOT + 4, data); + } + if (dso->info[DT_PLTGOT] == 0) return 0; @@ -953,6 +1010,30 @@ static int mips_arch_undo_prelink (DSO *dso) { struct mips_global_got_iterator ggi; + int i; + + if (dso->info_DT_MIPS_PLTGOT) + { + /* Clear gotplt[1] if it contains the address of .plt. */ + int sec = addr_to_sec (dso, dso->info_DT_MIPS_PLTGOT); + Elf32_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = read_une32 (dso, dso->info_DT_MIPS_PLTGOT + 4); + if (data == dso->shdr[i].sh_addr) + write_ne32 (dso, dso->info_DT_MIPS_PLTGOT + 4, 0); + } if (dso->info[DT_PLTGOT] == 0) return 0; @@ -971,6 +1052,9 @@ mips_arch_undo_prelink (DSO *dso) static int mips_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr) { + int sec; + const char *name; + /* Convert R_MIPS_GLOB_DAT relocations back into R_MIPS_REL32 relocations. Ideally we'd have some mechanism for recording these changes in the undo section, but in the absence of that, @@ -983,6 +1067,27 @@ mips_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr) rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_MIPS_REL32); return 2; } + else if (GELF_R_TYPE (rel->r_info) == R_MIPS_JUMP_SLOT) + { + sec = addr_to_sec (dso, rel->r_offset); + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[sec].sh_name); + if (sec == -1 || strcmp (name, ".got.plt")) + { + error (0, 0, + "%s: R_MIPS_JUMP_SLOT not pointing into .got.plt section", + dso->filename); + return 1; + } + else + { + Elf32_Addr data = read_une32 (dso, dso->shdr[sec].sh_addr + 4); + + assert (rel->r_offset >= dso->shdr[sec].sh_addr + 8); + assert (((rel->r_offset - dso->shdr[sec].sh_addr) & 3) == 0); + write_ne32 (dso, rel->r_offset, data); + } + } + return 0; } @@ -993,10 +1098,8 @@ PL_ARCH = { .max_reloc_size = 4, .dynamic_linker = "/lib/ld.so.1", .dynamic_linker_alt = "/lib32/ld.so.1", - /* MIPS does not use COPY relocs or jump slots. Pick a value outside - the ELF32_R_TYPE range. */ - .R_COPY = ~0U, - .R_JMP_SLOT = ~0U, + .R_COPY = R_MIPS_COPY, + .R_JMP_SLOT = R_MIPS_JUMP_SLOT, /* R_MIPS_REL32 relocations against symbol 0 do act as relative relocs, but those against other symbols don't. */ .R_RELATIVE = ~0U, diff --git a/trunk/src/dso-readonly.c b/trunk/src/dso-readonly.c index 8ad5865..06f5f09 100644 --- a/trunk/src/dso-readonly.c +++ b/trunk/src/dso-readonly.c @@ -115,6 +115,8 @@ read_dynamic (DSO *dso) dso->info_DT_MIPS_GOTSYM = dyn.d_un.d_val; else if (dyn.d_tag == DT_MIPS_SYMTABNO) dso->info_DT_MIPS_SYMTABNO = dyn.d_un.d_val; + else if (dyn.d_tag == DT_MIPS_PLTGOT) + dso->info_DT_MIPS_PLTGOT = dyn.d_un.d_val; } } if (ndx < maxndx) diff --git a/trunk/src/dso.c b/trunk/src/dso.c index 5080ffc..94a0176 100644 --- a/trunk/src/dso.c +++ b/trunk/src/dso.c @@ -115,6 +115,8 @@ read_dynamic (DSO *dso) dso->info_DT_MIPS_GOTSYM = dyn.d_un.d_val; else if (dyn.d_tag == DT_MIPS_SYMTABNO) dso->info_DT_MIPS_SYMTABNO = dyn.d_un.d_val; + else if (dyn.d_tag == DT_MIPS_PLTGOT) + dso->info_DT_MIPS_PLTGOT = dyn.d_un.d_val; } } if (ndx < maxndx) diff --git a/trunk/src/ld-do-lookup.h b/trunk/src/ld-do-lookup.h index 62a1280..3e792ba 100644 --- a/trunk/src/ld-do-lookup.h +++ b/trunk/src/ld-do-lookup.h @@ -82,7 +82,10 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, #ifdef USE_TLS && ELFW(ST_TYPE) (sym->st_info) != STT_TLS #endif - ) + ) + || (machine == EM_MIPS + && sym->st_shndx == SHN_UNDEF + && !(sym->st_other & STO_MIPS_PLT)) || (type_class & (sym->st_shndx == SHN_UNDEF))) continue; diff --git a/trunk/src/ld-libs.c b/trunk/src/ld-libs.c index df2bfc6..c84cbb0 100644 --- a/trunk/src/ld-libs.c +++ b/trunk/src/ld-libs.c @@ -173,10 +173,18 @@ reloc_type_class (int type, int machine) } case EM_MIPS: - /* MIPS lazy resolution stubs are local to the containing object, - so SHN_UNDEF symbols never participate in symbol lookup. */ - return ELF_RTYPE_CLASS_PLT; - + switch (type) + { + case R_MIPS_COPY: + return ELF_RTYPE_CLASS_COPY; + case R_MIPS_JUMP_SLOT: + case R_MIPS_TLS_DTPMOD32: + case R_MIPS_TLS_DTPREL32: + case R_MIPS_TLS_TPREL32: + return ELF_RTYPE_CLASS_PLT; + default: + return 0; + } default: printf ("Unknown architecture!\n"); exit (1); diff --git a/trunk/src/prelink.h b/trunk/src/prelink.h index e491c8f..5507eda 100644 --- a/trunk/src/prelink.h +++ b/trunk/src/prelink.h @@ -76,10 +76,24 @@ #define R_MIPS_TLS_TPREL32 47 #endif +#ifndef R_MIPS_TLS_DTPMOD64 +#define R_MIPS_TLS_DTPMOD64 40 +#define R_MIPS_TLS_DTPREL64 41 +#define R_MIPS_TLS_TPREL64 48 +#endif + #ifndef R_MIPS_GLOB_DAT #define R_MIPS_GLOB_DAT 51 #endif +#ifndef R_MIPS_COPY +#define R_MIPS_COPY 126 +#define R_MIPS_JUMP_SLOT 127 +#define STO_MIPS_PLT 0x8 +#define DT_MIPS_PLTGOT 0x70000032 +#define DT_MIPS_RWPLT 0x70000034 +#endif + struct prelink_entry; struct prelink_info; struct PLArch; @@ -115,6 +129,7 @@ typedef struct GElf_Addr info_DT_MIPS_LOCAL_GOTNO; GElf_Addr info_DT_MIPS_GOTSYM; GElf_Addr info_DT_MIPS_SYMTABNO; + GElf_Addr info_DT_MIPS_PLTGOT; #define DT_GNU_PRELINKED_BIT 50 #define DT_CHECKSUM_BIT 51 #define DT_VERNEED_BIT 52 |