| #include <u.h> |
| #include <libc.h> |
| #include <bio.h> |
| #include <mach.h> |
| #include "elf.h" |
| #include "stabs.h" |
| |
| void |
| usage(void) |
| { |
| fprint(2, "usage: elf file list\n"); |
| fprint(2, " elf file syms\n"); |
| fprint(2, " elf file prog n\n"); |
| fprint(2, " elf file sect n\n"); |
| exits("usage"); |
| } |
| |
| void |
| main(int argc, char **argv) |
| { |
| int i, n, nn; |
| char buf[512]; |
| ulong off, len; |
| Elf *elf; |
| ElfProg *p; |
| ElfSect *s; |
| |
| ARGBEGIN{ |
| default: |
| usage(); |
| }ARGEND |
| |
| if(argc < 2) |
| usage(); |
| |
| if((elf = elfopen(argv[0])) == nil) |
| sysfatal("elfopen %s: %r", argv[0]); |
| |
| if(strcmp(argv[1], "syms") == 0){ |
| ElfSym sym; |
| for(i=0; elfsym(elf, i, &sym) >= 0; i++){ |
| print("%s 0x%lux +%lud bind %d type %d other %d shndx 0x%ux\n", |
| sym.name, (ulong)sym.value, (ulong)sym.size, |
| sym.bind, sym.type, sym.other, (uint)sym.shndx); |
| } |
| } |
| else if(strcmp(argv[1], "stabs") == 0){ |
| ElfSect *s1, *s2; |
| Stab stabs; |
| StabSym sym; |
| |
| if((s1 = elfsection(elf, ".stab")) == nil) |
| sysfatal("no stabs"); |
| if(s1->link==0 || s1->link >= elf->nsect) |
| sysfatal("bad stabstr %d", s1->link); |
| s2 = &elf->sect[s1->link]; |
| if(elfmap(elf, s1) < 0 || elfmap(elf, s2) < 0) |
| sysfatal("elfmap"); |
| stabs.stabbase = s1->base; |
| stabs.stabsize = s1->size; |
| stabs.strbase = s2->base; |
| stabs.strsize = s2->size; |
| stabs.e2 = elf->hdr.e2; |
| stabs.e4 = elf->hdr.e4; |
| print("%ud %ud\n", stabs.stabsize, stabs.strsize); |
| for(i=0; stabsym(&stabs, i, &sym) >= 0; i++) |
| print("%s type 0x%x other %d desc %d value 0x%lux\n", |
| sym.name, sym.type, sym.other, (int)sym.desc, (ulong)sym.value); |
| fprint(2, "err at %d: %r\n", i); |
| } |
| else if(strcmp(argv[1], "list") == 0){ |
| if(argc != 2) |
| usage(); |
| print("elf %s %s v%d entry 0x%08lux phoff 0x%lux shoff 0x%lux flags 0x%lux\n", |
| elftype(elf->hdr.type), elfmachine(elf->hdr.machine), |
| elf->hdr.version, elf->hdr.entry, elf->hdr.phoff, elf->hdr.shoff, |
| elf->hdr.flags); |
| print("\tehsize %d phentsize %d phnum %d shentsize %d shnum %d shstrndx %d\n", |
| elf->hdr.ehsize, elf->hdr.phentsize, elf->hdr.phnum, elf->hdr.shentsize, |
| elf->hdr.shnum, elf->hdr.shstrndx); |
| for(i=0; i<elf->nprog; i++){ |
| p = &elf->prog[i]; |
| print("prog %d type %d offset 0x%08lux vaddr 0x%08lux paddr 0x%08lux filesz 0x%08lux memsz 0x%08lux flags 0x%08lux align 0x%08lux\n", |
| i, p->type, p->offset, p->vaddr, p->paddr, |
| p->filesz, p->memsz, p->flags, p->align); |
| } |
| for(i=0; i<elf->nsect; i++){ |
| s = &elf->sect[i]; |
| print("sect %d %s type %d flags 0x%lux addr 0x%08lux offset 0x%08lux size 0x%08lux link 0x%lux info 0x%lux align 0x%lux entsize 0x%lux\n", |
| i, s->name, s->type, s->flags, s->addr, s->offset, s->size, s->link, s->info, |
| s->align, s->entsize); |
| } |
| } |
| else if(strcmp(argv[1], "prog") == 0){ |
| if(argc != 3) |
| usage(); |
| i = atoi(argv[2]); |
| if(i < 0 || i >= elf->nprog) |
| sysfatal("bad prog number"); |
| off = elf->prog[i].offset; |
| len = elf->prog[i].filesz; |
| fprint(2, "prog %d offset 0x%lux size 0x%lux\n", i, off, len); |
| copy: |
| seek(elf->fd, off, 0); |
| for(n=0; n<len; n+=nn){ |
| nn = sizeof buf; |
| if(nn > len-n) |
| nn = len-n; |
| nn = read(elf->fd, buf, nn); |
| if(nn == 0) |
| break; |
| if(nn < 0) |
| sysfatal("read error"); |
| write(1, buf, nn); |
| } |
| if(n < len) |
| fprint(2, "early eof\n"); |
| } |
| else if(strcmp(argv[1], "sect") == 0){ |
| if(argc != 3) |
| usage(); |
| i = atoi(argv[2]); |
| if(i < 0 || i >= elf->nsect) |
| sysfatal("bad section number"); |
| off = elf->sect[i].offset; |
| len = elf->sect[i].size; |
| fprint(2, "section %d offset 0x%lux size 0x%lux\n", i, off, len); |
| goto copy; |
| } |
| else |
| usage(); |
| exits(0); |
| } |