ef_obj.c revision 134373
1134361Siedowse/* 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: head/usr.sbin/kldxref/ef_obj.c 134373 2004-08-27 08:54:40Z iedowse $ 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#include <link.h> 48134361Siedowse 49134361Siedowse#include <err.h> 50134361Siedowse 51134361Siedowse#include "ef.h" 52134361Siedowse 53134361Siedowsetypedef struct { 54134361Siedowse void *addr; 55134361Siedowse Elf_Off size; 56134361Siedowse int flags; 57134361Siedowse int sec; /* Original section */ 58134361Siedowse char *name; 59134361Siedowse} Elf_progent; 60134361Siedowse 61134361Siedowsetypedef struct { 62134361Siedowse Elf_Rel *rel; 63134361Siedowse int nrel; 64134361Siedowse int sec; 65134361Siedowse} Elf_relent; 66134361Siedowse 67134361Siedowsetypedef struct { 68134361Siedowse Elf_Rela *rela; 69134361Siedowse int nrela; 70134361Siedowse int sec; 71134361Siedowse} Elf_relaent; 72134361Siedowse 73134361Siedowsestruct ef_file { 74134361Siedowse char *ef_name; 75134361Siedowse int ef_fd; 76134361Siedowse Elf_Ehdr ef_hdr; 77134361Siedowse struct elf_file *ef_efile; 78134361Siedowse 79134361Siedowse caddr_t address; 80134361Siedowse Elf_Off size; 81134361Siedowse Elf_Shdr *e_shdr; 82134361Siedowse 83134361Siedowse Elf_progent *progtab; 84134361Siedowse int nprogtab; 85134361Siedowse 86134361Siedowse Elf_relaent *relatab; 87134361Siedowse int nrela; 88134361Siedowse 89134361Siedowse Elf_relent *reltab; 90134361Siedowse int nrel; 91134361Siedowse 92134361Siedowse Elf_Sym *ddbsymtab; /* The symbol table we are using */ 93134361Siedowse long ddbsymcnt; /* Number of symbols */ 94134361Siedowse caddr_t ddbstrtab; /* String table */ 95134361Siedowse long ddbstrcnt; /* number of bytes in string table */ 96134361Siedowse 97134361Siedowse caddr_t shstrtab; /* Section name string table */ 98134361Siedowse long shstrcnt; /* number of bytes in string table */ 99134361Siedowse 100134361Siedowse int ef_verbose; 101134361Siedowse}; 102134361Siedowse 103134361Siedowsestatic int ef_obj_get_type(elf_file_t ef); 104134361Siedowsestatic int ef_obj_close(elf_file_t ef); 105134361Siedowsestatic int ef_obj_read(elf_file_t ef, Elf_Off offset, size_t len, void* dest); 106134361Siedowsestatic int ef_obj_read_entry(elf_file_t ef, Elf_Off offset, size_t len, 107134361Siedowse void **ptr); 108134361Siedowsestatic int ef_obj_seg_read(elf_file_t ef, Elf_Off offset, size_t len, 109134361Siedowse void *dest); 110134361Siedowsestatic int ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, 111134361Siedowse void *dest); 112134361Siedowsestatic int ef_obj_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len, 113134361Siedowse void **ptr); 114134361Siedowsestatic int ef_obj_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len, 115134361Siedowse void **ptr); 116134361Siedowsestatic Elf_Addr ef_obj_symaddr(elf_file_t ef, Elf_Word symidx); 117134361Siedowsestatic int ef_obj_lookup_set(elf_file_t ef, const char *name, long *startp, 118134361Siedowse long *stopp, long *countp); 119134361Siedowsestatic int ef_obj_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym); 120134361Siedowse 121134361Siedowsestatic struct elf_file_ops ef_obj_file_ops = { 122134361Siedowse ef_obj_get_type, 123134361Siedowse ef_obj_close, 124134361Siedowse ef_obj_read, 125134361Siedowse ef_obj_read_entry, 126134361Siedowse ef_obj_seg_read, 127134361Siedowse ef_obj_seg_read_rel, 128134361Siedowse ef_obj_seg_read_entry, 129134361Siedowse ef_obj_seg_read_entry_rel, 130134361Siedowse ef_obj_symaddr, 131134361Siedowse ef_obj_lookup_set, 132134361Siedowse ef_obj_lookup_symbol 133134361Siedowse}; 134134361Siedowse 135134361Siedowsestatic int 136134361Siedowseef_obj_get_type(elf_file_t ef) 137134361Siedowse{ 138134361Siedowse 139134361Siedowse return (EFT_KLD); 140134361Siedowse} 141134361Siedowse 142134361Siedowsestatic int 143134361Siedowseef_obj_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym) 144134361Siedowse{ 145134361Siedowse Elf_Sym *symp; 146134361Siedowse const char *strp; 147134361Siedowse int i; 148134361Siedowse 149134361Siedowse for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 150134361Siedowse strp = ef->ddbstrtab + symp->st_name; 151134361Siedowse if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) { 152134361Siedowse *sym = symp; 153134361Siedowse return 0; 154134361Siedowse } 155134361Siedowse } 156134361Siedowse return ENOENT; 157134361Siedowse} 158134361Siedowse 159134361Siedowsestatic int 160134361Siedowseef_obj_lookup_set(elf_file_t ef, const char *name, long *startp, long *stopp, 161134361Siedowse long *countp) 162134361Siedowse{ 163134361Siedowse int i; 164134361Siedowse 165134361Siedowse for (i = 0; i < ef->nprogtab; i++) { 166134361Siedowse if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) && 167134361Siedowse strcmp(ef->progtab[i].name + 4, name) == 0) { 168134361Siedowse *startp = (char *)ef->progtab[i].addr - ef->address; 169134361Siedowse *stopp = (char *)ef->progtab[i].addr + 170134361Siedowse ef->progtab[i].size - ef->address; 171134361Siedowse *countp = (*stopp - *startp) / sizeof(void *); 172134361Siedowse return (0); 173134361Siedowse } 174134361Siedowse } 175134361Siedowse return (ESRCH); 176134361Siedowse} 177134361Siedowse 178134361Siedowsestatic Elf_Addr 179134361Siedowseef_obj_symaddr(elf_file_t ef, Elf_Word symidx) 180134361Siedowse{ 181134361Siedowse const Elf_Sym *sym; 182134361Siedowse 183134361Siedowse if (symidx >= ef->ddbsymcnt) 184134361Siedowse return (0); 185134361Siedowse sym = ef->ddbsymtab + symidx; 186134361Siedowse 187134361Siedowse if (sym->st_shndx != SHN_UNDEF) 188134361Siedowse return (sym->st_value - (Elf_Addr)ef->address); 189134361Siedowse return (0); 190134361Siedowse} 191134361Siedowse 192134361Siedowsestatic int 193134361Siedowseef_obj_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest) 194134361Siedowse{ 195134361Siedowse ssize_t r; 196134361Siedowse 197134361Siedowse if (offset != (Elf_Off)-1) { 198134361Siedowse if (lseek(ef->ef_fd, offset, SEEK_SET) == -1) 199134361Siedowse return EIO; 200134361Siedowse } 201134361Siedowse 202134361Siedowse r = read(ef->ef_fd, dest, len); 203134361Siedowse if (r != -1 && (size_t)r == len) 204134361Siedowse return 0; 205134361Siedowse else 206134361Siedowse return EIO; 207134361Siedowse} 208134361Siedowse 209134361Siedowsestatic int 210134361Siedowseef_obj_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void **ptr) 211134361Siedowse{ 212134361Siedowse int error; 213134361Siedowse 214134361Siedowse *ptr = malloc(len); 215134361Siedowse if (*ptr == NULL) 216134361Siedowse return ENOMEM; 217134361Siedowse error = ef_obj_read(ef, offset, len, *ptr); 218134361Siedowse if (error) 219134361Siedowse free(*ptr); 220134361Siedowse return error; 221134361Siedowse} 222134361Siedowse 223134361Siedowsestatic int 224134361Siedowseef_obj_seg_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest) 225134361Siedowse{ 226134361Siedowse 227134361Siedowse if (offset + len > ef->size) { 228134361Siedowse if (ef->ef_verbose) 229134361Siedowse warnx("ef_seg_read_rel(%s): bad offset/len (%lx:%ld)", 230134361Siedowse ef->ef_name, (long)offset, (long)len); 231134361Siedowse return (EFAULT); 232134361Siedowse } 233134361Siedowse bcopy(ef->address + offset, dest, len); 234134361Siedowse return (0); 235134361Siedowse} 236134361Siedowse 237134361Siedowsestatic int 238134361Siedowseef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void *dest) 239134361Siedowse{ 240134361Siedowse char *memaddr; 241134361Siedowse Elf_Rel *r; 242134361Siedowse Elf_Rela *a; 243134361Siedowse Elf_Off secoff; 244134361Siedowse int error, i, sec; 245134361Siedowse 246134361Siedowse if (offset + len > ef->size) { 247134361Siedowse if (ef->ef_verbose) 248134361Siedowse warnx("ef_seg_read_rel(%s): bad offset/len (%lx:%ld)", 249134361Siedowse ef->ef_name, (long)offset, (long)len); 250134361Siedowse return (EFAULT); 251134361Siedowse } 252134361Siedowse bcopy(ef->address + offset, dest, len); 253134361Siedowse 254134361Siedowse /* Find out which section contains the data. */ 255134361Siedowse memaddr = ef->address + offset; 256134361Siedowse sec = -1; 257134361Siedowse for (i = 0; i < ef->nprogtab; i++) { 258134361Siedowse if (ef->progtab[i].addr == NULL) 259134361Siedowse continue; 260134361Siedowse if (memaddr < (char *)ef->progtab[i].addr || memaddr + len > 261134361Siedowse (char *)ef->progtab[i].addr + ef->progtab[i].size) 262134361Siedowse continue; 263134361Siedowse sec = ef->progtab[i].sec; 264134361Siedowse secoff = memaddr - (char *)ef->progtab[i].addr; 265134361Siedowse break; 266134361Siedowse } 267134361Siedowse 268134361Siedowse if (sec == -1) 269134361Siedowse return (EFAULT); 270134361Siedowse 271134361Siedowse /* Now do the relocations. */ 272134361Siedowse for (i = 0; i < ef->nrel; i++) { 273134361Siedowse if (ef->reltab[i].sec != sec) 274134361Siedowse continue; 275134361Siedowse for (r = ef->reltab[i].rel; 276134361Siedowse r < &ef->reltab[i].rel[ef->reltab[i].nrel]; r++) { 277134361Siedowse error = ef_reloc(ef->ef_efile, r, EF_RELOC_REL, secoff, 278134361Siedowse len, dest); 279134361Siedowse if (error != 0) 280134361Siedowse return (error); 281134361Siedowse } 282134361Siedowse } 283134361Siedowse for (i = 0; i < ef->nrela; i++) { 284134361Siedowse if (ef->relatab[i].sec != sec) 285134361Siedowse continue; 286134361Siedowse for (a = ef->relatab[i].rela; 287134361Siedowse a < &ef->relatab[i].rela[ef->relatab[i].nrela]; a++) { 288134361Siedowse error = ef_reloc(ef->ef_efile, a, EF_RELOC_RELA, secoff, 289134361Siedowse len, dest); 290134361Siedowse if (error != 0) 291134361Siedowse return (error); 292134361Siedowse } 293134361Siedowse } 294134361Siedowse return (0); 295134361Siedowse} 296134361Siedowse 297134361Siedowsestatic int 298134361Siedowseef_obj_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void **ptr) 299134361Siedowse{ 300134361Siedowse int error; 301134361Siedowse 302134361Siedowse *ptr = malloc(len); 303134361Siedowse if (*ptr == NULL) 304134361Siedowse return ENOMEM; 305134361Siedowse error = ef_obj_seg_read(ef, offset, len, *ptr); 306134361Siedowse if (error) 307134361Siedowse free(*ptr); 308134361Siedowse return error; 309134361Siedowse} 310134361Siedowse 311134361Siedowsestatic int 312134361Siedowseef_obj_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len, 313134361Siedowse void **ptr) 314134361Siedowse{ 315134361Siedowse int error; 316134361Siedowse 317134361Siedowse *ptr = malloc(len); 318134361Siedowse if (*ptr == NULL) 319134361Siedowse return ENOMEM; 320134361Siedowse error = ef_obj_seg_read_rel(ef, offset, len, *ptr); 321134361Siedowse if (error) 322134361Siedowse free(*ptr); 323134361Siedowse return error; 324134361Siedowse} 325134361Siedowse 326134361Siedowseint 327134361Siedowseef_obj_open(const char *filename, struct elf_file *efile, int verbose) 328134361Siedowse{ 329134361Siedowse elf_file_t ef; 330134361Siedowse Elf_Ehdr *hdr; 331134361Siedowse Elf_Shdr *shdr; 332134361Siedowse Elf_Sym *es; 333134361Siedowse char *mapbase; 334134373Siedowse void *vtmp; 335134361Siedowse size_t mapsize; 336134361Siedowse int alignmask, error, fd, pb, ra, res, rl; 337134361Siedowse int i, j, nbytes, nsym, shstrindex, symstrindex, symtabindex; 338134361Siedowse 339134361Siedowse if (filename == NULL) 340134361Siedowse return EFTYPE; 341134361Siedowse if ((fd = open(filename, O_RDONLY)) == -1) 342134361Siedowse return errno; 343134361Siedowse 344134361Siedowse ef = malloc(sizeof(*ef)); 345134361Siedowse if (ef == NULL) { 346134361Siedowse close(fd); 347134361Siedowse return (ENOMEM); 348134361Siedowse } 349134361Siedowse 350134361Siedowse efile->ef_ef = ef; 351134361Siedowse efile->ef_ops = &ef_obj_file_ops; 352134361Siedowse 353134361Siedowse bzero(ef, sizeof(*ef)); 354134361Siedowse ef->ef_verbose = verbose; 355134361Siedowse ef->ef_fd = fd; 356134361Siedowse ef->ef_name = strdup(filename); 357134361Siedowse ef->ef_efile = efile; 358134361Siedowse hdr = (Elf_Ehdr *)&ef->ef_hdr; 359134361Siedowse 360134361Siedowse res = read(fd, hdr, sizeof(*hdr)); 361134361Siedowse error = EFTYPE; 362134361Siedowse if (res != sizeof(*hdr)) 363134361Siedowse goto out; 364134361Siedowse if (!IS_ELF(*hdr)) 365134361Siedowse goto out; 366134361Siedowse if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || 367134361Siedowse hdr->e_ident[EI_DATA] != ELF_TARG_DATA || 368134361Siedowse hdr->e_ident[EI_VERSION] != EV_CURRENT || 369134361Siedowse hdr->e_version != EV_CURRENT || hdr->e_machine != ELF_TARG_MACH || 370134361Siedowse hdr->e_type != ET_REL) 371134361Siedowse goto out; 372134361Siedowse 373134361Siedowse nbytes = hdr->e_shnum * hdr->e_shentsize; 374134361Siedowse if (nbytes == 0 || hdr->e_shoff == 0 || 375134361Siedowse hdr->e_shentsize != sizeof(Elf_Shdr)) 376134361Siedowse goto out; 377134361Siedowse 378134373Siedowse if (ef_obj_read_entry(ef, hdr->e_shoff, nbytes, &vtmp) != 0) { 379134361Siedowse printf("ef_read_entry failed\n"); 380134361Siedowse goto out; 381134361Siedowse } 382134373Siedowse ef->e_shdr = shdr = vtmp; 383134361Siedowse 384134361Siedowse /* Scan the section header for information and table sizing. */ 385134361Siedowse nsym = 0; 386134361Siedowse symtabindex = -1; 387134361Siedowse symstrindex = -1; 388134361Siedowse for (i = 0; i < hdr->e_shnum; i++) { 389134361Siedowse switch (shdr[i].sh_type) { 390134361Siedowse case SHT_PROGBITS: 391134361Siedowse case SHT_NOBITS: 392134361Siedowse ef->nprogtab++; 393134361Siedowse break; 394134361Siedowse case SHT_SYMTAB: 395134361Siedowse nsym++; 396134361Siedowse symtabindex = i; 397134361Siedowse symstrindex = shdr[i].sh_link; 398134361Siedowse break; 399134361Siedowse case SHT_REL: 400134361Siedowse ef->nrel++; 401134361Siedowse break; 402134361Siedowse case SHT_RELA: 403134361Siedowse ef->nrela++; 404134361Siedowse break; 405134361Siedowse case SHT_STRTAB: 406134361Siedowse break; 407134361Siedowse } 408134361Siedowse } 409134361Siedowse 410134361Siedowse if (ef->nprogtab == 0) { 411134361Siedowse warnx("%s: file has no contents", filename); 412134361Siedowse goto out; 413134361Siedowse } 414134361Siedowse if (nsym != 1) { 415134361Siedowse warnx("%s: file has no valid symbol table", filename); 416134361Siedowse goto out; 417134361Siedowse } 418134361Siedowse if (symstrindex < 0 || symstrindex > hdr->e_shnum || 419134361Siedowse shdr[symstrindex].sh_type != SHT_STRTAB) { 420134361Siedowse warnx("%s: file has invalid symbol strings", filename); 421134361Siedowse goto out; 422134361Siedowse } 423134361Siedowse 424134361Siedowse /* Allocate space for tracking the load chunks */ 425134361Siedowse if (ef->nprogtab != 0) 426134361Siedowse ef->progtab = calloc(ef->nprogtab, sizeof(*ef->progtab)); 427134361Siedowse if (ef->nrel != 0) 428134361Siedowse ef->reltab = calloc(ef->nrel, sizeof(*ef->reltab)); 429134361Siedowse if (ef->nrela != 0) 430134361Siedowse ef->relatab = calloc(ef->nrela, sizeof(*ef->relatab)); 431134361Siedowse if ((ef->nprogtab != 0 && ef->progtab == NULL) || 432134361Siedowse (ef->nrel != 0 && ef->reltab == NULL) || 433134361Siedowse (ef->nrela != 0 && ef->relatab == NULL)) { 434134361Siedowse printf("malloc failed\n"); 435134361Siedowse error = ENOMEM; 436134361Siedowse goto out; 437134361Siedowse } 438134361Siedowse 439134361Siedowse ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); 440134361Siedowse if (ef_obj_read_entry(ef, shdr[symtabindex].sh_offset, 441134361Siedowse shdr[symtabindex].sh_size, (void**)&ef->ddbsymtab) != 0) { 442134361Siedowse printf("ef_read_entry failed\n"); 443134361Siedowse goto out; 444134361Siedowse } 445134361Siedowse 446134361Siedowse ef->ddbstrcnt = shdr[symstrindex].sh_size; 447134361Siedowse if (ef_obj_read_entry(ef, shdr[symstrindex].sh_offset, 448134361Siedowse shdr[symstrindex].sh_size, (void**)&ef->ddbstrtab) != 0) { 449134361Siedowse printf("ef_read_entry failed\n"); 450134361Siedowse goto out; 451134361Siedowse } 452134361Siedowse 453134361Siedowse /* Do we have a string table for the section names? */ 454134361Siedowse shstrindex = -1; 455134361Siedowse if (hdr->e_shstrndx != 0 && 456134361Siedowse shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) { 457134361Siedowse shstrindex = hdr->e_shstrndx; 458134361Siedowse ef->shstrcnt = shdr[shstrindex].sh_size; 459134361Siedowse if (ef_obj_read_entry(ef, shdr[shstrindex].sh_offset, 460134361Siedowse shdr[shstrindex].sh_size, (void**)&ef->shstrtab) != 0) { 461134361Siedowse printf("ef_read_entry failed\n"); 462134361Siedowse goto out; 463134361Siedowse } 464134361Siedowse } 465134361Siedowse 466134361Siedowse /* Size up code/data(progbits) and bss(nobits). */ 467134361Siedowse alignmask = 0; 468134361Siedowse mapsize = 0; 469134361Siedowse for (i = 0; i < hdr->e_shnum; i++) { 470134361Siedowse switch (shdr[i].sh_type) { 471134361Siedowse case SHT_PROGBITS: 472134361Siedowse case SHT_NOBITS: 473134361Siedowse alignmask = shdr[i].sh_addralign - 1; 474134361Siedowse mapsize += alignmask; 475134361Siedowse mapsize &= ~alignmask; 476134361Siedowse mapsize += shdr[i].sh_size; 477134361Siedowse break; 478134361Siedowse } 479134361Siedowse } 480134361Siedowse 481134361Siedowse /* We know how much space we need for the text/data/bss/etc. */ 482134361Siedowse ef->address = malloc(mapsize); 483134361Siedowse ef->size = mapsize; 484134361Siedowse if (ef->address == NULL) { 485134361Siedowse printf("malloc failed\n"); 486134361Siedowse goto out; 487134361Siedowse } 488134361Siedowse mapbase = ef->address; 489134361Siedowse 490134361Siedowse /* 491134361Siedowse * Now load code/data(progbits), zero bss(nobits), allocate 492134361Siedowse * space for and load relocs 493134361Siedowse */ 494134361Siedowse pb = 0; 495134361Siedowse rl = 0; 496134361Siedowse ra = 0; 497134361Siedowse alignmask = 0; 498134361Siedowse for (i = 0; i < hdr->e_shnum; i++) { 499134361Siedowse switch (shdr[i].sh_type) { 500134361Siedowse case SHT_PROGBITS: 501134361Siedowse case SHT_NOBITS: 502134361Siedowse alignmask = shdr[i].sh_addralign - 1; 503134361Siedowse mapbase += alignmask; 504134361Siedowse mapbase = (char *)((uintptr_t)mapbase & ~alignmask); 505134361Siedowse ef->progtab[pb].addr = (void *)(uintptr_t)mapbase; 506134361Siedowse if (shdr[i].sh_type == SHT_PROGBITS) { 507134361Siedowse ef->progtab[pb].name = "<<PROGBITS>>"; 508134361Siedowse if (ef_obj_read(ef, shdr[i].sh_offset, 509134361Siedowse shdr[i].sh_size, 510134361Siedowse ef->progtab[pb].addr) != 0) { 511134361Siedowse printf("failed to read progbits\n"); 512134361Siedowse goto out; 513134361Siedowse } 514134361Siedowse } else { 515134361Siedowse ef->progtab[pb].name = "<<NOBITS>>"; 516134361Siedowse bzero(ef->progtab[pb].addr, shdr[i].sh_size); 517134361Siedowse } 518134361Siedowse ef->progtab[pb].size = shdr[i].sh_size; 519134361Siedowse ef->progtab[pb].sec = i; 520134361Siedowse if (ef->shstrtab && shdr[i].sh_name != 0) 521134361Siedowse ef->progtab[pb].name = 522134361Siedowse ef->shstrtab + shdr[i].sh_name; 523134361Siedowse 524134361Siedowse /* Update all symbol values with the offset. */ 525134361Siedowse for (j = 0; j < ef->ddbsymcnt; j++) { 526134361Siedowse es = &ef->ddbsymtab[j]; 527134361Siedowse if (es->st_shndx != i) 528134361Siedowse continue; 529134361Siedowse es->st_value += (Elf_Addr)ef->progtab[pb].addr; 530134361Siedowse } 531134361Siedowse mapbase += shdr[i].sh_size; 532134361Siedowse pb++; 533134361Siedowse break; 534134361Siedowse case SHT_REL: 535134361Siedowse ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel); 536134361Siedowse ef->reltab[rl].sec = shdr[i].sh_info; 537134361Siedowse if (ef_obj_read_entry(ef, shdr[i].sh_offset, 538134361Siedowse shdr[i].sh_size, (void**)&ef->reltab[rl].rel) != 539134361Siedowse 0) { 540134361Siedowse printf("ef_read_entry failed\n"); 541134361Siedowse goto out; 542134361Siedowse } 543134361Siedowse rl++; 544134361Siedowse break; 545134361Siedowse case SHT_RELA: 546134361Siedowse ef->relatab[ra].nrela = 547134361Siedowse shdr[i].sh_size / sizeof(Elf_Rela); 548134361Siedowse ef->relatab[ra].sec = shdr[i].sh_info; 549134361Siedowse if (ef_obj_read_entry(ef, shdr[i].sh_offset, 550134361Siedowse shdr[i].sh_size, (void**)&ef->relatab[ra].rela) != 551134361Siedowse 0) { 552134361Siedowse printf("ef_read_entry failed\n"); 553134361Siedowse goto out; 554134361Siedowse } 555134361Siedowse ra++; 556134361Siedowse break; 557134361Siedowse } 558134361Siedowse } 559134361Siedowse error = 0; 560134361Siedowseout: 561134361Siedowse if (error) 562134361Siedowse ef_obj_close(ef); 563134361Siedowse return error; 564134361Siedowse} 565134361Siedowse 566134361Siedowsestatic int 567134361Siedowseef_obj_close(elf_file_t ef) 568134361Siedowse{ 569134361Siedowse int i; 570134361Siedowse 571134361Siedowse close(ef->ef_fd); 572134361Siedowse if (ef->ef_name) 573134361Siedowse free(ef->ef_name); 574134361Siedowse if (ef->e_shdr != NULL) 575134361Siedowse free(ef->e_shdr); 576134361Siedowse if (ef->size != 0) 577134361Siedowse free(ef->address); 578134361Siedowse if (ef->nprogtab != 0) 579134361Siedowse free(ef->progtab); 580134361Siedowse if (ef->nrel != 0) { 581134361Siedowse for (i = 0; i < ef->nrel; i++) 582134361Siedowse if (ef->reltab[i].rel != NULL) 583134361Siedowse free(ef->reltab[i].rel); 584134361Siedowse free(ef->reltab); 585134361Siedowse } 586134361Siedowse if (ef->nrela != 0) { 587134361Siedowse for (i = 0; i < ef->nrela; i++) 588134361Siedowse if (ef->relatab[i].rela != NULL) 589134361Siedowse free(ef->relatab[i].rela); 590134361Siedowse free(ef->relatab); 591134361Siedowse } 592134361Siedowse if (ef->ddbsymtab != NULL) 593134361Siedowse free(ef->ddbsymtab); 594134361Siedowse if (ef->ddbstrtab != NULL) 595134361Siedowse free(ef->ddbstrtab); 596134361Siedowse if (ef->shstrtab != NULL) 597134361Siedowse free(ef->shstrtab); 598134361Siedowse ef->ef_efile->ef_ops = NULL; 599134361Siedowse ef->ef_efile->ef_ef = NULL; 600134361Siedowse free(ef); 601134361Siedowse 602134361Siedowse return 0; 603134361Siedowse} 604