Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/ld.elf_so/arch/mips Resolve the GOT before doing rel...
details: https://anonhg.NetBSD.org/src/rev/818523fd72ed
branches: trunk
changeset: 536986:818523fd72ed
user: mycroft <mycroft%NetBSD.org@localhost>
date: Wed Sep 25 03:52:06 2002 +0000
description:
Resolve the GOT before doing relocations. Then, when doing relocations, for
symbols in the global part of the symbol table, use the updated GOT entry
rather than doing a lookup. (This provides the same effect as `-z combreloc'
on other platforms -- at most one lookup is done per symbol.)
Unfortunately, it is necessary to turn off lazy binding on MIPS. As the
comment says:
* XXX DANGER WILL ROBINSON!
* You might think this is stupid, as it intentionally
* defeats lazy binding -- and you'd be right.
* Unfortunately, for lazy binding to work right, we
* need to a way to force the GOT slots used for
* function pointers to be resolved immediately. This
* is supposed to be done automatically by the linker,
* by not outputting a PLT slot and setting st_value
* to 0, but GNU ld does not do so reliably.
diffstat:
libexec/ld.elf_so/arch/mips/mips_reloc.c | 185 +++++++++++++++---------------
1 files changed, 91 insertions(+), 94 deletions(-)
diffs (240 lines):
diff -r f690a19403bd -r 818523fd72ed libexec/ld.elf_so/arch/mips/mips_reloc.c
--- a/libexec/ld.elf_so/arch/mips/mips_reloc.c Wed Sep 25 03:45:32 2002 +0000
+++ b/libexec/ld.elf_so/arch/mips/mips_reloc.c Wed Sep 25 03:52:06 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mips_reloc.c,v 1.33 2002/09/14 23:53:21 thorpej Exp $ */
+/* $NetBSD: mips_reloc.c,v 1.34 2002/09/25 03:52:06 mycroft Exp $ */
/*
* Copyright 1997 Michael L. Hitch <mhitch%montana.edu@localhost>
@@ -108,27 +108,6 @@
break;
}
}
- rellim = (const Elf_Rel *)((caddr_t)rel + relsz);
- for (; rel < rellim; rel++) {
- where = (Elf_Addr *)(relocbase + rel->r_offset);
-
- switch (ELF_R_TYPE(rel->r_info)) {
- case R_TYPE(NONE):
- break;
-
- case R_TYPE(REL32):
- sym = symtab + ELF_R_SYM(rel->r_info);
- if (ELF_ST_BIND(sym->st_info) == STB_LOCAL &&
- ELF_ST_TYPE(sym->st_info) == STT_SECTION)
- *where += (Elf_Addr)(sym->st_value + relocbase);
- else
- abort();
- break;
-
- default:
- abort();
- }
- }
i = (got[1] & 0x80000000) ? 2 : 1;
/* Relocate the local GOT entries */
@@ -142,6 +121,26 @@
++sym;
++got;
}
+
+ rellim = (const Elf_Rel *)((caddr_t)rel + relsz);
+ for (; rel < rellim; rel++) {
+ where = (Elf_Addr *)(relocbase + rel->r_offset);
+
+ switch (ELF_R_TYPE(rel->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(REL32):
+ assert(ELF_R_SYM(rel->r_info) < gotsym);
+ sym = symtab + ELF_R_SYM(rel->r_info);
+ assert(sym->st_info == STT_SECTION);
+ *where += (Elf_Addr)(sym->st_value + relocbase);
+ break;
+
+ default:
+ abort();
+ }
+ }
}
/*
@@ -182,6 +181,60 @@
if (self)
return 0;
+ i = (got[1] & 0x80000000) ? 2 : 1;
+ /* Relocate the local GOT entries */
+ got += i;
+ for (; i < obj->local_gotno; i++)
+ *got++ += (Elf_Addr)obj->relocbase;
+ sym = obj->symtab + obj->gotsym;
+ /* Now do the global GOT entries */
+ for (i = obj->gotsym; i < obj->symtabno; i++) {
+ rdbg((" doing got %d sym %p (%s, %x)", i - obj->gotsym, sym,
+ sym->st_name + obj->strtab, *got));
+
+ if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
+ sym->st_shndx == SHN_UNDEF) {
+ /*
+ * XXX DANGER WILL ROBINSON!
+ * You might think this is stupid, as it intentionally
+ * defeats lazy binding -- and you'd be right.
+ * Unfortunately, for lazy binding to work right, we
+ * need to a way to force the GOT slots used for
+ * function pointers to be resolved immediately. This
+ * is supposed to be done automatically by the linker,
+ * by not outputting a PLT slot and setting st_value
+ * to 0, but GNU ld does not do so reliably.
+ */
+ def = _rtld_find_symdef(i, obj, &defobj, true);
+ if (def == NULL)
+ return -1;
+ *got = def->st_value + (Elf_Addr)defobj->relocbase;
+ } else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
+ sym->st_value != 0) {
+ /*
+ * If there are non-PLT references to the function,
+ * st_value should be 0, forcing us to resolve the
+ * address immediately.
+ */
+ *got = sym->st_value + (Elf_Addr)obj->relocbase;
+ } else if (sym->st_info == ELF_ST_INFO(STB_GLOBAL, STT_SECTION)) {
+ /* Symbols with index SHN_ABS are not relocated. */
+ if (sym->st_shndx != SHN_ABS)
+ *got = sym->st_value +
+ (Elf_Addr)obj->relocbase;
+ } else {
+ def = _rtld_find_symdef(i, obj, &defobj, true);
+ if (def == NULL)
+ return -1;
+ *got = def->st_value + (Elf_Addr)defobj->relocbase;
+ }
+
+ rdbg((" --> now %x", *got));
+ ++sym;
+ ++got;
+ }
+
+ got = obj->pltgot;
for (rel = obj->rel; rel < obj->rellim; rel++) {
Elf_Addr *where, tmp;
unsigned long symnum;
@@ -197,9 +250,16 @@
/* 32-bit PC-relative reference */
def = obj->symtab + symnum;
- if (ELF_ST_BIND(def->st_info) == STB_LOCAL &&
- (ELF_ST_TYPE(def->st_info) == STT_SECTION ||
- ELF_ST_TYPE(def->st_info) == STT_NOTYPE)) {
+ if (symnum >= obj->gotsym) {
+ tmp = *where;
+ tmp += got[obj->local_gotno + symnum - obj->gotsym];
+ *where = tmp;
+
+ rdbg(("REL32/G %s in %s --> %p in %s",
+ obj->strtab + def->st_name, obj->path,
+ (void *)tmp, obj->path));
+ break;
+ } else {
/*
* XXX: ABI DIFFERENCE!
*
@@ -220,48 +280,18 @@
*
* --rkb, Oct 6, 2001
*/
- if (__predict_true(RELOC_ALIGNED_P(where))) {
- tmp = *where;
-
- if (def->st_info == STT_SECTION &&
- tmp < def->st_value)
- tmp += (Elf_Addr)def->st_value;
+ tmp = *where;
- tmp += (Elf_Addr)obj->relocbase;
- *where = tmp;
- } else {
- tmp = load_ptr(where);
+ if (def->st_info == STT_SECTION &&
+ tmp < def->st_value)
+ tmp += (Elf_Addr)def->st_value;
- if (def->st_info == STT_SECTION &&
- tmp < def->st_value)
- tmp += (Elf_Addr)def->st_value;
-
- tmp += (Elf_Addr)obj->relocbase;
- store_ptr(where, tmp);
- }
+ tmp += (Elf_Addr)obj->relocbase;
+ *where = tmp;
rdbg(("REL32 %s in %s --> %p in %s",
obj->strtab + def->st_name, obj->path,
(void *)tmp, obj->path));
- } else {
- def = _rtld_find_symdef(symnum, obj, &defobj,
- false);
- if (def == NULL)
- return -1;
- if (__predict_true(RELOC_ALIGNED_P(where))) {
- tmp = *where +
- (Elf_Addr)(defobj->relocbase +
- def->st_value);
- *where = tmp;
- } else {
- tmp = load_ptr(where) +
- (Elf_Addr)(defobj->relocbase +
- def->st_value);
- store_ptr(where, tmp);
- }
- rdbg(("REL32 %s in %s --> %p in %s",
- obj->strtab + obj->symtab[symnum].st_name,
- obj->path, (void *)tmp, defobj->path));
}
break;
@@ -278,39 +308,6 @@
}
}
- i = (got[1] & 0x80000000) ? 2 : 1;
- /* Relocate the local GOT entries */
- got += i;
- for (; i < obj->local_gotno; i++)
- *got++ += (Elf_Addr)obj->relocbase;
- sym = obj->symtab + obj->gotsym;
- /* Now do the global GOT entries */
- for (i = obj->gotsym; i < obj->symtabno; i++) {
- rdbg((" doing got %d sym %p (%s, %x)", i - obj->gotsym, sym,
- sym->st_name + obj->strtab, *got));
-
- if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
- sym->st_value != 0)
- /* The symbol table contains the address of the PLT
- slot. However, sometimes a PLT slot is not
- allocated, so we have to check st_value first. */
- *got = sym->st_value + (Elf_Addr)obj->relocbase;
- else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION &&
- ELF_ST_BIND(sym->st_info) == STB_GLOBAL) {
- /* Symbols with index SHN_ABS are not relocated. */
- if (sym->st_shndx != SHN_ABS)
- *got = sym->st_value +
- (Elf_Addr)obj->relocbase;
- } else {
- def = _rtld_find_symdef(i, obj, &defobj, true);
- if (def == NULL)
- return -1;
- *got = def->st_value + (Elf_Addr)defobj->relocbase;
- }
- ++sym;
- ++got;
- }
-
return 0;
}
Home |
Main Index |
Thread Index |
Old Index