summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trunk/ChangeLog.cross26
-rw-r--r--trunk/src/arch-mips.c121
-rw-r--r--trunk/src/dso-readonly.c2
-rw-r--r--trunk/src/dso.c2
-rw-r--r--trunk/src/ld-do-lookup.h5
-rw-r--r--trunk/src/ld-libs.c16
-rw-r--r--trunk/src/prelink.h15
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