diff --git a/sys/kern/kern_ctf.c b/sys/kern/kern_ctf.c --- a/sys/kern/kern_ctf.c +++ b/sys/kern/kern_ctf.c @@ -80,10 +80,10 @@ /* We only need to load once. */ lc->ctftab = ef->ctftab; lc->ctfcnt = ef->ctfcnt; - lc->symtab = ef->ddbsymtab; - lc->strtab = ef->ddbstrtab; - lc->strcnt = ef->ddbstrcnt; - lc->nsym = ef->ddbsymcnt; + lc->symtab = ef->base.ddbsymtab; + lc->strtab = ef->base.ddbstrtab; + lc->strcnt = ef->base.ddbstrcnt; + lc->nsym = ef->base.ddbsymcnt; lc->ctfoffp = (uint32_t **) &ef->ctfoff; lc->typoffp = (uint32_t **) &ef->typoff; lc->typlenp = &ef->typlen; @@ -278,10 +278,10 @@ /* Let the caller use the CTF data read. */ lc->ctftab = ef->ctftab; lc->ctfcnt = ef->ctfcnt; - lc->symtab = ef->ddbsymtab; - lc->strtab = ef->ddbstrtab; - lc->strcnt = ef->ddbstrcnt; - lc->nsym = ef->ddbsymcnt; + lc->symtab = ef->base.ddbsymtab; + lc->strtab = ef->base.ddbstrtab; + lc->strcnt = ef->base.ddbstrcnt; + lc->nsym = ef->base.ddbsymcnt; lc->ctfoffp = (uint32_t **) &ef->ctfoff; lc->typoffp = (uint32_t **) &ef->typoff; lc->typlenp = &ef->typlen; diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -114,7 +114,7 @@ static int loadcnt; static linker_class_list_t classes; -static linker_file_list_t linker_files; +linker_file_list_t linker_files; static int next_file_id = 1; static int linker_no_more_classes = 0; diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -64,6 +64,7 @@ #include #include +#include #include #include "linker_if.h" @@ -75,9 +76,7 @@ #define MAXSEGS 4 typedef struct elf_file { - struct linker_file lf; /* Common fields */ - int preloaded; /* Was file pre-loaded */ - caddr_t address; /* Relocation address */ + struct elf_file_base base; /* Common fields */ #ifdef SPARSE_MAPPING vm_object_t object; /* VM object to hold file pages */ #endif @@ -89,7 +88,7 @@ caddr_t hash; caddr_t strtab; /* DT_STRTAB */ int strsz; /* DT_STRSZ */ - const Elf_Sym *symtab; /* DT_SYMTAB */ + Elf_Sym *symtab; /* DT_SYMTAB */ Elf_Addr *got; /* DT_PLTGOT */ const Elf_Rel *pltrel; /* DT_JMPREL */ int pltrelsize; /* DT_PLTRELSZ */ @@ -100,10 +99,6 @@ const Elf_Rela *rela; /* DT_RELA */ int relasize; /* DT_RELASZ */ caddr_t modptr; - const Elf_Sym *ddbsymtab; /* The symbol table we are using */ - long ddbsymcnt; /* Number of symbols */ - caddr_t ddbstrtab; /* String table */ - long ddbstrcnt; /* number of bytes in string table */ caddr_t symbase; /* malloc'ed symbold base */ caddr_t strbase; /* malloc'ed string base */ caddr_t ctftab; /* CTF table */ @@ -470,12 +465,13 @@ __func__); ef = (elf_file_t) linker_kernel_file; - ef->preloaded = 1; + ef->base.version = ELF_FILE_BASE_VERSION; + ef->base.preloaded = 1; #ifdef RELOCATABLE_KERNEL /* Compute relative displacement */ - ef->address = (caddr_t) (__startkernel - KERNBASE); + ef->base.address = (caddr_t) (__startkernel - KERNBASE); #else - ef->address = 0; + ef->base.address = 0; #endif #ifdef SPARSE_MAPPING ef->object = NULL; @@ -506,7 +502,7 @@ ctors_sizep = (Elf_Size *)preload_search_info(modptr, MODINFO_METADATA | MODINFOMD_CTORS_SIZE); if (ctors_addrp != NULL && ctors_sizep != NULL) { - linker_kernel_file->ctors_addr = ef->address + + linker_kernel_file->ctors_addr = ef->base.address + *ctors_addrp; linker_kernel_file->ctors_size = *ctors_sizep; } @@ -575,10 +571,10 @@ return (EINVAL); } - ef->ddbsymtab = symtab; - ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); - ef->ddbstrtab = strtab; - ef->ddbstrcnt = strcnt; + ef->base.ddbsymtab = symtab; + ef->base.ddbsymcnt = symcnt / sizeof(Elf_Sym); + ef->base.ddbstrtab = strtab; + ef->base.ddbstrcnt = strcnt; return (0); } @@ -595,7 +591,7 @@ { /* From src/libexec/rtld-elf/rtld.c */ const Elf_Hashelt *hashtab = (const Elf_Hashelt *) - (ef->address + dp->d_un.d_ptr); + (ef->base.address + dp->d_un.d_ptr); ef->nbuckets = hashtab[0]; ef->nchains = hashtab[1]; ef->buckets = hashtab + 2; @@ -603,23 +599,27 @@ break; } case DT_STRTAB: - ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr); + ef->strtab = (caddr_t) + (ef->base.address + dp->d_un.d_ptr); break; case DT_STRSZ: ef->strsz = dp->d_un.d_val; break; case DT_SYMTAB: - ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr); + ef->symtab = (Elf_Sym*) + (ef->base.address + dp->d_un.d_ptr); break; case DT_SYMENT: if (dp->d_un.d_val != sizeof(Elf_Sym)) return (ENOEXEC); break; case DT_PLTGOT: - ef->got = (Elf_Addr *) (ef->address + dp->d_un.d_ptr); + ef->got = (Elf_Addr *) + (ef->base.address + dp->d_un.d_ptr); break; case DT_REL: - ef->rel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr); + ef->rel = (const Elf_Rel *) + (ef->base.address + dp->d_un.d_ptr); break; case DT_RELSZ: ef->relsize = dp->d_un.d_val; @@ -629,13 +629,15 @@ return (ENOEXEC); break; case DT_JMPREL: - ef->pltrel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr); + ef->pltrel = (const Elf_Rel *) + (ef->base.address + dp->d_un.d_ptr); break; case DT_PLTRELSZ: ef->pltrelsize = dp->d_un.d_val; break; case DT_RELA: - ef->rela = (const Elf_Rela *) (ef->address + dp->d_un.d_ptr); + ef->rela = (const Elf_Rela *) + (ef->base.address + dp->d_un.d_ptr); break; case DT_RELASZ: ef->relasize = dp->d_un.d_val; @@ -664,12 +666,12 @@ ef->pltrelsize = 0; } - ef->ddbsymtab = ef->symtab; - ef->ddbsymcnt = ef->nchains; - ef->ddbstrtab = ef->strtab; - ef->ddbstrcnt = ef->strsz; + ef->base.ddbsymtab = ef->symtab; + ef->base.ddbsymcnt = ef->nchains; + ef->base.ddbstrtab = ef->strtab; + ef->base.ddbstrcnt = ef->strsz; - return elf_cpu_parse_dynamic(ef->address, ef->dynamic); + return elf_cpu_parse_dynamic(ef->base.address, ef->dynamic); } #define LS_PADDING 0x90909090 @@ -683,8 +685,8 @@ ef->pcpu_start = 0; ef->pcpu_stop = 0; - error = link_elf_lookup_set(&ef->lf, "pcpu", (void ***)&ef->pcpu_start, - (void ***)&ef->pcpu_stop, NULL); + error = link_elf_lookup_set(&ef->base.lf, "pcpu", + (void ***)&ef->pcpu_start, (void ***)&ef->pcpu_stop, NULL); /* Error just means there is no pcpu set to relocate. */ if (error != 0) return (0); @@ -696,7 +698,7 @@ /* In case we do find __start/stop_set_ symbols double-check. */ if (size < 4) { uprintf("Kernel module '%s' must be recompiled with " - "linker script\n", ef->lf.pathname); + "linker script\n", ef->base.lf.pathname); return (ENOEXEC); } @@ -705,7 +707,7 @@ if (pad != LS_PADDING) { uprintf("Kernel module '%s' must be recompiled with " "linker script, invalid padding %#04x (%#04x)\n", - ef->lf.pathname, pad, LS_PADDING); + ef->base.lf.pathname, pad, LS_PADDING); return (ENOEXEC); } /* If we only have valid padding, nothing to do. */ @@ -721,7 +723,7 @@ if (ef->pcpu_base == 0) { printf("%s: pcpu module space is out of space; " "cannot allocate %d for %s\n", - __func__, size, ef->lf.pathname); + __func__, size, ef->base.lf.pathname); return (ENOSPC); } memcpy((void *)ef->pcpu_base, (void *)ef->pcpu_start, size); @@ -744,7 +746,7 @@ ef->vnet_start = 0; ef->vnet_stop = 0; ef->vnet_base = 0; - error = link_elf_lookup_set(&ef->lf, "vnet", (void ***)&ef->vnet_start, + error = link_elf_lookup_set(&ef->base.lf, "vnet", (void ***)&ef->vnet_start, (void ***)&ef->vnet_stop, NULL); /* Error just means there is no vnet data set to relocate. */ if (error != 0) @@ -757,7 +759,7 @@ /* In case we do find __start/stop_set_ symbols double-check. */ if (size < 4) { uprintf("Kernel module '%s' must be recompiled with " - "linker script\n", ef->lf.pathname); + "linker script\n", ef->base.lf.pathname); return (ENOEXEC); } @@ -766,7 +768,7 @@ if (pad != LS_PADDING) { uprintf("Kernel module '%s' must be recompiled with " "linker script, invalid padding %#04x (%#04x)\n", - ef->lf.pathname, pad, LS_PADDING); + ef->base.lf.pathname, pad, LS_PADDING); return (ENOEXEC); } /* If we only have valid padding, nothing to do. */ @@ -782,7 +784,7 @@ if (ef->vnet_base == 0) { printf("%s: vnet module space is out of space; " "cannot allocate %d for %s\n", - __func__, size, ef->lf.pathname); + __func__, size, ef->base.lf.pathname); return (ENOSPC); } memcpy((void *)ef->vnet_base, (void *)ef->vnet_start, size); @@ -809,8 +811,8 @@ int error; error = 0; - hdr = (Elf_Ehdr *)ef->address; - phdr = (Elf_Phdr *)(ef->address + hdr->e_phoff); + hdr = (Elf_Ehdr *)ef->base.address; + phdr = (Elf_Phdr *)(ef->base.address + hdr->e_phoff); phlimit = phdr + hdr->e_phnum; for (; phdr < phlimit; phdr++) { if (phdr->p_type != PT_LOAD) @@ -821,7 +823,7 @@ nprot |= VM_PROT_WRITE; if ((phdr->p_flags & PF_X) != 0) nprot |= VM_PROT_EXECUTE; - error = pmap_change_prot((vm_offset_t)ef->address + + error = pmap_change_prot((vm_offset_t)ef->base.address + phdr->p_vaddr, round_page(phdr->p_memsz), nprot); if (error != 0) break; @@ -911,15 +913,16 @@ return (ENOMEM); ef = (elf_file_t) lf; - ef->preloaded = 1; + ef->base.version = ELF_FILE_BASE_VERSION; + ef->base.preloaded = 1; ef->modptr = modptr; - ef->address = *(caddr_t *)baseptr; + ef->base.address = *(caddr_t *)baseptr; #ifdef SPARSE_MAPPING ef->object = NULL; #endif - dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr; + dp = (vm_offset_t)ef->base.address + *(vm_offset_t *)dynptr; ef->dynamic = (Elf_Dyn *)dp; - lf->address = ef->address; + lf->address = ef->base.address; lf->size = *(size_t *)sizeptr; ctors_addrp = (Elf_Addr *)preload_search_info(modptr, @@ -927,7 +930,7 @@ ctors_sizep = (Elf_Size *)preload_search_info(modptr, MODINFO_METADATA | MODINFOMD_CTORS_SIZE); if (ctors_addrp != NULL && ctors_sizep != NULL) { - lf->ctors_addr = ef->address + *ctors_addrp; + lf->ctors_addr = ef->base.address + *ctors_addrp; lf->ctors_size = *ctors_sizep; } @@ -1138,6 +1141,7 @@ } ef = (elf_file_t) lf; + ef->base.version = ELF_FILE_BASE_VERSION; #ifdef SPARSE_MAPPING ef->object = vm_pager_allocate(OBJT_PHYS, NULL, mapsize, VM_PROT_ALL, 0, thread0.td_ucred); @@ -1164,7 +1168,7 @@ #else mapbase = malloc_exec(mapsize, M_LINKER, M_WAITOK); #endif - ef->address = mapbase; + ef->base.address = mapbase; /* * Read the text and data sections and zero the bss. @@ -1204,7 +1208,7 @@ ef->dynamic = (Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr); - lf->address = ef->address; + lf->address = ef->base.address; lf->size = mapsize; error = parse_dynamic(ef); @@ -1319,10 +1323,10 @@ if (error != 0) goto out; - ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); - ef->ddbsymtab = (const Elf_Sym *)ef->symbase; - ef->ddbstrcnt = strcnt; - ef->ddbstrtab = ef->strbase; + ef->base.ddbsymcnt = symcnt / sizeof(Elf_Sym); + ef->base.ddbsymtab = (Elf_Sym *)ef->symbase; + ef->base.ddbstrcnt = strcnt; + ef->base.ddbstrtab = ef->strbase; nosyms: @@ -1395,19 +1399,19 @@ /* Notify MD code that a module is being unloaded. */ elf_cpu_unload_file(file); - if (ef->preloaded) { + if (ef->base.preloaded) { link_elf_unload_preload(file); return; } #ifdef SPARSE_MAPPING if (ef->object != NULL) { - vm_map_remove(kernel_map, (vm_offset_t) ef->address, - (vm_offset_t) ef->address + vm_map_remove(kernel_map, (vm_offset_t) ef->base.address, + (vm_offset_t) ef->base.address + (ef->object->size << PAGE_SHIFT)); } #else - free(ef->address, M_LINKER); + free(ef->base.address, M_LINKER); #endif free(ef->symbase, M_LINKER); free(ef->strbase, M_LINKER); @@ -1464,7 +1468,7 @@ STT_GNU_IFUNC || \ elf_is_ifunc_reloc((iter)->r_info)) != ifuncs) \ continue; \ - if (reloc(&ef->lf, (Elf_Addr)ef->address, \ + if (reloc(&ef->base.lf, (Elf_Addr)ef->base.address, \ (iter), (type), lookup)) { \ symname = symbol_name(ef, (iter)->r_info); \ printf("link_elf: symbol %s undefined\n", \ @@ -1589,8 +1593,9 @@ if (link_elf_lookup_symbol1(lf, name, sym, true) == 0) return (0); - for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { - strp = ef->ddbstrtab + symp->st_name; + for (i = 0, symp = ef->base.ddbsymtab; i < ef->base.ddbsymcnt; + i++, symp++) { + strp = ef->base.ddbstrtab + symp->st_name; if (strcmp(name, strp) == 0) { if (symp->st_shndx != SHN_UNDEF || (symp->st_value != 0 && @@ -1648,7 +1653,7 @@ if (!see_local && ELF_ST_BIND(es->st_info) == STB_LOCAL) return (ENOENT); symval->name = ef->strtab + es->st_name; - val = (caddr_t)ef->address + es->st_value; + val = (caddr_t)ef->base.address + es->st_value; if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) val = ((caddr_t (*)(void))val)(); symval->value = val; @@ -1677,12 +1682,13 @@ if (link_elf_symbol_values1(lf, sym, symval, true) == 0) return (0); - if (ef->symtab == ef->ddbsymtab) + if (ef->symtab == ef->base.ddbsymtab) return (ENOENT); - if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) { - symval->name = ef->ddbstrtab + es->st_name; - val = (caddr_t)ef->address + es->st_value; + if (es >= ef->base.ddbsymtab && + es < (ef->base.ddbsymtab + ef->base.ddbsymcnt)) { + symval->name = ef->base.ddbstrtab + es->st_name; + val = (caddr_t)ef->base.address + es->st_value; if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) val = ((caddr_t (*)(void))val)(); symval->value = val; @@ -1704,10 +1710,10 @@ const Elf_Sym *best = NULL; int i; - for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) { + for (i = 0, es = ef->base.ddbsymtab; i < ef->base.ddbsymcnt; i++, es++) { if (es->st_name == 0) continue; - st_value = es->st_value + (uintptr_t) (void *) ef->address; + st_value = es->st_value + (uintptr_t) (void *) ef->base.address; if (off >= st_value) { if (off - st_value < diff) { diff = off - st_value; @@ -1793,11 +1799,13 @@ int i, error; /* Exhaustive search */ - for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { + for (i = 0, symp = ef->base.ddbsymtab; i < ef->base.ddbsymcnt; + i++, symp++) { if (symp->st_value != 0 && (ELF_ST_TYPE(symp->st_info) == STT_FUNC || ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC)) { - error = callback(ef->ddbstrtab + symp->st_name, opaque); + error = callback(ef->base.ddbstrtab + symp->st_name, + opaque); if (error != 0) return (error); } @@ -1815,7 +1823,8 @@ int i, error; /* Exhaustive search */ - for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { + for (i = 0, symp = ef->base.ddbsymtab; i < ef->base.ddbsymcnt; + i++, symp++) { if (symp->st_value != 0 && (ELF_ST_TYPE(symp->st_info) == STT_FUNC || ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC)) { @@ -1885,7 +1894,7 @@ *res = 0; return (EINVAL); } - *res = ((Elf_Addr)ef->address + sym->st_value); + *res = ((Elf_Addr)ef->base.address + sym->st_value); return (0); } @@ -1933,7 +1942,7 @@ if ((rel = ef->rel) != NULL) { rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize); while (rel < rellim) { - elf_reloc_local(lf, (Elf_Addr)ef->address, rel, + elf_reloc_local(lf, (Elf_Addr)ef->base.address, rel, ELF_RELOC_REL, elf_lookup); rel++; } @@ -1944,7 +1953,7 @@ relalim = (const Elf_Rela *) ((const char *)ef->rela + ef->relasize); while (rela < relalim) { - elf_reloc_local(lf, (Elf_Addr)ef->address, rela, + elf_reloc_local(lf, (Elf_Addr)ef->base.address, rela, ELF_RELOC_RELA, elf_lookup); rela++; } @@ -1956,12 +1965,12 @@ { elf_file_t ef = (elf_file_t)lf; - *symtab = ef->ddbsymtab; + *symtab = ef->base.ddbsymtab; if (*symtab == NULL) return (0); - return (ef->ddbsymcnt); + return (ef->base.ddbsymcnt); } static long @@ -1969,12 +1978,12 @@ { elf_file_t ef = (elf_file_t)lf; - *strtab = ef->ddbstrtab; + *strtab = ef->base.ddbstrtab; if (*strtab == NULL) return (0); - return (ef->ddbstrcnt); + return (ef->base.ddbstrcnt); } #ifdef VIMAGE @@ -2008,7 +2017,7 @@ 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; + val = (caddr_t)ef->base.address + symp->st_value; *res = ((Elf_Addr (*)(void))val)(); return (0); } @@ -2030,9 +2039,9 @@ ef->dynamic = (Elf_Dyn *)&_DYNAMIC; #ifdef RELOCATABLE_KERNEL - ef->address = (caddr_t) (__startkernel - KERNBASE); + ef->base.address = (caddr_t) (__startkernel - KERNBASE); #else - ef->address = 0; + ef->base.address = 0; #endif parse_dynamic(ef); diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -60,6 +60,7 @@ #include #include +#include #include #ifdef DDB_CTF @@ -89,10 +90,8 @@ } Elf_relaent; typedef struct elf_file { - struct linker_file lf; /* Common fields */ + struct elf_file_base base; /* Common fields */ - int preloaded; - caddr_t address; /* Relocation address */ vm_object_t object; /* VM object to hold file pages */ Elf_Shdr *e_shdr; @@ -105,11 +104,6 @@ Elf_relent *reltab; int nreltab; - Elf_Sym *ddbsymtab; /* The symbol table we are using */ - long ddbsymcnt; /* Number of symbols */ - caddr_t ddbstrtab; /* String table */ - long ddbstrcnt; /* number of bytes in string table */ - caddr_t shstrtab; /* Section name string table */ long shstrcnt; /* number of bytes in string table */ @@ -222,14 +216,14 @@ { int error __unused; - KASSERT(start <= end && start >= (vm_offset_t)ef->address && - end <= round_page((vm_offset_t)ef->address + ef->lf.size), + KASSERT(start <= end && start >= (vm_offset_t)ef->base.address && + end <= round_page((vm_offset_t)ef->base.address + ef->base.lf.size), ("link_elf_protect_range: invalid range %#jx-%#jx", (uintmax_t)start, (uintmax_t)end)); if (start == end) return; - if (ef->preloaded) { + if (ef->base.preloaded) { #ifdef __amd64__ error = pmap_change_prot(start, end - start, prot); KASSERT(error == 0, @@ -261,9 +255,9 @@ * page-aligned, but other preloaded data, such as entropy or CPU * microcode may be loaded with a smaller alignment. */ - gapprot = ef->preloaded ? VM_PROT_RW : VM_PROT_READ; + gapprot = ef->base.preloaded ? VM_PROT_RW : VM_PROT_READ; - start = end = (vm_offset_t)ef->address; + start = end = (vm_offset_t)ef->base.address; prot = VM_PROT_READ; for (i = 0; i < ef->nprogtab; i++) { /* @@ -336,7 +330,8 @@ */ link_elf_protect_range(ef, start, end, prot); link_elf_protect_range(ef, end, - round_page((vm_offset_t)ef->address + ef->lf.size), gapprot); + round_page((vm_offset_t)ef->base.address + ef->base.lf.size), + gapprot); } static int @@ -379,8 +374,10 @@ return (ENOMEM); ef = (elf_file_t)lf; - ef->preloaded = 1; - ef->address = *(caddr_t *)baseptr; + ef->base.version = ELF_FILE_BASE_VERSION; + ef->base.is_obj = true; + ef->base.preloaded = 1; + ef->base.address = *(caddr_t *)baseptr; lf->address = *(caddr_t *)baseptr; lf->size = *(size_t *)sizeptr; @@ -470,13 +467,13 @@ for (i = 0; i < hdr->e_shnum; i++) { if (shdr[i].sh_addr != 0) shdr[i].sh_addr = shdr[i].sh_addr - off + - (Elf_Addr)ef->address; + (Elf_Addr)ef->base.address; } - ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); - ef->ddbsymtab = (Elf_Sym *)shdr[symtabindex].sh_addr; - ef->ddbstrcnt = shdr[symstrindex].sh_size; - ef->ddbstrtab = (char *)shdr[symstrindex].sh_addr; + ef->base.ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); + ef->base.ddbsymtab = (Elf_Sym *)shdr[symtabindex].sh_addr; + ef->base.ddbstrcnt = shdr[symstrindex].sh_size; + ef->base.ddbstrtab = (char *)shdr[symstrindex].sh_addr; ef->shstrcnt = shdr[shstrindex].sh_size; ef->shstrtab = (char *)shdr[shstrindex].sh_addr; @@ -578,8 +575,8 @@ } /* Update all symbol values with the offset. */ - for (j = 0; j < ef->ddbsymcnt; j++) { - es = &ef->ddbsymtab[j]; + for (j = 0; j < ef->base.ddbsymcnt; j++) { + es = &ef->base.ddbsymtab[j]; if (es->st_shndx != i) continue; es->st_value += (Elf_Addr)ef->progtab[pb].addr; @@ -626,8 +623,9 @@ * relocations. Mapping protections are applied once relocation * processing is complete. */ - link_elf_protect_range(ef, (vm_offset_t)ef->address, - round_page((vm_offset_t)ef->address + ef->lf.size), VM_PROT_ALL); + link_elf_protect_range(ef, (vm_offset_t)ef->base.address, + round_page((vm_offset_t)ef->base.address + ef->base.lf.size), + VM_PROT_ALL); /* Local intra-module relocations */ error = link_elf_reloc_local(lf, false); @@ -806,6 +804,8 @@ goto out; } ef = (elf_file_t) lf; + ef->base.version = ELF_FILE_BASE_VERSION; + ef->base.is_obj = true; ef->nprogtab = 0; ef->e_shdr = 0; ef->nreltab = 0; @@ -908,9 +908,9 @@ goto out; } /* Allocate space for and load the symbol table */ - ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); - ef->ddbsymtab = malloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK); - error = vn_rdwr(UIO_READ, nd->ni_vp, (void *)ef->ddbsymtab, + ef->base.ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); + ef->base.ddbsymtab = malloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK); + error = vn_rdwr(UIO_READ, nd->ni_vp, ef->base.ddbsymtab, shdr[symtabindex].sh_size, shdr[symtabindex].sh_offset, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); @@ -922,9 +922,9 @@ } /* Allocate space for and load the symbol strings */ - ef->ddbstrcnt = shdr[symstrindex].sh_size; - ef->ddbstrtab = malloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK); - error = vn_rdwr(UIO_READ, nd->ni_vp, ef->ddbstrtab, + ef->base.ddbstrcnt = shdr[symstrindex].sh_size; + ef->base.ddbstrtab = malloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK); + error = vn_rdwr(UIO_READ, nd->ni_vp, ef->base.ddbstrtab, shdr[symstrindex].sh_size, shdr[symstrindex].sh_offset, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); @@ -1025,7 +1025,7 @@ } /* Inform the kld system about the situation */ - lf->address = ef->address = (caddr_t)mapbase; + lf->address = ef->base.address = (caddr_t)mapbase; lf->size = mapsize; /* @@ -1156,8 +1156,8 @@ ef->progtab[pb].size); #endif /* Update all symbol values with the offset. */ - for (j = 0; j < ef->ddbsymcnt; j++) { - es = &ef->ddbsymtab[j]; + for (j = 0; j < ef->base.ddbsymcnt; j++) { + es = &ef->base.ddbsymtab[j]; if (es->st_shndx != i) continue; es->st_value += (Elf_Addr)ef->progtab[pb].addr; @@ -1223,12 +1223,12 @@ error = ENOEXEC; goto out; } - if (mapbase != (vm_offset_t)ef->address + mapsize) { + if (mapbase != (vm_offset_t)ef->base.address + mapsize) { printf( "%s: mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n", filename != NULL ? filename : "", - (u_long)mapbase, ef->address, (u_long)mapsize, - (u_long)(vm_offset_t)ef->address + mapsize); + (u_long)mapbase, ef->base.address, (u_long)mapsize, + (u_long)(vm_offset_t)ef->base.address + mapsize); error = ENOMEM; goto out; } @@ -1304,7 +1304,7 @@ #endif } } - if (ef->preloaded) { + if (ef->base.preloaded) { free(ef->reltab, M_LINKER); free(ef->relatab, M_LINKER); free(ef->progtab, M_LINKER); @@ -1325,11 +1325,11 @@ free(ef->progtab, M_LINKER); if (ef->object != NULL) - vm_map_remove(kernel_map, (vm_offset_t)ef->address, - (vm_offset_t)ef->address + ptoa(ef->object->size)); + vm_map_remove(kernel_map, (vm_offset_t)ef->base.address, + (vm_offset_t)ef->base.address + ptoa(ef->object->size)); free(ef->e_shdr, M_LINKER); - free(ef->ddbsymtab, M_LINKER); - free(ef->ddbstrtab, M_LINKER); + free(ef->base.ddbsymtab, M_LINKER); + free(ef->base.ddbstrtab, M_LINKER); free(ef->shstrtab, M_LINKER); free(ef->ctftab, M_LINKER); free(ef->ctfoff, M_LINKER); @@ -1342,8 +1342,8 @@ const Elf_Sym *ref; if (ELF_R_SYM(r_info)) { - ref = ef->ddbsymtab + ELF_R_SYM(r_info); - return ef->ddbstrtab + ref->st_name; + ref = ef->base.ddbsymtab + ELF_R_SYM(r_info); + return ef->base.ddbstrtab + ref->st_name; } else return NULL; } @@ -1380,27 +1380,29 @@ for (i = 0; i < ef->nreltab; i++) { rel = ef->reltab[i].rel; if (rel == NULL) { - link_elf_error(ef->lf.filename, "lost a reltab!"); + link_elf_error(ef->base.lf.filename, + "lost a reltab!"); return (ENOEXEC); } rellim = rel + ef->reltab[i].nrel; base = findbase(ef, ef->reltab[i].sec); if (base == 0) { - link_elf_error(ef->lf.filename, "lost base for reltab"); + link_elf_error(ef->base.lf.filename, + "lost base for reltab"); return (ENOEXEC); } for ( ; rel < rellim; rel++) { symidx = ELF_R_SYM(rel->r_info); - if (symidx >= ef->ddbsymcnt) + if (symidx >= ef->base.ddbsymcnt) continue; - sym = ef->ddbsymtab + symidx; + sym = ef->base.ddbsymtab + symidx; /* Local relocs are already done */ if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) continue; if ((ELF_ST_TYPE(sym->st_info) == STT_GNU_IFUNC || elf_is_ifunc_reloc(rel->r_info)) != ifuncs) continue; - if (elf_reloc(&ef->lf, base, rel, ELF_RELOC_REL, + if (elf_reloc(&ef->base.lf, base, rel, ELF_RELOC_REL, elf_obj_lookup)) { symname = symbol_name(ef, rel->r_info); printf("link_elf_obj: symbol %s undefined\n", @@ -1414,28 +1416,28 @@ for (i = 0; i < ef->nrelatab; i++) { rela = ef->relatab[i].rela; if (rela == NULL) { - link_elf_error(ef->lf.filename, "lost a relatab!"); + link_elf_error(ef->base.lf.filename, "lost a relatab!"); return (ENOEXEC); } relalim = rela + ef->relatab[i].nrela; base = findbase(ef, ef->relatab[i].sec); if (base == 0) { - link_elf_error(ef->lf.filename, + link_elf_error(ef->base.lf.filename, "lost base for relatab"); return (ENOEXEC); } for ( ; rela < relalim; rela++) { symidx = ELF_R_SYM(rela->r_info); - if (symidx >= ef->ddbsymcnt) + if (symidx >= ef->base.ddbsymcnt) continue; - sym = ef->ddbsymtab + symidx; + sym = ef->base.ddbsymtab + symidx; /* Local relocs are already done */ if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) continue; if ((ELF_ST_TYPE(sym->st_info) == STT_GNU_IFUNC || elf_is_ifunc_reloc(rela->r_info)) != ifuncs) continue; - if (elf_reloc(&ef->lf, base, rela, ELF_RELOC_RELA, + if (elf_reloc(&ef->base.lf, base, rela, ELF_RELOC_RELA, elf_obj_lookup)) { symname = symbol_name(ef, rela->r_info); printf("link_elf_obj: symbol %s undefined\n", @@ -1475,8 +1477,9 @@ const char *strp; int i; - for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { - strp = ef->ddbstrtab + symp->st_name; + for (i = 0, symp = ef->base.ddbsymtab; i < ef->base.ddbsymcnt; + i++, symp++) { + strp = ef->base.ddbstrtab + symp->st_name; if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) { if (see_local || ELF_ST_BIND(symp->st_info) == STB_GLOBAL) { @@ -1524,10 +1527,11 @@ ef = (elf_file_t) lf; es = (const Elf_Sym*) sym; val = (caddr_t)es->st_value; - if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) { + if (es >= ef->base.ddbsymtab && + es < (ef->base.ddbsymtab + ef->base.ddbsymcnt)) { if (!see_local && ELF_ST_BIND(es->st_info) == STB_LOCAL) return (ENOENT); - symval->name = ef->ddbstrtab + es->st_name; + symval->name = ef->base.ddbstrtab + es->st_name; val = (caddr_t)es->st_value; if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) val = ((caddr_t (*)(void))val)(); @@ -1565,7 +1569,8 @@ const Elf_Sym *best = NULL; int i; - for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) { + for (i = 0, es = ef->base.ddbsymtab; i < ef->base.ddbsymcnt; + i++, es++) { if (es->st_name == 0) continue; st_value = es->st_value; @@ -1629,11 +1634,11 @@ int i, error; /* Exhaustive search */ - for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { + for (i = 0, symp = ef->base.ddbsymtab; i < ef->base.ddbsymcnt; i++, symp++) { if (symp->st_value != 0 && (ELF_ST_TYPE(symp->st_info) == STT_FUNC || ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC)) { - error = callback(ef->ddbstrtab + symp->st_name, opaque); + error = callback(ef->base.ddbstrtab + symp->st_name, opaque); if (error) return (error); } @@ -1651,7 +1656,7 @@ int i, error; /* Exhaustive search */ - for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { + for (i = 0, symp = ef->base.ddbsymtab; i < ef->base.ddbsymcnt; i++, symp++) { if (symp->st_value != 0 && (ELF_ST_TYPE(symp->st_info) == STT_FUNC || ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC)) { @@ -1672,8 +1677,8 @@ Elf_Sym *sym; Elf_Size i; - for (i = 0; i < ef->ddbsymcnt; i++) { - sym = ef->ddbsymtab + i; + for (i = 0; i < ef->base.ddbsymcnt; i++) { + sym = ef->base.ddbsymtab + i; if (sym->st_shndx == SHN_FBSD_CACHED) { sym->st_shndx = SHN_UNDEF; sym->st_value = 0; @@ -1697,12 +1702,12 @@ Elf_Addr res1; /* Don't even try to lookup the symbol if the index is bogus. */ - if (symidx >= ef->ddbsymcnt) { + if (symidx >= ef->base.ddbsymcnt) { *res = 0; return (EINVAL); } - sym = ef->ddbsymtab + symidx; + sym = ef->base.ddbsymtab + symidx; /* Quick answer if there is a definition included. */ if (sym->st_shndx != SHN_UNDEF) { @@ -1723,7 +1728,7 @@ case STB_GLOBAL: case STB_WEAK: /* Relative to Data or Function name */ - symbol = ef->ddbstrtab + sym->st_name; + symbol = ef->base.ddbstrtab + sym->st_name; /* Force a lookup failure if the symbol name is bogus. */ if (*symbol == 0) { @@ -1772,12 +1777,12 @@ startp = stopp = 0; for (symidx = 1 /* zero entry is special */; - symidx < ef->ddbsymcnt; symidx++) { - sym = ef->ddbsymtab + symidx; + symidx < ef->base.ddbsymcnt; symidx++) { + sym = ef->base.ddbsymtab + symidx; if (sym->st_shndx != SHN_UNDEF) continue; - sym_name = ef->ddbstrtab + sym->st_name; + sym_name = ef->base.ddbstrtab + sym->st_name; if (strncmp(sym_name, startn, sizeof(startn) - 1) == 0) { start = 1; linkset_name = sym_name + sizeof(startn) - 1; @@ -1823,20 +1828,20 @@ for (i = 0; i < ef->nreltab; i++) { rel = ef->reltab[i].rel; if (rel == NULL) { - link_elf_error(ef->lf.filename, "lost a reltab"); + link_elf_error(ef->base.lf.filename, "lost a reltab"); return (ENOEXEC); } rellim = rel + ef->reltab[i].nrel; base = findbase(ef, ef->reltab[i].sec); if (base == 0) { - link_elf_error(ef->lf.filename, "lost base for reltab"); + link_elf_error(ef->base.lf.filename, "lost base for reltab"); return (ENOEXEC); } for ( ; rel < rellim; rel++) { symidx = ELF_R_SYM(rel->r_info); - if (symidx >= ef->ddbsymcnt) + if (symidx >= ef->base.ddbsymcnt) continue; - sym = ef->ddbsymtab + symidx; + sym = ef->base.ddbsymtab + symidx; /* Only do local relocs */ if (ELF_ST_BIND(sym->st_info) != STB_LOCAL) continue; @@ -1853,20 +1858,20 @@ for (i = 0; i < ef->nrelatab; i++) { rela = ef->relatab[i].rela; if (rela == NULL) { - link_elf_error(ef->lf.filename, "lost a relatab!"); + link_elf_error(ef->base.lf.filename, "lost a relatab!"); return (ENOEXEC); } relalim = rela + ef->relatab[i].nrela; base = findbase(ef, ef->relatab[i].sec); if (base == 0) { - link_elf_error(ef->lf.filename, "lost base for reltab"); + link_elf_error(ef->base.lf.filename, "lost base for reltab"); return (ENOEXEC); } for ( ; rela < relalim; rela++) { symidx = ELF_R_SYM(rela->r_info); - if (symidx >= ef->ddbsymcnt) + if (symidx >= ef->base.ddbsymcnt) continue; - sym = ef->ddbsymtab + symidx; + sym = ef->base.ddbsymtab + symidx; /* Only do local relocs */ if (ELF_ST_BIND(sym->st_info) != STB_LOCAL) continue; @@ -1886,10 +1891,10 @@ { elf_file_t ef = (elf_file_t)lf; - *symtab = ef->ddbsymtab; + *symtab = ef->base.ddbsymtab; if (*symtab == NULL) return (0); - return (ef->ddbsymcnt); + return (ef->base.ddbsymcnt); } static long @@ -1897,10 +1902,10 @@ { elf_file_t ef = (elf_file_t)lf; - *strtab = ef->ddbstrtab; + *strtab = ef->base.ddbstrtab; if (*strtab == NULL) return (0); - return (ef->ddbstrcnt); + return (ef->base.ddbstrcnt); } #ifdef VIMAGE diff --git a/sys/sys/_linker_elf_file.h b/sys/sys/_linker_elf_file.h new file mode 100644 --- /dev/null +++ b/sys/sys/_linker_elf_file.h @@ -0,0 +1,52 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1998-2000 Doug Rabson + * Copyright (c) 2004 Peter Wemm + * All rights reserved. + * + * Copyright (c) 2024 Juniper Networks, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _SYS_LINKER_ELF_FILE_H_ +#define _SYS_LINKER_ELF_FILE_H_ + +#ifndef _KERNEL +#include +#endif + +typedef struct elf_file_base { + struct linker_file lf; /* Common fields */ + unsigned int version; /* sizeof(struct elf_file_base) */ + bool is_obj; /* Was relocable object file */ + int preloaded; /* Was file pre-loaded */ + caddr_t address; /* Relocation address */ + Elf_Sym *ddbsymtab; /* The symbol table we are using */ + long ddbsymcnt; /* Number of symbols */ + caddr_t ddbstrtab; /* String table */ + long ddbstrcnt; /* number of bytes in string table */ +} *elf_file_base_t; + +#define ELF_FILE_BASE_VERSION (sizeof(struct elf_file_base)) + +#endif diff --git a/sys/sys/linker.h b/sys/sys/linker.h --- a/sys/sys/linker.h +++ b/sys/sys/linker.h @@ -29,7 +29,7 @@ #ifndef _SYS_LINKER_H_ #define _SYS_LINKER_H_ -#ifdef _KERNEL +#if defined(_KERNEL) || defined(_WANT_LINKER) #include #include @@ -216,7 +216,7 @@ int linker_kldload_busy(int flags); void linker_kldload_unbusy(int flags); -#endif /* _KERNEL */ +#endif /* defined(_KERNEL) || defined(_WANT_LINKER) */ /* * Module information subtypes