38#include <sys/kernel.h>
40#include <sys/malloc.h>
41#include <sys/linker.h>
46#include <sys/rwlock.h>
47#include <sys/sysctl.h>
50#include <machine/elf.h>
54#include <security/mac/mac_framework.h>
57#include <vm/vm_param.h>
59#include <vm/vm_extern.h>
60#include <vm/vm_kern.h>
62#include <vm/vm_object.h>
63#include <vm/vm_page.h>
64#include <vm/vm_pager.h>
66#include <sys/link_elf.h>
69#include <contrib/zlib/zlib.h>
95 struct linker_file
lf;
130 const char *, linker_file_t *);
146 void ***,
void ***,
int *);
148 int (*)(
const char *,
void *),
void *);
150 linker_function_nameval_callback_t,
156static int elf_obj_lookup(linker_file_t lf, Elf_Size symidx,
int deps,
179#if ELF_TARG_CLASS == ELFCLASS32
190 "Allow local symbols to participate in global module symbol resolution");
199 printf(
"kldload: %s\n", s);
218 KASSERT(start <= end && start >= (vm_offset_t)ef->
address &&
219 end <= round_page((vm_offset_t)ef->
address + ef->
lf.size),
220 (
"link_elf_protect_range: invalid range %#jx-%#jx",
221 (uintmax_t)
start, (uintmax_t)end));
227 error = pmap_change_prot(
start, end -
start, prot);
229 (
"link_elf_protect_range: pmap_change_prot() returned %d",
234 error = vm_map_protect(kernel_map,
start, end, prot, 0,
235 VM_MAP_PROTECT_SET_PROT);
236 KASSERT(error == KERN_SUCCESS,
237 (
"link_elf_protect_range: vm_map_protect() returned %d", error));
247 vm_offset_t end, segend, segstart,
start;
248 vm_prot_t gapprot, prot, segprot;
257 gapprot = ef->
preloaded ? VM_PROT_RW : VM_PROT_READ;
261 for (i = 0; i < ef->
nprogtab; i++) {
273 segstart = trunc_page((vm_offset_t)ef->
progtab[i].
addr);
274 segend = round_page((vm_offset_t)ef->
progtab[i].
addr +
276 segprot = VM_PROT_READ;
278 segprot |= VM_PROT_WRITE;
280 segprot |= VM_PROT_EXECUTE;
282 if (end <= segstart) {
295 }
else if (
start < segstart && end == segend) {
305 }
else if (end < segend) {
332 round_page((vm_offset_t)ef->
address + ef->
lf.size), gapprot);
342 void *
modptr, *baseptr, *sizeptr;
347 int error, i, j, pb, ra, rl, shstrindex, symstrindex, symtabindex;
362 " obj module") != 0 &&
363 strcmp(
type,
"elf obj module") != 0)) {
366 if (baseptr == NULL || sizeptr == NULL || hdr == NULL ||
376 ef->
address = *(caddr_t *)baseptr;
377 lf->address = *(caddr_t *)baseptr;
378 lf->size = *(
size_t *)sizeptr;
380 if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
381 hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
382 hdr->e_ident[EI_VERSION] != EV_CURRENT ||
383 hdr->e_version != EV_CURRENT ||
384 hdr->e_type != ET_REL ||
385 hdr->e_machine != ELF_TARG_MACH) {
394 for (i = 0; i < hdr->e_shnum; i++) {
395 switch (shdr[i].sh_type) {
399 case SHT_X86_64_UNWIND:
404 if (shdr[i].sh_addr == 0)
410 symstrindex = shdr[i].sh_link;
417 if (shdr[shdr[i].sh_info].sh_addr == 0)
422 if (shdr[shdr[i].sh_info].sh_addr == 0)
429 shstrindex = hdr->e_shstrndx;
430 if (ef->
nprogtab == 0 || symstrindex < 0 ||
431 symstrindex >= hdr->e_shnum ||
432 shdr[symstrindex].sh_type != SHT_STRTAB || shstrindex == 0 ||
433 shstrindex >= hdr->e_shnum ||
434 shdr[shstrindex].sh_type != SHT_STRTAB) {
443 M_LINKER, M_WAITOK | M_ZERO);
446 M_LINKER, M_WAITOK | M_ZERO);
449 M_LINKER, M_WAITOK | M_ZERO);
459 for (i = 0; i < hdr->e_shnum; i++) {
460 if (shdr[i].sh_addr != 0 && (off == 0 || shdr[i].sh_addr < off))
461 off = shdr[i].sh_addr;
463 for (i = 0; i < hdr->e_shnum; i++) {
464 if (shdr[i].sh_addr != 0)
465 shdr[i].sh_addr = shdr[i].sh_addr - off +
469 ef->
ddbsymcnt = shdr[symtabindex].sh_size /
sizeof(Elf_Sym);
470 ef->
ddbsymtab = (Elf_Sym *)shdr[symtabindex].sh_addr;
471 ef->
ddbstrcnt = shdr[symstrindex].sh_size;
472 ef->
ddbstrtab = (
char *)shdr[symstrindex].sh_addr;
473 ef->
shstrcnt = shdr[shstrindex].sh_size;
474 ef->
shstrtab = (
char *)shdr[shstrindex].sh_addr;
480 for (i = 0; i < hdr->e_shnum; i++) {
481 switch (shdr[i].sh_type) {
485 case SHT_X86_64_UNWIND:
489 if (shdr[i].sh_addr == 0)
492 if (shdr[i].sh_type == SHT_PROGBITS)
495 else if (shdr[i].sh_type == SHT_X86_64_UNWIND)
498 else if (shdr[i].sh_type == SHT_INIT_ARRAY)
500 else if (shdr[i].sh_type == SHT_FINI_ARRAY)
507 if (ef->
shstrtab && shdr[i].sh_name != 0)
516 printf(
"%s: pcpu module space is out "
517 "of space; cannot allocate %#jx "
518 "for %s\n", __func__,
519 (uintmax_t)shdr[i].sh_size,
533 vnet_data = vnet_data_alloc(shdr[i].sh_size);
534 if (vnet_data == NULL) {
535 printf(
"%s: vnet module space is out "
536 "of space; cannot allocate %#jx "
537 "for %s\n", __func__,
538 (uintmax_t)shdr[i].sh_size,
545 vnet_data_copy(vnet_data, shdr[i].sh_size);
550 shdr[i].sh_type == SHT_INIT_ARRAY) {
551 if (
lf->ctors_addr != 0) {
553 "%s: multiple ctor sections in %s\n",
557 lf->ctors_size = shdr[i].sh_size;
561 shdr[i].sh_type == SHT_FINI_ARRAY) {
562 if (
lf->dtors_addr != 0) {
564 "%s: multiple dtor sections in %s\n",
568 lf->dtors_size = shdr[i].sh_size;
575 if (es->st_shndx != i)
582 if (shdr[shdr[i].sh_info].sh_addr == 0)
584 ef->
reltab[rl].
rel = (Elf_Rel *)shdr[i].sh_addr;
585 ef->
reltab[rl].
nrel = shdr[i].sh_size /
sizeof(Elf_Rel);
590 if (shdr[shdr[i].sh_info].sh_addr == 0)
592 ef->
relatab[ra].
rela = (Elf_Rela *)shdr[i].sh_addr;
594 shdr[i].sh_size /
sizeof(Elf_Rela);
622 round_page((vm_offset_t)ef->
address + ef->
lf.size), VM_PROT_ALL);
643 if (
addr == NULL || size == 0)
645 cnt = size /
sizeof(*ctor);
647 for (i = 0; i < cnt; i++) {
665 error = elf_cpu_load_file(
lf);
669#if defined(__i386__) || defined(__amd64__)
687 struct nameidata *nd;
688 struct thread *td = curthread;
712 nd =
malloc(
sizeof(
struct nameidata), M_TEMP, M_WAITOK);
713 NDINIT(nd, LOOKUP, FOLLOW, UIO_SYSSPACE,
filename);
720 NDFREE(nd, NDF_ONLY_PNBUF);
721 if (nd->ni_vp->v_type != VREG) {
726 error = mac_kld_check_load(td->td_ucred, nd->ni_vp);
733 hdr =
malloc(
sizeof(*hdr), M_LINKER, M_WAITOK);
734 error =
vn_rdwr(UIO_READ, nd->ni_vp, (
void *)hdr,
sizeof(*hdr), 0,
735 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
749 if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
750 || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
755 if (hdr->e_ident[EI_VERSION] != EV_CURRENT
756 || hdr->e_version != EV_CURRENT) {
761 if (hdr->e_type != ET_REL) {
765 if (hdr->e_machine != ELF_TARG_MACH) {
783 nbytes = hdr->e_shnum * hdr->e_shentsize;
784 if (
nbytes == 0 || hdr->e_shoff == 0 ||
785 hdr->e_shentsize !=
sizeof(Elf_Shdr)) {
792 hdr->e_shoff, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
805 for (i = 0; i < hdr->e_shnum; i++) {
806 if (shdr[i].sh_size == 0)
808 switch (shdr[i].sh_type) {
812 case SHT_X86_64_UNWIND:
816 if ((shdr[i].sh_flags & SHF_ALLOC) == 0)
823 symstrindex = shdr[i].sh_link;
830 if ((shdr[shdr[i].sh_info].sh_flags & SHF_ALLOC) == 0)
835 if ((shdr[shdr[i].sh_info].sh_flags & SHF_ALLOC) == 0)
851 "file must have exactly one symbol table");
855 if (symstrindex < 0 || symstrindex > hdr->e_shnum ||
856 shdr[symstrindex].sh_type != SHT_STRTAB) {
865 M_LINKER, M_WAITOK | M_ZERO);
868 M_LINKER, M_WAITOK | M_ZERO);
871 M_LINKER, M_WAITOK | M_ZERO);
873 if (symtabindex == -1) {
879 ef->
ddbsymcnt = shdr[symtabindex].sh_size /
sizeof(Elf_Sym);
882 shdr[symtabindex].sh_size, shdr[symtabindex].sh_offset,
883 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
893 ef->
ddbstrcnt = shdr[symstrindex].sh_size;
896 shdr[symstrindex].sh_size, shdr[symstrindex].sh_offset,
897 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
908 if (hdr->e_shstrndx != 0 &&
909 shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
910 shstrindex = hdr->e_shstrndx;
911 ef->
shstrcnt = shdr[shstrindex].sh_size;
915 shdr[shstrindex].sh_size, shdr[shstrindex].sh_offset,
916 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
928 for (i = 0; i < hdr->e_shnum; i++) {
929 if (shdr[i].sh_size == 0)
931 switch (shdr[i].sh_type) {
935 case SHT_X86_64_UNWIND:
939 if ((shdr[i].sh_flags & SHF_ALLOC) == 0)
941 alignmask = shdr[i].sh_addralign - 1;
942 mapsize += alignmask;
943 mapsize &= ~alignmask;
944 mapsize += shdr[i].sh_size;
954 ef->
object = vm_pager_allocate(OBJT_PHYS, NULL, round_page(mapsize),
955 VM_PROT_ALL, 0, thread0.td_ucred);
960#if VM_NRESERVLEVEL > 0
961 vm_object_color(ef->
object, 0);
974 mapbase = VM_MIN_KERNEL_ADDRESS;
976 error = vm_map_find(kernel_map, ef->
object, 0, &mapbase,
977 round_page(mapsize), 0, VMFS_OPTIMAL_SPACE, VM_PROT_ALL,
979 if (error != KERN_SUCCESS) {
980 vm_object_deallocate(ef->
object);
987 error = vm_map_wire(kernel_map, mapbase,
988 mapbase + round_page(mapsize),
989 VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES);
990 if (error != KERN_SUCCESS) {
996 lf->address = ef->
address = (caddr_t)mapbase;
1007 for (i = 0; i < hdr->e_shnum; i++) {
1008 if (shdr[i].sh_size == 0)
1010 switch (shdr[i].sh_type) {
1014 case SHT_X86_64_UNWIND:
1016 case SHT_INIT_ARRAY:
1017 case SHT_FINI_ARRAY:
1018 if ((shdr[i].sh_flags & SHF_ALLOC) == 0)
1020 alignmask = shdr[i].sh_addralign - 1;
1021 mapbase += alignmask;
1022 mapbase &= ~alignmask;
1023 if (ef->
shstrtab != NULL && shdr[i].sh_name != 0) {
1027 shdr[i].sh_type == SHT_INIT_ARRAY) {
1028 if (lf->ctors_addr != 0) {
1030 "%s: multiple ctor sections in %s\n",
1040 shdr[i].sh_type == SHT_FINI_ARRAY) {
1041 if (lf->dtors_addr != 0) {
1043 "%s: multiple dtor sections in %s\n",
1052 }
else if (shdr[i].sh_type == SHT_PROGBITS)
1055 else if (shdr[i].sh_type == SHT_X86_64_UNWIND)
1065 printf(
"%s: pcpu module space is out "
1066 "of space; cannot allocate %#jx "
1067 "for %s\n", __func__,
1068 (uintmax_t)shdr[i].sh_size,
1076 vnet_data_alloc(shdr[i].sh_size);
1078 printf(
"%s: vnet module space is out "
1079 "of space; cannot allocate %#jx "
1080 "for %s\n", __func__,
1081 (uintmax_t)shdr[i].sh_size,
1088 (
void *)(uintptr_t)mapbase;
1096 if (shdr[i].sh_type == SHT_PROGBITS
1098 || shdr[i].sh_type == SHT_X86_64_UNWIND
1101 error =
vn_rdwr(UIO_READ, nd->ni_vp,
1103 shdr[i].sh_size, shdr[i].sh_offset,
1104 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
1105 NOCRED, &resid, td);
1130 if (es->st_shndx != i)
1134 mapbase += shdr[i].sh_size;
1138 if ((shdr[shdr[i].sh_info].sh_flags & SHF_ALLOC) == 0)
1142 ef->
reltab[rl].
nrel = shdr[i].sh_size /
sizeof(Elf_Rel);
1144 error =
vn_rdwr(UIO_READ, nd->ni_vp,
1146 shdr[i].sh_size, shdr[i].sh_offset,
1147 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
1158 if ((shdr[shdr[i].sh_info].sh_flags & SHF_ALLOC) == 0)
1163 shdr[i].sh_size /
sizeof(Elf_Rela);
1165 error =
vn_rdwr(UIO_READ, nd->ni_vp,
1167 shdr[i].sh_size, shdr[i].sh_offset,
1168 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
1195 if (mapbase != (vm_offset_t)ef->
address + mapsize) {
1197 "%s: mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n",
1199 (u_long)mapbase, ef->
address, (u_long)mapsize,
1200 (u_long)(vm_offset_t)ef->
address + mapsize);
1211 VOP_UNLOCK(nd->ni_vp);
1213 vn_lock(nd->ni_vp, LK_EXCLUSIVE | LK_RETRY);
1223 error = elf_cpu_load_file(lf);
1227#if defined(__i386__) || defined(__amd64__)
1239 VOP_UNLOCK(nd->ni_vp);
1240 vn_close(nd->ni_vp, FREAD, td->td_ucred, td);
1244 free(hdr, M_LINKER);
1258 elf_cpu_unload_file(file);
1261 for (i = 0; i < ef->
nprogtab; i++) {
1270 else if (!strcmp(ef->
progtab[i].
name, VNET_SETNAME))
1283 if (file->pathname != NULL)
1288 for (i = 0; i < ef->
nreltab; i++)
1297 vm_map_remove(kernel_map, (vm_offset_t)ef->
address,
1313 if (ELF_R_SYM(r_info)) {
1314 ref = ef->
ddbsymtab + ELF_R_SYM(r_info);
1326 for (i = 0; i < ef->
nprogtab; i++) {
1338 const Elf_Rel *rellim;
1340 const Elf_Rela *relalim;
1341 const Elf_Rela *rela;
1342 const char *symname;
1349 for (i = 0; i < ef->
nreltab; i++) {
1361 for ( ; rel < rellim; rel++) {
1362 symidx = ELF_R_SYM(rel->r_info);
1367 if (ELF_ST_BIND(
sym->st_info) == STB_LOCAL)
1369 if ((ELF_ST_TYPE(
sym->st_info) == STT_GNU_IFUNC ||
1370 elf_is_ifunc_reloc(rel->r_info)) != ifuncs)
1372 if (elf_reloc(&ef->
lf, base, rel, ELF_RELOC_REL,
1375 printf(
"link_elf_obj: symbol %s undefined\n",
1383 for (i = 0; i < ef->
nrelatab; i++) {
1393 "lost base for relatab");
1396 for ( ; rela < relalim; rela++) {
1397 symidx = ELF_R_SYM(rela->r_info);
1402 if (ELF_ST_BIND(
sym->st_info) == STB_LOCAL)
1404 if ((ELF_ST_TYPE(
sym->st_info) == STT_GNU_IFUNC ||
1405 elf_is_ifunc_reloc(rela->r_info)) != ifuncs)
1407 if (elf_reloc(&ef->
lf, base, rela, ELF_RELOC_RELA,
1410 printf(
"link_elf_obj: symbol %s undefined\n",
1443 const Elf_Sym *
symp;
1449 if (
symp->st_shndx != SHN_UNDEF && strcmp(
name, strp) == 0) {
1451 ELF_ST_BIND(
symp->st_info) == STB_GLOBAL) {
1470 c_linker_sym_t *
sym)
1477 linker_symval_t *symval,
bool see_local)
1484 es = (
const Elf_Sym*)
sym;
1485 val = (caddr_t)es->st_value;
1487 if (!see_local && ELF_ST_BIND(es->st_info) == STB_LOCAL)
1489 symval->name = ef->
ddbstrtab + es->st_name;
1490 val = (caddr_t)es->st_value;
1491 if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
1492 val = ((caddr_t (*)(void))val)();
1493 symval->value = val;
1494 symval->size = es->st_size;
1502 linker_symval_t *symval)
1510 linker_symval_t *symval)
1520 u_long off = (uintptr_t)(
void *)
value;
1524 const Elf_Sym *best = NULL;
1527 for (i = 0, es = ef->
ddbsymtab; i < ef->ddbsymcnt; i++, es++) {
1528 if (es->st_name == 0)
1530 st_value = es->st_value;
1531 if (off >= st_value) {
1532 if (off - st_value < diff) {
1533 diff = off - st_value;
1537 }
else if (off - st_value == diff) {
1546 *
sym = (c_linker_sym_t) best;
1556 void ***startp,
void ***stopp,
int *countp)
1563 for (i = 0; i < ef->
nprogtab; i++) {
1564 if ((strncmp(ef->
progtab[i].
name,
"set_", 4) == 0) &&
1587 const Elf_Sym *
symp;
1592 if (
symp->st_value != 0 &&
1593 (ELF_ST_TYPE(
symp->st_info) == STT_FUNC ||
1594 ELF_ST_TYPE(
symp->st_info) == STT_GNU_IFUNC)) {
1607 linker_symval_t symval;
1609 const Elf_Sym *
symp;
1614 if (
symp->st_value != 0 &&
1615 (ELF_ST_TYPE(
symp->st_info) == STT_FUNC ||
1616 ELF_ST_TYPE(
symp->st_info) == STT_GNU_IFUNC)) {
1618 (c_linker_sym_t)
symp, &symval);
1636 if (
sym->st_shndx == SHN_FBSD_CACHED) {
1637 sym->st_shndx = SHN_UNDEF;
1667 if (
sym->st_shndx != SHN_UNDEF) {
1668 res1 = (Elf_Addr)
sym->st_value;
1669 if (ELF_ST_TYPE(
sym->st_info) == STT_GNU_IFUNC)
1670 res1 = ((Elf_Addr (*)(void))res1)();
1676 switch (ELF_ST_BIND(
sym->st_info)) {
1705 sym->st_shndx = SHN_FBSD_CACHED;
1706 sym->st_value = res1;
1709 }
else if (ELF_ST_BIND(
sym->st_info) == STB_WEAK) {
1724 static const char startn[] =
"__start_";
1725 static const char stopn[] =
"__stop_";
1727 const char *sym_name, *linkset_name;
1728 Elf_Addr startp, stopp;
1736 if (
sym->st_shndx != SHN_UNDEF)
1740 if (strncmp(sym_name, startn,
sizeof(startn) - 1) == 0) {
1742 linkset_name = sym_name +
sizeof(startn) - 1;
1744 else if (strncmp(sym_name, stopn,
sizeof(stopn) - 1) == 0) {
1746 linkset_name = sym_name +
sizeof(stopn) - 1;
1751 for (i = 0; i < ef->
nprogtab; i++) {
1752 if (strcmp(ef->
progtab[i].
name, linkset_name) == 0) {
1761 sym->st_value =
start ? startp : stopp;
1770 const Elf_Rel *rellim;
1772 const Elf_Rela *relalim;
1773 const Elf_Rela *rela;
1782 for (i = 0; i < ef->
nreltab; i++) {
1794 for ( ; rel < rellim; rel++) {
1795 symidx = ELF_R_SYM(rel->r_info);
1800 if (ELF_ST_BIND(
sym->st_info) != STB_LOCAL)
1802 if ((ELF_ST_TYPE(
sym->st_info) == STT_GNU_IFUNC ||
1803 elf_is_ifunc_reloc(rel->r_info)) != ifuncs)
1805 if (elf_reloc_local(lf, base, rel, ELF_RELOC_REL,
1812 for (i = 0; i < ef->
nrelatab; i++) {
1824 for ( ; rela < relalim; rela++) {
1825 symidx = ELF_R_SYM(rela->r_info);
1830 if (ELF_ST_BIND(
sym->st_info) != STB_LOCAL)
1832 if ((ELF_ST_TYPE(
sym->st_info) == STT_GNU_IFUNC ||
1833 elf_is_ifunc_reloc(rela->r_info)) != ifuncs)
1835 if (elf_reloc_local(lf, base, rela, ELF_RELOC_RELA,
device_property_type_t type
static int link_elf_ctf_get(linker_file_t lf, linker_ctf_t *lc)
int linker_ctf_get(linker_file_t file, linker_ctf_t *lc)
static int linker_debug_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
int linker_file_unload(linker_file_t file, int flags)
caddr_t linker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
static int linker_load_file(const char *filename, linker_file_t *result)
int linker_load_dependencies(linker_file_t lf)
linker_file_t linker_make_file(const char *pathname, linker_class_t lc)
int linker_add_class(linker_class_t lc)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
static void link_elf_invoke_cbs(caddr_t addr, size_t size)
static int link_elf_lookup_debug_symbol(linker_file_t, const char *, c_linker_sym_t *)
static int link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym, linker_symval_t *symval, bool see_local)
static void link_elf_init(void *arg)
static int link_elf_link_preload_finish(linker_file_t)
static kobj_method_t link_elf_methods[]
static int link_elf_search_symbol(linker_file_t, caddr_t value, c_linker_sym_t *sym, long *diffp)
static long link_elf_symtab_get(linker_file_t, const Elf_Sym **)
static int link_elf_debug_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t *)
static int link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t *)
static int link_elf_each_function_nameval(linker_file_t, linker_function_nameval_callback_t, void *)
static void elf_obj_cleanup_globals_cache(elf_file_t)
static int link_elf_each_function_name(linker_file_t, int(*)(const char *, void *), void *)
static int link_elf_lookup_symbol(linker_file_t, const char *, c_linker_sym_t *)
static long link_elf_strtab_get(linker_file_t, caddr_t *)
SYSINIT(link_elf_obj, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, NULL)
static void link_elf_unload_file(linker_file_t)
SYSCTL_BOOL(_debug, OID_AUTO, link_elf_obj_leak_locals, CTLFLAG_RWTUN, &link_elf_obj_leak_locals, 0, "Allow local symbols to participate in global module symbol resolution")
static struct linker_class link_elf_class
static int relocate_file1(elf_file_t ef, bool ifuncs)
static int relocate_file(elf_file_t ef)
static bool link_elf_obj_leak_locals
static Elf_Addr findbase(elf_file_t ef, int sec)
static void link_elf_protect(elf_file_t ef)
static void link_elf_fix_link_set(elf_file_t ef)
static const char * symbol_name(elf_file_t ef, Elf_Size r_info)
static int link_elf_lookup_symbol1(linker_file_t lf, const char *name, c_linker_sym_t *sym, bool see_local)
static int link_elf_reloc_local(linker_file_t, bool)
struct elf_file * elf_file_t
static int link_elf_link_preload(linker_class_t cls, const char *, linker_file_t *)
static void link_elf_protect_range(elf_file_t ef, vm_offset_t start, vm_offset_t end, vm_prot_t prot)
static int link_elf_load_file(linker_class_t, const char *, linker_file_t *)
static int link_elf_lookup_set(linker_file_t, const char *, void ***, void ***, int *)
static int elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps, Elf_Addr *)
static void link_elf_error(const char *filename, const char *s)
linker_function_name_callback_t callback
const Elf_Sym * ddbsymtab
caddr_t preload_search_info(caddr_t mod, int inf)
caddr_t preload_search_by_name(const char *name)
void preload_delete_name(const char *name)
void dpcpu_copy(void *s, int size)
void * dpcpu_alloc(int size)
void dpcpu_free(void *s, int size)
int printf(const char *fmt,...)
void() NDFREE(struct nameidata *ndp, const u_int flags)
int vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset, enum uio_seg segflg, int ioflg, struct ucred *active_cred, struct ucred *file_cred, ssize_t *aresid, struct thread *td)
int vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp)
int vn_close(struct vnode *vp, int flags, struct ucred *file_cred, struct thread *td)