aboutsummaryrefslogtreecommitdiff
path: root/src/libmach/elfdl386.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmach/elfdl386.c')
-rw-r--r--src/libmach/elfdl386.c133
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);
+ }
+ }
+ }
+}
+