From: Alex Brainman Date: Wed, 6 Mar 2013 20:14:07 +0000 (-0500) Subject: libmach: fix amd64 pe handling X-Git-Tag: go1.1rc2~672 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e44f42e05696de40b0ebed3c480b628219e9e036;p=gostls13.git libmach: fix amd64 pe handling Fixes #4841. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/7475046 --- diff --git a/src/libmach/executable.c b/src/libmach/executable.c index a93a8c268c..221e56cdef 100644 --- a/src/libmach/executable.c +++ b/src/libmach/executable.c @@ -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