summaryrefslogtreecommitdiffstats
path: root/sys/kern/link_elf_obj.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/link_elf_obj.c')
-rw-r--r--sys/kern/link_elf_obj.c51
1 files changed, 31 insertions, 20 deletions
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index 4f40258..453d8ce 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -144,7 +144,8 @@ 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_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 ef)
* 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_Size symidx, int deps)
* 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);
}
}
OpenPOWER on IntegriCloud