diff options
author | Alex Brainman <alex.brainman@gmail.com> | 2010-02-10 00:47:52 -0800 |
---|---|---|
committer | Alex Brainman <alex.brainman@gmail.com> | 2010-02-10 00:47:52 -0800 |
commit | 7286058ee4b37e35a5f9702ddfec7ebb0d2599ff (patch) | |
tree | 66d8ed1e4e80f6c7a2065a1b2776704060272545 | |
parent | 8a851cc1c1781944d7cf8620bcc5319ab3337059 (diff) | |
download | golang-7286058ee4b37e35a5f9702ddfec7ebb0d2599ff.tar.gz |
8l: pe executable building code changed to include import table for kernel32.dll functions
Fixes issue 586.
R=rsc
CC=golang-dev
http://codereview.appspot.com/203060
Committer: Russ Cox <rsc@golang.org>
-rw-r--r-- | src/cmd/ld/pe.c | 74 | ||||
-rw-r--r-- | src/cmd/ld/pe.h | 25 |
2 files changed, 99 insertions, 0 deletions
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c index 3a3099d04..15bd7b70d 100644 --- a/src/cmd/ld/pe.c +++ b/src/cmd/ld/pe.c @@ -95,6 +95,78 @@ dope(void) IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; } +static void +strput(char *s) +{ + while(*s) + cput(*s++); + cput('\0'); +} + +static void +add_import_table(void) +{ + IMAGE_IMPORT_DESCRIPTOR ds[2], *d; + char *dllname = "kernel32.dll"; + struct { + char *name; + uint32 thunk; + } *f, fs[] = { + { "GetProcAddress", 0 }, + { "LoadLibraryExA", 0 }, + { 0, 0 } + }; + + uint32 size = 0; + memset(ds, 0, sizeof(ds)); + size += sizeof(ds); + ds[0].Name = size; + size += strlen(dllname) + 1; + for(f=fs; f->name; f++) { + f->thunk = size; + size += sizeof(uint16) + strlen(f->name) + 1; + } + ds[0].FirstThunk = size; + for(f=fs; f->name; f++) + size += sizeof(fs[0].thunk); + + IMAGE_SECTION_HEADER *isect; + isect = new_section(".idata", size, 0); + isect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| + IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; + + uint32 va = isect->VirtualAddress; + oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = va; + oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize; + + ds[0].Name += va; + ds[0].FirstThunk += va; + for(f=fs; f->name; f++) + f->thunk += va; + + vlong off = seek(cout, 0, 1); + seek(cout, 0, 2); + for(d=ds; ; d++) { + lputl(d->OriginalFirstThunk); + lputl(d->TimeDateStamp); + lputl(d->ForwarderChain); + lputl(d->Name); + lputl(d->FirstThunk); + if(!d->Name) + break; + } + strput(dllname); + for(f=fs; f->name; f++) { + wputl(0); + strput(f->name); + } + for(f=fs; f->name; f++) + lputl(f->thunk); + strnput("", isect->SizeOfRawData - size); + cflush(); + seek(cout, off, 0); +} + void asmbpe(void) { @@ -117,6 +189,8 @@ asmbpe(void) IMAGE_SCN_CNT_INITIALIZED_DATA; } + add_import_table(); + fh.NumberOfSections = nsect; fh.TimeDateStamp = time(0); fh.SizeOfOptionalHeader = sizeof(oh); diff --git a/src/cmd/ld/pe.h b/src/cmd/ld/pe.h index e7e2f9f08..b64dd97c0 100644 --- a/src/cmd/ld/pe.h +++ b/src/cmd/ld/pe.h @@ -64,6 +64,14 @@ typedef struct { uint32 Characteristics; } IMAGE_SECTION_HEADER; +typedef struct { + uint32 OriginalFirstThunk; + uint32 TimeDateStamp; + uint32 ForwarderChain; + uint32 Name; + uint32 FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR; + #define PERESERVE 0x400 #define PEALIGN 0x200 #define PEBASE 0x00400000 @@ -84,6 +92,23 @@ enum { IMAGE_SCN_MEM_EXECUTE = 0x20000000, IMAGE_SCN_MEM_READ = 0x40000000, IMAGE_SCN_MEM_WRITE = 0x80000000, + + IMAGE_DIRECTORY_ENTRY_EXPORT = 0, + IMAGE_DIRECTORY_ENTRY_IMPORT = 1, + IMAGE_DIRECTORY_ENTRY_RESOURCE = 2, + IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3, + IMAGE_DIRECTORY_ENTRY_SECURITY = 4, + IMAGE_DIRECTORY_ENTRY_BASERELOC = 5, + IMAGE_DIRECTORY_ENTRY_DEBUG = 6, + IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7, + IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7, + IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8, + IMAGE_DIRECTORY_ENTRY_TLS = 9, + IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10, + IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11, + IMAGE_DIRECTORY_ENTRY_IAT = 12, + IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13, + IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14, }; void peinit(void); |