diff --git a/usr.sbin/kldxref/Makefile b/usr.sbin/kldxref/Makefile --- a/usr.sbin/kldxref/Makefile +++ b/usr.sbin/kldxref/Makefile @@ -1,17 +1,12 @@ PACKAGE= runtime PROG= kldxref MAN= kldxref.8 -SRCS= kldxref.c ef.c ef_obj.c elf.c -SRCS+= ef_aarch64.c \ - ef_arm.c \ - ef_amd64.c \ - ef_i386.c \ - ef_mips.c \ - ef_powerpc.c \ - ef_riscv.c +SRCS= kldxref.c + +CFLAGS+=-I${SRCTOP}/lib/libkldelf WARNS?= 2 -LIBADD= elf +LIBADD= elf kldelf .include diff --git a/usr.sbin/kldxref/ef.h b/usr.sbin/kldxref/ef.h deleted file mode 100644 --- a/usr.sbin/kldxref/ef.h +++ /dev/null @@ -1,315 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2000, Boris Popov - * All rights reserved. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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 _EF_H_ -#define _EF_H_ - -#include -#include - -#define EF_CLOSE(ef) \ - (ef)->ef_ops->close((ef)->ef_ef) -#define EF_SEG_READ_REL(ef, address, len, dest) \ - (ef)->ef_ops->seg_read_rel((ef)->ef_ef, address, len, dest) -#define EF_SEG_READ_STRING(ef, address, len, dest) \ - (ef)->ef_ops->seg_read_string((ef)->ef_ef, address, len, dest) -#define EF_SYMADDR(ef, symidx) \ - (ef)->ef_ops->symaddr((ef)->ef_ef, symidx) -#define EF_LOOKUP_SET(ef, name, startp, stopp, countp) \ - (ef)->ef_ops->lookup_set((ef)->ef_ef, name, startp, stopp, countp) - -/* XXX, should have a different name. */ -typedef struct ef_file *elf_file_t; - -/* FreeBSD's headers define additional typedef's for ELF structures. */ -typedef Elf64_Size GElf_Size; -typedef Elf64_Hashelt GElf_Hashelt; - -struct elf_file; - -struct elf_file_ops { - void (*close)(elf_file_t ef); - int (*seg_read_rel)(elf_file_t ef, GElf_Addr address, size_t len, - void *dest); - int (*seg_read_string)(elf_file_t ef, GElf_Addr address, size_t len, - char *dest); - GElf_Addr (*symaddr)(elf_file_t ef, GElf_Size symidx); - int (*lookup_set)(elf_file_t ef, const char *name, GElf_Addr *startp, - GElf_Addr *stopp, long *countp); -}; - -typedef int (elf_reloc_t)(struct elf_file *ef, const void *reldata, - Elf_Type reltype, GElf_Addr relbase, GElf_Addr dataoff, size_t len, - void *dest); - -struct elf_reloc_data { - unsigned char class; - unsigned char data; - GElf_Half machine; - elf_reloc_t *reloc; -}; - -#define ELF_RELOC(_class, _data, _machine, _reloc) \ - static struct elf_reloc_data __CONCAT(elf_reloc_data_, __LINE__) = { \ - .class = (_class), \ - .data = (_data), \ - .machine = (_machine), \ - .reloc = (_reloc) \ - }; \ - DATA_SET(elf_reloc, __CONCAT(elf_reloc_data_, __LINE__)) - -struct elf_file { - elf_file_t ef_ef; - struct elf_file_ops *ef_ops; - const char *ef_filename; - Elf *ef_elf; - elf_reloc_t *ef_reloc; - GElf_Ehdr ef_hdr; - size_t ef_pointer_size; - int ef_fd; -}; - -#define elf_machine(ef) ((ef)->ef_hdr.e_machine) -#define elf_class(ef) ((ef)->ef_hdr.e_ident[EI_CLASS]) -#define elf_encoding(ef) ((ef)->ef_hdr.e_ident[EI_DATA]) - -/* - * "Generic" versions of module metadata structures. - */ -struct Gmod_depend { - int md_ver_minimum; - int md_ver_preferred; - int md_ver_maximum; -}; - -struct Gmod_version { - int mv_version; -}; - -struct Gmod_metadata { - int md_version; /* structure version MDTV_* */ - int md_type; /* type of entry MDT_* */ - GElf_Addr md_data; /* specific data */ - GElf_Addr md_cval; /* common string label */ -}; - -struct Gmod_pnp_match_info -{ - GElf_Addr descr; /* Description of the table */ - GElf_Addr bus; /* Name of the bus for this table */ - GElf_Addr table; /* Pointer to pnp table */ - int entry_len; /* Length of each entry in the table (may be */ - /* longer than descr describes). */ - int num_entry; /* Number of entries in the table */ -}; - -__BEGIN_DECLS - -/* - * Attempt to parse an open ELF file as either an executable or DSO - * (ef_open) or an object file (ef_obj_open). On success, these - * routines initialize the 'ef_ef' and 'ef_ops' members of 'ef'. - */ -int ef_open(struct elf_file *ef, int verbose); -int ef_obj_open(struct elf_file *ef, int verbose); - -/* - * Direct operations on an ELF file regardless of type. Many of these - * use libelf. - */ - -/* - * Open an ELF file with libelf. Populates fields other than ef_ef - * and ef_ops in '*efile'. - */ -int elf_open_file(struct elf_file *efile, const char *filename, - int verbose); - -/* Close an ELF file. */ -void elf_close_file(struct elf_file *efile); - -/* Is an ELF file the same architecture as hdr? */ -bool elf_compatible(struct elf_file *efile, const GElf_Ehdr *hdr); - -/* The size of a single object of 'type'. */ -size_t elf_object_size(struct elf_file *efile, Elf_Type type); - -/* The size of a pointer in architecture of 'efile'. */ -size_t elf_pointer_size(struct elf_file *efile); - -/* - * Read and convert an array of a data type from an ELF file. This is - * a wrapper around gelf_xlatetom() which reads an array of raw ELF - * objects from the file and converts them into host structures using - * native endianness. The data is returned in a dynamically-allocated - * buffer. - */ -int elf_read_data(struct elf_file *efile, Elf_Type type, off_t offset, - size_t len, void **out); - -/* Reads "raw" data from an ELF file without any translation. */ -int elf_read_raw_data(struct elf_file *efile, off_t offset, void *dst, - size_t len); - -/* - * A wrapper around elf_read_raw_data which returns the data in a - * dynamically-allocated buffer. - */ -int elf_read_raw_data_alloc(struct elf_file *efile, off_t offset, - size_t len, void **out); - -/* Reads a single string at the given offset from an ELF file. */ -int elf_read_raw_string(struct elf_file *efile, off_t offset, char *dst, - size_t len); - -/* - * Read relocated data from an ELF file and return it in a - * dynamically-allocated buffer. Note that no translation - * (byte-swapping for endianness, 32-vs-64) is performed on the - * returned data, but any ELF relocations which affect the contents - * are applied to the returned data. The address parameter gives the - * address of the data buffer if the ELF file were loaded into memory - * rather than a direct file offset. - */ -int elf_read_relocated_data(struct elf_file *efile, GElf_Addr address, - size_t len, void **buf); - -/* - * Read the program headers from an ELF file and return them in a - * dynamically-allocated array of GElf_Phdr objects. - */ -int elf_read_phdrs(struct elf_file *efile, size_t *nphdrp, - GElf_Phdr **phdrp); - -/* - * Read the section headers from an ELF file and return them in a - * dynamically-allocated array of GElf_Shdr objects. - */ -int elf_read_shdrs(struct elf_file *efile, size_t *nshdrp, - GElf_Shdr **shdrp); - -/* - * Read the dynamic table from a section of an ELF file into a - * dynamically-allocated array of GElf_Dyn objects. - */ -int elf_read_dynamic(struct elf_file *efile, int section_index, size_t *ndynp, - GElf_Dyn **dynp); - -/* - * Read a symbol table from a section of an ELF file into a - * dynamically-allocated array of GElf_Sym objects. - */ -int elf_read_symbols(struct elf_file *efile, int section_index, - size_t *nsymp, GElf_Sym **symp); - -/* - * Read a string table described by a section header of an ELF file - * into a dynamically-allocated buffer. - */ -int elf_read_string_table(struct elf_file *efile, const GElf_Shdr *shdr, - long *strcnt, char **strtab); - -/* - * Read a table of relocation objects from a section of an ELF file - * into a dynamically-allocated array of GElf_Rel objects. - */ -int elf_read_rel(struct elf_file *efile, int section_index, long *nrelp, - GElf_Rel **relp); - -/* - * Read a table of relocation-with-addend objects from a section of an - * ELF file into a dynamically-allocated array of GElf_Rela objects. - */ -int elf_read_rela(struct elf_file *efile, int section_index, long *nrelap, - GElf_Rela **relap); - -/* - * Read a string from an ELF file and return it in the provided - * buffer. If the string is longer than the buffer, this fails with - * EFAULT. The address parameter gives the address of the data buffer - * if the ELF file were loaded into memory rather than a direct file - * offset. - */ -int elf_read_string(struct elf_file *efile, GElf_Addr address, void *dst, - size_t len); - -/* Return the address extracted from a target pointer stored at 'p'. */ -GElf_Addr elf_address_from_pointer(struct elf_file *efile, const void *p); - -/* - * Read a linker set and return an array of addresses extracted from the - * relocated pointers in the linker set. - */ -int elf_read_linker_set(struct elf_file *efile, const char *name, - GElf_Addr **buf, long *countp); - -/* - * Read and convert a target 'struct mod_depend' into a host - * 'struct Gmod_depend'. - */ -int elf_read_mod_depend(struct elf_file *efile, GElf_Addr addr, - struct Gmod_depend *mdp); - -/* - * Read and convert a target 'struct mod_version' into a host - * 'struct Gmod_version'. - */ -int elf_read_mod_version(struct elf_file *efile, GElf_Addr addr, - struct Gmod_version *mdv); - -/* - * Read and convert a target 'struct mod_metadata' into a host - * 'struct Gmod_metadata'. - */ -int elf_read_mod_metadata(struct elf_file *efile, GElf_Addr addr, - struct Gmod_metadata *md); - -/* - * Read and convert a target 'struct mod_pnp_match_info' into a host - * 'struct Gmod_pnp_match_info'. - */ -int elf_read_mod_pnp_match_info(struct elf_file *efile, GElf_Addr addr, - struct Gmod_pnp_match_info *pnp); - -/* - * Apply relocations to the values obtained from the file. `relbase' is the - * target relocation address of the section, and `dataoff/len' is the region - * that is to be relocated, and has been copied to *dest - */ -int elf_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype, - GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest); - -__END_DECLS - -#endif /* _EF_H_*/ diff --git a/usr.sbin/kldxref/ef.c b/usr.sbin/kldxref/ef.c deleted file mode 100644 --- a/usr.sbin/kldxref/ef.c +++ /dev/null @@ -1,653 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2000, Boris Popov - * All rights reserved. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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. - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include "ef.h" - -#define MAXSEGS 16 -struct ef_file { - char *ef_name; - struct elf_file *ef_efile; - GElf_Phdr *ef_ph; - void *ef_fpage; /* First block of the file */ - int ef_fplen; /* length of first block */ - GElf_Hashelt ef_nbuckets; - GElf_Hashelt ef_nchains; - GElf_Hashelt *ef_buckets; - GElf_Hashelt *ef_chains; - GElf_Hashelt *ef_hashtab; - caddr_t ef_strtab; - long ef_strsz; - GElf_Sym *ef_symtab; - int ef_nsegs; - GElf_Phdr *ef_segs[MAXSEGS]; - int ef_verbose; - GElf_Rel *ef_rel; /* relocation table */ - long ef_relsz; /* number of entries */ - GElf_Rela *ef_rela; /* relocation table */ - long ef_relasz; /* number of entries */ -}; - -static void ef_print_phdr(GElf_Phdr *); -static GElf_Off ef_get_offset(elf_file_t, GElf_Addr); - -static void ef_close(elf_file_t ef); - -static int ef_seg_read_rel(elf_file_t ef, GElf_Addr address, size_t len, - void *dest); -static int ef_seg_read_string(elf_file_t ef, GElf_Addr address, size_t len, - char *dest); - -static GElf_Addr ef_symaddr(elf_file_t ef, GElf_Size symidx); -static int ef_lookup_set(elf_file_t ef, const char *name, - GElf_Addr *startp, GElf_Addr *stopp, long *countp); -static int ef_lookup_symbol(elf_file_t ef, const char *name, - GElf_Sym **sym); - -static struct elf_file_ops ef_file_ops = { - .close = ef_close, - .seg_read_rel = ef_seg_read_rel, - .seg_read_string = ef_seg_read_string, - .symaddr = ef_symaddr, - .lookup_set = ef_lookup_set, -}; - -static void -ef_print_phdr(GElf_Phdr *phdr) -{ - - if ((phdr->p_flags & PF_W) == 0) { - printf("text=0x%jx ", (uintmax_t)phdr->p_filesz); - } else { - printf("data=0x%jx", (uintmax_t)phdr->p_filesz); - if (phdr->p_filesz < phdr->p_memsz) - printf("+0x%jx", - (uintmax_t)(phdr->p_memsz - phdr->p_filesz)); - printf(" "); - } -} - -static GElf_Off -ef_get_offset(elf_file_t ef, GElf_Addr addr) -{ - GElf_Phdr *ph; - int i; - - for (i = 0; i < ef->ef_nsegs; i++) { - ph = ef->ef_segs[i]; - if (addr >= ph->p_vaddr && addr < ph->p_vaddr + ph->p_memsz) { - return (ph->p_offset + (addr - ph->p_vaddr)); - } - } - return (0); -} - -/* - * next two functions copied from link_elf.c - */ -static int -ef_lookup_symbol(elf_file_t ef, const char *name, GElf_Sym **sym) -{ - unsigned long hash, symnum; - GElf_Sym *symp; - char *strp; - - /* First, search hashed global symbols */ - hash = elf_hash(name); - symnum = ef->ef_buckets[hash % ef->ef_nbuckets]; - - while (symnum != STN_UNDEF) { - if (symnum >= ef->ef_nchains) { - warnx("ef_lookup_symbol: file %s have corrupted symbol table\n", - ef->ef_name); - return (ENOENT); - } - - symp = ef->ef_symtab + symnum; - if (symp->st_name == 0) { - warnx("ef_lookup_symbol: file %s have corrupted symbol table\n", - ef->ef_name); - return (ENOENT); - } - - strp = ef->ef_strtab + symp->st_name; - - if (strcmp(name, strp) == 0) { - if (symp->st_shndx != SHN_UNDEF || - (symp->st_value != 0 && - GELF_ST_TYPE(symp->st_info) == STT_FUNC)) { - *sym = symp; - return (0); - } else - return (ENOENT); - } - - symnum = ef->ef_chains[symnum]; - } - - return (ENOENT); -} - -static int -ef_lookup_set(elf_file_t ef, const char *name, GElf_Addr *startp, - GElf_Addr *stopp, long *countp) -{ - GElf_Sym *sym; - char *setsym; - int error, len; - - len = strlen(name) + sizeof("__start_set_"); /* sizeof includes \0 */ - setsym = malloc(len); - if (setsym == NULL) - return (errno); - - /* get address of first entry */ - snprintf(setsym, len, "%s%s", "__start_set_", name); - error = ef_lookup_symbol(ef, setsym, &sym); - if (error != 0) - goto out; - *startp = sym->st_value; - - /* get address of last entry */ - snprintf(setsym, len, "%s%s", "__stop_set_", name); - error = ef_lookup_symbol(ef, setsym, &sym); - if (error != 0) - goto out; - *stopp = sym->st_value; - - /* and the number of entries */ - *countp = (*stopp - *startp) / elf_pointer_size(ef->ef_efile); - -out: - free(setsym); - return (error); -} - -static GElf_Addr -ef_symaddr(elf_file_t ef, GElf_Size symidx) -{ - const GElf_Sym *sym; - - if (symidx >= ef->ef_nchains) - return (0); - sym = ef->ef_symtab + symidx; - - if (GELF_ST_BIND(sym->st_info) == STB_LOCAL && - sym->st_shndx != SHN_UNDEF && sym->st_value != 0) - return (sym->st_value); - return (0); -} - -static int -ef_parse_dynamic(elf_file_t ef, const GElf_Phdr *phdyn) -{ - GElf_Shdr *shdr; - GElf_Dyn *dyn, *dp; - size_t i, ndyn, nshdr, nsym; - int error; - GElf_Off hash_off, sym_off, str_off; - GElf_Off rel_off; - GElf_Off rela_off; - int rel_sz; - int rela_sz; - int dynamic_idx; - - /* - * The kernel linker parses the PT_DYNAMIC segment to find - * various important tables. The gelf API of libelf is - * section-oriented and requires extracting data from sections - * instead of segments (program headers). As a result, - * iterate over section headers to read various tables after - * parsing values from PT_DYNAMIC. - */ - error = elf_read_shdrs(ef->ef_efile, &nshdr, &shdr); - if (error != 0) - return (EFTYPE); - dyn = NULL; - - /* Find section for .dynamic. */ - dynamic_idx = -1; - for (i = 0; i < nshdr; i++) { - if (shdr[i].sh_type == SHT_DYNAMIC) { - /* - * PowerPC kernels contain additional sections - * beyond .dynamic in PT_DYNAMIC due to a linker - * script bug. Permit a section with a smaller - * size as a workaround. - */ - if (shdr[i].sh_offset != phdyn->p_offset || - ((elf_machine(ef->ef_efile) == EM_PPC || - elf_machine(ef->ef_efile) == EM_PPC64) ? - shdr[i].sh_size > phdyn->p_filesz : - shdr[i].sh_size != phdyn->p_filesz)) { - warnx(".dynamic section doesn't match phdr"); - error = EFTYPE; - goto out; - } - if (dynamic_idx != -1) { - warnx("multiple SHT_DYNAMIC sections"); - error = EFTYPE; - goto out; - } - dynamic_idx = i; - } - } - - error = elf_read_dynamic(ef->ef_efile, dynamic_idx, &ndyn, &dyn); - if (error != 0) - goto out; - - hash_off = rel_off = rela_off = sym_off = str_off = 0; - rel_sz = rela_sz = 0; - for (i = 0; i < ndyn; i++) { - dp = &dyn[i]; - if (dp->d_tag == DT_NULL) - break; - - switch (dp->d_tag) { - case DT_HASH: - if (hash_off != 0) - warnx("second DT_HASH entry ignored"); - else - hash_off = ef_get_offset(ef, dp->d_un.d_ptr); - break; - case DT_STRTAB: - if (str_off != 0) - warnx("second DT_STRTAB entry ignored"); - else - str_off = ef_get_offset(ef, dp->d_un.d_ptr); - break; - case DT_SYMTAB: - if (sym_off != 0) - warnx("second DT_SYMTAB entry ignored"); - else - sym_off = ef_get_offset(ef, dp->d_un.d_ptr); - break; - case DT_SYMENT: - if (dp->d_un.d_val != elf_object_size(ef->ef_efile, - ELF_T_SYM)) { - error = EFTYPE; - goto out; - } - break; - case DT_REL: - if (rel_off != 0) - warnx("second DT_REL entry ignored"); - else - rel_off = ef_get_offset(ef, dp->d_un.d_ptr); - break; - case DT_RELSZ: - if (rel_sz != 0) - warnx("second DT_RELSZ entry ignored"); - else - rel_sz = dp->d_un.d_val; - break; - case DT_RELENT: - if (dp->d_un.d_val != elf_object_size(ef->ef_efile, - ELF_T_REL)) { - error = EFTYPE; - goto out; - } - break; - case DT_RELA: - if (rela_off != 0) - warnx("second DT_RELA entry ignored"); - else - rela_off = ef_get_offset(ef, dp->d_un.d_ptr); - break; - case DT_RELASZ: - if (rela_sz != 0) - warnx("second DT_RELSZ entry ignored"); - else - rela_sz = dp->d_un.d_val; - break; - case DT_RELAENT: - if (dp->d_un.d_val != elf_object_size(ef->ef_efile, - ELF_T_RELA)) { - error = EFTYPE; - goto out; - } - break; - } - } - if (hash_off == 0) { - warnx("%s: no .hash section found\n", ef->ef_name); - error = EFTYPE; - goto out; - } - if (sym_off == 0) { - warnx("%s: no .dynsym section found\n", ef->ef_name); - error = EFTYPE; - goto out; - } - if (str_off == 0) { - warnx("%s: no .dynstr section found\n", ef->ef_name); - error = EFTYPE; - goto out; - } - if (rel_off == 0 && rela_off == 0) { - warnx("%s: no ELF relocation table found\n", ef->ef_name); - error = EFTYPE; - goto out; - } - - nsym = 0; - for (i = 0; i < nshdr; i++) { - switch (shdr[i].sh_type) { - case SHT_HASH: - if (shdr[i].sh_offset != hash_off) { - warnx("%s: ignoring SHT_HASH at different offset from DT_HASH", - ef->ef_name); - break; - } - - /* - * libelf(3) mentions ELF_T_HASH, but it is - * not defined. - */ - if (shdr[i].sh_size < sizeof(*ef->ef_hashtab) * 2) { - warnx("hash section too small"); - error = EFTYPE; - goto out; - } - error = elf_read_data(ef->ef_efile, ELF_T_WORD, - shdr[i].sh_offset, shdr[i].sh_size, - (void **)&ef->ef_hashtab); - if (error != 0) { - warnc(error, "can't read hash table"); - goto out; - } - ef->ef_nbuckets = ef->ef_hashtab[0]; - ef->ef_nchains = ef->ef_hashtab[1]; - if ((2 + ef->ef_nbuckets + ef->ef_nchains) * - sizeof(*ef->ef_hashtab) != shdr[i].sh_size) { - warnx("inconsistent hash section size"); - error = EFTYPE; - goto out; - } - - ef->ef_buckets = ef->ef_hashtab + 2; - ef->ef_chains = ef->ef_buckets + ef->ef_nbuckets; - break; - case SHT_DYNSYM: - if (shdr[i].sh_offset != sym_off) { - warnx("%s: ignoring SHT_DYNSYM at different offset from DT_SYMTAB", - ef->ef_name); - break; - } - error = elf_read_symbols(ef->ef_efile, i, &nsym, - &ef->ef_symtab); - if (error != 0) { - if (ef->ef_verbose) - warnx("%s: can't load .dynsym section (0x%jx)", - ef->ef_name, (uintmax_t)sym_off); - goto out; - } - break; - case SHT_STRTAB: - if (shdr[i].sh_offset != str_off) - break; - error = elf_read_string_table(ef->ef_efile, - &shdr[i], &ef->ef_strsz, &ef->ef_strtab); - if (error != 0) { - warnx("can't load .dynstr section"); - error = EIO; - goto out; - } - break; - case SHT_REL: - if (shdr[i].sh_offset != rel_off) - break; - if (shdr[i].sh_size != rel_sz) { - warnx("%s: size mismatch for DT_REL section", - ef->ef_name); - error = EFTYPE; - goto out; - } - error = elf_read_rel(ef->ef_efile, i, &ef->ef_relsz, - &ef->ef_rel); - if (error != 0) { - warnx("%s: cannot load DT_REL section", - ef->ef_name); - goto out; - } - break; - case SHT_RELA: - if (shdr[i].sh_offset != rela_off) - break; - if (shdr[i].sh_size != rela_sz) { - warnx("%s: size mismatch for DT_RELA section", - ef->ef_name); - error = EFTYPE; - goto out; - } - error = elf_read_rela(ef->ef_efile, i, &ef->ef_relasz, - &ef->ef_rela); - if (error != 0) { - warnx("%s: cannot load DT_RELA section", - ef->ef_name); - goto out; - } - break; - } - } - - if (ef->ef_hashtab == NULL) { - warnx("%s: did not find a symbol hash table", ef->ef_name); - error = EFTYPE; - goto out; - } - if (ef->ef_symtab == NULL) { - warnx("%s: did not find a dynamic symbol table", ef->ef_name); - error = EFTYPE; - goto out; - } - if (nsym != ef->ef_nchains) { - warnx("%s: symbol count mismatch", ef->ef_name); - error = EFTYPE; - goto out; - } - if (ef->ef_strtab == NULL) { - warnx("%s: did not find a dynamic string table", ef->ef_name); - error = EFTYPE; - goto out; - } - if (rel_off != 0 && ef->ef_rel == NULL) { - warnx("%s: did not find a DT_REL relocation table", - ef->ef_name); - error = EFTYPE; - goto out; - } - if (rela_off != 0 && ef->ef_rela == NULL) { - warnx("%s: did not find a DT_RELA relocation table", - ef->ef_name); - error = EFTYPE; - goto out; - } - - error = 0; -out: - free(dyn); - free(shdr); - return (error); -} - -static int -ef_seg_read_rel(elf_file_t ef, GElf_Addr address, size_t len, void *dest) -{ - GElf_Off ofs; - const GElf_Rela *a; - const GElf_Rel *r; - int error; - - ofs = ef_get_offset(ef, address); - if (ofs == 0) { - if (ef->ef_verbose) - warnx("ef_seg_read_rel(%s): bad address (%jx)", - ef->ef_name, (uintmax_t)address); - return (EFAULT); - } - error = elf_read_raw_data(ef->ef_efile, ofs, dest, len); - if (error != 0) - return (error); - - for (r = ef->ef_rel; r < &ef->ef_rel[ef->ef_relsz]; r++) { - error = elf_reloc(ef->ef_efile, r, ELF_T_REL, 0, address, - len, dest); - if (error != 0) - return (error); - } - for (a = ef->ef_rela; a < &ef->ef_rela[ef->ef_relasz]; a++) { - error = elf_reloc(ef->ef_efile, a, ELF_T_RELA, 0, address, - len, dest); - if (error != 0) - return (error); - } - return (0); -} - -static int -ef_seg_read_string(elf_file_t ef, GElf_Addr address, size_t len, char *dest) -{ - GElf_Off ofs; - - ofs = ef_get_offset(ef, address); - if (ofs == 0) { - if (ef->ef_verbose) - warnx("ef_seg_read_string(%s): bad offset (%jx:%ju)", - ef->ef_name, (uintmax_t)address, (uintmax_t)ofs); - return (EFAULT); - } - - return (elf_read_raw_string(ef->ef_efile, ofs, dest, len)); -} - -int -ef_open(struct elf_file *efile, int verbose) -{ - elf_file_t ef; - GElf_Ehdr *hdr; - size_t i, nphdr, nsegs; - int error; - GElf_Phdr *phdr, *phdyn; - - hdr = &efile->ef_hdr; - if (hdr->e_phnum == 0 || - hdr->e_phentsize != elf_object_size(efile, ELF_T_PHDR) || - hdr->e_shnum == 0 || hdr->e_shoff == 0 || - hdr->e_shentsize != elf_object_size(efile, ELF_T_SHDR)) - return (EFTYPE); - - ef = malloc(sizeof(*ef)); - if (ef == NULL) - return (errno); - - efile->ef_ef = ef; - efile->ef_ops = &ef_file_ops; - - bzero(ef, sizeof(*ef)); - ef->ef_verbose = verbose; - ef->ef_name = strdup(efile->ef_filename); - ef->ef_efile = efile; - - error = elf_read_phdrs(efile, &nphdr, &ef->ef_ph); - if (error != 0) { - phdr = NULL; - goto out; - } - - error = EFTYPE; - nsegs = 0; - phdyn = NULL; - phdr = ef->ef_ph; - for (i = 0; i < nphdr; i++, phdr++) { - if (verbose > 1) - ef_print_phdr(phdr); - switch (phdr->p_type) { - case PT_LOAD: - if (nsegs < MAXSEGS) - ef->ef_segs[nsegs] = phdr; - nsegs++; - break; - case PT_PHDR: - break; - case PT_DYNAMIC: - phdyn = phdr; - break; - } - } - if (verbose > 1) - printf("\n"); - if (phdyn == NULL) { - warnx("Skipping %s: not dynamically-linked", - ef->ef_name); - goto out; - } - - if (nsegs > MAXSEGS) { - warnx("%s: too many segments", ef->ef_name); - goto out; - } - ef->ef_nsegs = nsegs; - - error = ef_parse_dynamic(ef, phdyn); -out: - if (error != 0) - ef_close(ef); - return (error); -} - -static void -ef_close(elf_file_t ef) -{ - free(ef->ef_rela); - free(ef->ef_rel); - free(ef->ef_strtab); - free(ef->ef_symtab); - free(ef->ef_hashtab); - free(ef->ef_ph); - if (ef->ef_name) - free(ef->ef_name); - ef->ef_efile->ef_ops = NULL; - ef->ef_efile->ef_ef = NULL; - free(ef); -} diff --git a/usr.sbin/kldxref/ef_aarch64.c b/usr.sbin/kldxref/ef_aarch64.c deleted file mode 100644 --- a/usr.sbin/kldxref/ef_aarch64.c +++ /dev/null @@ -1,81 +0,0 @@ -/*- - * Copyright (c) 2005 Peter Grehan. - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * - * 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. - */ - -#include - -#include -#include -#include - -#include "ef.h" - -/* - * Apply relocations to the values obtained from the file. `relbase' is the - * target relocation address of the section, and `dataoff/len' is the region - * that is to be relocated, and has been copied to *dest - */ -static int -ef_aarch64_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype, - GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest) -{ - char *where; - GElf_Addr addr, addend; - GElf_Size rtype, symidx; - const GElf_Rela *rela; - - switch (reltype) { - case ELF_T_RELA: - rela = (const GElf_Rela *)reldata; - where = (char *)dest + (relbase + rela->r_offset - dataoff); - addend = rela->r_addend; - rtype = GELF_R_TYPE(rela->r_info); - symidx = GELF_R_SYM(rela->r_info); - break; - default: - return (EINVAL); - } - - if (where < (char *)dest || where >= (char *)dest + len) - return (0); - - switch (rtype) { - case R_AARCH64_RELATIVE: - addr = relbase + addend; - le64enc(where, addr); - break; - case R_AARCH64_ABS64: - addr = EF_SYMADDR(ef, symidx) + addend; - le64enc(where, addr); - break; - default: - warnx("unhandled relocation type %d", (int)rtype); - break; - } - return (0); -} - -ELF_RELOC(ELFCLASS64, ELFDATA2LSB, EM_AARCH64, ef_aarch64_reloc); diff --git a/usr.sbin/kldxref/ef_amd64.c b/usr.sbin/kldxref/ef_amd64.c deleted file mode 100644 --- a/usr.sbin/kldxref/ef_amd64.c +++ /dev/null @@ -1,113 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2003 Jake Burkholder. - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * - * 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. - */ - -#include - -#include -#include -#include - -#include "ef.h" - -/* - * Apply relocations to the values obtained from the file. `relbase' is the - * target relocation address of the section, and `dataoff/len' is the region - * that is to be relocated, and has been copied to *dest - */ -static int -ef_amd64_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype, - GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest) -{ - char *where; - GElf_Addr addr, addend; - GElf_Size rtype, symidx; - const GElf_Rel *rel; - const GElf_Rela *rela; - - switch (reltype) { - case ELF_T_REL: - rel = (const GElf_Rel *)reldata; - where = (char *)dest + (relbase + rel->r_offset - dataoff); - addend = 0; - rtype = GELF_R_TYPE(rel->r_info); - symidx = GELF_R_SYM(rel->r_info); - break; - case ELF_T_RELA: - rela = (const GElf_Rela *)reldata; - where = (char *)dest + (relbase + rela->r_offset - dataoff); - addend = rela->r_addend; - rtype = GELF_R_TYPE(rela->r_info); - symidx = GELF_R_SYM(rela->r_info); - break; - default: - return (EINVAL); - } - - if (where < (char *)dest || where >= (char *)dest + len) - return (0); - - if (reltype == ELF_T_REL) { - /* Addend is 32 bit on 32 bit relocs */ - switch (rtype) { - case R_X86_64_PC32: - case R_X86_64_32S: - addend = le32dec(where); - break; - default: - addend = le64dec(where); - break; - } - } - - switch (rtype) { - case R_X86_64_NONE: /* none */ - break; - case R_X86_64_64: /* S + A */ - addr = EF_SYMADDR(ef, symidx) + addend; - le64enc(where, addr); - break; - case R_X86_64_32S: /* S + A sign extend */ - addr = EF_SYMADDR(ef, symidx) + addend; - le32enc(where, addr); - break; - case R_X86_64_GLOB_DAT: /* S */ - addr = EF_SYMADDR(ef, symidx); - le64enc(where, addr); - break; - case R_X86_64_RELATIVE: /* B + A */ - addr = relbase + addend; - le64enc(where, addr); - break; - default: - warnx("unhandled relocation type %d", (int)rtype); - } - return (0); -} - -ELF_RELOC(ELFCLASS64, ELFDATA2LSB, EM_X86_64, ef_amd64_reloc); diff --git a/usr.sbin/kldxref/ef_arm.c b/usr.sbin/kldxref/ef_arm.c deleted file mode 100644 --- a/usr.sbin/kldxref/ef_arm.c +++ /dev/null @@ -1,94 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2003 Jake Burkholder. - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * Copyright (c) 2023 Jessica Clarke - * - * 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. - */ - -#include - -#include -#include -#include - -#include "ef.h" - -/* - * Apply relocations to the values obtained from the file. `relbase' is the - * target relocation address of the section, and `dataoff/len' is the region - * that is to be relocated, and has been copied to *dest - */ -static int -ef_arm_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype, - GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest) -{ - char *where; - GElf_Addr addr, addend; - GElf_Size rtype, symidx; - const GElf_Rel *rel; - const GElf_Rela *rela; - - switch (reltype) { - case ELF_T_REL: - rel = (const GElf_Rel *)reldata; - where = (char *)dest + (relbase + rel->r_offset - dataoff); - addend = 0; - rtype = GELF_R_TYPE(rel->r_info); - symidx = GELF_R_SYM(rel->r_info); - break; - case ELF_T_RELA: - rela = (const GElf_Rela *)reldata; - where = (char *)dest + (relbase + rela->r_offset - dataoff); - addend = rela->r_addend; - rtype = GELF_R_TYPE(rela->r_info); - symidx = GELF_R_SYM(rela->r_info); - break; - default: - return (EINVAL); - } - - if (where < (char *)dest || where >= (char *)dest + len) - return (0); - - if (reltype == ELF_T_REL) - addend = le32dec(where); - - switch (rtype) { - case R_ARM_ABS32: /* S + A */ - addr = EF_SYMADDR(ef, symidx) + addend; - le32enc(where, addr); - break; - case R_ARM_RELATIVE: /* B + A */ - addr = relbase + addend; - le32enc(where, addr); - break; - default: - warnx("unhandled relocation type %d", (int)rtype); - } - return (0); -} - -ELF_RELOC(ELFCLASS32, ELFDATA2LSB, EM_ARM, ef_arm_reloc); diff --git a/usr.sbin/kldxref/ef_i386.c b/usr.sbin/kldxref/ef_i386.c deleted file mode 100644 --- a/usr.sbin/kldxref/ef_i386.c +++ /dev/null @@ -1,97 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2003 Jake Burkholder. - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * - * 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. - */ - -#include - -#include -#include -#include - -#include "ef.h" - -/* - * Apply relocations to the values obtained from the file. `relbase' is the - * target relocation address of the section, and `dataoff/len' is the region - * that is to be relocated, and has been copied to *dest - */ -static int -ef_i386_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype, - GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest) -{ - char *where; - GElf_Addr addr, addend; - GElf_Size rtype, symidx; - const GElf_Rel *rel; - const GElf_Rela *rela; - - switch (reltype) { - case ELF_T_REL: - rel = (const GElf_Rel *)reldata; - where = (char *)dest + (relbase + rel->r_offset - dataoff); - addend = 0; - rtype = GELF_R_TYPE(rel->r_info); - symidx = GELF_R_SYM(rel->r_info); - break; - case ELF_T_RELA: - rela = (const GElf_Rela *)reldata; - where = (char *)dest + (relbase + rela->r_offset - dataoff); - addend = rela->r_addend; - rtype = GELF_R_TYPE(rela->r_info); - symidx = GELF_R_SYM(rela->r_info); - break; - default: - return (EINVAL); - } - - if (where < (char *)dest || where >= (char *)dest + len) - return (0); - - if (reltype == ELF_T_REL) - addend = le32dec(where); - - switch (rtype) { - case R_386_RELATIVE: /* B + A */ - addr = relbase + addend; - le32enc(where, addr); - break; - case R_386_32: /* S + A - P */ - addr = EF_SYMADDR(ef, symidx) + addend; - le32enc(where, addr); - break; - case R_386_GLOB_DAT: /* S */ - addr = EF_SYMADDR(ef, symidx); - le32enc(where, addr); - break; - default: - warnx("unhandled relocation type %d", (int)rtype); - } - return (0); -} - -ELF_RELOC(ELFCLASS32, ELFDATA2LSB, EM_386, ef_i386_reloc); diff --git a/usr.sbin/kldxref/ef_mips.c b/usr.sbin/kldxref/ef_mips.c deleted file mode 100644 --- a/usr.sbin/kldxref/ef_mips.c +++ /dev/null @@ -1,116 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 John Baldwin - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory (Department of Computer Science and - * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the - * DARPA SSITH research programme. - * - * 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. - */ - -#include - -#include -#include -#include - -#include "ef.h" - -/* - * Apply relocations to the values obtained from the file. `relbase' is the - * target relocation address of the section, and `dataoff/len' is the region - * that is to be relocated, and has been copied to *dest - */ -static int -ef_mips_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype, - GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest) -{ - char *where; - GElf_Addr addr, addend; - GElf_Size rtype, symidx; - const GElf_Rel *rel; - const GElf_Rela *rela; - - switch (reltype) { - case ELF_T_REL: - rel = (const GElf_Rel *)reldata; - where = (char *)dest + (relbase + rel->r_offset - dataoff); - addend = 0; - rtype = GELF_R_TYPE(rel->r_info); - symidx = GELF_R_SYM(rel->r_info); - break; - case ELF_T_RELA: - rela = (const GElf_Rela *)reldata; - where = (char *)dest + (relbase + rela->r_offset - dataoff); - addend = rela->r_addend; - rtype = GELF_R_TYPE(rela->r_info); - symidx = GELF_R_SYM(rela->r_info); - break; - default: - return (EINVAL); - } - - if (where < (char *)dest || where >= (char *)dest + len) - return (0); - - if (reltype == ELF_T_REL) { - if (elf_class(ef) == ELFCLASS64) { - if (elf_encoding(ef) == ELFDATA2LSB) - addend = le64dec(where); - else - addend = be64dec(where); - } else { - if (elf_encoding(ef) == ELFDATA2LSB) - addend = le32dec(where); - else - addend = be32dec(where); - } - } - - switch (rtype) { - case R_MIPS_64: /* S + A */ - addr = EF_SYMADDR(ef, symidx) + addend; - if (elf_encoding(ef) == ELFDATA2LSB) - le64enc(where, addr); - else - be64enc(where, addr); - break; - case R_MIPS_32: /* S + A */ - addr = EF_SYMADDR(ef, symidx) + addend; - if (elf_encoding(ef) == ELFDATA2LSB) - le32enc(where, addr); - else - be32enc(where, addr); - break; - default: - warnx("unhandled relocation type %d", (int)rtype); - } - return (0); -} - -ELF_RELOC(ELFCLASS32, ELFDATA2LSB, EM_MIPS, ef_mips_reloc); -ELF_RELOC(ELFCLASS32, ELFDATA2MSB, EM_MIPS, ef_mips_reloc); -ELF_RELOC(ELFCLASS64, ELFDATA2LSB, EM_MIPS, ef_mips_reloc); -ELF_RELOC(ELFCLASS64, ELFDATA2MSB, EM_MIPS, ef_mips_reloc); diff --git a/usr.sbin/kldxref/ef_obj.c b/usr.sbin/kldxref/ef_obj.c deleted file mode 100644 --- a/usr.sbin/kldxref/ef_obj.c +++ /dev/null @@ -1,469 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2000, Boris Popov - * Copyright (c) 1998-2000 Doug Rabson - * Copyright (c) 2004 Peter Wemm - * All rights reserved. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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. - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include "ef.h" - -typedef struct { - GElf_Addr addr; - GElf_Off offset; - GElf_Off size; - int flags; - int sec; /* Original section */ - char *name; -} Elf_progent; - -typedef struct { - GElf_Rel *rel; - long nrel; - int sec; -} Elf_relent; - -typedef struct { - GElf_Rela *rela; - long nrela; - int sec; -} Elf_relaent; - -struct ef_file { - char *ef_name; - struct elf_file *ef_efile; - - Elf_progent *progtab; - int nprogtab; - - Elf_relaent *relatab; - int nrela; - - Elf_relent *reltab; - int nrel; - - GElf_Sym *ddbsymtab; /* The symbol table we are using */ - size_t 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 */ - - int ef_verbose; -}; - -static void ef_obj_close(elf_file_t ef); - -static int ef_obj_seg_read_rel(elf_file_t ef, GElf_Addr address, - size_t len, void *dest); -static int ef_obj_seg_read_string(elf_file_t ef, GElf_Addr address, - size_t len, char *dest); - -static GElf_Addr ef_obj_symaddr(elf_file_t ef, GElf_Size symidx); -static int ef_obj_lookup_set(elf_file_t ef, const char *name, - GElf_Addr *startp, GElf_Addr *stopp, long *countp); -static int ef_obj_lookup_symbol(elf_file_t ef, const char *name, - GElf_Sym **sym); - -static struct elf_file_ops ef_obj_file_ops = { - .close = ef_obj_close, - .seg_read_rel = ef_obj_seg_read_rel, - .seg_read_string = ef_obj_seg_read_string, - .symaddr = ef_obj_symaddr, - .lookup_set = ef_obj_lookup_set, -}; - -static GElf_Off -ef_obj_get_offset(elf_file_t ef, GElf_Addr addr) -{ - Elf_progent *pt; - int i; - - for (i = 0; i < ef->nprogtab; i++) { - pt = &ef->progtab[i]; - if (pt->offset == (GElf_Off)-1) - continue; - if (addr >= pt->addr && addr < pt->addr + pt->size) - return (pt->offset + (addr - pt->addr)); - } - return (0); -} - -static int -ef_obj_lookup_symbol(elf_file_t ef, const char *name, GElf_Sym **sym) -{ - GElf_Sym *symp; - const char *strp; - int i; - - for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { - strp = ef->ddbstrtab + symp->st_name; - if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) { - *sym = symp; - return (0); - } - } - return (ENOENT); -} - -static int -ef_obj_lookup_set(elf_file_t ef, const char *name, GElf_Addr *startp, - GElf_Addr *stopp, long *countp) -{ - int i; - - for (i = 0; i < ef->nprogtab; i++) { - if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) && - strcmp(ef->progtab[i].name + 4, name) == 0) { - *startp = ef->progtab[i].addr; - *stopp = ef->progtab[i].addr + ef->progtab[i].size; - *countp = (*stopp - *startp) / - elf_pointer_size(ef->ef_efile); - return (0); - } - } - return (ESRCH); -} - -static GElf_Addr -ef_obj_symaddr(elf_file_t ef, GElf_Size symidx) -{ - const GElf_Sym *sym; - - if (symidx >= ef->ddbsymcnt) - return (0); - sym = ef->ddbsymtab + symidx; - - if (sym->st_shndx != SHN_UNDEF) - return (sym->st_value); - return (0); -} - -static int -ef_obj_seg_read_rel(elf_file_t ef, GElf_Addr address, size_t len, void *dest) -{ - GElf_Off secofs; - GElf_Rel *r; - GElf_Rela *a; - GElf_Addr secbase, dataoff; - int error, i, sec; - - /* Find out which section contains the data. */ - sec = -1; - for (i = 0; i < ef->nprogtab; i++) { - if (address < ef->progtab[i].addr) - continue; - - dataoff = address - ef->progtab[i].addr; - if (dataoff + len > ef->progtab[i].size) - continue; - - sec = ef->progtab[i].sec; - secbase = ef->progtab[i].addr; - secofs = ef->progtab[i].offset; - break; - } - - if (sec == -1) { - if (ef->ef_verbose) - warnx("ef_obj_seg_read_rel(%s): bad address (%jx)", - ef->ef_name, (uintmax_t)address); - return (EFAULT); - } - - if (secofs == (GElf_Off)-1) { - memset(dest, 0, len); - } else { - error = elf_read_raw_data(ef->ef_efile, secofs + dataoff, dest, - len); - if (error != 0) - return (error); - } - - /* Now do the relocations. */ - for (i = 0; i < ef->nrel; i++) { - if (ef->reltab[i].sec != sec) - continue; - for (r = ef->reltab[i].rel; - r < &ef->reltab[i].rel[ef->reltab[i].nrel]; r++) { - error = elf_reloc(ef->ef_efile, r, ELF_T_REL, secbase, - address, len, dest); - if (error != 0) - return (error); - } - } - for (i = 0; i < ef->nrela; i++) { - if (ef->relatab[i].sec != sec) - continue; - for (a = ef->relatab[i].rela; - a < &ef->relatab[i].rela[ef->relatab[i].nrela]; a++) { - error = elf_reloc(ef->ef_efile, a, ELF_T_RELA, secbase, - address, len, dest); - if (error != 0) - return (error); - } - } - return (0); -} - -static int -ef_obj_seg_read_string(elf_file_t ef, GElf_Addr address, size_t len, char *dest) -{ - GElf_Off ofs; - - ofs = ef_obj_get_offset(ef, address); - if (ofs == 0) { - if (ef->ef_verbose) - warnx("ef_obj_seg_read_string(%s): bad address (%jx)", - ef->ef_name, (uintmax_t)address); - return (EFAULT); - } - - return (elf_read_raw_string(ef->ef_efile, ofs, dest, len)); -} - -int -ef_obj_open(struct elf_file *efile, int verbose) -{ - elf_file_t ef; - GElf_Ehdr *hdr; - GElf_Shdr *shdr; - GElf_Sym *es; - GElf_Addr mapbase; - size_t i, nshdr; - int error, pb, ra, rl; - int j, nsym, symstrindex, symtabindex; - - hdr = &efile->ef_hdr; - if (hdr->e_type != ET_REL || hdr->e_shnum == 0 || hdr->e_shoff == 0 || - hdr->e_shentsize != elf_object_size(efile, ELF_T_SHDR)) - return (EFTYPE); - - ef = calloc(1, sizeof(*ef)); - if (ef == NULL) - return (errno); - - efile->ef_ef = ef; - efile->ef_ops = &ef_obj_file_ops; - - ef->ef_verbose = verbose; - ef->ef_name = strdup(efile->ef_filename); - ef->ef_efile = efile; - - error = elf_read_shdrs(efile, &nshdr, &shdr); - if (error != 0) { - shdr = NULL; - goto out; - } - - /* Scan the section headers for information and table sizing. */ - nsym = 0; - symtabindex = -1; - symstrindex = -1; - for (i = 0; i < nshdr; i++) { - switch (shdr[i].sh_type) { - case SHT_PROGBITS: - case SHT_NOBITS: - ef->nprogtab++; - break; - case SHT_SYMTAB: - nsym++; - symtabindex = i; - symstrindex = shdr[i].sh_link; - break; - case SHT_REL: - ef->nrel++; - break; - case SHT_RELA: - ef->nrela++; - break; - case SHT_STRTAB: - break; - } - } - - if (ef->nprogtab == 0) { - warnx("%s: file has no contents", ef->ef_name); - goto out; - } - if (nsym != 1) { - warnx("%s: file has no valid symbol table", ef->ef_name); - goto out; - } - if (symstrindex < 0 || symstrindex > nshdr || - shdr[symstrindex].sh_type != SHT_STRTAB) { - warnx("%s: file has invalid symbol strings", ef->ef_name); - goto out; - } - - /* Allocate space for tracking the load chunks */ - if (ef->nprogtab != 0) - ef->progtab = calloc(ef->nprogtab, sizeof(*ef->progtab)); - if (ef->nrel != 0) - ef->reltab = calloc(ef->nrel, sizeof(*ef->reltab)); - if (ef->nrela != 0) - ef->relatab = calloc(ef->nrela, sizeof(*ef->relatab)); - if ((ef->nprogtab != 0 && ef->progtab == NULL) || - (ef->nrel != 0 && ef->reltab == NULL) || - (ef->nrela != 0 && ef->relatab == NULL)) { - printf("malloc failed\n"); - error = ENOMEM; - goto out; - } - - if (elf_read_symbols(efile, symtabindex, &ef->ddbsymcnt, - &ef->ddbsymtab) != 0) { - printf("elf_read_symbols failed\n"); - goto out; - } - - if (elf_read_string_table(efile, &shdr[symstrindex], &ef->ddbstrcnt, - &ef->ddbstrtab) != 0) { - printf("elf_read_string_table failed\n"); - goto out; - } - - /* Do we have a string table for the section names? */ - if (hdr->e_shstrndx != 0 && - shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) { - if (elf_read_string_table(efile, &shdr[hdr->e_shstrndx], - &ef->shstrcnt, &ef->shstrtab) != 0) { - printf("elf_read_string_table failed\n"); - goto out; - } - } - - /* - * Now allocate address space for code/data(progbits) and - * bss(nobits) and allocate space for and load relocs. - */ - pb = 0; - rl = 0; - ra = 0; - mapbase = 0; - for (i = 0; i < nshdr; i++) { - switch (shdr[i].sh_type) { - case SHT_PROGBITS: - case SHT_NOBITS: - mapbase = roundup2(mapbase, shdr[i].sh_addralign); - ef->progtab[pb].addr = mapbase; - if (shdr[i].sh_type == SHT_PROGBITS) { - ef->progtab[pb].name = "<>"; - ef->progtab[pb].offset = shdr[i].sh_offset; - } else { - ef->progtab[pb].name = "<>"; - ef->progtab[pb].offset = (GElf_Off)-1; - } - ef->progtab[pb].size = shdr[i].sh_size; - ef->progtab[pb].sec = i; - if (ef->shstrtab && shdr[i].sh_name != 0) - ef->progtab[pb].name = - ef->shstrtab + shdr[i].sh_name; - - /* Update all symbol values with the offset. */ - for (j = 0; j < ef->ddbsymcnt; j++) { - es = &ef->ddbsymtab[j]; - if (es->st_shndx != i) - continue; - es->st_value += ef->progtab[pb].addr; - } - mapbase += shdr[i].sh_size; - pb++; - break; - case SHT_REL: - ef->reltab[rl].sec = shdr[i].sh_info; - if (elf_read_rel(efile, i, &ef->reltab[rl].nrel, - &ef->reltab[rl].rel) != 0) { - printf("elf_read_rel failed\n"); - goto out; - } - rl++; - break; - case SHT_RELA: - ef->relatab[ra].sec = shdr[i].sh_info; - if (elf_read_rela(efile, i, &ef->relatab[ra].nrela, - &ef->relatab[ra].rela) != 0) { - printf("elf_read_rela failed\n"); - goto out; - } - ra++; - break; - } - } - error = 0; -out: - free(shdr); - if (error != 0) - ef_obj_close(ef); - return (error); -} - -static void -ef_obj_close(elf_file_t ef) -{ - int i; - - if (ef->ef_name) - free(ef->ef_name); - if (ef->nprogtab != 0) - free(ef->progtab); - if (ef->nrel != 0) { - for (i = 0; i < ef->nrel; i++) - if (ef->reltab[i].rel != NULL) - free(ef->reltab[i].rel); - free(ef->reltab); - } - if (ef->nrela != 0) { - for (i = 0; i < ef->nrela; i++) - if (ef->relatab[i].rela != NULL) - free(ef->relatab[i].rela); - free(ef->relatab); - } - if (ef->ddbsymtab != NULL) - free(ef->ddbsymtab); - if (ef->ddbstrtab != NULL) - free(ef->ddbstrtab); - if (ef->shstrtab != NULL) - free(ef->shstrtab); - ef->ef_efile->ef_ops = NULL; - ef->ef_efile->ef_ef = NULL; - free(ef); -} diff --git a/usr.sbin/kldxref/ef_powerpc.c b/usr.sbin/kldxref/ef_powerpc.c deleted file mode 100644 --- a/usr.sbin/kldxref/ef_powerpc.c +++ /dev/null @@ -1,97 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2005 Peter Grehan. - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * - * 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. - */ - -#include - -#include -#include -#include - -#include "ef.h" - -/* - * Apply relocations to the values obtained from the file. `relbase' is the - * target relocation address of the section, and `dataoff/len' is the region - * that is to be relocated, and has been copied to *dest - */ -static int -ef_ppc_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype, - GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest) -{ - char *where; - GElf_Addr addr, addend; - GElf_Size rtype, symidx; - const GElf_Rela *rela; - - switch (reltype) { - case ELF_T_RELA: - rela = (const GElf_Rela *)reldata; - where = (char *)dest + (relbase + rela->r_offset - dataoff); - addend = rela->r_addend; - rtype = GELF_R_TYPE(rela->r_info); - symidx = GELF_R_SYM(rela->r_info); - break; - default: - return (EINVAL); - } - - if (where < (char *)dest || where >= (char *)dest + len) - return (0); - - switch (rtype) { - case R_PPC_RELATIVE: /* word32|doubleword64 B + A */ - addr = relbase + addend; - if (elf_class(ef) == ELFCLASS64) { - if (elf_encoding(ef) == ELFDATA2LSB) - le64enc(where, addr); - else - be64enc(where, addr); - } else - be32enc(where, addr); - break; - case R_PPC_ADDR32: /* word32 S + A */ - addr = EF_SYMADDR(ef, symidx) + addend; - be32enc(where, addr); - break; - case R_PPC64_ADDR64: /* doubleword64 S + A */ - addr = EF_SYMADDR(ef, symidx) + addend; - if (elf_encoding(ef) == ELFDATA2LSB) - le64enc(where, addr); - else - be64enc(where, addr); - break; - default: - warnx("unhandled relocation type %d", (int)rtype); - } - return (0); -} - -ELF_RELOC(ELFCLASS32, ELFDATA2MSB, EM_PPC, ef_ppc_reloc); -ELF_RELOC(ELFCLASS64, ELFDATA2LSB, EM_PPC64, ef_ppc_reloc); -ELF_RELOC(ELFCLASS64, ELFDATA2MSB, EM_PPC64, ef_ppc_reloc); diff --git a/usr.sbin/kldxref/ef_riscv.c b/usr.sbin/kldxref/ef_riscv.c deleted file mode 100644 --- a/usr.sbin/kldxref/ef_riscv.c +++ /dev/null @@ -1,85 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2018 John Baldwin - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory (Department of Computer Science and - * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the - * DARPA SSITH research programme. - * - * 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. - */ - -#include - -#include -#include -#include - -#include "ef.h" - -/* - * Apply relocations to the values obtained from the file. `relbase' is the - * target relocation address of the section, and `dataoff/len' is the region - * that is to be relocated, and has been copied to *dest - */ -static int -ef_riscv_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype, - GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest) -{ - char *where; - GElf_Addr addr, addend; - GElf_Size rtype, symidx; - const GElf_Rela *rela; - - switch (reltype) { - case ELF_T_RELA: - rela = (const GElf_Rela *)reldata; - where = (char *)dest + (relbase + rela->r_offset - dataoff); - addend = rela->r_addend; - rtype = GELF_R_TYPE(rela->r_info); - symidx = GELF_R_SYM(rela->r_info); - break; - default: - return (EINVAL); - } - - if (where < (char *)dest || where >= (char *)dest + len) - return (0); - - switch (rtype) { - case R_RISCV_64: /* S + A */ - addr = EF_SYMADDR(ef, symidx) + addend; - le64enc(where, addr); - break; - case R_RISCV_RELATIVE: /* B + A */ - addr = relbase + addend; - le64enc(where, addr); - break; - default: - warnx("unhandled relocation type %d", (int)rtype); - } - return (0); -} - -ELF_RELOC(ELFCLASS64, ELFDATA2LSB, EM_RISCV, ef_riscv_reloc); diff --git a/usr.sbin/kldxref/elf.c b/usr.sbin/kldxref/elf.c deleted file mode 100644 --- a/usr.sbin/kldxref/elf.c +++ /dev/null @@ -1,688 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2021-2023 John Baldwin - * - * This software was developed by SRI International and the University - * of Cambridge Computer Laboratory (Department of Computer Science - * and Technology) under Defense Advanced Research Projects Agency - * (DARPA) contract HR0011-18-C-0016 ("ECATS"), as part of the DARPA - * SSITH research programme and under DARPA Contract No. HR001123C0031 - * ("MTSS"). - * - * 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. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ef.h" - -SET_DECLARE(elf_reloc, struct elf_reloc_data); - -static elf_reloc_t * -elf_find_reloc(const GElf_Ehdr *hdr) -{ - struct elf_reloc_data **erd; - - SET_FOREACH(erd, elf_reloc) { - if (hdr->e_ident[EI_CLASS] == (*erd)->class && - hdr->e_ident[EI_DATA] == (*erd)->data && - hdr->e_machine == (*erd)->machine) - return ((*erd)->reloc); - } - return (NULL); -} - -int -elf_open_file(struct elf_file *efile, const char *filename, int verbose) -{ - int error; - - memset(efile, 0, sizeof(*efile)); - efile->ef_filename = filename; - efile->ef_fd = open(filename, O_RDONLY); - if (efile->ef_fd == -1) { - if (verbose) - warn("open(%s)", filename); - return (errno); - } - - efile->ef_elf = elf_begin(efile->ef_fd, ELF_C_READ, NULL); - if (efile->ef_elf == NULL) { - if (verbose) - warnx("elf_begin(%s): %s", filename, elf_errmsg(0)); - elf_close_file(efile); - return (EINVAL); - } - - if (elf_kind(efile->ef_elf) != ELF_K_ELF) { - if (verbose) - warnx("%s: not an ELF file", filename); - elf_close_file(efile); - return (EINVAL); - } - - if (gelf_getehdr(efile->ef_elf, &efile->ef_hdr) == NULL) { - if (verbose) - warnx("gelf_getehdr(%s): %s", filename, elf_errmsg(0)); - elf_close_file(efile); - return (EINVAL); - } - - efile->ef_reloc = elf_find_reloc(&efile->ef_hdr); - if (efile->ef_reloc == NULL) { - if (verbose) - warnx("%s: unsupported architecture", filename); - elf_close_file(efile); - return (EFTYPE); - } - - error = ef_open(efile, verbose); - if (error != 0) { - error = ef_obj_open(efile, verbose); - if (error != 0) { - if (verbose) - warnc(error, "%s: not a valid DSO or object file", - filename); - elf_close_file(efile); - return (error); - } - } - - efile->ef_pointer_size = elf_object_size(efile, ELF_T_ADDR); - - return (0); -} - -void -elf_close_file(struct elf_file *efile) -{ - if (efile->ef_ops != NULL) { - EF_CLOSE(efile); - } - if (efile->ef_elf != NULL) { - elf_end(efile->ef_elf); - efile->ef_elf = NULL; - } - if (efile->ef_fd > 0) { - close(efile->ef_fd); - efile->ef_fd = -1; - } -} - -bool -elf_compatible(struct elf_file *efile, const GElf_Ehdr *hdr) -{ - if (efile->ef_hdr.e_ident[EI_CLASS] != hdr->e_ident[EI_CLASS] || - efile->ef_hdr.e_ident[EI_DATA] != hdr->e_ident[EI_DATA] || - efile->ef_hdr.e_machine != hdr->e_machine) - return (false); - return (true); -} - -size_t -elf_object_size(struct elf_file *efile, Elf_Type type) -{ - return (gelf_fsize(efile->ef_elf, type, 1, efile->ef_hdr.e_version)); -} - -/* - * The number of objects of 'type' in region of the file of size - * 'file_size'. - */ -static size_t -elf_object_count(struct elf_file *efile, Elf_Type type, size_t file_size) -{ - return (file_size / elf_object_size(efile, type)); -} - -int -elf_read_raw_data(struct elf_file *efile, off_t offset, void *dst, size_t len) -{ - ssize_t nread; - - nread = pread(efile->ef_fd, dst, len, offset); - if (nread == -1) - return (errno); - if (nread != len) - return (EIO); - return (0); -} - -int -elf_read_raw_data_alloc(struct elf_file *efile, off_t offset, size_t len, - void **out) -{ - void *buf; - int error; - - buf = malloc(len); - if (buf == NULL) - return (ENOMEM); - error = elf_read_raw_data(efile, offset, buf, len); - if (error != 0) { - free(buf); - return (error); - } - *out = buf; - return (0); -} - -int -elf_read_raw_string(struct elf_file *efile, off_t offset, char *dst, size_t len) -{ - ssize_t nread; - - nread = pread(efile->ef_fd, dst, len, offset); - if (nread == -1) - return (errno); - if (nread == 0) - return (EIO); - - /* A short read is ok so long as the data contains a terminator. */ - if (strnlen(dst, nread) == nread) - return (EFAULT); - - return (0); -} - -int -elf_read_data(struct elf_file *efile, Elf_Type type, off_t offset, size_t len, - void **out) -{ - Elf_Data dst, src; - void *buf; - int error; - - buf = malloc(len); - if (buf == NULL) - return (ENOMEM); - - error = elf_read_raw_data(efile, offset, buf, len); - if (error != 0) { - free(buf); - return (error); - } - - memset(&dst, 0, sizeof(dst)); - memset(&src, 0, sizeof(src)); - - src.d_buf = buf; - src.d_size = len; - src.d_type = type; - src.d_version = efile->ef_hdr.e_version; - - dst.d_buf = buf; - dst.d_size = len; - dst.d_version = EV_CURRENT; - - if (gelf_xlatetom(efile->ef_elf, &dst, &src, elf_encoding(efile)) == - NULL) { - free(buf); - return (ENXIO); - } - - if (dst.d_size != len) - warnx("elf_read_data: translation of type %u size mismatch", - type); - - *out = buf; - return (0); -} - -int -elf_read_relocated_data(struct elf_file *efile, GElf_Addr address, size_t len, - void **buf) -{ - int error; - void *p; - - p = malloc(len); - if (p == NULL) - return (ENOMEM); - error = EF_SEG_READ_REL(efile, address, len, p); - if (error != 0) { - free(p); - return (error); - } - *buf = p; - return (0); -} - -int -elf_read_phdrs(struct elf_file *efile, size_t *nphdrp, GElf_Phdr **phdrp) -{ - GElf_Phdr *phdr; - size_t nphdr, i; - int error; - - if (elf_getphdrnum(efile->ef_elf, &nphdr) == -1) - return (EFTYPE); - - phdr = calloc(nphdr, sizeof(*phdr)); - if (phdr == NULL) - return (ENOMEM); - - for (i = 0; i < nphdr; i++) { - if (gelf_getphdr(efile->ef_elf, i, &phdr[i]) == NULL) { - error = EFTYPE; - goto out; - } - } - - *nphdrp = nphdr; - *phdrp = phdr; - return (0); -out: - free(phdr); - return (error); -} - -int -elf_read_shdrs(struct elf_file *efile, size_t *nshdrp, GElf_Shdr **shdrp) -{ - GElf_Shdr *shdr; - Elf_Scn *scn; - size_t nshdr, i; - int error; - - if (elf_getshdrnum(efile->ef_elf, &nshdr) == -1) - return (EFTYPE); - - shdr = calloc(nshdr, sizeof(*shdr)); - if (shdr == NULL) - return (ENOMEM); - - for (i = 0; i < nshdr; i++) { - scn = elf_getscn(efile->ef_elf, i); - if (scn == NULL) { - error = EFTYPE; - goto out; - } - if (gelf_getshdr(scn, &shdr[i]) == NULL) { - error = EFTYPE; - goto out; - } - } - - *nshdrp = nshdr; - *shdrp = shdr; - return (0); -out: - free(shdr); - return (error); -} - -int -elf_read_dynamic(struct elf_file *efile, int section_index, size_t *ndynp, - GElf_Dyn **dynp) -{ - GElf_Shdr shdr; - Elf_Scn *scn; - Elf_Data *data; - GElf_Dyn *dyn; - long i, ndyn; - - scn = elf_getscn(efile->ef_elf, section_index); - if (scn == NULL) - return (EINVAL); - if (gelf_getshdr(scn, &shdr) == NULL) - return (EINVAL); - data = elf_getdata(scn, NULL); - if (data == NULL) - return (EINVAL); - - ndyn = elf_object_count(efile, ELF_T_DYN, shdr.sh_size); - dyn = calloc(ndyn, sizeof(*dyn)); - if (dyn == NULL) - return (ENOMEM); - - for (i = 0; i < ndyn; i++) { - if (gelf_getdyn(data, i, &dyn[i]) == NULL) { - free(dyn); - return (EINVAL); - } - } - - *ndynp = ndyn; - *dynp = dyn; - return (0); -} - -int -elf_read_symbols(struct elf_file *efile, int section_index, size_t *nsymp, - GElf_Sym **symp) -{ - GElf_Shdr shdr; - Elf_Scn *scn; - Elf_Data *data; - GElf_Sym *sym; - size_t i, nsym; - - scn = elf_getscn(efile->ef_elf, section_index); - if (scn == NULL) - return (EINVAL); - if (gelf_getshdr(scn, &shdr) == NULL) - return (EINVAL); - data = elf_getdata(scn, NULL); - if (data == NULL) - return (EINVAL); - - nsym = elf_object_count(efile, ELF_T_SYM, shdr.sh_size); - sym = calloc(nsym, sizeof(*sym)); - if (sym == NULL) - return (ENOMEM); - - for (i = 0; i < nsym; i++) { - if (gelf_getsym(data, i, &sym[i]) == NULL) { - free(sym); - return (EINVAL); - } - } - - *nsymp = nsym; - *symp = sym; - return (0); -} - -int -elf_read_string_table(struct elf_file *efile, const GElf_Shdr *shdr, - long *strcnt, char **strtab) -{ - int error; - - if (shdr->sh_type != SHT_STRTAB) - return (EINVAL); - error = elf_read_raw_data_alloc(efile, shdr->sh_offset, shdr->sh_size, - (void **)strtab); - if (error != 0) - return (error); - *strcnt = shdr->sh_size; - return (0); -} - -int -elf_read_rel(struct elf_file *efile, int section_index, long *nrelp, - GElf_Rel **relp) -{ - GElf_Shdr shdr; - Elf_Scn *scn; - Elf_Data *data; - GElf_Rel *rel; - long i, nrel; - - scn = elf_getscn(efile->ef_elf, section_index); - if (scn == NULL) - return (EINVAL); - if (gelf_getshdr(scn, &shdr) == NULL) - return (EINVAL); - data = elf_getdata(scn, NULL); - if (data == NULL) - return (EINVAL); - - nrel = elf_object_count(efile, ELF_T_REL, shdr.sh_size); - rel = calloc(nrel, sizeof(*rel)); - if (rel == NULL) - return (ENOMEM); - - for (i = 0; i < nrel; i++) { - if (gelf_getrel(data, i, &rel[i]) == NULL) { - free(rel); - return (EINVAL); - } - } - - *nrelp = nrel; - *relp = rel; - return (0); -} - -int -elf_read_rela(struct elf_file *efile, int section_index, long *nrelap, - GElf_Rela **relap) -{ - GElf_Shdr shdr; - Elf_Scn *scn; - Elf_Data *data; - GElf_Rela *rela; - long i, nrela; - - scn = elf_getscn(efile->ef_elf, section_index); - if (scn == NULL) - return (EINVAL); - if (gelf_getshdr(scn, &shdr) == NULL) - return (EINVAL); - data = elf_getdata(scn, NULL); - if (data == NULL) - return (EINVAL); - - nrela = elf_object_count(efile, ELF_T_RELA, shdr.sh_size); - rela = calloc(nrela, sizeof(*rela)); - if (rela == NULL) - return (ENOMEM); - - for (i = 0; i < nrela; i++) { - if (gelf_getrela(data, i, &rela[i]) == NULL) { - free(rela); - return (EINVAL); - } - } - - *nrelap = nrela; - *relap = rela; - return (0); -} - -size_t -elf_pointer_size(struct elf_file *efile) -{ - return (efile->ef_pointer_size); -} - -int -elf_int(struct elf_file *efile, const void *p) -{ - if (elf_encoding(efile) == ELFDATA2LSB) - return (le32dec(p)); - else - return (be32dec(p)); -} - -GElf_Addr -elf_address_from_pointer(struct elf_file *efile, const void *p) -{ - switch (elf_class(efile)) { - case ELFCLASS32: - if (elf_encoding(efile) == ELFDATA2LSB) - return (le32dec(p)); - else - return (be32dec(p)); - case ELFCLASS64: - if (elf_encoding(efile) == ELFDATA2LSB) - return (le64dec(p)); - else - return (be64dec(p)); - default: - __unreachable(); - } -} - -int -elf_read_string(struct elf_file *efile, GElf_Addr address, void *dst, - size_t len) -{ - return (EF_SEG_READ_STRING(efile, address, len, dst)); -} - -int -elf_read_linker_set(struct elf_file *efile, const char *name, GElf_Addr **bufp, - long *countp) -{ - GElf_Addr *buf, start, stop; - char *p; - void *raw; - long i, count; - int error; - - error = EF_LOOKUP_SET(efile, name, &start, &stop, &count); - if (error != 0) - return (error); - - error = elf_read_relocated_data(efile, start, - count * elf_pointer_size(efile), &raw); - if (error != 0) - return (error); - - buf = calloc(count, sizeof(*buf)); - if (buf == NULL) { - free(raw); - return (ENOMEM); - } - - p = raw; - for (i = 0; i < count; i++) { - buf[i] = elf_address_from_pointer(efile, p); - p += elf_pointer_size(efile); - } - free(raw); - - *bufp = buf; - *countp = count; - return (0); -} - -int -elf_read_mod_depend(struct elf_file *efile, GElf_Addr addr, - struct Gmod_depend *mdp) -{ - int *p; - int error; - - error = elf_read_relocated_data(efile, addr, sizeof(int) * 3, - (void **)&p); - if (error != 0) - return (error); - - memset(mdp, 0, sizeof(*mdp)); - mdp->md_ver_minimum = elf_int(efile, p); - mdp->md_ver_preferred = elf_int(efile, p + 1); - mdp->md_ver_maximum = elf_int(efile, p + 2); - free(p); - return (0); -} - -int -elf_read_mod_version(struct elf_file *efile, GElf_Addr addr, - struct Gmod_version *mdv) -{ - int error, value; - - error = EF_SEG_READ_REL(efile, addr, sizeof(int), &value); - if (error != 0) - return (error); - - memset(mdv, 0, sizeof(*mdv)); - mdv->mv_version = elf_int(efile, &value); - return (0); -} - -int -elf_read_mod_metadata(struct elf_file *efile, GElf_Addr addr, - struct Gmod_metadata *md) -{ - char *p; - size_t len, offset, pointer_size; - int error; - - pointer_size = elf_pointer_size(efile); - len = 2 * sizeof(int); - len = roundup(len, pointer_size); - len += 2 * pointer_size; - - error = elf_read_relocated_data(efile, addr, len, (void **)&p); - if (error != 0) - return (error); - - memset(md, 0, sizeof(*md)); - offset = 0; - md->md_version = elf_int(efile, p + offset); - offset += sizeof(int); - md->md_type = elf_int(efile, p + offset); - offset += sizeof(int); - offset = roundup(offset, pointer_size); - md->md_data = elf_address_from_pointer(efile, p + offset); - offset += pointer_size; - md->md_cval = elf_address_from_pointer(efile, p + offset); - free(p); - return (0); -} - -int -elf_read_mod_pnp_match_info(struct elf_file *efile, GElf_Addr addr, - struct Gmod_pnp_match_info *pnp) -{ - char *p; - size_t len, offset, pointer_size; - int error; - - pointer_size = elf_pointer_size(efile); - len = 3 * pointer_size; - len = roundup(len, pointer_size); - len += 2 * sizeof(int); - - error = elf_read_relocated_data(efile, addr, len, (void **)&p); - if (error != 0) - return (error); - - memset(pnp, 0, sizeof(*pnp)); - offset = 0; - pnp->descr = elf_address_from_pointer(efile, p + offset); - offset += pointer_size; - pnp->bus = elf_address_from_pointer(efile, p + offset); - offset += pointer_size; - pnp->table = elf_address_from_pointer(efile, p + offset); - offset += pointer_size; - offset = roundup(offset, pointer_size); - pnp->entry_len = elf_int(efile, p + offset); - offset += sizeof(int); - pnp->num_entry = elf_int(efile, p + offset); - free(p); - return (0); -} - -int -elf_reloc(struct elf_file *efile, const void *reldata, Elf_Type reltype, - GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest) -{ - return (efile->ef_reloc(efile, reldata, reltype, relbase, dataoff, len, - dest)); -} diff --git a/usr.sbin/kldxref/kldxref.c b/usr.sbin/kldxref/kldxref.c --- a/usr.sbin/kldxref/kldxref.c +++ b/usr.sbin/kldxref/kldxref.c @@ -51,7 +51,7 @@ #include #include -#include "ef.h" +#include #define MAXRECSIZE (64 << 10) /* 64k */ #define check(val) if ((error = (val)) != 0) break