Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/link_elf_obj.c
Show First 20 Lines • Show All 167 Lines • ▼ Show 20 Lines | #if ELF_TARG_CLASS == ELFCLASS32 | ||||
"elf32_obj", | "elf32_obj", | ||||
#else | #else | ||||
"elf64_obj", | "elf64_obj", | ||||
#endif | #endif | ||||
link_elf_methods, sizeof(struct elf_file) | link_elf_methods, sizeof(struct elf_file) | ||||
}; | }; | ||||
static int relocate_file(elf_file_t ef); | static int relocate_file(elf_file_t ef); | ||||
static void elf_obj_cleanup_globals_cache(elf_file_t); | |||||
static void | static void | ||||
link_elf_error(const char *filename, const char *s) | link_elf_error(const char *filename, const char *s) | ||||
{ | { | ||||
if (filename == NULL) | if (filename == NULL) | ||||
printf("kldload: %s\n", s); | printf("kldload: %s\n", s); | ||||
else | else | ||||
printf("kldload: %s: %s\n", filename, s); | printf("kldload: %s: %s\n", filename, s); | ||||
▲ Show 20 Lines • Show All 700 Lines • ▼ Show 20 Lines | #endif | ||||
/* Notify MD code that a module is being loaded. */ | /* Notify MD code that a module is being loaded. */ | ||||
error = elf_cpu_load_file(lf); | error = elf_cpu_load_file(lf); | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
/* Invoke .ctors */ | /* Invoke .ctors */ | ||||
link_elf_invoke_ctors(lf->ctors_addr, lf->ctors_size); | link_elf_invoke_ctors(lf->ctors_addr, lf->ctors_size); | ||||
elf_obj_cleanup_globals_cache(ef); | |||||
kib: Why do you only clean for the runtime loaded objects, and do not clean for the preloaded… | |||||
*result = lf; | *result = lf; | ||||
out: | out: | ||||
VOP_UNLOCK(nd.ni_vp, 0); | VOP_UNLOCK(nd.ni_vp, 0); | ||||
vn_close(nd.ni_vp, FREAD, td->td_ucred, td); | vn_close(nd.ni_vp, FREAD, td->td_ucred, td); | ||||
if (error && lf) | if (error && lf) | ||||
linker_file_unload(lf, LINKER_UNLOAD_FORCE); | linker_file_unload(lf, LINKER_UNLOAD_FORCE); | ||||
if (hdr) | if (hdr) | ||||
▲ Show 20 Lines • Show All 318 Lines • ▼ Show 20 Lines | if (symp->st_value != 0 && | ||||
error = callback(file, i, &symval, opaque); | error = callback(file, i, &symval, opaque); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | |||||
elf_obj_cleanup_globals_cache(elf_file_t ef) | |||||
{ | |||||
Elf_Size i; | |||||
Elf_Sym *sym; | |||||
for (i = 0; i < ef->ddbsymcnt; i++) { | |||||
sym = ef->ddbsymtab + i; | |||||
if (sym->st_shndx == SHN_FBSD_CACHED) { | |||||
sym->st_shndx = SHN_UNDEF; | |||||
sym->st_value = 0; | |||||
} | |||||
} | |||||
} | |||||
/* | /* | ||||
* Symbol lookup function that can be used when the symbol index is known (ie | * 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 | * in relocations). It uses the symbol index instead of doing a fully fledged | ||||
* hash table based lookup when such is valid. For example for local symbols. | * hash table based lookup when such is valid. For example for local symbols. | ||||
* This is not only more efficient, it's also more correct. It's not always | * 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. | * the case that the symbol can be found through the hash table. | ||||
*/ | */ | ||||
static Elf_Addr | static Elf_Addr | ||||
elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps) | elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps) | ||||
{ | { | ||||
elf_file_t ef = (elf_file_t)lf; | elf_file_t ef = (elf_file_t)lf; | ||||
const Elf_Sym *sym; | Elf_Sym *sym; | ||||
const char *symbol; | const char *symbol; | ||||
Elf_Addr ret; | Elf_Addr ret; | ||||
/* Don't even try to lookup the symbol if the index is bogus. */ | /* Don't even try to lookup the symbol if the index is bogus. */ | ||||
if (symidx >= ef->ddbsymcnt) | if (symidx >= ef->ddbsymcnt) | ||||
return (0); | return (0); | ||||
sym = ef->ddbsymtab + symidx; | sym = ef->ddbsymtab + symidx; | ||||
Show All 11 Lines | elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps) | ||||
case STB_GLOBAL: | case STB_GLOBAL: | ||||
/* Relative to Data or Function name */ | /* Relative to Data or Function name */ | ||||
symbol = ef->ddbstrtab + sym->st_name; | symbol = ef->ddbstrtab + sym->st_name; | ||||
/* Force a lookup failure if the symbol name is bogus. */ | /* Force a lookup failure if the symbol name is bogus. */ | ||||
if (*symbol == 0) | if (*symbol == 0) | ||||
return (0); | return (0); | ||||
ret = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); | ret = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); | ||||
return ret; | /* Cache global lookups */ | ||||
if (ret != 0) { | |||||
sym->st_shndx = SHN_FBSD_CACHED; | |||||
sym->st_value = ret; | |||||
} | |||||
return (ret); | |||||
case STB_WEAK: | case STB_WEAK: | ||||
printf("link_elf_obj: Weak symbols not supported\n"); | printf("link_elf_obj: Weak symbols not supported\n"); | ||||
return (0); | return (0); | ||||
default: | default: | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 132 Lines • Show Last 20 Lines |
Why do you only clean for the runtime loaded objects, and do not clean for the preloaded objects ?
IMO, the cleanup must be done much closer to the relocator, probably in relocate_file().
It would be nice to assert that kld_sx is exclusively owned while SHN_FBSD_CACHED hack is in the symbol table, but this might be not easy to implement.