From 47f750125bc4d739c12cac17e23ff2683c0469f2 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Tue, 15 Oct 2002 05:40:07 +0000 Subject: [PATCH] Fix kernel module loading on ia64. Cross-module function calls were improperly relocated due to faulty logic in lookup_fdesc() in elf_machdep.c. The symbol index (symidx) was bogusly used for load modules other than the one the relocation applied to. This resulted in bogus bindings and consequently runtime failures. The fix is to use the symbol index only for the module being relocated and to use the symbol name for look-ups in the modules in the dependent list. As such, we need a function to return the symbol name given the linker file and symbol index. --- sys/ia64/ia64/elf_machdep.c | 15 +++++++++++---- sys/kern/link_elf.c | 12 ++++++++++++ sys/kern/link_elf_obj.c | 12 ++++++++++++ sys/sys/linker.h | 1 + 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/sys/ia64/ia64/elf_machdep.c b/sys/ia64/ia64/elf_machdep.c index 4977e6ef98f1..5b2bc2eec3a1 100644 --- a/sys/ia64/ia64/elf_machdep.c +++ b/sys/ia64/ia64/elf_machdep.c @@ -95,18 +95,25 @@ extern Elf_Addr fptr_storage[]; static Elf_Addr lookup_fdesc(linker_file_t lf, Elf_Word symidx) { + linker_file_t top; Elf_Addr addr; + const char *symname; int i; static int eot = 0; addr = elf_lookup(lf, symidx, 0); if (addr == 0) { - for (i = 0; i < lf->ndeps; i++) { - addr = lookup_fdesc(lf->deps[i], symidx); + top = lf; + symname = elf_get_symname(top, symidx); + for (i = 0; i < top->ndeps; i++) { + lf = top->deps[i]; + addr = (Elf_Addr)linker_file_lookup_symbol(lf, + symname, 0); if (addr != 0) - return (addr); + break; } - return (0); + if (addr == 0) + return (0); } if (eot) diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 83fbe17af215..a2ba84e339e7 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -1198,6 +1198,18 @@ elf_get_sym(linker_file_t lf, Elf_Word symidx) return (ef->symtab + symidx); } +const char * +elf_get_symname(linker_file_t lf, Elf_Word symidx) +{ + elf_file_t ef = (elf_file_t)lf; + const Elf_Sym *sym; + + if (symidx >= ef->nchains) + return (NULL); + sym = ef->symtab + symidx; + return (ef->strtab + sym->st_name); +} + /* * Symbol lookup function that can be used when the symbol index is known (ie * in relocations). It uses the symbol index instead of doing a fully fledged diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index 83fbe17af215..a2ba84e339e7 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -1198,6 +1198,18 @@ elf_get_sym(linker_file_t lf, Elf_Word symidx) return (ef->symtab + symidx); } +const char * +elf_get_symname(linker_file_t lf, Elf_Word symidx) +{ + elf_file_t ef = (elf_file_t)lf; + const Elf_Sym *sym; + + if (symidx >= ef->nchains) + return (NULL); + sym = ef->symtab + symidx; + return (ef->strtab + sym->st_name); +} + /* * Symbol lookup function that can be used when the symbol index is known (ie * in relocations). It uses the symbol index instead of doing a fully fledged diff --git a/sys/sys/linker.h b/sys/sys/linker.h index bd45a698438e..d15a3872e53a 100644 --- a/sys/sys/linker.h +++ b/sys/sys/linker.h @@ -231,6 +231,7 @@ extern int kld_debug; int elf_reloc(linker_file_t _lf, const void *_rel, int _type); Elf_Addr elf_lookup(linker_file_t, Elf_Word, int); const Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Word _symidx); +const char *elf_get_symname(linker_file_t _lf, Elf_Word _symidx); /* values for type */ #define ELF_RELOC_REL 1