1160383Snetchild/*- 2160383Snetchild * SPDX-License-Identifier: BSD-2-Clause 3172150Sariff * 4160383Snetchild * Copyright (c) 2021-2023 John Baldwin <jhb@FreeBSD.org> 5160383Snetchild * 6160383Snetchild * This software was developed by SRI International and the University 7160383Snetchild * of Cambridge Computer Laboratory (Department of Computer Science 8160383Snetchild * and Technology) under Defense Advanced Research Projects Agency 9160383Snetchild * (DARPA) contract HR0011-18-C-0016 ("ECATS"), as part of the DARPA 10160383Snetchild * SSITH research programme and under DARPA Contract No. HR001123C0031 11160383Snetchild * ("MTSS"). 12160383Snetchild * 13160383Snetchild * Redistribution and use in source and binary forms, with or without 14160383Snetchild * modification, are permitted provided that the following conditions 15160383Snetchild * are met: 16160383Snetchild * 1. Redistributions of source code must retain the above copyright 17160383Snetchild * notice, this list of conditions and the following disclaimer. 18160383Snetchild * 2. Redistributions in binary form must reproduce the above copyright 19160383Snetchild * notice, this list of conditions and the following disclaimer in the 20160383Snetchild * documentation and/or other materials provided with the distribution. 21160383Snetchild * 22160383Snetchild * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23160383Snetchild * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24160383Snetchild * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25160383Snetchild * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26160383Snetchild * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27160383Snetchild * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28160383Snetchild * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29160383Snetchild * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30160383Snetchild * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31160383Snetchild * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32160383Snetchild * SUCH DAMAGE. 33160383Snetchild */ 34160383Snetchild 35160383Snetchild#include <sys/param.h> 36160383Snetchild#include <sys/endian.h> 37160383Snetchild 38160383Snetchild#include <err.h> 39160383Snetchild#include <errno.h> 40160383Snetchild#include <fcntl.h> 41172150Sariff#include <gelf.h> 42160383Snetchild#include <libelf.h> 43160383Snetchild#include <stdlib.h> 44160383Snetchild#include <string.h> 45160383Snetchild#include <unistd.h> 46160383Snetchild 47160383Snetchild#include "ef.h" 48193640Sariff 49193640SariffSET_DECLARE(elf_reloc, struct elf_reloc_data); 50193640Sariff 51193640Sariffstatic elf_reloc_t * 52160383Snetchildelf_find_reloc(const GElf_Ehdr *hdr) 53160383Snetchild{ 54160383Snetchild struct elf_reloc_data **erd; 55160383Snetchild 56229981Spfg SET_FOREACH(erd, elf_reloc) { 57160383Snetchild if (hdr->e_ident[EI_CLASS] == (*erd)->class && 58160383Snetchild hdr->e_ident[EI_DATA] == (*erd)->data && 59160383Snetchild hdr->e_machine == (*erd)->machine) 60160383Snetchild return ((*erd)->reloc); 61160383Snetchild } 62160383Snetchild return (NULL); 63160383Snetchild} 64160383Snetchild 65160383Snetchildint 66160383Snetchildelf_open_file(struct elf_file *efile, const char *filename, int verbose) 67160383Snetchild{ 68160383Snetchild int error; 69160383Snetchild 70160383Snetchild memset(efile, 0, sizeof(*efile)); 71160383Snetchild efile->ef_filename = filename; 72160383Snetchild efile->ef_fd = open(filename, O_RDONLY); 73160383Snetchild if (efile->ef_fd == -1) { 74160383Snetchild if (verbose) 75160383Snetchild warn("open(%s)", filename); 76160383Snetchild return (errno); 77160383Snetchild } 78160383Snetchild 79160383Snetchild efile->ef_elf = elf_begin(efile->ef_fd, ELF_C_READ, NULL); 80160383Snetchild if (efile->ef_elf == NULL) { 81160383Snetchild if (verbose) 82160383Snetchild warnx("elf_begin(%s): %s", filename, elf_errmsg(0)); 83160383Snetchild elf_close_file(efile); 84160383Snetchild return (EINVAL); 85160383Snetchild } 86160383Snetchild 87160383Snetchild if (elf_kind(efile->ef_elf) != ELF_K_ELF) { 88160383Snetchild if (verbose) 89160383Snetchild warnx("%s: not an ELF file", filename); 90160383Snetchild elf_close_file(efile); 91160383Snetchild return (EINVAL); 92160383Snetchild } 93160383Snetchild 94160383Snetchild if (gelf_getehdr(efile->ef_elf, &efile->ef_hdr) == NULL) { 95160383Snetchild if (verbose) 96160383Snetchild warnx("gelf_getehdr(%s): %s", filename, elf_errmsg(0)); 97160383Snetchild elf_close_file(efile); 98160383Snetchild return (EINVAL); 99160383Snetchild } 100160383Snetchild 101160383Snetchild efile->ef_reloc = elf_find_reloc(&efile->ef_hdr); 102160383Snetchild if (efile->ef_reloc == NULL) { 103160383Snetchild if (verbose) 104160383Snetchild warnx("%s: unsupported architecture", filename); 105160383Snetchild elf_close_file(efile); 106160383Snetchild return (EFTYPE); 107160383Snetchild } 108160383Snetchild 109160383Snetchild error = ef_open(efile, verbose); 110160383Snetchild if (error != 0) { 111160383Snetchild error = ef_obj_open(efile, verbose); 112172150Sariff if (error != 0) { 113172150Sariff if (verbose) 114172150Sariff warnc(error, "%s: not a valid DSO or object file", 115160383Snetchild filename); 116160383Snetchild elf_close_file(efile); 117160383Snetchild return (error); 118160383Snetchild } 119160383Snetchild } 120160383Snetchild 121160383Snetchild efile->ef_pointer_size = elf_object_size(efile, ELF_T_ADDR); 122160383Snetchild 123160383Snetchild return (0); 124160383Snetchild} 125160383Snetchild 126160383Snetchildvoid 127160383Snetchildelf_close_file(struct elf_file *efile) 128160383Snetchild{ 129160383Snetchild if (efile->ef_ops != NULL) { 130160383Snetchild EF_CLOSE(efile); 131160383Snetchild } 132160383Snetchild if (efile->ef_elf != NULL) { 133160383Snetchild elf_end(efile->ef_elf); 134160383Snetchild efile->ef_elf = NULL; 135160383Snetchild } 136160383Snetchild if (efile->ef_fd > 0) { 137160383Snetchild close(efile->ef_fd); 138160383Snetchild efile->ef_fd = -1; 139160383Snetchild } 140160383Snetchild} 141160383Snetchild 142160383Snetchildbool 143160383Snetchildelf_compatible(struct elf_file *efile, const GElf_Ehdr *hdr) 144160383Snetchild{ 145160383Snetchild if (efile->ef_hdr.e_ident[EI_CLASS] != hdr->e_ident[EI_CLASS] || 146160383Snetchild efile->ef_hdr.e_ident[EI_DATA] != hdr->e_ident[EI_DATA] || 147160383Snetchild efile->ef_hdr.e_machine != hdr->e_machine) 148160383Snetchild return (false); 149160383Snetchild return (true); 150160383Snetchild} 151160383Snetchild 152160383Snetchildsize_t 153160383Snetchildelf_object_size(struct elf_file *efile, Elf_Type type) 154160383Snetchild{ 155160383Snetchild return (gelf_fsize(efile->ef_elf, type, 1, efile->ef_hdr.e_version)); 156160383Snetchild} 157160383Snetchild 158160383Snetchild/* 159160383Snetchild * The number of objects of 'type' in region of the file of size 160165833Snetchild * 'file_size'. 161230137Sjoel */ 162160383Snetchildstatic size_t 163160383Snetchildelf_object_count(struct elf_file *efile, Elf_Type type, size_t file_size) 164160383Snetchild{ 165160383Snetchild return (file_size / elf_object_size(efile, type)); 166160383Snetchild} 167160383Snetchild 168160383Snetchildint 169160383Snetchildelf_read_raw_data(struct elf_file *efile, off_t offset, void *dst, size_t len) 170160383Snetchild{ 171160383Snetchild ssize_t nread; 172160383Snetchild 173160383Snetchild nread = pread(efile->ef_fd, dst, len, offset); 174160383Snetchild if (nread == -1) 175160383Snetchild return (errno); 176160383Snetchild if (nread != len) 177160383Snetchild return (EIO); 178160383Snetchild return (0); 179160383Snetchild} 180160383Snetchild 181160383Snetchildint 182160383Snetchildelf_read_raw_data_alloc(struct elf_file *efile, off_t offset, size_t len, 183160383Snetchild void **out) 184160383Snetchild{ 185229981Spfg void *buf; 186160383Snetchild int error; 187160383Snetchild 188160383Snetchild buf = malloc(len); 189160383Snetchild if (buf == NULL) 190160383Snetchild return (ENOMEM); 191160383Snetchild error = elf_read_raw_data(efile, offset, buf, len); 192160383Snetchild if (error != 0) { 193160383Snetchild free(buf); 194160383Snetchild return (error); 195160383Snetchild } 196160383Snetchild *out = buf; 197160383Snetchild return (0); 198160383Snetchild} 199160383Snetchild 200160383Snetchildint 201160383Snetchildelf_read_raw_string(struct elf_file *efile, off_t offset, char *dst, size_t len) 202160383Snetchild{ 203160383Snetchild ssize_t nread; 204160383Snetchild 205160383Snetchild nread = pread(efile->ef_fd, dst, len, offset); 206160383Snetchild if (nread == -1) 207160383Snetchild return (errno); 208160383Snetchild if (nread == 0) 209160383Snetchild return (EIO); 210160383Snetchild 211160383Snetchild /* A short read is ok so long as the data contains a terminator. */ 212160383Snetchild if (strnlen(dst, nread) == nread) 213160383Snetchild return (EFAULT); 214160383Snetchild 215160383Snetchild return (0); 216160383Snetchild} 217160383Snetchild 218160383Snetchildint 219160383Snetchildelf_read_data(struct elf_file *efile, Elf_Type type, off_t offset, size_t len, 220160383Snetchild void **out) 221229981Spfg{ 222229981Spfg Elf_Data dst, src; 223229981Spfg void *buf; 224229981Spfg int error; 225229981Spfg 226160383Snetchild buf = malloc(len); 227229981Spfg if (buf == NULL) 228229981Spfg return (ENOMEM); 229229981Spfg 230229981Spfg error = elf_read_raw_data(efile, offset, buf, len); 231229981Spfg if (error != 0) { 232229981Spfg free(buf); 233229981Spfg return (error); 234229981Spfg } 235160383Snetchild 236160383Snetchild memset(&dst, 0, sizeof(dst)); 237160383Snetchild memset(&src, 0, sizeof(src)); 238160383Snetchild 239160383Snetchild src.d_buf = buf; 240160383Snetchild src.d_size = len; 241160383Snetchild src.d_type = type; 242160383Snetchild src.d_version = efile->ef_hdr.e_version; 243160383Snetchild 244160383Snetchild dst.d_buf = buf; 245160383Snetchild dst.d_size = len; 246160383Snetchild dst.d_version = EV_CURRENT; 247172150Sariff 248172150Sariff if (gelf_xlatetom(efile->ef_elf, &dst, &src, elf_encoding(efile)) == 249172150Sariff NULL) { 250165833Snetchild free(buf); 251160383Snetchild return (ENXIO); 252160383Snetchild } 253160383Snetchild 254160383Snetchild if (dst.d_size != len) 255160383Snetchild warnx("elf_read_data: translation of type %u size mismatch", 256161055Snetchild type); 257160383Snetchild 258160383Snetchild *out = buf; 259160383Snetchild return (0); 260160383Snetchild} 261160383Snetchild 262160383Snetchildint 263160383Snetchildelf_read_relocated_data(struct elf_file *efile, GElf_Addr address, size_t len, 264160383Snetchild void **buf) 265160383Snetchild{ 266172150Sariff int error; 267172150Sariff void *p; 268160383Snetchild 269160383Snetchild p = malloc(len); 270160383Snetchild if (p == NULL) 271160383Snetchild return (ENOMEM); 272160383Snetchild error = EF_SEG_READ_REL(efile, address, len, p); 273160383Snetchild if (error != 0) { 274160383Snetchild free(p); 275160383Snetchild return (error); 276160383Snetchild } 277160383Snetchild *buf = p; 278160383Snetchild return (0); 279161054Snetchild} 280160383Snetchild 281160383Snetchildint 282160383Snetchildelf_read_phdrs(struct elf_file *efile, size_t *nphdrp, GElf_Phdr **phdrp) 283160383Snetchild{ 284160383Snetchild GElf_Phdr *phdr; 285172150Sariff size_t nphdr, i; 286160383Snetchild int error; 287160383Snetchild 288160383Snetchild if (elf_getphdrnum(efile->ef_elf, &nphdr) == -1) 289160383Snetchild return (EFTYPE); 290160383Snetchild 291160383Snetchild phdr = calloc(nphdr, sizeof(*phdr)); 292160383Snetchild if (phdr == NULL) 293160383Snetchild return (ENOMEM); 294160383Snetchild 295160383Snetchild for (i = 0; i < nphdr; i++) { 296160383Snetchild if (gelf_getphdr(efile->ef_elf, i, &phdr[i]) == NULL) { 297160383Snetchild error = EFTYPE; 298160383Snetchild goto out; 299160383Snetchild } 300160383Snetchild } 301160383Snetchild 302160383Snetchild *nphdrp = nphdr; 303160383Snetchild *phdrp = phdr; 304160383Snetchild return (0); 305160383Snetchildout: 306160383Snetchild free(phdr); 307160383Snetchild return (error); 308160383Snetchild} 309160383Snetchild 310160383Snetchildint 311160383Snetchildelf_read_shdrs(struct elf_file *efile, size_t *nshdrp, GElf_Shdr **shdrp) 312165833Snetchild{ 313160383Snetchild GElf_Shdr *shdr; 314160383Snetchild Elf_Scn *scn; 315160383Snetchild size_t nshdr, i; 316160383Snetchild int error; 317160383Snetchild 318160383Snetchild if (elf_getshdrnum(efile->ef_elf, &nshdr) == -1) 319160383Snetchild return (EFTYPE); 320160383Snetchild 321160383Snetchild shdr = calloc(nshdr, sizeof(*shdr)); 322160383Snetchild if (shdr == NULL) 323160383Snetchild return (ENOMEM); 324160383Snetchild 325160383Snetchild for (i = 0; i < nshdr; i++) { 326160383Snetchild scn = elf_getscn(efile->ef_elf, i); 327160383Snetchild if (scn == NULL) { 328160383Snetchild error = EFTYPE; 329160383Snetchild goto out; 330160383Snetchild } 331160383Snetchild if (gelf_getshdr(scn, &shdr[i]) == NULL) { 332160383Snetchild error = EFTYPE; 333160383Snetchild goto out; 334160383Snetchild } 335160383Snetchild } 336172150Sariff 337160383Snetchild *nshdrp = nshdr; 338160383Snetchild *shdrp = shdr; 339160383Snetchild return (0); 340160383Snetchildout: 341160383Snetchild free(shdr); 342160383Snetchild return (error); 343160383Snetchild} 344160383Snetchild 345160383Snetchildint 346160383Snetchildelf_read_dynamic(struct elf_file *efile, int section_index, size_t *ndynp, 347160383Snetchild GElf_Dyn **dynp) 348160383Snetchild{ 349160383Snetchild GElf_Shdr shdr; 350160383Snetchild Elf_Scn *scn; 351172150Sariff Elf_Data *data; 352160383Snetchild GElf_Dyn *dyn; 353160383Snetchild long i, ndyn; 354172150Sariff 355172150Sariff scn = elf_getscn(efile->ef_elf, section_index); 356160383Snetchild if (scn == NULL) 357160383Snetchild return (EINVAL); 358160383Snetchild if (gelf_getshdr(scn, &shdr) == NULL) 359160383Snetchild return (EINVAL); 360160383Snetchild data = elf_getdata(scn, NULL); 361160383Snetchild if (data == NULL) 362160383Snetchild return (EINVAL); 363160383Snetchild 364160383Snetchild ndyn = elf_object_count(efile, ELF_T_DYN, shdr.sh_size); 365160383Snetchild dyn = calloc(ndyn, sizeof(*dyn)); 366160383Snetchild if (dyn == NULL) 367160383Snetchild return (ENOMEM); 368160383Snetchild 369160383Snetchild for (i = 0; i < ndyn; i++) { 370160383Snetchild if (gelf_getdyn(data, i, &dyn[i]) == NULL) { 371160383Snetchild free(dyn); 372160383Snetchild return (EINVAL); 373172150Sariff } 374172150Sariff } 375160383Snetchild 376160383Snetchild *ndynp = ndyn; 377160383Snetchild *dynp = dyn; 378160383Snetchild return (0); 379160383Snetchild} 380160383Snetchild 381160383Snetchildint 382160383Snetchildelf_read_symbols(struct elf_file *efile, int section_index, size_t *nsymp, 383160383Snetchild GElf_Sym **symp) 384160383Snetchild{ 385160383Snetchild GElf_Shdr shdr; 386160383Snetchild Elf_Scn *scn; 387160383Snetchild Elf_Data *data; 388160383Snetchild GElf_Sym *sym; 389160383Snetchild size_t i, nsym; 390160383Snetchild 391160383Snetchild scn = elf_getscn(efile->ef_elf, section_index); 392160383Snetchild if (scn == NULL) 393160383Snetchild return (EINVAL); 394160383Snetchild if (gelf_getshdr(scn, &shdr) == NULL) 395160383Snetchild return (EINVAL); 396160383Snetchild data = elf_getdata(scn, NULL); 397160383Snetchild if (data == NULL) 398160383Snetchild return (EINVAL); 399160383Snetchild 400160383Snetchild nsym = elf_object_count(efile, ELF_T_SYM, shdr.sh_size); 401165833Snetchild sym = calloc(nsym, sizeof(*sym)); 402160383Snetchild if (sym == NULL) 403160383Snetchild return (ENOMEM); 404160383Snetchild 405160383Snetchild for (i = 0; i < nsym; i++) { 406160383Snetchild if (gelf_getsym(data, i, &sym[i]) == NULL) { 407160383Snetchild free(sym); 408160383Snetchild return (EINVAL); 409160383Snetchild } 410160383Snetchild } 411160383Snetchild 412160383Snetchild *nsymp = nsym; 413160383Snetchild *symp = sym; 414166919Sariff return (0); 415160383Snetchild} 416160383Snetchild 417160383Snetchildint 418160383Snetchildelf_read_string_table(struct elf_file *efile, const GElf_Shdr *shdr, 419160383Snetchild long *strcnt, char **strtab) 420160383Snetchild{ 421160383Snetchild int error; 422160383Snetchild 423160383Snetchild if (shdr->sh_type != SHT_STRTAB) 424160383Snetchild return (EINVAL); 425160383Snetchild error = elf_read_raw_data_alloc(efile, shdr->sh_offset, shdr->sh_size, 426172150Sariff (void **)strtab); 427172150Sariff if (error != 0) 428172150Sariff return (error); 429172150Sariff *strcnt = shdr->sh_size; 430172150Sariff return (0); 431172150Sariff} 432172150Sariff 433172150Sariffint 434172150Sariffelf_read_rel(struct elf_file *efile, int section_index, long *nrelp, 435172150Sariff GElf_Rel **relp) 436172150Sariff{ 437172150Sariff GElf_Shdr shdr; 438172150Sariff Elf_Scn *scn; 439172150Sariff Elf_Data *data; 440172150Sariff GElf_Rel *rel; 441172150Sariff long i, nrel; 442172150Sariff 443172150Sariff scn = elf_getscn(efile->ef_elf, section_index); 444172150Sariff if (scn == NULL) 445172150Sariff return (EINVAL); 446172150Sariff if (gelf_getshdr(scn, &shdr) == NULL) 447172150Sariff return (EINVAL); 448172150Sariff data = elf_getdata(scn, NULL); 449172150Sariff if (data == NULL) 450172150Sariff return (EINVAL); 451172150Sariff 452172150Sariff nrel = elf_object_count(efile, ELF_T_REL, shdr.sh_size); 453172150Sariff rel = calloc(nrel, sizeof(*rel)); 454172150Sariff if (rel == NULL) 455160383Snetchild return (ENOMEM); 456160383Snetchild 457160383Snetchild for (i = 0; i < nrel; i++) { 458160383Snetchild if (gelf_getrel(data, i, &rel[i]) == NULL) { 459160383Snetchild free(rel); 460160383Snetchild return (EINVAL); 461160383Snetchild } 462160383Snetchild } 463160383Snetchild 464160383Snetchild *nrelp = nrel; 465160383Snetchild *relp = rel; 466160383Snetchild return (0); 467165833Snetchild} 468160383Snetchild 469160383Snetchildint 470160383Snetchildelf_read_rela(struct elf_file *efile, int section_index, long *nrelap, 471160383Snetchild GElf_Rela **relap) 472160383Snetchild{ 473160383Snetchild GElf_Shdr shdr; 474160383Snetchild Elf_Scn *scn; 475160383Snetchild Elf_Data *data; 476160383Snetchild GElf_Rela *rela; 477160383Snetchild long i, nrela; 478160383Snetchild 479160383Snetchild scn = elf_getscn(efile->ef_elf, section_index); 480160383Snetchild if (scn == NULL) 481160383Snetchild return (EINVAL); 482160383Snetchild if (gelf_getshdr(scn, &shdr) == NULL) 483160383Snetchild return (EINVAL); 484160383Snetchild data = elf_getdata(scn, NULL); 485160383Snetchild if (data == NULL) 486160383Snetchild return (EINVAL); 487160383Snetchild 488160383Snetchild nrela = elf_object_count(efile, ELF_T_RELA, shdr.sh_size); 489160383Snetchild rela = calloc(nrela, sizeof(*rela)); 490172150Sariff if (rela == NULL) 491160383Snetchild return (ENOMEM); 492160383Snetchild 493160383Snetchild for (i = 0; i < nrela; i++) { 494160383Snetchild if (gelf_getrela(data, i, &rela[i]) == NULL) { 495160383Snetchild free(rela); 496160383Snetchild return (EINVAL); 497160383Snetchild } 498160383Snetchild } 499160383Snetchild 500160383Snetchild *nrelap = nrela; 501160383Snetchild *relap = rela; 502160383Snetchild return (0); 503160383Snetchild} 504160383Snetchild 505160383Snetchildsize_t 506160383Snetchildelf_pointer_size(struct elf_file *efile) 507160383Snetchild{ 508160383Snetchild return (efile->ef_pointer_size); 509160383Snetchild} 510160383Snetchild 511160383Snetchildint 512160383Snetchildelf_int(struct elf_file *efile, const void *p) 513160383Snetchild{ 514160383Snetchild if (elf_encoding(efile) == ELFDATA2LSB) 515160383Snetchild return (le32dec(p)); 516160383Snetchild else 517165833Snetchild return (be32dec(p)); 518165833Snetchild} 519165833Snetchild 520165833SnetchildGElf_Addr 521160383Snetchildelf_address_from_pointer(struct elf_file *efile, const void *p) 522160383Snetchild{ 523160383Snetchild switch (elf_class(efile)) { 524160383Snetchild case ELFCLASS32: 525160383Snetchild if (elf_encoding(efile) == ELFDATA2LSB) 526160383Snetchild return (le32dec(p)); 527160383Snetchild else 528160383Snetchild return (be32dec(p)); 529160383Snetchild case ELFCLASS64: 530160383Snetchild if (elf_encoding(efile) == ELFDATA2LSB) 531160383Snetchild return (le64dec(p)); 532160383Snetchild else 533160383Snetchild return (be64dec(p)); 534160383Snetchild default: 535160383Snetchild __unreachable(); 536160383Snetchild } 537160383Snetchild} 538160383Snetchild 539160383Snetchildint 540160383Snetchildelf_read_string(struct elf_file *efile, GElf_Addr address, void *dst, 541160383Snetchild size_t len) 542160383Snetchild{ 543160383Snetchild return (EF_SEG_READ_STRING(efile, address, len, dst)); 544160383Snetchild} 545160383Snetchild 546160383Snetchildint 547160383Snetchildelf_read_linker_set(struct elf_file *efile, const char *name, GElf_Addr **bufp, 548160383Snetchild long *countp) 549160383Snetchild{ 550160383Snetchild GElf_Addr *buf, start, stop; 551160383Snetchild char *p; 552160383Snetchild void *raw; 553160383Snetchild long i, count; 554160383Snetchild int error; 555160383Snetchild 556160383Snetchild error = EF_LOOKUP_SET(efile, name, &start, &stop, &count); 557160383Snetchild if (error != 0) 558160383Snetchild return (error); 559165833Snetchild 560160383Snetchild error = elf_read_relocated_data(efile, start, 561160383Snetchild count * elf_pointer_size(efile), &raw); 562160383Snetchild if (error != 0) 563160383Snetchild return (error); 564160383Snetchild 565165833Snetchild buf = calloc(count, sizeof(*buf)); 566160383Snetchild if (buf == NULL) { 567160383Snetchild free(raw); 568160383Snetchild return (ENOMEM); 569160383Snetchild } 570160383Snetchild 571160383Snetchild p = raw; 572165833Snetchild for (i = 0; i < count; i++) { 573165833Snetchild buf[i] = elf_address_from_pointer(efile, p); 574160383Snetchild p += elf_pointer_size(efile); 575160383Snetchild } 576160383Snetchild free(raw); 577160383Snetchild 578160383Snetchild *bufp = buf; 579160383Snetchild *countp = count; 580160383Snetchild return (0); 581172150Sariff} 582172150Sariff 583172150Sariffint 584172150Sariffelf_read_mod_depend(struct elf_file *efile, GElf_Addr addr, 585160383Snetchild struct Gmod_depend *mdp) 586160383Snetchild{ 587160383Snetchild int *p; 588160383Snetchild int error; 589160383Snetchild 590160383Snetchild error = elf_read_relocated_data(efile, addr, sizeof(int) * 3, 591160383Snetchild (void **)&p); 592160383Snetchild if (error != 0) 593165833Snetchild return (error); 594160383Snetchild 595160383Snetchild memset(mdp, 0, sizeof(*mdp)); 596160383Snetchild mdp->md_ver_minimum = elf_int(efile, p); 597165833Snetchild mdp->md_ver_preferred = elf_int(efile, p + 1); 598160383Snetchild mdp->md_ver_maximum = elf_int(efile, p + 2); 599160383Snetchild free(p); 600160383Snetchild return (0); 601160383Snetchild} 602160383Snetchild 603160383Snetchildint 604160383Snetchildelf_read_mod_version(struct elf_file *efile, GElf_Addr addr, 605160383Snetchild struct Gmod_version *mdv) 606160383Snetchild{ 607160383Snetchild int error, value; 608160383Snetchild 609160383Snetchild error = EF_SEG_READ_REL(efile, addr, sizeof(int), &value); 610160383Snetchild if (error != 0) 611160383Snetchild return (error); 612160383Snetchild 613160383Snetchild memset(mdv, 0, sizeof(*mdv)); 614160383Snetchild mdv->mv_version = elf_int(efile, &value); 615160383Snetchild return (0); 616160383Snetchild} 617160383Snetchild 618160383Snetchildint 619160383Snetchildelf_read_mod_metadata(struct elf_file *efile, GElf_Addr addr, 620160383Snetchild struct Gmod_metadata *md) 621160383Snetchild{ 622160383Snetchild char *p; 623160383Snetchild size_t len, offset, pointer_size; 624160383Snetchild int error; 625160383Snetchild 626160383Snetchild pointer_size = elf_pointer_size(efile); 627160383Snetchild len = 2 * sizeof(int); 628160383Snetchild len = roundup(len, pointer_size); 629160383Snetchild len += 2 * pointer_size; 630160383Snetchild 631160383Snetchild error = elf_read_relocated_data(efile, addr, len, (void **)&p); 632160383Snetchild if (error != 0) 633160383Snetchild return (error); 634160383Snetchild 635160383Snetchild memset(md, 0, sizeof(*md)); 636160383Snetchild offset = 0; 637160383Snetchild md->md_version = elf_int(efile, p + offset); 638160383Snetchild offset += sizeof(int); 639160383Snetchild md->md_type = elf_int(efile, p + offset); 640160383Snetchild offset += sizeof(int); 641160383Snetchild offset = roundup(offset, pointer_size); 642160383Snetchild md->md_data = elf_address_from_pointer(efile, p + offset); 643160383Snetchild offset += pointer_size; 644229981Spfg md->md_cval = elf_address_from_pointer(efile, p + offset); 645160383Snetchild free(p); 646160383Snetchild return (0); 647160383Snetchild} 648160383Snetchild 649160383Snetchildint 650160383Snetchildelf_read_mod_pnp_match_info(struct elf_file *efile, GElf_Addr addr, 651160383Snetchild struct Gmod_pnp_match_info *pnp) 652160383Snetchild{ 653229981Spfg char *p; 654172150Sariff size_t len, offset, pointer_size; 655172150Sariff int error; 656229981Spfg 657229981Spfg pointer_size = elf_pointer_size(efile); 658172150Sariff len = 3 * pointer_size; 659172150Sariff len = roundup(len, pointer_size); 660160383Snetchild len += 2 * sizeof(int); 661160383Snetchild 662160383Snetchild error = elf_read_relocated_data(efile, addr, len, (void **)&p); 663160383Snetchild if (error != 0) 664160383Snetchild return (error); 665160383Snetchild 666160383Snetchild memset(pnp, 0, sizeof(*pnp)); 667160383Snetchild offset = 0; 668160383Snetchild pnp->descr = elf_address_from_pointer(efile, p + offset); 669160383Snetchild offset += pointer_size; 670160383Snetchild pnp->bus = elf_address_from_pointer(efile, p + offset); 671160383Snetchild offset += pointer_size; 672160383Snetchild pnp->table = elf_address_from_pointer(efile, p + offset); 673160383Snetchild offset += pointer_size; 674160383Snetchild offset = roundup(offset, pointer_size); 675160383Snetchild pnp->entry_len = elf_int(efile, p + offset); 676160383Snetchild offset += sizeof(int); 677160383Snetchild pnp->num_entry = elf_int(efile, p + offset); 678160383Snetchild free(p); 679172150Sariff return (0); 680229981Spfg} 681172150Sariff 682172150Sariffint 683229981Spfgelf_reloc(struct elf_file *efile, const void *reldata, Elf_Type reltype, 684160383Snetchild GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest) 685160383Snetchild{ 686160383Snetchild return (efile->ef_reloc(efile, reldata, reltype, relbase, dataoff, len, 687160383Snetchild dest)); 688160383Snetchild} 689160383Snetchild