diff options
author | Alex Brainman <alex.brainman@gmail.com> | 2010-02-10 00:47:52 -0800 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2010-02-10 00:47:52 -0800 |
commit | 3b1a71862e0db013ec1b2c1cb55212e9611e8885 (patch) | |
tree | e38f5f1f32101747687b959ebfabac98594115c5 | |
parent | 1ca39fb1fdce4d9371d5b95829234490ff9f8327 (diff) | |
download | go-3b1a71862e0db013ec1b2c1cb55212e9611e8885.tar.gz go-3b1a71862e0db013ec1b2c1cb55212e9611e8885.zip |
8l: pe executable building code changed to include import table for kernel32.dll functions
Fixes #586.
R=rsc
CC=golang-dev
https://golang.org/cl/203060
-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 3a3099d044..15bd7b70d6 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 e7e2f9f08b..b64dd97c07 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); |