]> Cypherpunks repositories - gostls13.git/commitdiff
libmach: many pe handling fixes
authorAlex Brainman <alex.brainman@gmail.com>
Fri, 1 Mar 2013 03:49:23 +0000 (14:49 +1100)
committerAlex Brainman <alex.brainman@gmail.com>
Fri, 1 Mar 2013 03:49:23 +0000 (14:49 +1100)
- implement windows pread;
- set correct Fhdr.type;
- add ImageBase to all pe "virtual" addresses;
- correct settext parameter order;
- use pclntab/epclntab to find line numbers.

Fixes #4841.
Fixes #4926.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/7405050

src/libmach/executable.c
src/libmach/windows.c

index 3fd3e0968e76ec54f618d869498b797bdcd03580..a93a8c268c4273ea576f5b5ccb3e5bf7b4d28afc 100644 (file)
@@ -1349,12 +1349,12 @@ static int
 pedotout(int fd, Fhdr *fp, ExecHdr *hp)
 {
        uint32 start, magic;
-       uint32 symtab, esymtab;
+       uint32 symtab, esymtab, pclntab, epclntab;
        IMAGE_FILE_HEADER fh;
        IMAGE_SECTION_HEADER sh;
        IMAGE_OPTIONAL_HEADER oh;
        uint8 sym[18];
-       uint32 *valp;
+       uint32 *valp, ib;
        int i;
 
        USED(hp);
@@ -1389,6 +1389,19 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
                return 0;
        }
 
+       switch(oh.Magic) {
+       case 0x10b:     // PE32
+               fp->type = FI386;
+               break;
+       case 0x20b:     // PE32+
+               fp->type = FAMD64;
+               break;
+       default:
+               werrstr("invalid PE Optional magic number");
+               return 0;
+       }
+
+       ib=leswal(oh.ImageBase);
        seek(fd, start+sizeof(magic)+sizeof(fh)+leswab(fh.SizeOfOptionalHeader), 0);
        fp->txtaddr = 0;
        fp->dataddr = 0;
@@ -1398,9 +1411,9 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
                        return 0;
                }
                if (match8(sh.Name, ".text"))
-                       settext(fp, leswal(sh.VirtualAddress), leswal(oh.AddressOfEntryPoint), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
+                       settext(fp, ib+leswal(oh.AddressOfEntryPoint), ib+leswal(sh.VirtualAddress), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
                if (match8(sh.Name, ".data"))
-                       setdata(fp, leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
+                       setdata(fp, ib+leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
        }
        if (fp->txtaddr==0 || fp->dataddr==0) {
                werrstr("no .text or .data");
@@ -1408,7 +1421,7 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
        }
 
        seek(fd, leswal(fh.PointerToSymbolTable), 0);
-       symtab = esymtab = 0;
+       symtab = esymtab = pclntab = epclntab = 0;
        for (i=0; i<leswal(fh.NumberOfSymbols); i++) {
                if (readn(fd, sym, sizeof(sym)) != sizeof(sym)) {
                        werrstr("crippled COFF symbol %d", i);
@@ -1419,12 +1432,16 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
                        symtab = leswal(*valp);
                if (match8(sym, "esymtab"))
                        esymtab = leswal(*valp);
+               if (match8(sym, "pclntab"))
+                       pclntab = leswal(*valp);
+               if (match8(sym, "epclntab"))
+                       epclntab = leswal(*valp);
        }
-       if (symtab==0 || esymtab==0) {
-               werrstr("no symtab or esymtab in COFF symbol table");
+       if (symtab==0 || esymtab==0 || pclntab==0 || epclntab==0) {
+               werrstr("no symtab or esymtab or pclntab or epclntab in COFF symbol table");
                return 0;
        }
-       setsym(fp, symtab, esymtab-symtab, 0, 0, 0, 0);
+       setsym(fp, symtab, esymtab-symtab, 0, 0, pclntab, epclntab-pclntab);
 
        return 1;
 }
index 81fa6b6d2778758a2b231729883eac5709e0ee14..aea7bace07b1a9b3736fcdd74402094e8bc7949c 100644 (file)
@@ -48,8 +48,12 @@ procthreadpids(int pid, int *p, int np)
 int 
 pread(int fd, void *buf, int count, int offset)
 {
-       sysfatal("pread unimplemented in Windows");
-       return -1;
+       int oldoffset, n;
+       
+       oldoffset = seek(fd, offset, 0);
+       n = read(fd, buf, count);
+       seek(fd, oldoffset, 0);
+       return n;
 }
 
 int