From a3120f67ca69de705d6e604de5df842681bf3921 Mon Sep 17 00:00:00 2001 From: Wei Guangjing Date: Thu, 27 Jan 2011 08:26:31 -0500 Subject: [PATCH] 8l: add PE dynexport R=rsc, brainman, mattn CC=golang-dev https://golang.org/cl/4022043 --- src/cmd/8l/asm.c | 4 +- src/cmd/ld/pe.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++- src/cmd/ld/pe.h | 14 +++++++ 3 files changed, 118 insertions(+), 3 deletions(-) diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index cdb5a33e6f..0c698990c3 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -520,7 +520,7 @@ adddynsym(Sym *s) adduint8(d, 0); // section adduint16(d, 0); // desc adduint32(d, 0); // value - } else { + } else if(HEADTYPE != 10) { diag("adddynsym: unsupported binary format"); } } @@ -540,7 +540,7 @@ adddynlib(char *lib) elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, lib)); } else if(HEADTYPE == 6) { // Mach-O machoadddynlib(lib); - } else { + } else if(HEADTYPE != 10) { diag("adddynlib: unsupported binary format"); } } diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c index 860910e345..5663ae42d8 100644 --- a/src/cmd/ld/pe.c +++ b/src/cmd/ld/pe.c @@ -68,6 +68,9 @@ struct Dll { static Dll* dr; +static Sym *dexport[1024]; +static int nexport; + static IMAGE_SECTION_HEADER* addpesection(char *name, int sectsize, int filesize, Segment *s) { @@ -169,7 +172,7 @@ initdynimport(void) for(i=0; ihash) { - if(!s->reachable || !s->dynimpname) + if(!s->reachable || !s->dynimpname || s->dynexport) continue; for(d = dr; d != nil; d = d->next) { if(strcmp(d->name,s->dynimplib) == 0) { @@ -298,6 +301,101 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect) seek(cout, 0, 2); } +static int +scmp(const void *p1, const void *p2) +{ + Sym *s1, *s2; + + s1 = *(Sym**)p1; + s2 = *(Sym**)p2; + return strcmp(s1->dynimpname, s2->dynimpname); +} + +static void +initdynexport(void) +{ + int i; + Sym *s; + + nexport = 0; + for(i=0; ihash) { + if(!s->reachable || !s->dynimpname || !s->dynexport) + continue; + if(nexport+1 > sizeof(dexport)/sizeof(dexport[0])) { + diag("pe dynexport table is full"); + errorexit(); + } + + dexport[nexport] = s; + nexport++; + } + + qsort(dexport, nexport, sizeof dexport[0], scmp); +} + +void +addexports(vlong fileoff) +{ + IMAGE_SECTION_HEADER *sect; + IMAGE_EXPORT_DIRECTORY e; + int size, i, va, va_name, va_addr, va_na, v; + Sym *s; + + size = sizeof e + 10*nexport + strlen(outfile) + 1; + for(i=0; idynimpname) + 1; + + if (nexport == 0) + return; + + sect = addpesection(".edata", size, size, 0); + sect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ; + va = sect->VirtualAddress; + oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = va; + oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect->VirtualSize; + + seek(cout, fileoff, 0); + va_name = va + sizeof e + nexport*4; + va_addr = va + sizeof e; + va_na = va + sizeof e + nexport*8; + + e.Characteristics = 0; + e.MajorVersion = 0; + e.MinorVersion = 0; + e.NumberOfFunctions = nexport; + e.NumberOfNames = nexport; + e.Name = va + sizeof e + nexport*10; // Program names. + e.Base = 1; + e.AddressOfFunctions = va_addr; + e.AddressOfNames = va_name; + e.AddressOfNameOrdinals = va_na; + // put IMAGE_EXPORT_DIRECTORY + for (i=0; ivalue - PEBASE); + // put EXPORT Name Pointer Table + v = e.Name + strlen(outfile)+1; + for(i=0; idynimpname)+1; + } + // put EXPORT Ordinal Table + for(i=0; idynimpname, strlen(dexport[i]->dynimpname)+1); + strnput("", sect->SizeOfRawData - size); + cflush(); + + seek(cout, 0, 2); +} + + void dope(void) { @@ -309,6 +407,7 @@ dope(void) rel->type = SELFDATA; initdynimport(); + initdynexport(); } /* @@ -393,6 +492,8 @@ asmbpe(void) addimports(nextfileoff, d); + addexports(nextfileoff); + if(!debug['s']) dwarfaddpeheaders(); diff --git a/src/cmd/ld/pe.h b/src/cmd/ld/pe.h index 6fb37c37dc..6dbf6a5be6 100644 --- a/src/cmd/ld/pe.h +++ b/src/cmd/ld/pe.h @@ -72,6 +72,20 @@ typedef struct { uint32 FirstThunk; } IMAGE_IMPORT_DESCRIPTOR; +typedef struct _IMAGE_EXPORT_DIRECTORY { + uint32 Characteristics; + uint32 TimeDateStamp; + uint16 MajorVersion; + uint16 MinorVersion; + uint32 Name; + uint32 Base; + uint32 NumberOfFunctions; + uint32 NumberOfNames; + uint32 AddressOfFunctions; + uint32 AddressOfNames; + uint32 AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY; + #define PEBASE 0x00400000 // SectionAlignment must be greater than or equal to FileAlignment. // The default is the page size for the architecture. -- 2.48.1