From 2346aaad048ff1815fc0eceb5393050ee525515e Mon Sep 17 00:00:00 2001 From: mycroft Date: Thu, 12 Sep 2002 18:21:18 +0000 Subject: [PATCH] Move GOT relocation code from _rtld_setup_pltgot() to _rtld_relocate_nonplt_objects(). Add GOT self-relocation in _rtld_relocate_nonplt_self(). MIPS ld.elf_so can now relocate itself. --- libexec/ld.elf_so/arch/mips/mips_reloc.c | 173 ++++++++++++++--------- 1 file changed, 106 insertions(+), 67 deletions(-) diff --git a/libexec/ld.elf_so/arch/mips/mips_reloc.c b/libexec/ld.elf_so/arch/mips/mips_reloc.c index e79356df0694..25521a25c564 100644 --- a/libexec/ld.elf_so/arch/mips/mips_reloc.c +++ b/libexec/ld.elf_so/arch/mips/mips_reloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: mips_reloc.c,v 1.17 2002/09/12 17:08:32 mycroft Exp $ */ +/* $NetBSD: mips_reloc.c,v 1.18 2002/09/12 18:21:18 mycroft Exp $ */ /* * Copyright 1997 Michael L. Hitch @@ -62,65 +62,6 @@ void _rtld_setup_pltgot(obj) const Obj_Entry *obj; { - Elf_Addr *got = obj->pltgot; - const Elf_Sym *sym = obj->symtab; - const Elf_Sym *def; - const Obj_Entry *defobj; - int i; - - i = (got[1] & 0x80000000) ? 2 : 1; - /* Relocate the local GOT entries */ - while (i < obj->local_gotno) - got[i++] += (Elf_Word)obj->relocbase; - got += obj->local_gotno; - sym += obj->gotsym; - /* Now do the global GOT entries */ - for (i = obj->gotsym; i < obj->symtabno; i++) { - rdbg(1, (" doing got %d sym %p (%s, %x)", i - obj->gotsym, - sym, sym->st_name + obj->strtab, *got)); - - def = _rtld_find_symdef(i, obj, &defobj, true); - if (def == NULL) - _rtld_error( - "%s: Undefined PLT symbol \"%s\" (section type = %ld, symnum = %ld)", - obj->path, sym->st_name + obj->strtab, - (u_long) ELF_ST_TYPE(sym->st_info), (u_long) i); - else { - if (sym->st_shndx == SHN_UNDEF) { -#if 0 /* These don't seem to work? */ - - if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) { - if (sym->st_value) - *got = sym->st_value + - (Elf_Word)obj->relocbase; - else - *got = def->st_value + - (Elf_Word)defobj->relocbase; - } else -#endif - *got = def->st_value + - (Elf_Word)defobj->relocbase; - } else if (sym->st_shndx == SHN_COMMON) { - *got = def->st_value + - (Elf_Word)defobj->relocbase; - } else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && - *got != sym->st_value) { - *got += (Elf_Word)obj->relocbase; - } else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION && - ELF_ST_BIND(sym->st_info) == STB_GLOBAL) { - if (sym->st_shndx == SHN_ABS) - *got = sym->st_value + - (Elf_Word)obj->relocbase; - /* else SGI stuff ignored */ - } else - *got = def->st_value + - (Elf_Word)defobj->relocbase; - } - - ++sym; - ++got; - } - obj->pltgot[0] = (Elf_Addr) &_rtld_bind_start; /* XXX only if obj->pltgot[1] & 0x80000000 ?? */ obj->pltgot[1] |= (Elf_Addr) obj; @@ -134,7 +75,10 @@ _rtld_relocate_nonplt_self(dynp, relocbase) const Elf_Rel *rel = 0, *rellim; Elf_Addr relsz = 0; Elf_Addr *where; - const Elf_Sym *def, *symtab; + const Elf_Sym *symtab, *sym; + Elf_Addr *got; + Elf_Word local_gotno, symtabno, gotsym; + int i; for (; dynp->d_tag != DT_NULL; dynp++) { switch (dynp->d_tag) { @@ -147,6 +91,18 @@ _rtld_relocate_nonplt_self(dynp, relocbase) case DT_SYMTAB: symtab = (const Elf_Sym *)(relocbase + dynp->d_un.d_ptr); break; + case DT_PLTGOT: + got = (Elf_Addr *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_MIPS_LOCAL_GOTNO: + local_gotno = dynp->d_un.d_val; + break; + case DT_MIPS_SYMTABNO: + symtabno = dynp->d_un.d_val; + break; + case DT_MIPS_GOTSYM: + gotsym = dynp->d_un.d_val; + break; } } rellim = (const Elf_Rel *)((caddr_t)rel + relsz); @@ -158,12 +114,11 @@ _rtld_relocate_nonplt_self(dynp, relocbase) break; case R_TYPE(REL32): - def = symtab + ELF_R_SYM(rel->r_info); - if (ELF_ST_BIND(def->st_info) == STB_LOCAL && - ELF_ST_TYPE(def->st_info) == STT_SECTION) { - *where += (Elf_Addr)def->st_value; - *where += (Elf_Addr)relocbase; - } else + 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; @@ -171,6 +126,31 @@ _rtld_relocate_nonplt_self(dynp, relocbase) abort(); } } + + i = (got[1] & 0x80000000) ? 2 : 1; + /* Relocate the local GOT entries */ + while (i < local_gotno) + got[i++] += relocbase; + got += local_gotno; + sym = symtab + gotsym; + /* Now do the global GOT entries */ + for (i = gotsym; i < symtabno; i++) { + if (sym->st_shndx == SHN_UNDEF || + sym->st_shndx == SHN_COMMON) { + *got = sym->st_value + relocbase; + } else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && + *got != sym->st_value) { + *got += relocbase; + } else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION && + ELF_ST_BIND(sym->st_info) == STB_GLOBAL) { + if (sym->st_shndx == SHN_ABS) + *got = sym->st_value + relocbase; + /* else SGI stuff ignored */ + } else + *got = sym->st_value + relocbase; + ++sym; + ++got; + } } int @@ -180,6 +160,11 @@ _rtld_relocate_nonplt_objects(obj, self, dodebug) bool dodebug; { const Elf_Rel *rel; + Elf_Addr *got = obj->pltgot; + const Elf_Sym *sym = obj->symtab; + const Elf_Sym *def; + const Obj_Entry *defobj; + int i; if (self) return 0; @@ -259,6 +244,60 @@ _rtld_relocate_nonplt_objects(obj, self, dodebug) return -1; } } + + i = (got[1] & 0x80000000) ? 2 : 1; + /* Relocate the local GOT entries */ + while (i < obj->local_gotno) + got[i++] += (Elf_Word)obj->relocbase; + got += obj->local_gotno; + sym += obj->gotsym; + /* Now do the global GOT entries */ + for (i = obj->gotsym; i < obj->symtabno; i++) { + rdbg(1, (" doing got %d sym %p (%s, %x)", i - obj->gotsym, + sym, sym->st_name + obj->strtab, *got)); + + def = _rtld_find_symdef(i, obj, &defobj, true); + if (def == NULL) + _rtld_error( + "%s: Undefined PLT symbol \"%s\" (section type = %ld, symnum = %ld)", + obj->path, sym->st_name + obj->strtab, + (u_long) ELF_ST_TYPE(sym->st_info), (u_long) i); + else { + if (sym->st_shndx == SHN_UNDEF) { +#if 0 /* These don't seem to work? */ + + if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) { + if (sym->st_value) + *got = sym->st_value + + (Elf_Word)obj->relocbase; + else + *got = def->st_value + + (Elf_Word)defobj->relocbase; + } else +#endif + *got = def->st_value + + (Elf_Word)defobj->relocbase; + } else if (sym->st_shndx == SHN_COMMON) { + *got = def->st_value + + (Elf_Word)defobj->relocbase; + } else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && + *got != sym->st_value) { + *got += (Elf_Word)obj->relocbase; + } else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION && + ELF_ST_BIND(sym->st_info) == STB_GLOBAL) { + if (sym->st_shndx == SHN_ABS) + *got = sym->st_value + + (Elf_Word)obj->relocbase; + /* else SGI stuff ignored */ + } else + *got = def->st_value + + (Elf_Word)defobj->relocbase; + } + + ++sym; + ++got; + } + return 0; }