Date: Sun, 27 Sep 2015 01:33:44 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r288287 - in stable/10/sys: amd64/amd64 arm/arm i386/i386 ia64/ia64 kern mips/mips powerpc/powerpc sparc64/sparc64 sys Message-ID: <201509270133.t8R1Xix6099851@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Sun Sep 27 01:33:43 2015 New Revision: 288287 URL: https://svnweb.freebsd.org/changeset/base/288287 Log: MFC r288000: Add support for weak symbols to the kernel linkers. Modified: stable/10/sys/amd64/amd64/elf_machdep.c stable/10/sys/arm/arm/elf_machdep.c stable/10/sys/i386/i386/elf_machdep.c stable/10/sys/ia64/ia64/elf_machdep.c stable/10/sys/kern/link_elf.c stable/10/sys/kern/link_elf_obj.c stable/10/sys/mips/mips/elf_machdep.c stable/10/sys/powerpc/powerpc/elf32_machdep.c stable/10/sys/powerpc/powerpc/elf64_machdep.c stable/10/sys/sparc64/sparc64/elf_machdep.c stable/10/sys/sys/linker.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/amd64/amd64/elf_machdep.c ============================================================================== --- stable/10/sys/amd64/amd64/elf_machdep.c Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/amd64/amd64/elf_machdep.c Sun Sep 27 01:33:43 2015 (r288287) @@ -167,6 +167,7 @@ elf_reloc_internal(linker_file_t lf, Elf Elf_Size rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; + int error; switch (type) { case ELF_RELOC_REL: @@ -202,29 +203,29 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_X86_64_64: /* S + A */ - addr = lookup(lf, symidx, 1); + error = lookup(lf, symidx, 1, &addr); val = addr + addend; - if (addr == 0) + if (error != 0) return -1; if (*where != val) *where = val; break; case R_X86_64_PC32: /* S + A - P */ - addr = lookup(lf, symidx, 1); + error = lookup(lf, symidx, 1, &addr); where32 = (Elf32_Addr *)where; val32 = (Elf32_Addr)(addr + addend - (Elf_Addr)where); - if (addr == 0) + if (error != 0) return -1; if (*where32 != val32) *where32 = val32; break; case R_X86_64_32S: /* S + A sign extend */ - addr = lookup(lf, symidx, 1); + error = lookup(lf, symidx, 1, &addr); val32 = (Elf32_Addr)(addr + addend); where32 = (Elf32_Addr *)where; - if (addr == 0) + if (error != 0) return -1; if (*where32 != val32) *where32 = val32; @@ -241,8 +242,8 @@ elf_reloc_internal(linker_file_t lf, Elf case R_X86_64_GLOB_DAT: /* S */ case R_X86_64_JMP_SLOT: /* XXX need addend + offset */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return -1; if (*where != addr) *where = addr; Modified: stable/10/sys/arm/arm/elf_machdep.c ============================================================================== --- stable/10/sys/arm/arm/elf_machdep.c Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/arm/arm/elf_machdep.c Sun Sep 27 01:33:43 2015 (r288287) @@ -132,6 +132,7 @@ elf_reloc_internal(linker_file_t lf, Elf Elf_Word rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; + int error; switch (type) { case ELF_RELOC_REL: @@ -167,8 +168,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_ARM_ABS32: - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return -1; *where += addr; break; @@ -183,8 +184,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_ARM_JUMP_SLOT: - addr = lookup(lf, symidx, 1); - if (addr) { + error = lookup(lf, symidx, 1, &addr); + if (error == 0) { *where = addr; return (0); } Modified: stable/10/sys/i386/i386/elf_machdep.c ============================================================================== --- stable/10/sys/i386/i386/elf_machdep.c Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/i386/i386/elf_machdep.c Sun Sep 27 01:33:43 2015 (r288287) @@ -177,6 +177,7 @@ elf_reloc_internal(linker_file_t lf, Elf Elf_Word rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; + int error; switch (type) { case ELF_RELOC_REL: @@ -212,8 +213,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_386_32: /* S + A */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return -1; addr += addend; if (*where != addr) @@ -221,8 +222,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_386_PC32: /* S + A - P */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return -1; addr += addend - (Elf_Addr)where; if (*where != addr) @@ -239,8 +240,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_386_GLOB_DAT: /* S */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return -1; if (*where != addr) *where = addr; Modified: stable/10/sys/ia64/ia64/elf_machdep.c ============================================================================== --- stable/10/sys/ia64/ia64/elf_machdep.c Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/ia64/ia64/elf_machdep.c Sun Sep 27 01:33:43 2015 (r288287) @@ -127,17 +127,18 @@ elf64_dump_thread(struct thread *td, voi } -static Elf_Addr -lookup_fdesc(linker_file_t lf, Elf_Size symidx, elf_lookup_fn lookup) +static int +lookup_fdesc(linker_file_t lf, Elf_Size symidx, elf_lookup_fn lookup, + Elf_Addr *addr1) { linker_file_t top; Elf_Addr addr; const char *symname; - int i; + int i, error; static int eot = 0; - addr = lookup(lf, symidx, 0); - if (addr == 0) { + error = lookup(lf, symidx, 0, &addr); + if (error != 0) { top = lf; symname = elf_get_symname(top, symidx); for (i = 0; i < top->ndeps; i++) { @@ -148,30 +149,33 @@ lookup_fdesc(linker_file_t lf, Elf_Size break; } if (addr == 0) - return (0); + return (EINVAL); } if (eot) - return (0); + return (EINVAL); /* * Lookup and/or construct OPD */ for (i = 0; i < 8192; i += 2) { - if (fptr_storage[i] == addr) - return (Elf_Addr)(fptr_storage + i); + if (fptr_storage[i] == addr) { + *addr1 = (Elf_Addr)(fptr_storage + i); + return (0); + } if (fptr_storage[i] == 0) { fptr_storage[i] = addr; fptr_storage[i+1] = link_elf_get_gp(lf); - return (Elf_Addr)(fptr_storage + i); + *addr1 = (Elf_Addr)(fptr_storage + i); + return (0); } } printf("%s: fptr table full\n", __func__); eot = 1; - return (0); + return (EINVAL); } /* Process one elf relocation with addend. */ @@ -184,6 +188,7 @@ elf_reloc_internal(linker_file_t lf, Elf Elf_Size rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; + int error; switch (type) { case ELF_RELOC_REL: @@ -223,8 +228,8 @@ elf_reloc_internal(linker_file_t lf, Elf case R_IA_64_NONE: break; case R_IA_64_DIR64LSB: /* word64 LSB S + A */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return (-1); *where = addr + addend; break; @@ -233,16 +238,16 @@ elf_reloc_internal(linker_file_t lf, Elf printf("%s: addend ignored for OPD relocation\n", __func__); } - addr = lookup_fdesc(lf, symidx, lookup); - if (addr == 0) + error = lookup_fdesc(lf, symidx, lookup, &addr); + if (error != 0) return (-1); *where = addr; break; case R_IA_64_REL64LSB: /* word64 LSB BD + A */ break; case R_IA_64_IPLTLSB: - addr = lookup_fdesc(lf, symidx, lookup); - if (addr == 0) + error = lookup_fdesc(lf, symidx, lookup, &addr); + if (error != 0) return (-1); where[0] = *((Elf_Addr*)addr) + addend; where[1] = *((Elf_Addr*)addr + 1); Modified: stable/10/sys/kern/link_elf.c ============================================================================== --- stable/10/sys/kern/link_elf.c Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/kern/link_elf.c Sun Sep 27 01:33:43 2015 (r288287) @@ -158,7 +158,7 @@ static int link_elf_each_function_nameva static void link_elf_reloc_local(linker_file_t); static long link_elf_symtab_get(linker_file_t, const Elf_Sym **); static long link_elf_strtab_get(linker_file_t, caddr_t *); -static Elf_Addr elf_lookup(linker_file_t, Elf_Size, int); +static int elf_lookup(linker_file_t, Elf_Size, int, Elf_Addr *); static kobj_method_t link_elf_methods[] = { KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol), @@ -1498,8 +1498,8 @@ elf_get_symname(linker_file_t lf, Elf_Si * This is not only more efficient, it's also more correct. It's not always * the case that the symbol can be found through the hash table. */ -static Elf_Addr -elf_lookup(linker_file_t lf, Elf_Size symidx, int deps) +static int +elf_lookup(linker_file_t lf, Elf_Size symidx, int deps, Elf_Addr *res) { elf_file_t ef = (elf_file_t)lf; const Elf_Sym *sym; @@ -1507,8 +1507,10 @@ elf_lookup(linker_file_t lf, Elf_Size sy Elf_Addr addr, start, base; /* Don't even try to lookup the symbol if the index is bogus. */ - if (symidx >= ef->nchains) - return (0); + if (symidx >= ef->nchains) { + *res = 0; + return (EINVAL); + } sym = ef->symtab + symidx; @@ -1518,9 +1520,12 @@ elf_lookup(linker_file_t lf, Elf_Size sy */ if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) { /* Force lookup failure when we have an insanity. */ - if (sym->st_shndx == SHN_UNDEF || sym->st_value == 0) - return (0); - return ((Elf_Addr)ef->address + sym->st_value); + if (sym->st_shndx == SHN_UNDEF || sym->st_value == 0) { + *res = 0; + return (EINVAL); + } + *res = ((Elf_Addr)ef->address + sym->st_value); + return (0); } /* @@ -1533,8 +1538,10 @@ elf_lookup(linker_file_t lf, Elf_Size sy symbol = ef->strtab + sym->st_name; /* Force a lookup failure if the symbol name is bogus. */ - if (*symbol == 0) - return (0); + if (*symbol == 0) { + *res = 0; + return (EINVAL); + } addr = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); @@ -1544,7 +1551,8 @@ elf_lookup(linker_file_t lf, Elf_Size sy else if (elf_set_find(&set_vnet_list, addr, &start, &base)) addr = addr - start + base; #endif - return addr; + *res = addr; + return (0); } static void Modified: stable/10/sys/kern/link_elf_obj.c ============================================================================== --- stable/10/sys/kern/link_elf_obj.c Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/kern/link_elf_obj.c Sun Sep 27 01:33:43 2015 (r288287) @@ -144,7 +144,8 @@ static void link_elf_reloc_local(linker_ static long link_elf_symtab_get(linker_file_t, const Elf_Sym **); static long link_elf_strtab_get(linker_file_t, caddr_t *); -static Elf_Addr elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps); +static int elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps, + Elf_Addr *); static kobj_method_t link_elf_methods[] = { KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol), @@ -1224,38 +1225,46 @@ elf_obj_cleanup_globals_cache(elf_file_t * This is not only more efficient, it's also more correct. It's not always * the case that the symbol can be found through the hash table. */ -static Elf_Addr -elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps) +static int +elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps, Elf_Addr *res) { elf_file_t ef = (elf_file_t)lf; Elf_Sym *sym; const char *symbol; - Elf_Addr ret; + Elf_Addr res1; /* Don't even try to lookup the symbol if the index is bogus. */ - if (symidx >= ef->ddbsymcnt) - return (0); + if (symidx >= ef->ddbsymcnt) { + *res = 0; + return (EINVAL); + } sym = ef->ddbsymtab + symidx; /* Quick answer if there is a definition included. */ - if (sym->st_shndx != SHN_UNDEF) - return (sym->st_value); + if (sym->st_shndx != SHN_UNDEF) { + *res = sym->st_value; + return (0); + } /* If we get here, then it is undefined and needs a lookup. */ switch (ELF_ST_BIND(sym->st_info)) { case STB_LOCAL: /* Local, but undefined? huh? */ - return (0); + *res = 0; + return (EINVAL); case STB_GLOBAL: + case STB_WEAK: /* Relative to Data or Function name */ symbol = ef->ddbstrtab + sym->st_name; /* Force a lookup failure if the symbol name is bogus. */ - if (*symbol == 0) - return (0); - ret = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); + if (*symbol == 0) { + *res = 0; + return (EINVAL); + } + res1 = (Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps); /* * Cache global lookups during module relocation. The failure @@ -1267,18 +1276,20 @@ elf_obj_lookup(linker_file_t lf, Elf_Siz * restored to SHN_UNDEF in elf_obj_cleanup_globals_cache(), * above. */ - if (ret != 0) { + if (res1 != 0) { sym->st_shndx = SHN_FBSD_CACHED; - sym->st_value = ret; + sym->st_value = res1; + *res = res1; + return (0); + } else if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { + sym->st_value = 0; + *res = 0; + return (0); } - return (ret); - - case STB_WEAK: - printf("link_elf_obj: Weak symbols not supported\n"); - return (0); + return (EINVAL); default: - return (0); + return (EINVAL); } } Modified: stable/10/sys/mips/mips/elf_machdep.c ============================================================================== --- stable/10/sys/mips/mips/elf_machdep.c Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/mips/mips/elf_machdep.c Sun Sep 27 01:33:43 2015 (r288287) @@ -174,6 +174,7 @@ elf_reloc_internal(linker_file_t lf, Elf Elf_Word rtype = (Elf_Word)0, symidx; const Elf_Rel *rel = NULL; const Elf_Rela *rela = NULL; + int error; /* * Stash R_MIPS_HI16 info so we can use it when processing R_MIPS_LO16 @@ -213,8 +214,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_MIPS_32: /* S + A */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return (-1); addr += addend; if (*where != addr) @@ -222,8 +223,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_MIPS_26: /* ((A << 2) | (P & 0xf0000000) + S) >> 2 */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return (-1); addend &= 0x03ffffff; @@ -241,8 +242,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_MIPS_64: /* S + A */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return (-1); addr += addend; if (*(Elf64_Addr*)where != addr) @@ -251,8 +252,8 @@ elf_reloc_internal(linker_file_t lf, Elf case R_MIPS_HI16: /* ((AHL + S) - ((short)(AHL + S)) >> 16 */ if (rela != NULL) { - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return (-1); addr += addend; *where &= 0xffff0000; @@ -266,8 +267,8 @@ elf_reloc_internal(linker_file_t lf, Elf case R_MIPS_LO16: /* AHL + S */ if (rela != NULL) { - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return (-1); addr += addend; *where &= 0xffff0000; @@ -275,8 +276,8 @@ elf_reloc_internal(linker_file_t lf, Elf } else { ahl += (int16_t)addend; - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return (-1); addend &= 0xffff0000; @@ -292,8 +293,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_MIPS_HIGHER: /* %higher(A+S) */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return (-1); addr += addend; *where &= 0xffff0000; @@ -301,8 +302,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_MIPS_HIGHEST: /* %highest(A+S) */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return (-1); addr += addend; *where &= 0xffff0000; Modified: stable/10/sys/powerpc/powerpc/elf32_machdep.c ============================================================================== --- stable/10/sys/powerpc/powerpc/elf32_machdep.c Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/powerpc/powerpc/elf32_machdep.c Sun Sep 27 01:33:43 2015 (r288287) @@ -164,6 +164,7 @@ elf_reloc_internal(linker_file_t lf, Elf Elf_Addr addend; Elf_Word rtype, symidx; const Elf_Rela *rela; + int error; switch (type) { case ELF_RELOC_REL: @@ -187,16 +188,16 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_PPC_ADDR32: /* word32 S + A */ - addr = lookup(lf, symidx, 1); - if (addr == 0) - return -1; + error = lookup(lf, symidx, 1, &addr); + if (error != 0) + return -1; addr += addend; *where = addr; break; case R_PPC_ADDR16_LO: /* #lo(S) */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return -1; /* * addend values are sometimes relative to sections @@ -211,8 +212,8 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_PPC_ADDR16_HA: /* #ha(S) */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return -1; /* * addend values are sometimes relative to sections Modified: stable/10/sys/powerpc/powerpc/elf64_machdep.c ============================================================================== --- stable/10/sys/powerpc/powerpc/elf64_machdep.c Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/powerpc/powerpc/elf64_machdep.c Sun Sep 27 01:33:43 2015 (r288287) @@ -135,6 +135,7 @@ elf_reloc_internal(linker_file_t lf, Elf Elf_Addr addend; Elf_Word rtype, symidx; const Elf_Rela *rela; + int error; switch (type) { case ELF_RELOC_REL: @@ -157,9 +158,9 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_PPC64_ADDR64: /* doubleword64 S + A */ - addr = lookup(lf, symidx, 1); - if (addr == 0) - return -1; + error = lookup(lf, symidx, 1, &addr); + if (error != 0) + return -1; addr += addend; *where = addr; break; @@ -169,7 +170,7 @@ elf_reloc_internal(linker_file_t lf, Elf break; case R_PPC_JMP_SLOT: /* function descriptor copy */ - addr = lookup(lf, symidx, 1); + lookup(lf, symidx, 1, &addr); memcpy(where, (Elf_Addr *)addr, 3*sizeof(Elf_Addr)); __asm __volatile("dcbst 0,%0; sync" :: "r"(where) : "memory"); break; Modified: stable/10/sys/sparc64/sparc64/elf_machdep.c ============================================================================== --- stable/10/sys/sparc64/sparc64/elf_machdep.c Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/sparc64/sparc64/elf_machdep.c Sun Sep 27 01:33:43 2015 (r288287) @@ -343,6 +343,7 @@ elf_reloc(linker_file_t lf, Elf_Addr rel Elf_Addr value; Elf_Addr mask; Elf_Addr addr; + int error; if (type != ELF_RELOC_RELA) return (-1); @@ -371,8 +372,8 @@ elf_reloc(linker_file_t lf, Elf_Addr rel value = rela->r_addend; if (RELOC_RESOLVE_SYMBOL(rtype)) { - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return (-1); value += addr; if (RELOC_BARE_SYMBOL(rtype)) Modified: stable/10/sys/sys/linker.h ============================================================================== --- stable/10/sys/sys/linker.h Sun Sep 27 01:26:41 2015 (r288286) +++ stable/10/sys/sys/linker.h Sun Sep 27 01:33:43 2015 (r288287) @@ -259,7 +259,7 @@ extern int kld_debug; #endif -typedef Elf_Addr elf_lookup_fn(linker_file_t, Elf_Size, int); +typedef int elf_lookup_fn(linker_file_t, Elf_Size, int, Elf_Addr *); /* Support functions */ int elf_reloc(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509270133.t8R1Xix6099851>