elf.c (10236B)
1 /* 2 * Parse 32-bit ELF files. 3 * Copyright (c) 2004 Russ Cox. See LICENSE. 4 */ 5 6 #include <u.h> 7 #include <libc.h> 8 #include <mach.h> 9 #include "elf.h" 10 11 typedef struct ElfHdrBytes ElfHdrBytes; 12 typedef struct ElfSectBytes ElfSectBytes; 13 typedef struct ElfProgBytes ElfProgBytes; 14 typedef struct ElfSymBytes ElfSymBytes; 15 16 typedef struct ElfHdrBytes64 ElfHdrBytes64; 17 typedef struct ElfSectBytes64 ElfSectBytes64; 18 typedef struct ElfProgBytes64 ElfProgBytes64; 19 typedef struct ElfSymBytes64 ElfSymBytes64; 20 21 struct ElfHdrBytes 22 { 23 uchar ident[16]; 24 uchar type[2]; 25 uchar machine[2]; 26 uchar version[4]; 27 uchar entry[4]; 28 uchar phoff[4]; 29 uchar shoff[4]; 30 uchar flags[4]; 31 uchar ehsize[2]; 32 uchar phentsize[2]; 33 uchar phnum[2]; 34 uchar shentsize[2]; 35 uchar shnum[2]; 36 uchar shstrndx[2]; 37 }; 38 39 struct ElfHdrBytes64 40 { 41 uchar ident[16]; 42 uchar type[2]; 43 uchar machine[2]; 44 uchar version[4]; 45 uchar entry[8]; 46 uchar phoff[8]; 47 uchar shoff[8]; 48 uchar flags[4]; 49 uchar ehsize[2]; 50 uchar phentsize[2]; 51 uchar phnum[2]; 52 uchar shentsize[2]; 53 uchar shnum[2]; 54 uchar shstrndx[2]; 55 }; 56 57 struct ElfSectBytes 58 { 59 uchar name[4]; 60 uchar type[4]; 61 uchar flags[4]; 62 uchar addr[4]; 63 uchar offset[4]; 64 uchar size[4]; 65 uchar link[4]; 66 uchar info[4]; 67 uchar align[4]; 68 uchar entsize[4]; 69 }; 70 71 struct ElfSectBytes64 72 { 73 uchar name[4]; 74 uchar type[4]; 75 uchar flags[8]; 76 uchar addr[8]; 77 uchar offset[8]; 78 uchar size[8]; 79 uchar link[4]; 80 uchar info[4]; 81 uchar align[8]; 82 uchar entsize[8]; 83 }; 84 85 struct ElfSymBytes 86 { 87 uchar name[4]; 88 uchar value[4]; 89 uchar size[4]; 90 uchar info; /* top4: bind, bottom4: type */ 91 uchar other; 92 uchar shndx[2]; 93 }; 94 95 struct ElfSymBytes64 96 { 97 uchar name[4]; 98 uchar info; 99 uchar other; 100 uchar shndx[2]; 101 uchar value[8]; 102 uchar size[8]; 103 }; 104 105 struct ElfProgBytes 106 { 107 uchar type[4]; 108 uchar offset[4]; 109 uchar vaddr[4]; 110 uchar paddr[4]; 111 uchar filesz[4]; 112 uchar memsz[4]; 113 uchar flags[4]; 114 uchar align[4]; 115 }; 116 117 struct ElfProgBytes64 118 { 119 uchar type[4]; 120 uchar flags[4]; 121 uchar offset[8]; 122 uchar vaddr[8]; 123 uchar paddr[8]; 124 uchar filesz[8]; 125 uchar memsz[8]; 126 uchar align[8]; 127 }; 128 129 uchar ElfMagic[4] = { 0x7F, 'E', 'L', 'F' }; 130 131 static void unpackhdr(ElfHdr*, void*); 132 static void unpackprog(ElfHdr*, ElfProg*, void*); 133 static void unpacksect(ElfHdr*, ElfSect*, void*); 134 135 static char *elftypes[] = { 136 "none", 137 "relocatable", 138 "executable", 139 "shared object", 140 "core", 141 }; 142 143 char* 144 elftype(int t) 145 { 146 if(t < 0 || t >= nelem(elftypes)) 147 return "unknown"; 148 return elftypes[t]; 149 } 150 151 static char *elfmachs[] = { 152 "none", 153 "32100", 154 "sparc", 155 "386", 156 "68000", 157 "88000", 158 "486", 159 "860", 160 "MIPS", 161 }; 162 163 char* 164 elfmachine(int t) 165 { 166 if(t < 0 || t >= nelem(elfmachs)) 167 return "unknown"; 168 return elfmachs[t]; 169 } 170 171 Elf* 172 elfopen(char *name) 173 { 174 int fd; 175 Elf *e; 176 177 if((fd = open(name, OREAD)) < 0) 178 return nil; 179 if((e = elfinit(fd)) == nil) 180 close(fd); 181 return e; 182 } 183 184 Elf* 185 elfinit(int fd) 186 { 187 int i; 188 Elf *e; 189 ElfHdr *h; 190 union { 191 ElfHdrBytes h32; 192 ElfHdrBytes64 h64; 193 } hdrb; 194 void *p = nil; 195 ElfSect *s; 196 197 e = mallocz(sizeof(Elf), 1); 198 if(e == nil) 199 return nil; 200 e->fd = fd; 201 202 /* 203 * parse header 204 */ 205 seek(fd, 0, 0); 206 if(readn(fd, &hdrb, sizeof hdrb) != sizeof hdrb) 207 goto err; 208 h = &e->hdr; 209 unpackhdr(h, &hdrb); 210 if(h->class != ElfClass32 && h->class != ElfClass64){ 211 werrstr("bad ELF class - not 32-bit, 64-bit"); 212 goto err; 213 } 214 if(h->encoding != ElfDataLsb && h->encoding != ElfDataMsb){ 215 werrstr("bad ELF encoding - not LSB, MSB"); 216 goto err; 217 } 218 if(hdrb.h32.ident[6] != h->version){ 219 werrstr("bad ELF encoding - version mismatch %02ux and %08ux", 220 (uint)hdrb.h32.ident[6], (uint)h->version); 221 goto err; 222 } 223 224 /* 225 * the prog+section info is almost always small - just load it into memory. 226 */ 227 e->nprog = h->phnum; 228 e->prog = mallocz(sizeof(ElfProg)*e->nprog, 1); 229 p = mallocz(h->phentsize, 1); 230 for(i=0; i<e->nprog; i++){ 231 if(seek(fd, h->phoff+i*h->phentsize, 0) < 0 232 || readn(fd, p, h->phentsize) != h->phentsize) 233 goto err; 234 unpackprog(h, &e->prog[i], p); 235 } 236 free(p); 237 p = nil; 238 239 e->nsect = h->shnum; 240 if(e->nsect == 0) 241 goto nosects; 242 e->sect = mallocz(sizeof(ElfSect)*e->nsect, 1); 243 p = mallocz(h->shentsize, 1); 244 for(i=0; i<e->nsect; i++){ 245 if(seek(fd, h->shoff+i*h->shentsize, 0) < 0 246 || readn(fd, p, h->shentsize) != h->shentsize) 247 goto err; 248 unpacksect(h, &e->sect[i], p); 249 } 250 free(p); 251 p = nil; 252 253 if(h->shstrndx >= e->nsect){ 254 fprint(2, "warning: bad string section index %d >= %d", h->shstrndx, e->nsect); 255 h->shnum = 0; 256 e->nsect = 0; 257 goto nosects; 258 } 259 s = &e->sect[h->shstrndx]; 260 if(elfmap(e, s) < 0) 261 goto err; 262 263 for(i=0; i<e->nsect; i++) 264 if(e->sect[i].name) 265 e->sect[i].name = (char*)s->base + (ulong)e->sect[i].name; 266 267 e->symtab = elfsection(e, ".symtab"); 268 if(e->symtab){ 269 if(e->symtab->link >= e->nsect) 270 e->symtab = nil; 271 else{ 272 e->symstr = &e->sect[e->symtab->link]; 273 e->nsymtab = e->symtab->size / sizeof(ElfSymBytes); 274 } 275 } 276 e->dynsym = elfsection(e, ".dynsym"); 277 if(e->dynsym){ 278 if(e->dynsym->link >= e->nsect) 279 e->dynsym = nil; 280 else{ 281 e->dynstr = &e->sect[e->dynsym->link]; 282 e->ndynsym = e->dynsym->size / sizeof(ElfSymBytes); 283 } 284 } 285 286 e->bss = elfsection(e, ".bss"); 287 288 nosects: 289 return e; 290 291 err: 292 free(p); 293 free(e->sect); 294 free(e->prog); 295 free(e->shstrtab); 296 free(e); 297 return nil; 298 } 299 300 void 301 elfclose(Elf *elf) 302 { 303 int i; 304 305 for(i=0; i<elf->nsect; i++) 306 free(elf->sect[i].base); 307 free(elf->sect); 308 free(elf->prog); 309 free(elf->shstrtab); 310 free(elf); 311 } 312 313 static void 314 unpackhdr(ElfHdr *h, void *v) 315 { 316 u16int (*e2)(uchar*); 317 u32int (*e4)(uchar*); 318 u64int (*e8)(uchar*); 319 ElfHdrBytes *b; 320 ElfHdrBytes64 *b64; 321 322 b = v; 323 memmove(h->magic, b->ident, 4); 324 h->class = b->ident[4]; 325 h->encoding = b->ident[5]; 326 switch(h->encoding){ 327 case ElfDataLsb: 328 e2 = leload2; 329 e4 = leload4; 330 e8 = leload8; 331 break; 332 case ElfDataMsb: 333 e2 = beload2; 334 e4 = beload4; 335 e8 = beload8; 336 break; 337 default: 338 return; 339 } 340 h->abi = b->ident[7]; 341 h->abiversion = b->ident[8]; 342 343 h->e2 = e2; 344 h->e4 = e4; 345 h->e8 = e8; 346 347 if(h->class == ElfClass64) 348 goto b64; 349 350 h->type = e2(b->type); 351 h->machine = e2(b->machine); 352 h->version = e4(b->version); 353 h->entry = e4(b->entry); 354 h->phoff = e4(b->phoff); 355 h->shoff = e4(b->shoff); 356 h->flags = e4(b->flags); 357 h->ehsize = e2(b->ehsize); 358 h->phentsize = e2(b->phentsize); 359 h->phnum = e2(b->phnum); 360 h->shentsize = e2(b->shentsize); 361 h->shnum = e2(b->shnum); 362 h->shstrndx = e2(b->shstrndx); 363 return; 364 365 b64: 366 b64 = v; 367 h->type = e2(b64->type); 368 h->machine = e2(b64->machine); 369 h->version = e4(b64->version); 370 h->entry = e8(b64->entry); 371 h->phoff = e8(b64->phoff); 372 h->shoff = e8(b64->shoff); 373 h->flags = e4(b64->flags); 374 h->ehsize = e2(b64->ehsize); 375 h->phentsize = e2(b64->phentsize); 376 h->phnum = e2(b64->phnum); 377 h->shentsize = e2(b64->shentsize); 378 h->shnum = e2(b64->shnum); 379 h->shstrndx = e2(b64->shstrndx); 380 return; 381 } 382 383 static void 384 unpackprog(ElfHdr *h, ElfProg *p, void *v) 385 { 386 u32int (*e4)(uchar*); 387 u64int (*e8)(uchar*); 388 389 if(h->class == ElfClass32) { 390 ElfProgBytes *b; 391 392 b = v; 393 e4 = h->e4; 394 p->type = e4(b->type); 395 p->offset = e4(b->offset); 396 p->vaddr = e4(b->vaddr); 397 p->paddr = e4(b->paddr); 398 p->filesz = e4(b->filesz); 399 p->memsz = e4(b->memsz); 400 p->flags = e4(b->flags); 401 p->align = e4(b->align); 402 } else { 403 ElfProgBytes64 *b; 404 405 b = v; 406 e4 = h->e4; 407 e8 = h->e8; 408 p->type = e4(b->type); 409 p->offset = e8(b->offset); 410 p->vaddr = e8(b->vaddr); 411 p->paddr = e8(b->paddr); 412 p->filesz = e8(b->filesz); 413 p->memsz = e8(b->memsz); 414 p->flags = e4(b->flags); 415 p->align = e8(b->align); 416 } 417 } 418 419 static void 420 unpacksect(ElfHdr *h, ElfSect *s, void *v) 421 { 422 u32int (*e4)(uchar*); 423 u64int (*e8)(uchar*); 424 425 if(h->class == ElfClass32) { 426 ElfSectBytes *b; 427 428 b = v; 429 e4 = h->e4; 430 s->name = (char*)(uintptr)e4(b->name); 431 s->type = e4(b->type); 432 s->flags = e4(b->flags); 433 s->addr = e4(b->addr); 434 s->offset = e4(b->offset); 435 s->size = e4(b->size); 436 s->link = e4(b->link); 437 s->info = e4(b->info); 438 s->align = e4(b->align); 439 s->entsize = e4(b->entsize); 440 } else { 441 ElfSectBytes64 *b; 442 443 b = v; 444 e4 = h->e4; 445 e8 = h->e8; 446 s->name = (char*)(uintptr)e4(b->name); 447 s->type = e4(b->type); 448 s->flags = e8(b->flags); 449 s->addr = e8(b->addr); 450 s->offset = e8(b->offset); 451 s->size = e8(b->size); 452 s->link = e4(b->link); 453 s->info = e4(b->info); 454 s->align = e8(b->align); 455 s->entsize = e8(b->entsize); 456 } 457 } 458 459 ElfSect* 460 elfsection(Elf *elf, char *name) 461 { 462 int i; 463 464 for(i=0; i<elf->nsect; i++){ 465 if(elf->sect[i].name == name) 466 return &elf->sect[i]; 467 if(elf->sect[i].name && name 468 && strcmp(elf->sect[i].name, name) == 0) 469 return &elf->sect[i]; 470 } 471 werrstr("elf section '%s' not found", name); 472 return nil; 473 } 474 475 int 476 elfmap(Elf *elf, ElfSect *sect) 477 { 478 if(sect->base) 479 return 0; 480 if((sect->base = malloc(sect->size)) == nil) 481 return -1; 482 werrstr("short read"); 483 if(seek(elf->fd, sect->offset, 0) < 0 484 || readn(elf->fd, sect->base, sect->size) != sect->size){ 485 free(sect->base); 486 sect->base = nil; 487 return -1; 488 } 489 return 0; 490 } 491 492 int 493 elfsym(Elf *elf, int i, ElfSym *sym) 494 { 495 ElfSect *symtab, *strtab; 496 uchar *p; 497 char *s; 498 ulong x; 499 500 if(i < 0){ 501 werrstr("bad index %d in elfsym", i); 502 return -1; 503 } 504 505 if(i < elf->nsymtab){ 506 symtab = elf->symtab; 507 strtab = elf->symstr; 508 extract: 509 if(elfmap(elf, symtab) < 0 || elfmap(elf, strtab) < 0) 510 return -1; 511 if(elf->hdr.class == ElfClass32) { 512 p = symtab->base + i * sizeof(ElfSymBytes); 513 s = (char*)strtab->base; 514 x = elf->hdr.e4(p); 515 if(x >= strtab->size){ 516 werrstr("bad symbol name offset 0x%lux", x); 517 return -1; 518 } 519 sym->name = s + x; 520 sym->value = elf->hdr.e4(p+4); 521 sym->size = elf->hdr.e4(p+8); 522 x = p[12]; 523 sym->bind = x>>4; 524 sym->type = x & 0xF; 525 sym->other = p[13]; 526 sym->shndx = elf->hdr.e2(p+14); 527 } else { 528 p = symtab->base + i * sizeof(ElfSymBytes64); 529 s = (char*)strtab->base; 530 x = elf->hdr.e4(p); 531 if(x >= strtab->size){ 532 werrstr("bad symbol name offset 0x%lux", x); 533 return -1; 534 } 535 sym->name = s + x; 536 x = p[4]; 537 sym->bind = x>>4; 538 sym->type = x & 0xF; 539 sym->other = p[5]; 540 sym->shndx = elf->hdr.e2(p+6); 541 sym->value = elf->hdr.e8(p+8); 542 sym->size = elf->hdr.e8(p+16); 543 } 544 return 0; 545 } 546 i -= elf->nsymtab; 547 if(i < elf->ndynsym){ 548 symtab = elf->dynsym; 549 strtab = elf->dynstr; 550 goto extract; 551 } 552 /* i -= elf->ndynsym */ 553 554 werrstr("symbol index out of range"); 555 return -1; 556 }