1*968bcca2SKa Ho Ng /*- 2*968bcca2SKa Ho Ng * SPDX-License-Identifier: BSD-4-Clause 3*968bcca2SKa Ho Ng * 4*968bcca2SKa Ho Ng * Copyright (c) 2000, Boris Popov 5*968bcca2SKa Ho Ng * Copyright (c) 1998-2000 Doug Rabson 6*968bcca2SKa Ho Ng * Copyright (c) 2004 Peter Wemm 7*968bcca2SKa Ho Ng * All rights reserved. 8*968bcca2SKa Ho Ng * 9*968bcca2SKa Ho Ng * Redistribution and use in source and binary forms, with or without 10*968bcca2SKa Ho Ng * modification, are permitted provided that the following conditions 11*968bcca2SKa Ho Ng * are met: 12*968bcca2SKa Ho Ng * 1. Redistributions of source code must retain the above copyright 13*968bcca2SKa Ho Ng * notice, this list of conditions and the following disclaimer. 14*968bcca2SKa Ho Ng * 2. Redistributions in binary form must reproduce the above copyright 15*968bcca2SKa Ho Ng * notice, this list of conditions and the following disclaimer in the 16*968bcca2SKa Ho Ng * documentation and/or other materials provided with the distribution. 17*968bcca2SKa Ho Ng * 3. All advertising materials mentioning features or use of this software 18*968bcca2SKa Ho Ng * must display the following acknowledgement: 19*968bcca2SKa Ho Ng * This product includes software developed by Boris Popov. 20*968bcca2SKa Ho Ng * 4. Neither the name of the author nor the names of any co-contributors 21*968bcca2SKa Ho Ng * may be used to endorse or promote products derived from this software 22*968bcca2SKa Ho Ng * without specific prior written permission. 23*968bcca2SKa Ho Ng * 24*968bcca2SKa Ho Ng * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25*968bcca2SKa Ho Ng * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26*968bcca2SKa Ho Ng * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27*968bcca2SKa Ho Ng * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28*968bcca2SKa Ho Ng * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29*968bcca2SKa Ho Ng * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30*968bcca2SKa Ho Ng * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31*968bcca2SKa Ho Ng * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32*968bcca2SKa Ho Ng * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33*968bcca2SKa Ho Ng * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34*968bcca2SKa Ho Ng * SUCH DAMAGE. 35*968bcca2SKa Ho Ng */ 36*968bcca2SKa Ho Ng 37*968bcca2SKa Ho Ng #include <sys/param.h> 38*968bcca2SKa Ho Ng 39*968bcca2SKa Ho Ng #include <err.h> 40*968bcca2SKa Ho Ng #include <errno.h> 41*968bcca2SKa Ho Ng #include <gelf.h> 42*968bcca2SKa Ho Ng #include <stdio.h> 43*968bcca2SKa Ho Ng #include <stdlib.h> 44*968bcca2SKa Ho Ng #include <string.h> 45*968bcca2SKa Ho Ng 46*968bcca2SKa Ho Ng #include "kldelf.h" 47*968bcca2SKa Ho Ng 48*968bcca2SKa Ho Ng typedef struct { 49*968bcca2SKa Ho Ng GElf_Addr addr; 50*968bcca2SKa Ho Ng GElf_Off offset; 51*968bcca2SKa Ho Ng GElf_Off size; 52*968bcca2SKa Ho Ng int flags; 53*968bcca2SKa Ho Ng int sec; /* Original section */ 54*968bcca2SKa Ho Ng char *name; 55*968bcca2SKa Ho Ng } Elf_progent; 56*968bcca2SKa Ho Ng 57*968bcca2SKa Ho Ng typedef struct { 58*968bcca2SKa Ho Ng GElf_Rel *rel; 59*968bcca2SKa Ho Ng long nrel; 60*968bcca2SKa Ho Ng int sec; 61*968bcca2SKa Ho Ng } Elf_relent; 62*968bcca2SKa Ho Ng 63*968bcca2SKa Ho Ng typedef struct { 64*968bcca2SKa Ho Ng GElf_Rela *rela; 65*968bcca2SKa Ho Ng long nrela; 66*968bcca2SKa Ho Ng int sec; 67*968bcca2SKa Ho Ng } Elf_relaent; 68*968bcca2SKa Ho Ng 69*968bcca2SKa Ho Ng struct ef_file { 70*968bcca2SKa Ho Ng char *ef_name; 71*968bcca2SKa Ho Ng struct elf_file *ef_efile; 72*968bcca2SKa Ho Ng 73*968bcca2SKa Ho Ng Elf_progent *progtab; 74*968bcca2SKa Ho Ng int nprogtab; 75*968bcca2SKa Ho Ng 76*968bcca2SKa Ho Ng Elf_relaent *relatab; 77*968bcca2SKa Ho Ng int nrela; 78*968bcca2SKa Ho Ng 79*968bcca2SKa Ho Ng Elf_relent *reltab; 80*968bcca2SKa Ho Ng int nrel; 81*968bcca2SKa Ho Ng 82*968bcca2SKa Ho Ng GElf_Sym *ddbsymtab; /* The symbol table we are using */ 83*968bcca2SKa Ho Ng size_t ddbsymcnt; /* Number of symbols */ 84*968bcca2SKa Ho Ng caddr_t ddbstrtab; /* String table */ 85*968bcca2SKa Ho Ng long ddbstrcnt; /* number of bytes in string table */ 86*968bcca2SKa Ho Ng 87*968bcca2SKa Ho Ng caddr_t shstrtab; /* Section name string table */ 88*968bcca2SKa Ho Ng long shstrcnt; /* number of bytes in string table */ 89*968bcca2SKa Ho Ng 90*968bcca2SKa Ho Ng int ef_verbose; 91*968bcca2SKa Ho Ng }; 92*968bcca2SKa Ho Ng 93*968bcca2SKa Ho Ng static void ef_obj_close(elf_file_t ef); 94*968bcca2SKa Ho Ng 95*968bcca2SKa Ho Ng static int ef_obj_seg_read_rel(elf_file_t ef, GElf_Addr address, 96*968bcca2SKa Ho Ng size_t len, void *dest); 97*968bcca2SKa Ho Ng static int ef_obj_seg_read_string(elf_file_t ef, GElf_Addr address, 98*968bcca2SKa Ho Ng size_t len, char *dest); 99*968bcca2SKa Ho Ng 100*968bcca2SKa Ho Ng static GElf_Addr ef_obj_symaddr(elf_file_t ef, GElf_Size symidx); 101*968bcca2SKa Ho Ng static int ef_obj_lookup_set(elf_file_t ef, const char *name, 102*968bcca2SKa Ho Ng GElf_Addr *startp, GElf_Addr *stopp, long *countp); 103*968bcca2SKa Ho Ng static int ef_obj_lookup_symbol(elf_file_t ef, const char *name, 104*968bcca2SKa Ho Ng GElf_Sym **sym); 105*968bcca2SKa Ho Ng 106*968bcca2SKa Ho Ng static struct elf_file_ops ef_obj_file_ops = { 107*968bcca2SKa Ho Ng .close = ef_obj_close, 108*968bcca2SKa Ho Ng .seg_read_rel = ef_obj_seg_read_rel, 109*968bcca2SKa Ho Ng .seg_read_string = ef_obj_seg_read_string, 110*968bcca2SKa Ho Ng .symaddr = ef_obj_symaddr, 111*968bcca2SKa Ho Ng .lookup_set = ef_obj_lookup_set, 112*968bcca2SKa Ho Ng }; 113*968bcca2SKa Ho Ng 114*968bcca2SKa Ho Ng static GElf_Off 115*968bcca2SKa Ho Ng ef_obj_get_offset(elf_file_t ef, GElf_Addr addr) 116*968bcca2SKa Ho Ng { 117*968bcca2SKa Ho Ng Elf_progent *pt; 118*968bcca2SKa Ho Ng int i; 119*968bcca2SKa Ho Ng 120*968bcca2SKa Ho Ng for (i = 0; i < ef->nprogtab; i++) { 121*968bcca2SKa Ho Ng pt = &ef->progtab[i]; 122*968bcca2SKa Ho Ng if (pt->offset == (GElf_Off)-1) 123*968bcca2SKa Ho Ng continue; 124*968bcca2SKa Ho Ng if (addr >= pt->addr && addr < pt->addr + pt->size) 125*968bcca2SKa Ho Ng return (pt->offset + (addr - pt->addr)); 126*968bcca2SKa Ho Ng } 127*968bcca2SKa Ho Ng return (0); 128*968bcca2SKa Ho Ng } 129*968bcca2SKa Ho Ng 130*968bcca2SKa Ho Ng static int 131*968bcca2SKa Ho Ng ef_obj_lookup_symbol(elf_file_t ef, const char *name, GElf_Sym **sym) 132*968bcca2SKa Ho Ng { 133*968bcca2SKa Ho Ng GElf_Sym *symp; 134*968bcca2SKa Ho Ng const char *strp; 135*968bcca2SKa Ho Ng int i; 136*968bcca2SKa Ho Ng 137*968bcca2SKa Ho Ng for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 138*968bcca2SKa Ho Ng strp = ef->ddbstrtab + symp->st_name; 139*968bcca2SKa Ho Ng if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) { 140*968bcca2SKa Ho Ng *sym = symp; 141*968bcca2SKa Ho Ng return (0); 142*968bcca2SKa Ho Ng } 143*968bcca2SKa Ho Ng } 144*968bcca2SKa Ho Ng return (ENOENT); 145*968bcca2SKa Ho Ng } 146*968bcca2SKa Ho Ng 147*968bcca2SKa Ho Ng static int 148*968bcca2SKa Ho Ng ef_obj_lookup_set(elf_file_t ef, const char *name, GElf_Addr *startp, 149*968bcca2SKa Ho Ng GElf_Addr *stopp, long *countp) 150*968bcca2SKa Ho Ng { 151*968bcca2SKa Ho Ng int i; 152*968bcca2SKa Ho Ng 153*968bcca2SKa Ho Ng for (i = 0; i < ef->nprogtab; i++) { 154*968bcca2SKa Ho Ng if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) && 155*968bcca2SKa Ho Ng strcmp(ef->progtab[i].name + 4, name) == 0) { 156*968bcca2SKa Ho Ng *startp = ef->progtab[i].addr; 157*968bcca2SKa Ho Ng *stopp = ef->progtab[i].addr + ef->progtab[i].size; 158*968bcca2SKa Ho Ng *countp = (*stopp - *startp) / 159*968bcca2SKa Ho Ng elf_pointer_size(ef->ef_efile); 160*968bcca2SKa Ho Ng return (0); 161*968bcca2SKa Ho Ng } 162*968bcca2SKa Ho Ng } 163*968bcca2SKa Ho Ng return (ESRCH); 164*968bcca2SKa Ho Ng } 165*968bcca2SKa Ho Ng 166*968bcca2SKa Ho Ng static GElf_Addr 167*968bcca2SKa Ho Ng ef_obj_symaddr(elf_file_t ef, GElf_Size symidx) 168*968bcca2SKa Ho Ng { 169*968bcca2SKa Ho Ng const GElf_Sym *sym; 170*968bcca2SKa Ho Ng 171*968bcca2SKa Ho Ng if (symidx >= ef->ddbsymcnt) 172*968bcca2SKa Ho Ng return (0); 173*968bcca2SKa Ho Ng sym = ef->ddbsymtab + symidx; 174*968bcca2SKa Ho Ng 175*968bcca2SKa Ho Ng if (sym->st_shndx != SHN_UNDEF) 176*968bcca2SKa Ho Ng return (sym->st_value); 177*968bcca2SKa Ho Ng return (0); 178*968bcca2SKa Ho Ng } 179*968bcca2SKa Ho Ng 180*968bcca2SKa Ho Ng static int 181*968bcca2SKa Ho Ng ef_obj_seg_read_rel(elf_file_t ef, GElf_Addr address, size_t len, void *dest) 182*968bcca2SKa Ho Ng { 183*968bcca2SKa Ho Ng GElf_Off secofs; 184*968bcca2SKa Ho Ng GElf_Rel *r; 185*968bcca2SKa Ho Ng GElf_Rela *a; 186*968bcca2SKa Ho Ng GElf_Addr secbase, dataoff; 187*968bcca2SKa Ho Ng int error, i, sec; 188*968bcca2SKa Ho Ng 189*968bcca2SKa Ho Ng /* Find out which section contains the data. */ 190*968bcca2SKa Ho Ng sec = -1; 191*968bcca2SKa Ho Ng for (i = 0; i < ef->nprogtab; i++) { 192*968bcca2SKa Ho Ng if (address < ef->progtab[i].addr) 193*968bcca2SKa Ho Ng continue; 194*968bcca2SKa Ho Ng 195*968bcca2SKa Ho Ng dataoff = address - ef->progtab[i].addr; 196*968bcca2SKa Ho Ng if (dataoff + len > ef->progtab[i].size) 197*968bcca2SKa Ho Ng continue; 198*968bcca2SKa Ho Ng 199*968bcca2SKa Ho Ng sec = ef->progtab[i].sec; 200*968bcca2SKa Ho Ng secbase = ef->progtab[i].addr; 201*968bcca2SKa Ho Ng secofs = ef->progtab[i].offset; 202*968bcca2SKa Ho Ng break; 203*968bcca2SKa Ho Ng } 204*968bcca2SKa Ho Ng 205*968bcca2SKa Ho Ng if (sec == -1) { 206*968bcca2SKa Ho Ng if (ef->ef_verbose) 207*968bcca2SKa Ho Ng warnx("ef_obj_seg_read_rel(%s): bad address (%jx)", 208*968bcca2SKa Ho Ng ef->ef_name, (uintmax_t)address); 209*968bcca2SKa Ho Ng return (EFAULT); 210*968bcca2SKa Ho Ng } 211*968bcca2SKa Ho Ng 212*968bcca2SKa Ho Ng if (secofs == (GElf_Off)-1) { 213*968bcca2SKa Ho Ng memset(dest, 0, len); 214*968bcca2SKa Ho Ng } else { 215*968bcca2SKa Ho Ng error = elf_read_raw_data(ef->ef_efile, secofs + dataoff, dest, 216*968bcca2SKa Ho Ng len); 217*968bcca2SKa Ho Ng if (error != 0) 218*968bcca2SKa Ho Ng return (error); 219*968bcca2SKa Ho Ng } 220*968bcca2SKa Ho Ng 221*968bcca2SKa Ho Ng /* Now do the relocations. */ 222*968bcca2SKa Ho Ng for (i = 0; i < ef->nrel; i++) { 223*968bcca2SKa Ho Ng if (ef->reltab[i].sec != sec) 224*968bcca2SKa Ho Ng continue; 225*968bcca2SKa Ho Ng for (r = ef->reltab[i].rel; 226*968bcca2SKa Ho Ng r < &ef->reltab[i].rel[ef->reltab[i].nrel]; r++) { 227*968bcca2SKa Ho Ng error = elf_reloc(ef->ef_efile, r, ELF_T_REL, secbase, 228*968bcca2SKa Ho Ng address, len, dest); 229*968bcca2SKa Ho Ng if (error != 0) 230*968bcca2SKa Ho Ng return (error); 231*968bcca2SKa Ho Ng } 232*968bcca2SKa Ho Ng } 233*968bcca2SKa Ho Ng for (i = 0; i < ef->nrela; i++) { 234*968bcca2SKa Ho Ng if (ef->relatab[i].sec != sec) 235*968bcca2SKa Ho Ng continue; 236*968bcca2SKa Ho Ng for (a = ef->relatab[i].rela; 237*968bcca2SKa Ho Ng a < &ef->relatab[i].rela[ef->relatab[i].nrela]; a++) { 238*968bcca2SKa Ho Ng error = elf_reloc(ef->ef_efile, a, ELF_T_RELA, secbase, 239*968bcca2SKa Ho Ng address, len, dest); 240*968bcca2SKa Ho Ng if (error != 0) 241*968bcca2SKa Ho Ng return (error); 242*968bcca2SKa Ho Ng } 243*968bcca2SKa Ho Ng } 244*968bcca2SKa Ho Ng return (0); 245*968bcca2SKa Ho Ng } 246*968bcca2SKa Ho Ng 247*968bcca2SKa Ho Ng static int 248*968bcca2SKa Ho Ng ef_obj_seg_read_string(elf_file_t ef, GElf_Addr address, size_t len, char *dest) 249*968bcca2SKa Ho Ng { 250*968bcca2SKa Ho Ng GElf_Off ofs; 251*968bcca2SKa Ho Ng 252*968bcca2SKa Ho Ng ofs = ef_obj_get_offset(ef, address); 253*968bcca2SKa Ho Ng if (ofs == 0) { 254*968bcca2SKa Ho Ng if (ef->ef_verbose) 255*968bcca2SKa Ho Ng warnx("ef_obj_seg_read_string(%s): bad address (%jx)", 256*968bcca2SKa Ho Ng ef->ef_name, (uintmax_t)address); 257*968bcca2SKa Ho Ng return (EFAULT); 258*968bcca2SKa Ho Ng } 259*968bcca2SKa Ho Ng 260*968bcca2SKa Ho Ng return (elf_read_raw_string(ef->ef_efile, ofs, dest, len)); 261*968bcca2SKa Ho Ng } 262*968bcca2SKa Ho Ng 263*968bcca2SKa Ho Ng int 264*968bcca2SKa Ho Ng ef_obj_open(struct elf_file *efile, int verbose) 265*968bcca2SKa Ho Ng { 266*968bcca2SKa Ho Ng elf_file_t ef; 267*968bcca2SKa Ho Ng GElf_Ehdr *hdr; 268*968bcca2SKa Ho Ng GElf_Shdr *shdr; 269*968bcca2SKa Ho Ng GElf_Sym *es; 270*968bcca2SKa Ho Ng GElf_Addr mapbase; 271*968bcca2SKa Ho Ng size_t i, nshdr; 272*968bcca2SKa Ho Ng int error, pb, ra, rl; 273*968bcca2SKa Ho Ng int j, nsym, symstrindex, symtabindex; 274*968bcca2SKa Ho Ng 275*968bcca2SKa Ho Ng hdr = &efile->ef_hdr; 276*968bcca2SKa Ho Ng if (hdr->e_type != ET_REL || hdr->e_shnum == 0 || hdr->e_shoff == 0 || 277*968bcca2SKa Ho Ng hdr->e_shentsize != elf_object_size(efile, ELF_T_SHDR)) 278*968bcca2SKa Ho Ng return (EFTYPE); 279*968bcca2SKa Ho Ng 280*968bcca2SKa Ho Ng ef = calloc(1, sizeof(*ef)); 281*968bcca2SKa Ho Ng if (ef == NULL) 282*968bcca2SKa Ho Ng return (errno); 283*968bcca2SKa Ho Ng 284*968bcca2SKa Ho Ng efile->ef_ef = ef; 285*968bcca2SKa Ho Ng efile->ef_ops = &ef_obj_file_ops; 286*968bcca2SKa Ho Ng 287*968bcca2SKa Ho Ng ef->ef_verbose = verbose; 288*968bcca2SKa Ho Ng ef->ef_name = strdup(efile->ef_filename); 289*968bcca2SKa Ho Ng ef->ef_efile = efile; 290*968bcca2SKa Ho Ng 291*968bcca2SKa Ho Ng error = elf_read_shdrs(efile, &nshdr, &shdr); 292*968bcca2SKa Ho Ng if (error != 0) { 293*968bcca2SKa Ho Ng shdr = NULL; 294*968bcca2SKa Ho Ng goto out; 295*968bcca2SKa Ho Ng } 296*968bcca2SKa Ho Ng 297*968bcca2SKa Ho Ng /* Scan the section headers for information and table sizing. */ 298*968bcca2SKa Ho Ng nsym = 0; 299*968bcca2SKa Ho Ng symtabindex = -1; 300*968bcca2SKa Ho Ng symstrindex = -1; 301*968bcca2SKa Ho Ng for (i = 0; i < nshdr; i++) { 302*968bcca2SKa Ho Ng switch (shdr[i].sh_type) { 303*968bcca2SKa Ho Ng case SHT_PROGBITS: 304*968bcca2SKa Ho Ng case SHT_NOBITS: 305*968bcca2SKa Ho Ng ef->nprogtab++; 306*968bcca2SKa Ho Ng break; 307*968bcca2SKa Ho Ng case SHT_SYMTAB: 308*968bcca2SKa Ho Ng nsym++; 309*968bcca2SKa Ho Ng symtabindex = i; 310*968bcca2SKa Ho Ng symstrindex = shdr[i].sh_link; 311*968bcca2SKa Ho Ng break; 312*968bcca2SKa Ho Ng case SHT_REL: 313*968bcca2SKa Ho Ng ef->nrel++; 314*968bcca2SKa Ho Ng break; 315*968bcca2SKa Ho Ng case SHT_RELA: 316*968bcca2SKa Ho Ng ef->nrela++; 317*968bcca2SKa Ho Ng break; 318*968bcca2SKa Ho Ng case SHT_STRTAB: 319*968bcca2SKa Ho Ng break; 320*968bcca2SKa Ho Ng } 321*968bcca2SKa Ho Ng } 322*968bcca2SKa Ho Ng 323*968bcca2SKa Ho Ng if (ef->nprogtab == 0) { 324*968bcca2SKa Ho Ng warnx("%s: file has no contents", ef->ef_name); 325*968bcca2SKa Ho Ng goto out; 326*968bcca2SKa Ho Ng } 327*968bcca2SKa Ho Ng if (nsym != 1) { 328*968bcca2SKa Ho Ng warnx("%s: file has no valid symbol table", ef->ef_name); 329*968bcca2SKa Ho Ng goto out; 330*968bcca2SKa Ho Ng } 331*968bcca2SKa Ho Ng if (symstrindex < 0 || symstrindex > nshdr || 332*968bcca2SKa Ho Ng shdr[symstrindex].sh_type != SHT_STRTAB) { 333*968bcca2SKa Ho Ng warnx("%s: file has invalid symbol strings", ef->ef_name); 334*968bcca2SKa Ho Ng goto out; 335*968bcca2SKa Ho Ng } 336*968bcca2SKa Ho Ng 337*968bcca2SKa Ho Ng /* Allocate space for tracking the load chunks */ 338*968bcca2SKa Ho Ng if (ef->nprogtab != 0) 339*968bcca2SKa Ho Ng ef->progtab = calloc(ef->nprogtab, sizeof(*ef->progtab)); 340*968bcca2SKa Ho Ng if (ef->nrel != 0) 341*968bcca2SKa Ho Ng ef->reltab = calloc(ef->nrel, sizeof(*ef->reltab)); 342*968bcca2SKa Ho Ng if (ef->nrela != 0) 343*968bcca2SKa Ho Ng ef->relatab = calloc(ef->nrela, sizeof(*ef->relatab)); 344*968bcca2SKa Ho Ng if ((ef->nprogtab != 0 && ef->progtab == NULL) || 345*968bcca2SKa Ho Ng (ef->nrel != 0 && ef->reltab == NULL) || 346*968bcca2SKa Ho Ng (ef->nrela != 0 && ef->relatab == NULL)) { 347*968bcca2SKa Ho Ng printf("malloc failed\n"); 348*968bcca2SKa Ho Ng error = ENOMEM; 349*968bcca2SKa Ho Ng goto out; 350*968bcca2SKa Ho Ng } 351*968bcca2SKa Ho Ng 352*968bcca2SKa Ho Ng if (elf_read_symbols(efile, symtabindex, &ef->ddbsymcnt, 353*968bcca2SKa Ho Ng &ef->ddbsymtab) != 0) { 354*968bcca2SKa Ho Ng printf("elf_read_symbols failed\n"); 355*968bcca2SKa Ho Ng goto out; 356*968bcca2SKa Ho Ng } 357*968bcca2SKa Ho Ng 358*968bcca2SKa Ho Ng if (elf_read_string_table(efile, &shdr[symstrindex], &ef->ddbstrcnt, 359*968bcca2SKa Ho Ng &ef->ddbstrtab) != 0) { 360*968bcca2SKa Ho Ng printf("elf_read_string_table failed\n"); 361*968bcca2SKa Ho Ng goto out; 362*968bcca2SKa Ho Ng } 363*968bcca2SKa Ho Ng 364*968bcca2SKa Ho Ng /* Do we have a string table for the section names? */ 365*968bcca2SKa Ho Ng if (hdr->e_shstrndx != 0 && 366*968bcca2SKa Ho Ng shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) { 367*968bcca2SKa Ho Ng if (elf_read_string_table(efile, &shdr[hdr->e_shstrndx], 368*968bcca2SKa Ho Ng &ef->shstrcnt, &ef->shstrtab) != 0) { 369*968bcca2SKa Ho Ng printf("elf_read_string_table failed\n"); 370*968bcca2SKa Ho Ng goto out; 371*968bcca2SKa Ho Ng } 372*968bcca2SKa Ho Ng } 373*968bcca2SKa Ho Ng 374*968bcca2SKa Ho Ng /* 375*968bcca2SKa Ho Ng * Now allocate address space for code/data(progbits) and 376*968bcca2SKa Ho Ng * bss(nobits) and allocate space for and load relocs. 377*968bcca2SKa Ho Ng */ 378*968bcca2SKa Ho Ng pb = 0; 379*968bcca2SKa Ho Ng rl = 0; 380*968bcca2SKa Ho Ng ra = 0; 381*968bcca2SKa Ho Ng mapbase = 0; 382*968bcca2SKa Ho Ng for (i = 0; i < nshdr; i++) { 383*968bcca2SKa Ho Ng switch (shdr[i].sh_type) { 384*968bcca2SKa Ho Ng case SHT_PROGBITS: 385*968bcca2SKa Ho Ng case SHT_NOBITS: 386*968bcca2SKa Ho Ng mapbase = roundup2(mapbase, shdr[i].sh_addralign); 387*968bcca2SKa Ho Ng ef->progtab[pb].addr = mapbase; 388*968bcca2SKa Ho Ng if (shdr[i].sh_type == SHT_PROGBITS) { 389*968bcca2SKa Ho Ng ef->progtab[pb].name = "<<PROGBITS>>"; 390*968bcca2SKa Ho Ng ef->progtab[pb].offset = shdr[i].sh_offset; 391*968bcca2SKa Ho Ng } else { 392*968bcca2SKa Ho Ng ef->progtab[pb].name = "<<NOBITS>>"; 393*968bcca2SKa Ho Ng ef->progtab[pb].offset = (GElf_Off)-1; 394*968bcca2SKa Ho Ng } 395*968bcca2SKa Ho Ng ef->progtab[pb].size = shdr[i].sh_size; 396*968bcca2SKa Ho Ng ef->progtab[pb].sec = i; 397*968bcca2SKa Ho Ng if (ef->shstrtab && shdr[i].sh_name != 0) 398*968bcca2SKa Ho Ng ef->progtab[pb].name = 399*968bcca2SKa Ho Ng ef->shstrtab + shdr[i].sh_name; 400*968bcca2SKa Ho Ng 401*968bcca2SKa Ho Ng /* Update all symbol values with the offset. */ 402*968bcca2SKa Ho Ng for (j = 0; j < ef->ddbsymcnt; j++) { 403*968bcca2SKa Ho Ng es = &ef->ddbsymtab[j]; 404*968bcca2SKa Ho Ng if (es->st_shndx != i) 405*968bcca2SKa Ho Ng continue; 406*968bcca2SKa Ho Ng es->st_value += ef->progtab[pb].addr; 407*968bcca2SKa Ho Ng } 408*968bcca2SKa Ho Ng mapbase += shdr[i].sh_size; 409*968bcca2SKa Ho Ng pb++; 410*968bcca2SKa Ho Ng break; 411*968bcca2SKa Ho Ng case SHT_REL: 412*968bcca2SKa Ho Ng ef->reltab[rl].sec = shdr[i].sh_info; 413*968bcca2SKa Ho Ng if (elf_read_rel(efile, i, &ef->reltab[rl].nrel, 414*968bcca2SKa Ho Ng &ef->reltab[rl].rel) != 0) { 415*968bcca2SKa Ho Ng printf("elf_read_rel failed\n"); 416*968bcca2SKa Ho Ng goto out; 417*968bcca2SKa Ho Ng } 418*968bcca2SKa Ho Ng rl++; 419*968bcca2SKa Ho Ng break; 420*968bcca2SKa Ho Ng case SHT_RELA: 421*968bcca2SKa Ho Ng ef->relatab[ra].sec = shdr[i].sh_info; 422*968bcca2SKa Ho Ng if (elf_read_rela(efile, i, &ef->relatab[ra].nrela, 423*968bcca2SKa Ho Ng &ef->relatab[ra].rela) != 0) { 424*968bcca2SKa Ho Ng printf("elf_read_rela failed\n"); 425*968bcca2SKa Ho Ng goto out; 426*968bcca2SKa Ho Ng } 427*968bcca2SKa Ho Ng ra++; 428*968bcca2SKa Ho Ng break; 429*968bcca2SKa Ho Ng } 430*968bcca2SKa Ho Ng } 431*968bcca2SKa Ho Ng error = 0; 432*968bcca2SKa Ho Ng out: 433*968bcca2SKa Ho Ng free(shdr); 434*968bcca2SKa Ho Ng if (error != 0) 435*968bcca2SKa Ho Ng ef_obj_close(ef); 436*968bcca2SKa Ho Ng return (error); 437*968bcca2SKa Ho Ng } 438*968bcca2SKa Ho Ng 439*968bcca2SKa Ho Ng static void 440*968bcca2SKa Ho Ng ef_obj_close(elf_file_t ef) 441*968bcca2SKa Ho Ng { 442*968bcca2SKa Ho Ng int i; 443*968bcca2SKa Ho Ng 444*968bcca2SKa Ho Ng if (ef->ef_name) 445*968bcca2SKa Ho Ng free(ef->ef_name); 446*968bcca2SKa Ho Ng if (ef->nprogtab != 0) 447*968bcca2SKa Ho Ng free(ef->progtab); 448*968bcca2SKa Ho Ng if (ef->nrel != 0) { 449*968bcca2SKa Ho Ng for (i = 0; i < ef->nrel; i++) 450*968bcca2SKa Ho Ng if (ef->reltab[i].rel != NULL) 451*968bcca2SKa Ho Ng free(ef->reltab[i].rel); 452*968bcca2SKa Ho Ng free(ef->reltab); 453*968bcca2SKa Ho Ng } 454*968bcca2SKa Ho Ng if (ef->nrela != 0) { 455*968bcca2SKa Ho Ng for (i = 0; i < ef->nrela; i++) 456*968bcca2SKa Ho Ng if (ef->relatab[i].rela != NULL) 457*968bcca2SKa Ho Ng free(ef->relatab[i].rela); 458*968bcca2SKa Ho Ng free(ef->relatab); 459*968bcca2SKa Ho Ng } 460*968bcca2SKa Ho Ng if (ef->ddbsymtab != NULL) 461*968bcca2SKa Ho Ng free(ef->ddbsymtab); 462*968bcca2SKa Ho Ng if (ef->ddbstrtab != NULL) 463*968bcca2SKa Ho Ng free(ef->ddbstrtab); 464*968bcca2SKa Ho Ng if (ef->shstrtab != NULL) 465*968bcca2SKa Ho Ng free(ef->shstrtab); 466*968bcca2SKa Ho Ng ef->ef_efile->ef_ops = NULL; 467*968bcca2SKa Ho Ng ef->ef_efile->ef_ef = NULL; 468*968bcca2SKa Ho Ng free(ef); 469*968bcca2SKa Ho Ng } 470