*** src/arch-mips.c (revision 230136) --- src/arch-mips.c (local) *************** mips_prelink_reloc (struct prelink_info *** 451,456 **** --- 451,457 ---- break; case R_MIPS_GLOB_DAT: + case R_MIPS_JUMP_SLOT: write_ne32 (dso, r_offset, info->resolve (info, r_sym, r_type)); break; *************** mips_prelink_reloc (struct prelink_info *** 481,486 **** --- 482,494 ---- } 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)); *************** mips_prelink_conflict_reloc (DSO *dso, s *** 596,601 **** --- 604,613 ---- 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; *************** mips_apply_conflict_rela (struct prelink *** 690,695 **** --- 702,708 ---- switch (GELF_R_TYPE (rela->r_info)) { case R_MIPS_REL32: + case R_MIPS_JUMP_SLOT: buf_write_ne32 (info->dso, buf, rela->r_addend); break; *************** mips_apply_reloc (struct prelink_info *i *** 720,736 **** GElf_Rela *rela, char *buf) { DSO *dso; dso = info->dso; switch (GELF_R_TYPE (r_info)) { case R_MIPS_NONE: break; case R_MIPS_REL32: ! mips_apply_adjustment (dso, rela, buf, ! info->resolve (info, GELF_R_SYM (r_info), ! GELF_R_TYPE (r_info))); break; default: --- 733,756 ---- GElf_Rela *rela, char *buf) { DSO *dso; + GElf_Addr value; + value = info->resolve (info, GELF_R_SYM (r_info), GELF_R_TYPE (r_info)); dso = info->dso; switch (GELF_R_TYPE (r_info)) { case R_MIPS_NONE: break; + case R_MIPS_JUMP_SLOT: + buf_write_ne32 (info->dso, buf, value); + break; + + case R_MIPS_COPY: + abort (); + case R_MIPS_REL32: ! mips_apply_adjustment (dso, rela, buf, value); break; default: *************** mips_rel_to_rela (DSO *dso, GElf_Rel *re *** 766,771 **** --- 786,792 ---- break; case R_MIPS_NONE: + case R_MIPS_COPY: case R_MIPS_GLOB_DAT: case R_MIPS_TLS_DTPMOD32: /* These relocations have no addend. */ *************** mips_rela_to_rel (DSO *dso, GElf_Rela *r *** 788,793 **** --- 809,815 ---- switch (GELF_R_TYPE (rela->r_info)) { case R_MIPS_NONE: + case R_MIPS_COPY: break; case R_MIPS_REL32: *************** mips_need_rel_to_rela (DSO *dso, int fir *** 831,836 **** --- 853,860 ---- 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: *************** mips_need_rel_to_rela (DSO *dso, int fir *** 871,877 **** default: error (0, 0, "%s: Unknown MIPS relocation type %d", ! dso->filename, (int) GELF_R_TYPE (rel->r_info)); return 1; } } --- 895,901 ---- default: error (0, 0, "%s: Unknown MIPS relocation type %d", ! dso->filename, (int) ELF32_R_TYPE (rel->r_info)); return 1; } } *************** mips_reloc_class (int reloc_type) *** 890,903 **** { switch (reloc_type) { 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; } } --- 914,929 ---- { 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: ! return RTYPE_CLASS_VALID; } } *************** mips_arch_prelink (struct prelink_info * *** 907,914 **** --- 933,965 ---- 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; *************** static int *** 953,958 **** --- 1004,1033 ---- 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; *************** mips_arch_undo_prelink (DSO *dso) *** 971,976 **** --- 1046,1054 ---- 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, *************** mips_undo_prelink_rel (DSO *dso, GElf_Re *** 983,988 **** --- 1061,1086 ---- 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; } *************** PL_ARCH = { *** 992,1001 **** .machine = EM_MIPS, .max_reloc_size = 4, .dynamic_linker = "/lib/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_MIPS_REL32 relocations against symbol 0 do act as relative relocs, but those against other symbols don't. */ .R_RELATIVE = ~0U, --- 1090,1097 ---- .machine = EM_MIPS, .max_reloc_size = 4, .dynamic_linker = "/lib/ld.so.1", ! .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, *** src/dso.c (revision 230136) --- src/dso.c (local) *************** read_dynamic (DSO *dso) *** 115,120 **** --- 115,122 ---- 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) *** src/prelink.h (revision 230136) --- src/prelink.h (local) *************** *** 78,83 **** --- 78,91 ---- #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; *************** typedef struct *** 113,118 **** --- 121,127 ---- 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