diff options
Diffstat (limited to 'src/libmach/elfdl386.c')
-rw-r--r-- | src/libmach/elfdl386.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/libmach/elfdl386.c b/src/libmach/elfdl386.c new file mode 100644 index 00000000..104e5a95 --- /dev/null +++ b/src/libmach/elfdl386.c @@ -0,0 +1,133 @@ +#include <u.h> +#include <libc.h> +#include <mach.h> +#include "elf.h" + +/* +aggr Linkdebug +{ + 'X' 0 version; + 'X' 4 map; +}; + +aggr Linkmap +{ + 'X' 0 addr; + 'X' 4 name; + 'X' 8 dynsect; + 'X' 12 next; + 'X' 16 prev; +}; +*/ +enum +{ + DT_NULL = 0, + DT_NEEDED, + DT_PLTRRELSZ, + DT_PLTGOT, + DT_HASH, + DT_STRTAB, + DT_SYMTAB, + DT_RELA, + DT_RELASZ = 8, + DT_RELAENT, + DT_STSZ, + DT_SYMENT, + DT_INIT, + DT_FINI, + DT_SONAME, + DT_RPATH, + DT_SYMBOLIC = 16, + DT_REL, + DT_RELSZ, + DT_RELENT, + DT_PLTREL, + DT_DEBUG, + DT_TEXTREL, + DT_JMPREL, +}; + +static int +getstr(Map *map, ulong addr, char *buf, uint nbuf) +{ + int i; + + for(i=0; i<nbuf; i++){ + if(get1(map, addr+i, buf+i, 1) < 0) + return -1; + if(buf[i] == 0) + return 0; + } + return -1; /* no nul */ +} + +static ulong +dyninfo(Fhdr *hdr, int x) +{ + u32int addr, u; + + if(hdr == nil || (addr = ((Elf*)hdr->elf)->dynamic) == 0){ + fprint(2, "no hdr/dynamic %p\n", hdr); + return 0; + } + addr += hdr->base; + + while(addr != 0){ + if(get4(cormap, addr, &u) < 0) + return 0; + if(u == x){ + if(get4(cormap, addr+4, &u) < 0) + return 0; + return u; + } + addr += 8; + } + return 0; +} + +void +elfdl386mapdl(void) +{ + int i; + Fhdr *hdr; + u32int linkdebug, linkmap, name, addr; + char buf[1024]; + +print("elfdl386mapdl\n"); + if((linkdebug = dyninfo(symhdr, DT_DEBUG)) == 0){ + fprint(2, "no dt_debug section\n"); + return; + } + if(get4(cormap, linkdebug+4, &linkmap) < 0){ + fprint(2, "get4 linkdebug+4 (0x%lux) failed\n", linkdebug); + return; + } + + for(i=0; i<100 && linkmap != 0; i++){ + if(get4(cormap, linkmap, &addr) < 0 + || get4(cormap, linkmap+4, &name) < 0 + || get4(cormap, linkmap+12, &linkmap) < 0) + break; + + if(name + && getstr(cormap, name, buf, sizeof buf) >= 0 + && buf[0] + && access(buf, AEXIST) >= 0){ + if((hdr = crackhdr(buf, OREAD)) == nil) + fprint(2, "crackhdr %s: %r\n", buf); + else{ + fprint(2, "%s: %s %s %s\n", buf, hdr->aname, hdr->mname, hdr->fname); + hdr->base = addr; + if(mapfile(hdr, addr, symmap, nil) < 0) + fprint(2, "mapfile %s: %r\n", buf); + if(corhdr){ + unmapfile(corhdr, cormap); + mapfile(hdr, addr, cormap, nil); + } + if(syminit(hdr) < 0) + fprint(2, "syminit %s: %\r", buf); + } + } + } +} + |