]> Cypherpunks repositories - gostls13.git/commitdiff
libmach: fix amd64 pe handling
authorAlex Brainman <alex.brainman@gmail.com>
Wed, 6 Mar 2013 20:14:07 +0000 (15:14 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 6 Mar 2013 20:14:07 +0000 (15:14 -0500)
Fixes #4841.

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

src/libmach/executable.c

index a93a8c268c4273ea576f5b5ccb3e5bf7b4d28afc..221e56cdef2e1343945262904539448c18d03425 100644 (file)
@@ -1335,13 +1335,45 @@ typedef struct {
        IMAGE_DATA_DIRECTORY DataDirectory[16];
 } IMAGE_OPTIONAL_HEADER;
 
+typedef struct {
+       uint16 Magic;
+       uint8  MajorLinkerVersion;
+       uint8  MinorLinkerVersion;
+       uint32 SizeOfCode;
+       uint32 SizeOfInitializedData;
+       uint32 SizeOfUninitializedData;
+       uint32 AddressOfEntryPoint;
+       uint32 BaseOfCode;
+       uint64 ImageBase;
+       uint32 SectionAlignment;
+       uint32 FileAlignment;
+       uint16 MajorOperatingSystemVersion;
+       uint16 MinorOperatingSystemVersion;
+       uint16 MajorImageVersion;
+       uint16 MinorImageVersion;
+       uint16 MajorSubsystemVersion;
+       uint16 MinorSubsystemVersion;
+       uint32 Win32VersionValue;
+       uint32 SizeOfImage;
+       uint32 SizeOfHeaders;
+       uint32 CheckSum;
+       uint16 Subsystem;
+       uint16 DllCharacteristics;
+       uint64 SizeOfStackReserve;
+       uint64 SizeOfStackCommit;
+       uint64 SizeOfHeapReserve;
+       uint64 SizeOfHeapCommit;
+       uint32 LoaderFlags;
+       uint32 NumberOfRvaAndSizes;
+       IMAGE_DATA_DIRECTORY DataDirectory[16];
+} PE64_IMAGE_OPTIONAL_HEADER;
+
 static int
 match8(void *buf, char *cmp)
 {
        return strncmp((char*)buf, cmp, 8) == 0;
 }
 
-/* TODO(czaplinski): 64b windows? */
 /*
  * Read from Windows PE/COFF .exe file image.
  */
@@ -1353,9 +1385,10 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
        IMAGE_FILE_HEADER fh;
        IMAGE_SECTION_HEADER sh;
        IMAGE_OPTIONAL_HEADER oh;
+       PE64_IMAGE_OPTIONAL_HEADER oh64;
        uint8 sym[18];
-       uint32 *valp, ib;
-       int i;
+       uint32 *valp, ib, entry;
+       int i, ohoffset;
 
        USED(hp);
        seek(fd, 0x3c, 0);
@@ -1384,6 +1417,7 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
                return 0;
        }
 
+       ohoffset = seek(fd, 0, 1);
        if (readn(fd, &oh, sizeof(oh)) != sizeof(oh)) {
                werrstr("crippled PE Optional Header");
                return 0;
@@ -1392,17 +1426,24 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
        switch(oh.Magic) {
        case 0x10b:     // PE32
                fp->type = FI386;
+               ib = leswal(oh.ImageBase);
+               entry = leswal(oh.AddressOfEntryPoint);
                break;
        case 0x20b:     // PE32+
                fp->type = FAMD64;
+               seek(fd, ohoffset, 0);
+               if (readn(fd, &oh64, sizeof(oh64)) != sizeof(oh64)) {
+                       werrstr("crippled PE32+ Optional Header");
+                       return 0;
+               }
+               ib = leswal(oh64.ImageBase);
+               entry = leswal(oh64.AddressOfEntryPoint);
                break;
        default:
-               werrstr("invalid PE Optional magic number");
+               werrstr("invalid PE Optional Header 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;
        for (i=0; i<leswab(fh.NumberOfSections); i++) {
@@ -1411,7 +1452,7 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
                        return 0;
                }
                if (match8(sh.Name, ".text"))
-                       settext(fp, ib+leswal(oh.AddressOfEntryPoint), ib+leswal(sh.VirtualAddress), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
+                       settext(fp, ib+entry, ib+leswal(sh.VirtualAddress), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
                if (match8(sh.Name, ".data"))
                        setdata(fp, ib+leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
        }