Subject: Re: BFD/ld lossage on MIPS with NEW_TOOLCHAIN
To: None <tech-toolchain@netbsd.org, tv@netbsd.org>
From: Rafal Boni <rafal@mediaone.net>
List: tech-toolchain
Date: 10/06/2001 23:58:13
In message <200110050132.VAA28062@doppelganger.waterside.net>, you write:
-> In message <200110040251.WAA23590@doppelganger.waterside.net>, you write:
->
-> -> Folks:
-> -> I seem to be tripping over a nasty ld (actually, BFD) bug on my SGI
-> -> (mips) box with the new toolchain.
-> [...]
-> -> So attached are two things:
-> -> (1) My patch, which is less than clean in that it still
-> -> contains debug printf's strewn about, but has the gist
-> -> of the proposed fix. Line numbers may not match 100%
-> -> vs. the in-tree files since I removed one or two bits
-> -> of purely debugging additions by hand from the patch.
->
-> Though I'm not sure if this change is to blame, my build of the world on
-> sgimips with the new toolchain (with this patch) seems to have generated
-> stuffed-up crtstuff files (I think specifically crtbegin.o).
->
[...]
-> Along the way, I've also either confused the runtime linker or tripped
-> over a bug there that causes it to crash when faced with undefined weak
-> symbols.
With a clue from Jason, I went looking at the powerpc runtime linker, where
Charles had fixed a very similar bug -- it turns out that the MIPS runtime
linker just didn't deal real well with unresolved weak symbols. This means
by BFD patch is (for now) exonarated -- I'm starting a complete build of
the NEW_TOOLCHAIN world on sgimips as I write this.
Attached is a patch that both works around the change in binutils behaviour
(the change to reloc.c with the big block comment) and fixes the unresolved-
weak-symbols issue (the changes in arch/mips/mips_reloc.c and symbol.c).
I'd like to commit at least the fix for the weak symbol foo soon (the other
one merits more discussion, I think), and I'm heading on the road most of
next week, so quick feedback would be appreciated.
Thanks!
--rafal
Index: reloc.c
===================================================================
RCS file: /cvsroot/basesrc/libexec/ld.elf_so/reloc.c,v
retrieving revision 1.42
diff -b -u -r1.42 reloc.c
--- reloc.c 2001/09/10 06:09:41 1.42
+++ reloc.c 2001/10/07 03:22:47
@@ -337,9 +337,33 @@
if (ELFDEFNNAME(ST_BIND)(def->st_info) == STB_LOCAL &&
(ELFDEFNNAME(ST_TYPE)(def->st_info) == STT_SECTION ||
ELFDEFNNAME(ST_TYPE)(def->st_info) == STT_NOTYPE)) {
+ /*
+ * XXX: ABI DIFFERENCE!
+ *
+ * Old NetBSD binutils would generate shared libs
+ * with section-relative relocations being already
+ * adjusted for the start address of the section.
+ *
+ * New binutils, OTOH, generate shared libs with
+ * the same relocations being based at zero, so we
+ * need to add in the start address of the section.
+ *
+ * We assume that all section-relative relocs with
+ * contents less than the start of the section need
+ * to be adjusted; this should work with both old
+ * and new shlibs.
+ *
+ * --rkb, Oct 6, 2001
+ */
+ if (def->st_info == STT_SECTION &&
+ (*where < def->st_value))
+ *where += (Elf_Addr) def->st_value;
+
*where += (Elf_Addr)obj->relocbase;
- rdbg(dodebug, ("REL32 in %s --> %p", obj->path,
- (void *)*where));
+
+ rdbg(dodebug, ("REL32 %s in %s --> %p in %s",
+ obj->strtab + def->st_name, obj->path,
+ (void *)*where, obj->path));
} else {
/* XXX maybe do something re: bootstrapping? */
def = _rtld_find_symdef(_rtld_objlist, rela->r_info,
Index: symbol.c
===================================================================
RCS file: /cvsroot/basesrc/libexec/ld.elf_so/symbol.c,v
retrieving revision 1.10
diff -b -u -r1.10 symbol.c
--- symbol.c 2000/10/11 20:46:08 1.10
+++ symbol.c 2001/10/07 03:22:47
@@ -163,7 +163,7 @@
bool in_plt;
{
Elf_Addr symnum = ELF_R_SYM(r_info);
- const Elf_Sym *ref = NULL;
+ const Elf_Sym *ref;
const Elf_Sym *def;
const Elf_Sym *symp;
const Obj_Entry *obj;
@@ -171,10 +171,10 @@
const Objlist_Entry *elm;
unsigned long hash;
- if (name == NULL) {
ref = refobj->symtab + symnum;
+ if (name == NULL)
name = refobj->strtab + ref->st_name;
- }
+
hash = _rtld_elf_hash(name);
def = NULL;
defobj = NULL;
@@ -227,6 +227,7 @@
* symbol as having the value zero.
*/
if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) {
+ rdbg(1, (" returning _rtld_sym_zero@_rtld_objmain"));
def = &_rtld_sym_zero;
defobj = _rtld_objmain;
}
Index: arch/mips/mips_reloc.c
===================================================================
RCS file: /cvsroot/basesrc/libexec/ld.elf_so/arch/mips/mips_reloc.c,v
retrieving revision 1.3
diff -b -u -r1.3 mips_reloc.c
--- arch/mips/mips_reloc.c 1999/11/07 08:01:51 1.3
+++ arch/mips/mips_reloc.c 2001/10/07 03:22:47
@@ -47,6 +47,7 @@
const Elf_Sym *sym = obj->symtab;
const Elf_Sym *def;
const Obj_Entry *defobj;
+ Elf_Word info;
int i;
i = (got[1] & 0x80000000) ? 2 : 1;
@@ -58,9 +59,21 @@
sym += obj->gotsym;
/* Now do the global GOT entries */
while (i--) {
- def = _rtld_find_symdef(_rtld_objlist, 0,
- sym->st_name + obj->strtab, obj, &defobj, true);
- if (def != NULL) {
+ rdbg(1, (" doing got %d sym %p (%s, %x)",
+ obj->symtabno - obj->gotsym - i - 1,
+ sym, sym->st_name + obj->strtab, *got));
+
+ info = ELF32_R_INFO(obj->symtabno - i - 1, sym->st_info);
+ def = _rtld_find_symdef(_rtld_objlist, info, NULL, obj,
+ &defobj, true);
+
+ if (def == NULL)
+ _rtld_error(
+ "%s: Undefined PLT symbol \"%s\" (reloc type = %ld, symnum = %ld)",
+ obj->path, sym->st_name + obj->strtab,
+ (u_long) ELF_R_TYPE(info),
+ (u_long) obj->symtabno - i - 1);
+
if (sym->st_shndx == SHN_UNDEF) {
#if 0 /* These don't seem to work? */
@@ -93,7 +106,7 @@
} else
*got = def->st_value +
(Elf_Word)defobj->relocbase;
- }
+
++sym;
++got;
}
----
Rafal Boni rafal@mediaone.net