]> Cypherpunks repositories - gostls13.git/commitdiff
8l: add PE dynexport
authorWei Guangjing <vcc.163@gmail.com>
Thu, 27 Jan 2011 13:26:31 +0000 (08:26 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 27 Jan 2011 13:26:31 +0000 (08:26 -0500)
R=rsc, brainman, mattn
CC=golang-dev
https://golang.org/cl/4022043

src/cmd/8l/asm.c
src/cmd/ld/pe.c
src/cmd/ld/pe.h

index cdb5a33e6f4dbe28e51f50fd8476bc3535049d7f..0c698990c39ce7bb196667b196b1a49af0839050 100644 (file)
@@ -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");
        }
 }
index 860910e3455288138565866f8a84ce41d5074dd9..5663ae42d88be029b7d47e12678ae0a4ee7eb1f1 100644 (file)
@@ -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; i<NHASH; i++)
        for(s = hash[i]; s != S; s = s->hash) {
-               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; i<NHASH; i++)
+       for(s = hash[i]; s != S; s = s->hash) {
+               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; i<nexport; i++)
+               size += strlen(dexport[i]->dynimpname) + 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; i<sizeof(e); i++)
+               cput(((char*)&e)[i]);
+       // put EXPORT Address Table
+       for(i=0; i<nexport; i++)
+               lputl(dexport[i]->value - PEBASE);              
+       // put EXPORT Name Pointer Table
+       v = e.Name + strlen(outfile)+1;
+       for(i=0; i<nexport; i++) {
+               lputl(v);
+               v += strlen(dexport[i]->dynimpname)+1;
+       }
+       // put EXPORT Ordinal Table
+       for(i=0; i<nexport; i++)
+               wputl(i);
+       // put Names
+       strnput(outfile, strlen(outfile)+1);
+       for(i=0; i<nexport; i++)
+               strnput(dexport[i]->dynimpname, 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();
 
index 6fb37c37dcf05c8743926de720df7f13547c5aeb..6dbf6a5be6fce22840edc78d5eb4538d33198fc6 100644 (file)
@@ -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.