2 * Parse 32-bit ELF files.
3 * Copyright (c) 2004 Russ Cox. See LICENSE.
11 typedef struct ElfHdrBytes ElfHdrBytes;
12 typedef struct ElfSectBytes ElfSectBytes;
13 typedef struct ElfProgBytes ElfProgBytes;
14 typedef struct ElfSymBytes ElfSymBytes;
16 typedef struct ElfHdrBytes64 ElfHdrBytes64;
17 typedef struct ElfSectBytes64 ElfSectBytes64;
18 typedef struct ElfProgBytes64 ElfProgBytes64;
19 typedef struct ElfSymBytes64 ElfSymBytes64;
90 uchar info; /* top4: bind, bottom4: type */
117 struct ElfProgBytes64
129 uchar ElfMagic[4] = { 0x7F, 'E', 'L', 'F' };
131 static void unpackhdr(ElfHdr*, void*);
132 static void unpackprog(ElfHdr*, ElfProg*, void*);
133 static void unpacksect(ElfHdr*, ElfSect*, void*);
135 static char *elftypes[] = {
146 if(t < 0 || t >= nelem(elftypes))
151 static char *elfmachs[] = {
166 if(t < 0 || t >= nelem(elfmachs))
177 if((fd = open(name, OREAD)) < 0)
179 if((e = elfinit(fd)) == nil)
197 e = mallocz(sizeof(Elf), 1);
206 if(readn(fd, &hdrb, sizeof hdrb) != sizeof hdrb)
210 if(h->class != ElfClass32 && h->class != ElfClass64){
211 werrstr("bad ELF class - not 32-bit, 64-bit");
214 if(h->encoding != ElfDataLsb && h->encoding != ElfDataMsb){
215 werrstr("bad ELF encoding - not LSB, MSB");
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);
225 * the prog+section info is almost always small - just load it into memory.
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)
234 unpackprog(h, &e->prog[i], p);
241 e->sect = mallocz(sizeof(ElfSect)*e->nsect, 1);
242 p = mallocz(h->shentsize, 1);
243 for(i=0; i<e->nsect; i++){
244 if(seek(fd, h->shoff+i*h->shentsize, 0) < 0
245 || readn(fd, p, h->shentsize) != h->shentsize)
247 unpacksect(h, &e->sect[i], p);
251 if(h->shstrndx >= e->nsect){
252 fprint(2, "warning: bad string section index %d >= %d", h->shstrndx, e->nsect);
257 s = &e->sect[h->shstrndx];
261 for(i=0; i<e->nsect; i++)
263 e->sect[i].name = (char*)s->base + (ulong)e->sect[i].name;
265 e->symtab = elfsection(e, ".symtab");
267 if(e->symtab->link >= e->nsect)
270 e->symstr = &e->sect[e->symtab->link];
271 e->nsymtab = e->symtab->size / sizeof(ElfSymBytes);
274 e->dynsym = elfsection(e, ".dynsym");
276 if(e->dynsym->link >= e->nsect)
279 e->dynstr = &e->sect[e->dynsym->link];
280 e->ndynsym = e->dynsym->size / sizeof(ElfSymBytes);
284 e->bss = elfsection(e, ".bss");
302 for(i=0; i<elf->nsect; i++)
303 free(elf->sect[i].base);
311 unpackhdr(ElfHdr *h, void *v)
313 u16int (*e2)(uchar*);
314 u32int (*e4)(uchar*);
315 u64int (*e8)(uchar*);
320 memmove(h->magic, b->ident, 4);
321 h->class = b->ident[4];
322 h->encoding = b->ident[5];
337 h->abi = b->ident[7];
338 h->abiversion = b->ident[8];
344 if(h->class == ElfClass64)
347 h->type = e2(b->type);
348 h->machine = e2(b->machine);
349 h->version = e4(b->version);
350 h->entry = e4(b->entry);
351 h->phoff = e4(b->phoff);
352 h->shoff = e4(b->shoff);
353 h->flags = e4(b->flags);
354 h->ehsize = e2(b->ehsize);
355 h->phentsize = e2(b->phentsize);
356 h->phnum = e2(b->phnum);
357 h->shentsize = e2(b->shentsize);
358 h->shnum = e2(b->shnum);
359 h->shstrndx = e2(b->shstrndx);
364 h->type = e2(b64->type);
365 h->machine = e2(b64->machine);
366 h->version = e4(b64->version);
367 h->entry = e8(b64->entry);
368 h->phoff = e8(b64->phoff);
369 h->shoff = e8(b64->shoff);
370 h->flags = e4(b64->flags);
371 h->ehsize = e2(b64->ehsize);
372 h->phentsize = e2(b64->phentsize);
373 h->phnum = e2(b64->phnum);
374 h->shentsize = e2(b64->shentsize);
375 h->shnum = e2(b64->shnum);
376 h->shstrndx = e2(b64->shstrndx);
381 unpackprog(ElfHdr *h, ElfProg *p, void *v)
383 u32int (*e4)(uchar*);
384 u64int (*e8)(uchar*);
386 if(h->class == ElfClass32) {
391 p->type = e4(b->type);
392 p->offset = e4(b->offset);
393 p->vaddr = e4(b->vaddr);
394 p->paddr = e4(b->paddr);
395 p->filesz = e4(b->filesz);
396 p->memsz = e4(b->memsz);
397 p->flags = e4(b->flags);
398 p->align = e4(b->align);
405 p->type = e4(b->type);
406 p->offset = e8(b->offset);
407 p->vaddr = e8(b->vaddr);
408 p->paddr = e8(b->paddr);
409 p->filesz = e8(b->filesz);
410 p->memsz = e8(b->memsz);
411 p->flags = e4(b->flags);
412 p->align = e8(b->align);
417 unpacksect(ElfHdr *h, ElfSect *s, void *v)
419 u32int (*e4)(uchar*);
420 u64int (*e8)(uchar*);
422 if(h->class == ElfClass32) {
427 s->name = (char*)(uintptr)e4(b->name);
428 s->type = e4(b->type);
429 s->flags = e4(b->flags);
430 s->addr = e4(b->addr);
431 s->offset = e4(b->offset);
432 s->size = e4(b->size);
433 s->link = e4(b->link);
434 s->info = e4(b->info);
435 s->align = e4(b->align);
436 s->entsize = e4(b->entsize);
443 s->name = (char*)(uintptr)e4(b->name);
444 s->type = e4(b->type);
445 s->flags = e8(b->flags);
446 s->addr = e8(b->addr);
447 s->offset = e8(b->offset);
448 s->size = e8(b->size);
449 s->link = e4(b->link);
450 s->info = e4(b->info);
451 s->align = e8(b->align);
452 s->entsize = e8(b->entsize);
457 elfsection(Elf *elf, char *name)
461 for(i=0; i<elf->nsect; i++){
462 if(elf->sect[i].name == name)
463 return &elf->sect[i];
464 if(elf->sect[i].name && name
465 && strcmp(elf->sect[i].name, name) == 0)
466 return &elf->sect[i];
468 werrstr("elf section '%s' not found", name);
473 elfmap(Elf *elf, ElfSect *sect)
477 if((sect->base = malloc(sect->size)) == nil)
479 werrstr("short read");
480 if(seek(elf->fd, sect->offset, 0) < 0
481 || readn(elf->fd, sect->base, sect->size) != sect->size){
490 elfsym(Elf *elf, int i, ElfSym *sym)
492 ElfSect *symtab, *strtab;
498 werrstr("bad index %d in elfsym", i);
502 if(i < elf->nsymtab){
503 symtab = elf->symtab;
504 strtab = elf->symstr;
506 if(elfmap(elf, symtab) < 0 || elfmap(elf, strtab) < 0)
508 if(elf->hdr.class == ElfClass32) {
509 p = symtab->base + i * sizeof(ElfSymBytes);
510 s = (char*)strtab->base;
512 if(x >= strtab->size){
513 werrstr("bad symbol name offset 0x%lux", x);
517 sym->value = elf->hdr.e4(p+4);
518 sym->size = elf->hdr.e4(p+8);
523 sym->shndx = elf->hdr.e2(p+14);
525 p = symtab->base + i * sizeof(ElfSymBytes64);
526 s = (char*)strtab->base;
528 if(x >= strtab->size){
529 werrstr("bad symbol name offset 0x%lux", x);
537 sym->shndx = elf->hdr.e2(p+6);
538 sym->value = elf->hdr.e8(p+8);
539 sym->size = elf->hdr.e8(p+16);
544 if(i < elf->ndynsym){
545 symtab = elf->dynsym;
546 strtab = elf->dynstr;
549 /* i -= elf->ndynsym */
551 werrstr("symbol index out of range");