1331722Seadler/* 2134361Siedowse * Copyright (c) 2000, Boris Popov 3134361Siedowse * Copyright (c) 1998-2000 Doug Rabson 4134361Siedowse * Copyright (c) 2004 Peter Wemm 5134361Siedowse * All rights reserved. 6134361Siedowse * 7134361Siedowse * Redistribution and use in source and binary forms, with or without 8134361Siedowse * modification, are permitted provided that the following conditions 9134361Siedowse * are met: 10134361Siedowse * 1. Redistributions of source code must retain the above copyright 11134361Siedowse * notice, this list of conditions and the following disclaimer. 12134361Siedowse * 2. Redistributions in binary form must reproduce the above copyright 13134361Siedowse * notice, this list of conditions and the following disclaimer in the 14134361Siedowse * documentation and/or other materials provided with the distribution. 15134361Siedowse * 3. All advertising materials mentioning features or use of this software 16134361Siedowse * must display the following acknowledgement: 17134361Siedowse * This product includes software developed by Boris Popov. 18134361Siedowse * 4. Neither the name of the author nor the names of any co-contributors 19134361Siedowse * may be used to endorse or promote products derived from this software 20134361Siedowse * without specific prior written permission. 21134361Siedowse * 22134361Siedowse * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23134361Siedowse * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24134361Siedowse * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25134361Siedowse * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26134361Siedowse * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27134361Siedowse * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28134361Siedowse * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29134361Siedowse * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30134361Siedowse * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31134361Siedowse * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32134361Siedowse * SUCH DAMAGE. 33134361Siedowse * 34134361Siedowse * $FreeBSD: stable/11/usr.sbin/kldxref/ef_obj.c 329247 2018-02-13 22:40:33Z emaste $ 35134361Siedowse */ 36134361Siedowse 37134361Siedowse#include <sys/param.h> 38134361Siedowse#include <sys/linker.h> 39134361Siedowse#include <string.h> 40134361Siedowse#include <stdio.h> 41134361Siedowse#include <stdlib.h> 42134361Siedowse#include <unistd.h> 43134361Siedowse#include <errno.h> 44134361Siedowse#include <fcntl.h> 45134361Siedowse#include <machine/elf.h> 46134361Siedowse#define FREEBSD_ELF 47134361Siedowse 48134361Siedowse#include <err.h> 49134361Siedowse 50134361Siedowse#include "ef.h" 51134361Siedowse 52134361Siedowsetypedef struct { 53134361Siedowse void *addr; 54134361Siedowse Elf_Off size; 55134361Siedowse int flags; 56134361Siedowse int sec; /* Original section */ 57134361Siedowse char *name; 58134361Siedowse} Elf_progent; 59134361Siedowse 60134361Siedowsetypedef struct { 61134361Siedowse Elf_Rel *rel; 62134361Siedowse int nrel; 63134361Siedowse int sec; 64134361Siedowse} Elf_relent; 65134361Siedowse 66134361Siedowsetypedef struct { 67134361Siedowse Elf_Rela *rela; 68134361Siedowse int nrela; 69134361Siedowse int sec; 70134361Siedowse} Elf_relaent; 71134361Siedowse 72134361Siedowsestruct ef_file { 73134361Siedowse char *ef_name; 74134361Siedowse int ef_fd; 75134361Siedowse Elf_Ehdr ef_hdr; 76134361Siedowse struct elf_file *ef_efile; 77134361Siedowse 78134361Siedowse caddr_t address; 79134361Siedowse Elf_Off size; 80134361Siedowse Elf_Shdr *e_shdr; 81134361Siedowse 82134361Siedowse Elf_progent *progtab; 83134361Siedowse int nprogtab; 84134361Siedowse 85134361Siedowse Elf_relaent *relatab; 86134361Siedowse int nrela; 87134361Siedowse 88134361Siedowse Elf_relent *reltab; 89134361Siedowse int nrel; 90134361Siedowse 91134361Siedowse Elf_Sym *ddbsymtab; /* The symbol table we are using */ 92134361Siedowse long ddbsymcnt; /* Number of symbols */ 93134361Siedowse caddr_t ddbstrtab; /* String table */ 94134361Siedowse long ddbstrcnt; /* number of bytes in string table */ 95134361Siedowse 96134361Siedowse caddr_t shstrtab; /* Section name string table */ 97134361Siedowse long shstrcnt; /* number of bytes in string table */ 98134361Siedowse 99134361Siedowse int ef_verbose; 100134361Siedowse}; 101134361Siedowse 102134361Siedowsestatic int ef_obj_get_type(elf_file_t ef); 103134361Siedowsestatic int ef_obj_close(elf_file_t ef); 104134361Siedowsestatic int ef_obj_read(elf_file_t ef, Elf_Off offset, size_t len, void* dest); 105134361Siedowsestatic int ef_obj_read_entry(elf_file_t ef, Elf_Off offset, size_t len, 106134361Siedowse void **ptr); 107134361Siedowsestatic int ef_obj_seg_read(elf_file_t ef, Elf_Off offset, size_t len, 108134361Siedowse void *dest); 109134361Siedowsestatic int ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, 110134361Siedowse void *dest); 111329247Semastestatic int ef_obj_seg_read_string(elf_file_t ef, Elf_Off offset, size_t len, 112329247Semaste char *dest); 113134361Siedowsestatic int ef_obj_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len, 114134361Siedowse void **ptr); 115134361Siedowsestatic int ef_obj_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len, 116134361Siedowse void **ptr); 117153504Smarcelstatic Elf_Addr ef_obj_symaddr(elf_file_t ef, Elf_Size symidx); 118134361Siedowsestatic int ef_obj_lookup_set(elf_file_t ef, const char *name, long *startp, 119134361Siedowse long *stopp, long *countp); 120134361Siedowsestatic int ef_obj_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym); 121134361Siedowse 122134361Siedowsestatic struct elf_file_ops ef_obj_file_ops = { 123134361Siedowse ef_obj_get_type, 124134361Siedowse ef_obj_close, 125134361Siedowse ef_obj_read, 126134361Siedowse ef_obj_read_entry, 127134361Siedowse ef_obj_seg_read, 128134361Siedowse ef_obj_seg_read_rel, 129329247Semaste ef_obj_seg_read_string, 130134361Siedowse ef_obj_seg_read_entry, 131134361Siedowse ef_obj_seg_read_entry_rel, 132134361Siedowse ef_obj_symaddr, 133134361Siedowse ef_obj_lookup_set, 134134361Siedowse ef_obj_lookup_symbol 135134361Siedowse}; 136134361Siedowse 137134361Siedowsestatic int 138186826Sluigief_obj_get_type(elf_file_t __unused ef) 139134361Siedowse{ 140134361Siedowse 141134361Siedowse return (EFT_KLD); 142134361Siedowse} 143134361Siedowse 144134361Siedowsestatic int 145134361Siedowseef_obj_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym) 146134361Siedowse{ 147134361Siedowse Elf_Sym *symp; 148134361Siedowse const char *strp; 149134361Siedowse int i; 150134361Siedowse 151134361Siedowse for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 152134361Siedowse strp = ef->ddbstrtab + symp->st_name; 153134361Siedowse if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) { 154134361Siedowse *sym = symp; 155134361Siedowse return 0; 156134361Siedowse } 157134361Siedowse } 158134361Siedowse return ENOENT; 159134361Siedowse} 160134361Siedowse 161134361Siedowsestatic int 162134361Siedowseef_obj_lookup_set(elf_file_t ef, const char *name, long *startp, long *stopp, 163134361Siedowse long *countp) 164134361Siedowse{ 165134361Siedowse int i; 166134361Siedowse 167134361Siedowse for (i = 0; i < ef->nprogtab; i++) { 168134361Siedowse if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) && 169134361Siedowse strcmp(ef->progtab[i].name + 4, name) == 0) { 170134361Siedowse *startp = (char *)ef->progtab[i].addr - ef->address; 171134361Siedowse *stopp = (char *)ef->progtab[i].addr + 172134361Siedowse ef->progtab[i].size - ef->address; 173134361Siedowse *countp = (*stopp - *startp) / sizeof(void *); 174134361Siedowse return (0); 175134361Siedowse } 176134361Siedowse } 177134361Siedowse return (ESRCH); 178134361Siedowse} 179134361Siedowse 180134361Siedowsestatic Elf_Addr 181153504Smarcelef_obj_symaddr(elf_file_t ef, Elf_Size symidx) 182134361Siedowse{ 183134361Siedowse const Elf_Sym *sym; 184134361Siedowse 185186826Sluigi if (symidx >= (size_t) ef->ddbsymcnt) 186134361Siedowse return (0); 187134361Siedowse sym = ef->ddbsymtab + symidx; 188134361Siedowse 189134361Siedowse if (sym->st_shndx != SHN_UNDEF) 190134361Siedowse return (sym->st_value - (Elf_Addr)ef->address); 191134361Siedowse return (0); 192134361Siedowse} 193134361Siedowse 194134361Siedowsestatic int 195134361Siedowseef_obj_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest) 196134361Siedowse{ 197134361Siedowse ssize_t r; 198134361Siedowse 199134361Siedowse if (offset != (Elf_Off)-1) { 200134361Siedowse if (lseek(ef->ef_fd, offset, SEEK_SET) == -1) 201134361Siedowse return EIO; 202134361Siedowse } 203134361Siedowse 204134361Siedowse r = read(ef->ef_fd, dest, len); 205134361Siedowse if (r != -1 && (size_t)r == len) 206134361Siedowse return 0; 207134361Siedowse else 208134361Siedowse return EIO; 209134361Siedowse} 210134361Siedowse 211134361Siedowsestatic int 212134361Siedowseef_obj_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void **ptr) 213134361Siedowse{ 214134361Siedowse int error; 215134361Siedowse 216134361Siedowse *ptr = malloc(len); 217134361Siedowse if (*ptr == NULL) 218134361Siedowse return ENOMEM; 219134361Siedowse error = ef_obj_read(ef, offset, len, *ptr); 220134361Siedowse if (error) 221134361Siedowse free(*ptr); 222134361Siedowse return error; 223134361Siedowse} 224134361Siedowse 225134361Siedowsestatic int 226134361Siedowseef_obj_seg_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest) 227134361Siedowse{ 228134361Siedowse 229134361Siedowse if (offset + len > ef->size) { 230134361Siedowse if (ef->ef_verbose) 231329246Semaste warnx("ef_obj_seg_read(%s): bad offset/len (%lx:%ld)", 232134361Siedowse ef->ef_name, (long)offset, (long)len); 233134361Siedowse return (EFAULT); 234134361Siedowse } 235134361Siedowse bcopy(ef->address + offset, dest, len); 236134361Siedowse return (0); 237134361Siedowse} 238134361Siedowse 239134361Siedowsestatic int 240134361Siedowseef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void *dest) 241134361Siedowse{ 242134361Siedowse char *memaddr; 243134361Siedowse Elf_Rel *r; 244134361Siedowse Elf_Rela *a; 245134450Siedowse Elf_Off secbase, dataoff; 246134361Siedowse int error, i, sec; 247134450Siedowse 248134361Siedowse if (offset + len > ef->size) { 249134361Siedowse if (ef->ef_verbose) 250329246Semaste warnx("ef_obj_seg_read_rel(%s): bad offset/len (%lx:%ld)", 251134361Siedowse ef->ef_name, (long)offset, (long)len); 252134361Siedowse return (EFAULT); 253134361Siedowse } 254134361Siedowse bcopy(ef->address + offset, dest, len); 255134361Siedowse 256134361Siedowse /* Find out which section contains the data. */ 257134361Siedowse memaddr = ef->address + offset; 258134361Siedowse sec = -1; 259134450Siedowse secbase = dataoff = 0; 260134361Siedowse for (i = 0; i < ef->nprogtab; i++) { 261134361Siedowse if (ef->progtab[i].addr == NULL) 262134361Siedowse continue; 263134361Siedowse if (memaddr < (char *)ef->progtab[i].addr || memaddr + len > 264134361Siedowse (char *)ef->progtab[i].addr + ef->progtab[i].size) 265134361Siedowse continue; 266134361Siedowse sec = ef->progtab[i].sec; 267134450Siedowse /* We relocate to address 0. */ 268134450Siedowse secbase = (char *)ef->progtab[i].addr - ef->address; 269134450Siedowse dataoff = memaddr - ef->address; 270134361Siedowse break; 271134361Siedowse } 272134361Siedowse 273134361Siedowse if (sec == -1) 274134361Siedowse return (EFAULT); 275134361Siedowse 276134361Siedowse /* Now do the relocations. */ 277134361Siedowse for (i = 0; i < ef->nrel; i++) { 278134361Siedowse if (ef->reltab[i].sec != sec) 279134361Siedowse continue; 280134361Siedowse for (r = ef->reltab[i].rel; 281134361Siedowse r < &ef->reltab[i].rel[ef->reltab[i].nrel]; r++) { 282134450Siedowse error = ef_reloc(ef->ef_efile, r, EF_RELOC_REL, secbase, 283134450Siedowse dataoff, len, dest); 284134361Siedowse if (error != 0) 285134361Siedowse return (error); 286134361Siedowse } 287134361Siedowse } 288134361Siedowse for (i = 0; i < ef->nrela; i++) { 289134361Siedowse if (ef->relatab[i].sec != sec) 290134361Siedowse continue; 291134361Siedowse for (a = ef->relatab[i].rela; 292134361Siedowse a < &ef->relatab[i].rela[ef->relatab[i].nrela]; a++) { 293134450Siedowse error = ef_reloc(ef->ef_efile, a, EF_RELOC_RELA, 294134450Siedowse secbase, dataoff, len, dest); 295134361Siedowse if (error != 0) 296134361Siedowse return (error); 297134361Siedowse } 298134361Siedowse } 299134361Siedowse return (0); 300134361Siedowse} 301134361Siedowse 302134361Siedowsestatic int 303329247Semasteef_obj_seg_read_string(elf_file_t ef, Elf_Off offset, size_t len, char *dest) 304329247Semaste{ 305329247Semaste 306329247Semaste if (offset >= ef->size) { 307329247Semaste if (ef->ef_verbose) 308329247Semaste warnx("ef_obj_seg_read_string(%s): bad offset (%lx)", 309329247Semaste ef->ef_name, (long)offset); 310329247Semaste return (EFAULT); 311329247Semaste } 312329247Semaste 313329247Semaste if (ef->size - offset < len) 314329247Semaste len = ef->size - offset; 315329247Semaste 316329247Semaste if (strnlen(ef->address + offset, len) == len) 317329247Semaste return (EFAULT); 318329247Semaste 319329247Semaste memcpy(dest, ef->address + offset, len); 320329247Semaste return (0); 321329247Semaste} 322329247Semaste 323329247Semastestatic int 324134361Siedowseef_obj_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void **ptr) 325134361Siedowse{ 326134361Siedowse int error; 327134361Siedowse 328134361Siedowse *ptr = malloc(len); 329134361Siedowse if (*ptr == NULL) 330134361Siedowse return ENOMEM; 331134361Siedowse error = ef_obj_seg_read(ef, offset, len, *ptr); 332134361Siedowse if (error) 333134361Siedowse free(*ptr); 334134361Siedowse return error; 335134361Siedowse} 336134361Siedowse 337134361Siedowsestatic int 338134361Siedowseef_obj_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len, 339134361Siedowse void **ptr) 340134361Siedowse{ 341134361Siedowse int error; 342134361Siedowse 343134361Siedowse *ptr = malloc(len); 344134361Siedowse if (*ptr == NULL) 345134361Siedowse return ENOMEM; 346134361Siedowse error = ef_obj_seg_read_rel(ef, offset, len, *ptr); 347134361Siedowse if (error) 348134361Siedowse free(*ptr); 349134361Siedowse return error; 350134361Siedowse} 351134361Siedowse 352134361Siedowseint 353134361Siedowseef_obj_open(const char *filename, struct elf_file *efile, int verbose) 354134361Siedowse{ 355134361Siedowse elf_file_t ef; 356134361Siedowse Elf_Ehdr *hdr; 357134361Siedowse Elf_Shdr *shdr; 358134361Siedowse Elf_Sym *es; 359134361Siedowse char *mapbase; 360134373Siedowse void *vtmp; 361154251Sjasone size_t mapsize, alignmask, max_addralign; 362154251Sjasone int error, fd, pb, ra, res, rl; 363134361Siedowse int i, j, nbytes, nsym, shstrindex, symstrindex, symtabindex; 364134361Siedowse 365134361Siedowse if (filename == NULL) 366134361Siedowse return EFTYPE; 367134361Siedowse if ((fd = open(filename, O_RDONLY)) == -1) 368134361Siedowse return errno; 369134361Siedowse 370251440Sdelphij ef = calloc(1, sizeof(*ef)); 371134361Siedowse if (ef == NULL) { 372134361Siedowse close(fd); 373134361Siedowse return (ENOMEM); 374134361Siedowse } 375134361Siedowse 376134361Siedowse efile->ef_ef = ef; 377134361Siedowse efile->ef_ops = &ef_obj_file_ops; 378134361Siedowse 379134361Siedowse ef->ef_verbose = verbose; 380134361Siedowse ef->ef_fd = fd; 381134361Siedowse ef->ef_name = strdup(filename); 382134361Siedowse ef->ef_efile = efile; 383134361Siedowse hdr = (Elf_Ehdr *)&ef->ef_hdr; 384134361Siedowse 385134361Siedowse res = read(fd, hdr, sizeof(*hdr)); 386134361Siedowse error = EFTYPE; 387134361Siedowse if (res != sizeof(*hdr)) 388134361Siedowse goto out; 389134361Siedowse if (!IS_ELF(*hdr)) 390134361Siedowse goto out; 391134361Siedowse if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || 392134361Siedowse hdr->e_ident[EI_DATA] != ELF_TARG_DATA || 393134361Siedowse hdr->e_ident[EI_VERSION] != EV_CURRENT || 394134361Siedowse hdr->e_version != EV_CURRENT || hdr->e_machine != ELF_TARG_MACH || 395134361Siedowse hdr->e_type != ET_REL) 396134361Siedowse goto out; 397134361Siedowse 398134361Siedowse nbytes = hdr->e_shnum * hdr->e_shentsize; 399134361Siedowse if (nbytes == 0 || hdr->e_shoff == 0 || 400134361Siedowse hdr->e_shentsize != sizeof(Elf_Shdr)) 401134361Siedowse goto out; 402134361Siedowse 403134373Siedowse if (ef_obj_read_entry(ef, hdr->e_shoff, nbytes, &vtmp) != 0) { 404134361Siedowse printf("ef_read_entry failed\n"); 405134361Siedowse goto out; 406134361Siedowse } 407134373Siedowse ef->e_shdr = shdr = vtmp; 408134361Siedowse 409134361Siedowse /* Scan the section header for information and table sizing. */ 410134361Siedowse nsym = 0; 411134361Siedowse symtabindex = -1; 412134361Siedowse symstrindex = -1; 413134361Siedowse for (i = 0; i < hdr->e_shnum; i++) { 414134361Siedowse switch (shdr[i].sh_type) { 415134361Siedowse case SHT_PROGBITS: 416134361Siedowse case SHT_NOBITS: 417134361Siedowse ef->nprogtab++; 418134361Siedowse break; 419134361Siedowse case SHT_SYMTAB: 420134361Siedowse nsym++; 421134361Siedowse symtabindex = i; 422134361Siedowse symstrindex = shdr[i].sh_link; 423134361Siedowse break; 424134361Siedowse case SHT_REL: 425134361Siedowse ef->nrel++; 426134361Siedowse break; 427134361Siedowse case SHT_RELA: 428134361Siedowse ef->nrela++; 429134361Siedowse break; 430134361Siedowse case SHT_STRTAB: 431134361Siedowse break; 432134361Siedowse } 433134361Siedowse } 434134361Siedowse 435134361Siedowse if (ef->nprogtab == 0) { 436134361Siedowse warnx("%s: file has no contents", filename); 437134361Siedowse goto out; 438134361Siedowse } 439134361Siedowse if (nsym != 1) { 440134361Siedowse warnx("%s: file has no valid symbol table", filename); 441134361Siedowse goto out; 442134361Siedowse } 443134361Siedowse if (symstrindex < 0 || symstrindex > hdr->e_shnum || 444134361Siedowse shdr[symstrindex].sh_type != SHT_STRTAB) { 445134361Siedowse warnx("%s: file has invalid symbol strings", filename); 446134361Siedowse goto out; 447134361Siedowse } 448134361Siedowse 449134361Siedowse /* Allocate space for tracking the load chunks */ 450134361Siedowse if (ef->nprogtab != 0) 451134361Siedowse ef->progtab = calloc(ef->nprogtab, sizeof(*ef->progtab)); 452134361Siedowse if (ef->nrel != 0) 453134361Siedowse ef->reltab = calloc(ef->nrel, sizeof(*ef->reltab)); 454134361Siedowse if (ef->nrela != 0) 455134361Siedowse ef->relatab = calloc(ef->nrela, sizeof(*ef->relatab)); 456134361Siedowse if ((ef->nprogtab != 0 && ef->progtab == NULL) || 457134361Siedowse (ef->nrel != 0 && ef->reltab == NULL) || 458134361Siedowse (ef->nrela != 0 && ef->relatab == NULL)) { 459134361Siedowse printf("malloc failed\n"); 460134361Siedowse error = ENOMEM; 461134361Siedowse goto out; 462134361Siedowse } 463134361Siedowse 464134361Siedowse ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); 465134361Siedowse if (ef_obj_read_entry(ef, shdr[symtabindex].sh_offset, 466134361Siedowse shdr[symtabindex].sh_size, (void**)&ef->ddbsymtab) != 0) { 467134361Siedowse printf("ef_read_entry failed\n"); 468134361Siedowse goto out; 469134361Siedowse } 470134361Siedowse 471134361Siedowse ef->ddbstrcnt = shdr[symstrindex].sh_size; 472134361Siedowse if (ef_obj_read_entry(ef, shdr[symstrindex].sh_offset, 473134361Siedowse shdr[symstrindex].sh_size, (void**)&ef->ddbstrtab) != 0) { 474134361Siedowse printf("ef_read_entry failed\n"); 475134361Siedowse goto out; 476134361Siedowse } 477134361Siedowse 478134361Siedowse /* Do we have a string table for the section names? */ 479134361Siedowse shstrindex = -1; 480134361Siedowse if (hdr->e_shstrndx != 0 && 481134361Siedowse shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) { 482134361Siedowse shstrindex = hdr->e_shstrndx; 483134361Siedowse ef->shstrcnt = shdr[shstrindex].sh_size; 484134361Siedowse if (ef_obj_read_entry(ef, shdr[shstrindex].sh_offset, 485134361Siedowse shdr[shstrindex].sh_size, (void**)&ef->shstrtab) != 0) { 486134361Siedowse printf("ef_read_entry failed\n"); 487134361Siedowse goto out; 488134361Siedowse } 489134361Siedowse } 490134361Siedowse 491134361Siedowse /* Size up code/data(progbits) and bss(nobits). */ 492134361Siedowse alignmask = 0; 493154251Sjasone max_addralign = 0; 494134361Siedowse mapsize = 0; 495134361Siedowse for (i = 0; i < hdr->e_shnum; i++) { 496134361Siedowse switch (shdr[i].sh_type) { 497134361Siedowse case SHT_PROGBITS: 498134361Siedowse case SHT_NOBITS: 499134361Siedowse alignmask = shdr[i].sh_addralign - 1; 500154251Sjasone if (shdr[i].sh_addralign > max_addralign) 501154251Sjasone max_addralign = shdr[i].sh_addralign; 502134361Siedowse mapsize += alignmask; 503134361Siedowse mapsize &= ~alignmask; 504134361Siedowse mapsize += shdr[i].sh_size; 505134361Siedowse break; 506134361Siedowse } 507134361Siedowse } 508134361Siedowse 509134361Siedowse /* We know how much space we need for the text/data/bss/etc. */ 510134361Siedowse ef->size = mapsize; 511154251Sjasone if (posix_memalign((void **)&ef->address, max_addralign, mapsize)) { 512154251Sjasone printf("posix_memalign failed\n"); 513134361Siedowse goto out; 514134361Siedowse } 515134361Siedowse mapbase = ef->address; 516134361Siedowse 517134361Siedowse /* 518134361Siedowse * Now load code/data(progbits), zero bss(nobits), allocate 519134361Siedowse * space for and load relocs 520134361Siedowse */ 521134361Siedowse pb = 0; 522134361Siedowse rl = 0; 523134361Siedowse ra = 0; 524134361Siedowse alignmask = 0; 525134361Siedowse for (i = 0; i < hdr->e_shnum; i++) { 526134361Siedowse switch (shdr[i].sh_type) { 527134361Siedowse case SHT_PROGBITS: 528134361Siedowse case SHT_NOBITS: 529134361Siedowse alignmask = shdr[i].sh_addralign - 1; 530134361Siedowse mapbase += alignmask; 531134361Siedowse mapbase = (char *)((uintptr_t)mapbase & ~alignmask); 532134361Siedowse ef->progtab[pb].addr = (void *)(uintptr_t)mapbase; 533134361Siedowse if (shdr[i].sh_type == SHT_PROGBITS) { 534134361Siedowse ef->progtab[pb].name = "<<PROGBITS>>"; 535134361Siedowse if (ef_obj_read(ef, shdr[i].sh_offset, 536134361Siedowse shdr[i].sh_size, 537134361Siedowse ef->progtab[pb].addr) != 0) { 538134361Siedowse printf("failed to read progbits\n"); 539134361Siedowse goto out; 540134361Siedowse } 541134361Siedowse } else { 542134361Siedowse ef->progtab[pb].name = "<<NOBITS>>"; 543134361Siedowse bzero(ef->progtab[pb].addr, shdr[i].sh_size); 544134361Siedowse } 545134361Siedowse ef->progtab[pb].size = shdr[i].sh_size; 546134361Siedowse ef->progtab[pb].sec = i; 547134361Siedowse if (ef->shstrtab && shdr[i].sh_name != 0) 548134361Siedowse ef->progtab[pb].name = 549134361Siedowse ef->shstrtab + shdr[i].sh_name; 550134361Siedowse 551134361Siedowse /* Update all symbol values with the offset. */ 552134361Siedowse for (j = 0; j < ef->ddbsymcnt; j++) { 553134361Siedowse es = &ef->ddbsymtab[j]; 554134361Siedowse if (es->st_shndx != i) 555134361Siedowse continue; 556134361Siedowse es->st_value += (Elf_Addr)ef->progtab[pb].addr; 557134361Siedowse } 558134361Siedowse mapbase += shdr[i].sh_size; 559134361Siedowse pb++; 560134361Siedowse break; 561134361Siedowse case SHT_REL: 562134361Siedowse ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel); 563134361Siedowse ef->reltab[rl].sec = shdr[i].sh_info; 564134361Siedowse if (ef_obj_read_entry(ef, shdr[i].sh_offset, 565134361Siedowse shdr[i].sh_size, (void**)&ef->reltab[rl].rel) != 566134361Siedowse 0) { 567134361Siedowse printf("ef_read_entry failed\n"); 568134361Siedowse goto out; 569134361Siedowse } 570134361Siedowse rl++; 571134361Siedowse break; 572134361Siedowse case SHT_RELA: 573134361Siedowse ef->relatab[ra].nrela = 574134361Siedowse shdr[i].sh_size / sizeof(Elf_Rela); 575134361Siedowse ef->relatab[ra].sec = shdr[i].sh_info; 576134361Siedowse if (ef_obj_read_entry(ef, shdr[i].sh_offset, 577134361Siedowse shdr[i].sh_size, (void**)&ef->relatab[ra].rela) != 578134361Siedowse 0) { 579134361Siedowse printf("ef_read_entry failed\n"); 580134361Siedowse goto out; 581134361Siedowse } 582134361Siedowse ra++; 583134361Siedowse break; 584134361Siedowse } 585134361Siedowse } 586134361Siedowse error = 0; 587134361Siedowseout: 588134361Siedowse if (error) 589134361Siedowse ef_obj_close(ef); 590134361Siedowse return error; 591134361Siedowse} 592134361Siedowse 593134361Siedowsestatic int 594134361Siedowseef_obj_close(elf_file_t ef) 595134361Siedowse{ 596134361Siedowse int i; 597134361Siedowse 598134361Siedowse close(ef->ef_fd); 599134361Siedowse if (ef->ef_name) 600134361Siedowse free(ef->ef_name); 601134361Siedowse if (ef->e_shdr != NULL) 602134361Siedowse free(ef->e_shdr); 603134361Siedowse if (ef->size != 0) 604134361Siedowse free(ef->address); 605134361Siedowse if (ef->nprogtab != 0) 606134361Siedowse free(ef->progtab); 607134361Siedowse if (ef->nrel != 0) { 608134361Siedowse for (i = 0; i < ef->nrel; i++) 609134361Siedowse if (ef->reltab[i].rel != NULL) 610134361Siedowse free(ef->reltab[i].rel); 611134361Siedowse free(ef->reltab); 612134361Siedowse } 613134361Siedowse if (ef->nrela != 0) { 614134361Siedowse for (i = 0; i < ef->nrela; i++) 615134361Siedowse if (ef->relatab[i].rela != NULL) 616134361Siedowse free(ef->relatab[i].rela); 617134361Siedowse free(ef->relatab); 618134361Siedowse } 619134361Siedowse if (ef->ddbsymtab != NULL) 620134361Siedowse free(ef->ddbsymtab); 621134361Siedowse if (ef->ddbstrtab != NULL) 622134361Siedowse free(ef->ddbstrtab); 623134361Siedowse if (ef->shstrtab != NULL) 624134361Siedowse free(ef->shstrtab); 625134361Siedowse ef->ef_efile->ef_ops = NULL; 626134361Siedowse ef->ef_efile->ef_ef = NULL; 627134361Siedowse free(ef); 628134361Siedowse 629134361Siedowse return 0; 630134361Siedowse} 631