1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 2000, Boris Popov 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Boris Popov. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifndef _KLDELF_H_ 36 #define _KLDELF_H_ 37 38 #include <sys/linker_set.h> 39 #include <stdbool.h> 40 41 #define EF_CLOSE(ef) \ 42 (ef)->ef_ops->close((ef)->ef_ef) 43 #define EF_SEG_READ_REL(ef, address, len, dest) \ 44 (ef)->ef_ops->seg_read_rel((ef)->ef_ef, address, len, dest) 45 #define EF_SEG_READ_STRING(ef, address, len, dest) \ 46 (ef)->ef_ops->seg_read_string((ef)->ef_ef, address, len, dest) 47 #define EF_SYMADDR(ef, symidx) \ 48 (ef)->ef_ops->symaddr((ef)->ef_ef, symidx) 49 #define EF_LOOKUP_SET(ef, name, startp, stopp, countp) \ 50 (ef)->ef_ops->lookup_set((ef)->ef_ef, name, startp, stopp, countp) 51 #define EF_LOOKUP_SYMBOL(ef, name, sym) \ 52 (ef)->ef_ops->lookup_symbol((ef)->ef_ef, name, sym) 53 54 /* XXX, should have a different name. */ 55 typedef struct ef_file *elf_file_t; 56 57 /* FreeBSD's headers define additional typedef's for ELF structures. */ 58 typedef Elf64_Size GElf_Size; 59 typedef Elf64_Hashelt GElf_Hashelt; 60 61 struct elf_file; 62 63 struct elf_file_ops { 64 void (*close)(elf_file_t ef); 65 int (*seg_read_rel)(elf_file_t ef, GElf_Addr address, size_t len, 66 void *dest); 67 int (*seg_read_string)(elf_file_t ef, GElf_Addr address, size_t len, 68 char *dest); 69 GElf_Addr (*symaddr)(elf_file_t ef, GElf_Size symidx); 70 int (*lookup_set)(elf_file_t ef, const char *name, GElf_Addr *startp, 71 GElf_Addr *stopp, long *countp); 72 int (*lookup_symbol)(elf_file_t ef, const char *name, GElf_Sym **sym); 73 }; 74 75 typedef int (elf_reloc_t)(struct elf_file *ef, const void *reldata, 76 Elf_Type reltype, GElf_Addr relbase, GElf_Addr dataoff, size_t len, 77 void *dest); 78 79 struct elf_reloc_data { 80 unsigned char class; 81 unsigned char data; 82 GElf_Half machine; 83 elf_reloc_t *reloc; 84 }; 85 86 #define ELF_RELOC(_class, _data, _machine, _reloc) \ 87 static struct elf_reloc_data __CONCAT(elf_reloc_data_, __LINE__) = { \ 88 .class = (_class), \ 89 .data = (_data), \ 90 .machine = (_machine), \ 91 .reloc = (_reloc) \ 92 }; \ 93 DATA_SET(elf_reloc, __CONCAT(elf_reloc_data_, __LINE__)) 94 95 struct elf_file { 96 elf_file_t ef_ef; 97 struct elf_file_ops *ef_ops; 98 const char *ef_filename; 99 Elf *ef_elf; 100 elf_reloc_t *ef_reloc; 101 GElf_Ehdr ef_hdr; 102 size_t ef_pointer_size; 103 int ef_fd; 104 }; 105 106 #define elf_machine(ef) ((ef)->ef_hdr.e_machine) 107 #define elf_class(ef) ((ef)->ef_hdr.e_ident[EI_CLASS]) 108 #define elf_encoding(ef) ((ef)->ef_hdr.e_ident[EI_DATA]) 109 110 /* 111 * "Generic" versions of module metadata structures. 112 */ 113 struct Gmod_depend { 114 int md_ver_minimum; 115 int md_ver_preferred; 116 int md_ver_maximum; 117 }; 118 119 struct Gmod_version { 120 int mv_version; 121 }; 122 123 struct Gmod_metadata { 124 int md_version; /* structure version MDTV_* */ 125 int md_type; /* type of entry MDT_* */ 126 GElf_Addr md_data; /* specific data */ 127 GElf_Addr md_cval; /* common string label */ 128 }; 129 130 struct Gmod_pnp_match_info 131 { 132 GElf_Addr descr; /* Description of the table */ 133 GElf_Addr bus; /* Name of the bus for this table */ 134 GElf_Addr table; /* Pointer to pnp table */ 135 int entry_len; /* Length of each entry in the table (may be */ 136 /* longer than descr describes). */ 137 int num_entry; /* Number of entries in the table */ 138 }; 139 140 __BEGIN_DECLS 141 142 /* 143 * Attempt to parse an open ELF file as either an executable or DSO 144 * (ef_open) or an object file (ef_obj_open). On success, these 145 * routines initialize the 'ef_ef' and 'ef_ops' members of 'ef'. 146 */ 147 int ef_open(struct elf_file *ef, int verbose); 148 int ef_obj_open(struct elf_file *ef, int verbose); 149 150 /* 151 * Direct operations on an ELF file regardless of type. Many of these 152 * use libelf. 153 */ 154 155 /* 156 * Open an ELF file with libelf. Populates fields other than ef_ef 157 * and ef_ops in '*efile'. 158 */ 159 int elf_open_file(struct elf_file *efile, const char *filename, 160 int verbose); 161 162 /* Close an ELF file. */ 163 void elf_close_file(struct elf_file *efile); 164 165 /* Is an ELF file the same architecture as hdr? */ 166 bool elf_compatible(struct elf_file *efile, const GElf_Ehdr *hdr); 167 168 /* The size of a single object of 'type'. */ 169 size_t elf_object_size(struct elf_file *efile, Elf_Type type); 170 171 /* The size of a pointer in architecture of 'efile'. */ 172 size_t elf_pointer_size(struct elf_file *efile); 173 174 /* 175 * Read and convert an array of a data type from an ELF file. This is 176 * a wrapper around gelf_xlatetom() which reads an array of raw ELF 177 * objects from the file and converts them into host structures using 178 * native endianness. The data is returned in a dynamically-allocated 179 * buffer. 180 */ 181 int elf_read_data(struct elf_file *efile, Elf_Type type, off_t offset, 182 size_t len, void **out); 183 184 /* Reads "raw" data from an ELF file without any translation. */ 185 int elf_read_raw_data(struct elf_file *efile, off_t offset, void *dst, 186 size_t len); 187 188 /* 189 * A wrapper around elf_read_raw_data which returns the data in a 190 * dynamically-allocated buffer. 191 */ 192 int elf_read_raw_data_alloc(struct elf_file *efile, off_t offset, 193 size_t len, void **out); 194 195 /* Reads a single string at the given offset from an ELF file. */ 196 int elf_read_raw_string(struct elf_file *efile, off_t offset, char *dst, 197 size_t len); 198 199 /* 200 * Read relocated data from an ELF file and return it in a 201 * dynamically-allocated buffer. Note that no translation 202 * (byte-swapping for endianness, 32-vs-64) is performed on the 203 * returned data, but any ELF relocations which affect the contents 204 * are applied to the returned data. The address parameter gives the 205 * address of the data buffer if the ELF file were loaded into memory 206 * rather than a direct file offset. 207 */ 208 int elf_read_relocated_data(struct elf_file *efile, GElf_Addr address, 209 size_t len, void **buf); 210 211 /* 212 * Read the program headers from an ELF file and return them in a 213 * dynamically-allocated array of GElf_Phdr objects. 214 */ 215 int elf_read_phdrs(struct elf_file *efile, size_t *nphdrp, 216 GElf_Phdr **phdrp); 217 218 /* 219 * Read the section headers from an ELF file and return them in a 220 * dynamically-allocated array of GElf_Shdr objects. 221 */ 222 int elf_read_shdrs(struct elf_file *efile, size_t *nshdrp, 223 GElf_Shdr **shdrp); 224 225 /* 226 * Read the dynamic table from a section of an ELF file into a 227 * dynamically-allocated array of GElf_Dyn objects. 228 */ 229 int elf_read_dynamic(struct elf_file *efile, int section_index, size_t *ndynp, 230 GElf_Dyn **dynp); 231 232 /* 233 * Read a symbol table from a section of an ELF file into a 234 * dynamically-allocated array of GElf_Sym objects. 235 */ 236 int elf_read_symbols(struct elf_file *efile, int section_index, 237 size_t *nsymp, GElf_Sym **symp); 238 239 /* 240 * Read a string table described by a section header of an ELF file 241 * into a dynamically-allocated buffer. 242 */ 243 int elf_read_string_table(struct elf_file *efile, const GElf_Shdr *shdr, 244 long *strcnt, char **strtab); 245 246 /* 247 * Read a table of relocation objects from a section of an ELF file 248 * into a dynamically-allocated array of GElf_Rel objects. 249 */ 250 int elf_read_rel(struct elf_file *efile, int section_index, long *nrelp, 251 GElf_Rel **relp); 252 253 /* 254 * Read a table of relocation-with-addend objects from a section of an 255 * ELF file into a dynamically-allocated array of GElf_Rela objects. 256 */ 257 int elf_read_rela(struct elf_file *efile, int section_index, long *nrelap, 258 GElf_Rela **relap); 259 260 /* 261 * Read a string from an ELF file and return it in the provided 262 * buffer. If the string is longer than the buffer, this fails with 263 * EFAULT. The address parameter gives the address of the data buffer 264 * if the ELF file were loaded into memory rather than a direct file 265 * offset. 266 */ 267 int elf_read_string(struct elf_file *efile, GElf_Addr address, void *dst, 268 size_t len); 269 270 /* Return the address extracted from a target pointer stored at 'p'. */ 271 GElf_Addr elf_address_from_pointer(struct elf_file *efile, const void *p); 272 273 /* 274 * Read a linker set and return an array of addresses extracted from the 275 * relocated pointers in the linker set. 276 */ 277 int elf_read_linker_set(struct elf_file *efile, const char *name, 278 GElf_Addr **buf, long *countp); 279 280 /* 281 * Read and convert a target 'struct mod_depend' into a host 282 * 'struct Gmod_depend'. 283 */ 284 int elf_read_mod_depend(struct elf_file *efile, GElf_Addr addr, 285 struct Gmod_depend *mdp); 286 287 /* 288 * Read and convert a target 'struct mod_version' into a host 289 * 'struct Gmod_version'. 290 */ 291 int elf_read_mod_version(struct elf_file *efile, GElf_Addr addr, 292 struct Gmod_version *mdv); 293 294 /* 295 * Read and convert a target 'struct mod_metadata' into a host 296 * 'struct Gmod_metadata'. 297 */ 298 int elf_read_mod_metadata(struct elf_file *efile, GElf_Addr addr, 299 struct Gmod_metadata *md); 300 301 /* 302 * Read and convert a target 'struct mod_pnp_match_info' into a host 303 * 'struct Gmod_pnp_match_info'. 304 */ 305 int elf_read_mod_pnp_match_info(struct elf_file *efile, GElf_Addr addr, 306 struct Gmod_pnp_match_info *pnp); 307 308 /* 309 * Apply relocations to the values obtained from the file. `relbase' is the 310 * target relocation address of the section, and `dataoff/len' is the region 311 * that is to be relocated, and has been copied to *dest 312 */ 313 int elf_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype, 314 GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest); 315 316 /* 317 * Find the symbol with the specified symbol name 'name' within the given 318 * 'efile'. 0 is returned when such a symbol is found, otherwise ENOENT is 319 * returned. 320 * 321 * XXX: This only return the first symbol being found when traversing symtab. 322 */ 323 int elf_lookup_symbol(struct elf_file *efile, const char *name, 324 GElf_Sym **sym); 325 326 __END_DECLS 327 328 #endif /* _KLDELF_H_*/ 329