Index: sys/amd64/amd64/elf_machdep.c =================================================================== --- sys/amd64/amd64/elf_machdep.c +++ sys/amd64/amd64/elf_machdep.c @@ -175,13 +175,10 @@ *off = len; } -#define ERI_LOCAL 0x0001 -#define ERI_ONLYIFUNC 0x0002 - /* Process one elf relocation with addend. */ static int elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, - int type, elf_lookup_fn lookup, int flags) + int type, elf_lookup_fn lookup) { Elf64_Addr *where, val; Elf32_Addr *where32, val32; @@ -221,9 +218,6 @@ panic("unknown reloc type %d\n", type); } - if (((flags & ERI_ONLYIFUNC) == 0) ^ (rtype != R_X86_64_IRELATIVE)) - return (0); - switch (rtype) { case R_X86_64_NONE: /* none */ break; @@ -299,21 +293,12 @@ return (0); } -int -elf_reloc_ifunc(linker_file_t lf, Elf_Addr relocbase, const void *data, - int type, elf_lookup_fn lookup) -{ - - return (elf_reloc_internal(lf, relocbase, data, type, lookup, - ERI_ONLYIFUNC)); -} - int elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup) { - return (elf_reloc_internal(lf, relocbase, data, type, lookup, 0)); + return (elf_reloc_internal(lf, relocbase, data, type, lookup)); } int @@ -321,8 +306,7 @@ int type, elf_lookup_fn lookup) { - return (elf_reloc_internal(lf, relocbase, data, type, lookup, - ERI_LOCAL)); + return (elf_reloc_internal(lf, relocbase, data, type, lookup)); } int Index: sys/i386/i386/elf_machdep.c =================================================================== --- sys/i386/i386/elf_machdep.c +++ sys/i386/i386/elf_machdep.c @@ -160,7 +160,6 @@ } #define ERI_LOCAL 0x0001 -#define ERI_ONLYIFUNC 0x0002 /* Process one elf relocation with addend. */ static int @@ -194,9 +193,6 @@ panic("unknown reloc type %d\n", type); } - if (((flags & ERI_ONLYIFUNC) == 0) ^ (rtype != R_386_IRELATIVE)) - return (0); - if ((flags & ERI_LOCAL) != 0) { if (rtype == R_386_RELATIVE) { /* A + B */ addr = elf_relocaddr(lf, relocbase + addend); @@ -263,15 +259,6 @@ return(0); } -int -elf_reloc_ifunc(linker_file_t lf, Elf_Addr relocbase, const void *data, - int type, elf_lookup_fn lookup) -{ - - return (elf_reloc_internal(lf, relocbase, data, type, lookup, - ERI_ONLYIFUNC)); -} - int elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup) Index: sys/kern/link_elf.c =================================================================== --- sys/kern/link_elf.c +++ sys/kern/link_elf.c @@ -188,11 +188,13 @@ link_elf_methods, sizeof(struct elf_file) }; +typedef int (*elf_reloc_fn)(linker_file_t lf, Elf_Addr relocbase, + const void *data, int type, elf_lookup_fn lookup); + static int parse_dynamic(elf_file_t); static int relocate_file(elf_file_t); -static int relocate_file1(elf_file_t ef, int (*elf_reloc_func)( - linker_file_t lf, Elf_Addr relocbase, const void *data, - int type, elf_lookup_fn lookup)); +static int relocate_file1(elf_file_t ef, elf_lookup_fn lookup, + elf_reloc_fn reloc); static int link_elf_preload_parse_symbols(elf_file_t); static struct elf_set_head set_pcpu_list; @@ -1185,8 +1187,7 @@ } static int -relocate_file1(elf_file_t ef, int (*elf_reloc_func)(linker_file_t lf, - Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup)) +relocate_file1(elf_file_t ef, elf_lookup_fn lookup, elf_reloc_fn reloc) { const Elf_Rel *rellim; const Elf_Rel *rel; @@ -1200,10 +1201,11 @@ rellim = (const Elf_Rel *) ((const char *)ef->rel + ef->relsize); while (rel < rellim) { - if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rel, - ELF_RELOC_REL, elf_lookup)) { + if (reloc(&ef->lf, (Elf_Addr)ef->address, rel, + ELF_RELOC_REL, lookup)) { symname = symbol_name(ef, rel->r_info); - printf("link_elf: symbol %s undefined\n", symname); + printf("link_elf: symbol %s undefined\n", + symname); return (ENOENT); } rel++; @@ -1216,8 +1218,8 @@ relalim = (const Elf_Rela *) ((const char *)ef->rela + ef->relasize); while (rela < relalim) { - if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rela, - ELF_RELOC_RELA, elf_lookup)) { + if (reloc(&ef->lf, (Elf_Addr)ef->address, rela, + ELF_RELOC_RELA, lookup)) { symname = symbol_name(ef, rela->r_info); printf("link_elf: symbol %s undefined\n", symname); @@ -1233,8 +1235,8 @@ rellim = (const Elf_Rel *) ((const char *)ef->pltrel + ef->pltrelsize); while (rel < rellim) { - if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rel, - ELF_RELOC_REL, elf_lookup)) { + if (reloc(&ef->lf, (Elf_Addr)ef->address, rel, + ELF_RELOC_REL, lookup)) { symname = symbol_name(ef, rel->r_info); printf("link_elf: symbol %s undefined\n", symname); @@ -1250,8 +1252,8 @@ relalim = (const Elf_Rela *) ((const char *)ef->pltrela + ef->pltrelasize); while (rela < relalim) { - if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rela, - ELF_RELOC_RELA, elf_lookup)) { + if (reloc(&ef->lf, (Elf_Addr)ef->address, rela, + ELF_RELOC_RELA, lookup)) { symname = symbol_name(ef, rela->r_info); printf("link_elf: symbol %s undefined\n", symname); @@ -1267,14 +1269,8 @@ static int relocate_file(elf_file_t ef) { - int e; - e = relocate_file1(ef, elf_reloc); -#if defined(__i386__) || defined(__amd64__) - if (e == 0) - e = relocate_file1(ef, elf_reloc_ifunc); -#endif - return (e); + return (relocate_file1(ef, elf_lookup, elf_reloc)); } /* @@ -1298,7 +1294,7 @@ } static int -link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym) +link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym) { elf_file_t ef = (elf_file_t) lf; unsigned long symnum; @@ -1687,6 +1683,29 @@ } #if defined(__i386__) || defined(__amd64__) +/* + * Use this lookup routine when performing relocations early during boot. + * The generic lookup routine depends on kobj, which is not initialized + * at that point. + */ +static int +elf_lookup_ifunc(linker_file_t lf, Elf_Size symidx, int deps __unused, + Elf_Addr *res) +{ + elf_file_t ef; + const Elf_Sym *symp; + caddr_t val; + + ef = (elf_file_t)lf; + symp = ef->symtab + symidx; + if (ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC) { + val = (caddr_t)ef->address + symp->st_value; + *res = ((Elf_Addr (*)(void))val)(); + return (0); + } + return (ENOENT); +} + void link_elf_ireloc(caddr_t kmdp) { @@ -1695,7 +1714,7 @@ volatile char *c; size_t i; - ef = &eff; + ef = &eff; /* Do not use bzero/memset before ireloc is done. */ for (c = (char *)ef, i = 0; i < sizeof(*ef); i++) @@ -1706,6 +1725,6 @@ parse_dynamic(ef); ef->address = 0; link_elf_preload_parse_symbols(ef); - relocate_file1(ef, elf_reloc_ifunc); + relocate_file1(ef, elf_lookup_ifunc, elf_reloc); } #endif Index: sys/kern/link_elf_obj.c =================================================================== --- sys/kern/link_elf_obj.c +++ sys/kern/link_elf_obj.c @@ -1527,7 +1527,7 @@ elf_obj_lookup); #if defined(__i386__) || defined(__amd64__) else if (ifuncs) - elf_reloc_ifunc(lf, base, rel, ELF_RELOC_REL, + elf_reloc_local(lf, base, rel, ELF_RELOC_REL, elf_obj_lookup); #endif } @@ -1560,7 +1560,7 @@ elf_obj_lookup); #if defined(__i386__) || defined(__amd64__) else if (ifuncs) - elf_reloc_ifunc(lf, base, rela, ELF_RELOC_RELA, + elf_reloc_local(lf, base, rela, ELF_RELOC_RELA, elf_obj_lookup); #endif } Index: sys/sys/linker.h =================================================================== --- sys/sys/linker.h +++ sys/sys/linker.h @@ -274,8 +274,6 @@ /* Support functions */ int elf_reloc(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu); -int elf_reloc_ifunc(linker_file_t _lf, Elf_Addr base, const void *_rel, - int _type, elf_lookup_fn _lu); int elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu); Elf_Addr elf_relocaddr(linker_file_t _lf, Elf_Addr addr);