]> Cypherpunks repositories - gostls13.git/commitdiff
6l: windows/amd64 port
authorWei Guangjing <vcc.163@gmail.com>
Thu, 20 Jan 2011 14:21:10 +0000 (09:21 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 20 Jan 2011 14:21:10 +0000 (09:21 -0500)
R=rsc
CC=golang-dev
https://golang.org/cl/3746044

src/cmd/6l/Makefile
src/cmd/6l/asm.c
src/cmd/6l/l.h
src/cmd/6l/obj.c
src/cmd/6l/pass.c
src/cmd/ld/data.c
src/cmd/ld/pe.c
src/cmd/ld/pe.h

index fba1b42ae4de36d3ffa3d400a270ce4e6c1e6d10..f7d2a550c348b37df17472b12bc86486afff99d5 100644 (file)
@@ -22,6 +22,7 @@ OFILES=\
        obj.$O\
        optab.$O\
        pass.$O\
+       pe.$O\
        prof.$O\
        span.$O\
        symtab.$O\
@@ -33,6 +34,7 @@ HFILES=\
        ../ld/elf.h\
        ../ld/macho.h\
        ../ld/dwarf.h\
+       ../ld/pe.h\
 
 include ../../Make.ccmd
 
index 9726d227cdb7d63b883916940186eb4f79980f64..2119395b38b72ec86b781e1ac5ede35f6d7e63cc 100644 (file)
@@ -35,6 +35,7 @@
 #include       "../ld/elf.h"
 #include       "../ld/dwarf.h"
 #include       "../ld/macho.h"
+#include       "../ld/pe.h"
 
 #define        Dbufslop        100
 
@@ -782,6 +783,8 @@ asmb(void)
                if(!debug['d'])
                        elftextsh += 10;
                break;
+       case 10:
+               break;
        }
 
        symsize = 0;
@@ -807,6 +810,10 @@ asmb(void)
                        symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen;
                        symo = rnd(symo, INITRND);
                        break;
+               case 10:
+                       symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen;
+                       symo = rnd(symo, PEFILEALIGN);
+                       break;
                }
                /*
                 * the symbol information is stored as
@@ -829,7 +836,7 @@ asmb(void)
                lputl(symsize);
                lputl(lcsize);
                cflush();
-               if(!debug['s']) {
+               if(HEADTYPE != 10 && !debug['s']) {
                        elfsymo = symo+8+symsize+lcsize;
                        seek(cout, elfsymo, 0);
                        asmelfsym64();
@@ -1090,6 +1097,9 @@ asmb(void)
                if(a+elfwriteinterp() > ELFRESERVE)
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
+       case 10:
+               asmbpe();
+               break;
        }
        cflush();
 }
@@ -1143,6 +1153,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
                        case SDATA:
                        case SELFDATA:
                        case SMACHOGOT:
+                       case SWINDOWS:
                                if(!s->reachable)
                                        continue;
                                put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
index d3639d0f2b886226ff5e6cfaae55068c87abf903..01896d3599168a143df44a7902c98bee85223d5d 100644 (file)
@@ -183,6 +183,7 @@ enum
        SRODATA,
        SDATA,
        SMACHOGOT,
+       SWINDOWS,
        SBSS,
 
        SXREF,
index 96d78c3b99b1185f6cf9d89583e563d2a9dfde5f..eae76e5d86b2559d02ccdccaf6450492d4b36c6c 100644 (file)
@@ -36,6 +36,7 @@
 #include       "../ld/elf.h"
 #include       "../ld/macho.h"
 #include       "../ld/dwarf.h"
+#include       "../ld/pe.h"
 #include       <ar.h>
 
 char   *noname         = "<none>";
@@ -132,6 +133,9 @@ main(int argc, char *argv[])
                else
                if(strcmp(goos, "freebsd") == 0)
                        HEADTYPE = 9;
+               else
+               if(strcmp(goos, "windows") == 0)
+                       HEADTYPE = 10;
                else
                        print("goos is not known: %s\n", goos);
        }
@@ -200,6 +204,16 @@ main(int argc, char *argv[])
                if(INITRND == -1)
                        INITRND = 4096;
                break;
+       case 10: /* PE executable */
+               peinit();
+               HEADR = PEFILEHEADR;
+               if(INITTEXT == -1)
+                       INITTEXT = PEBASE+PESECTHEADR;
+               if(INITDAT == -1)
+                       INITDAT = 0;
+               if(INITRND == -1)
+                       INITRND = PESECTALIGN;
+               break;
        }
        if(INITDAT != 0 && INITRND != 0)
                print("warning: -D0x%llux is ignored because of -R0x%ux\n",
@@ -245,6 +259,8 @@ main(int argc, char *argv[])
                else
                        doprof2();
        span();
+       if(HEADTYPE == 10)
+               dope();
        addexport();
        textaddress();
        pclntab();
index 5c4ed00a69c7ca341ca934e595949646c57dcb5a..5eb221a35d2502fd5e472336de87ae0b06e0b284 100644 (file)
@@ -277,6 +277,29 @@ patch(void)
        vexit = s->value;
        for(cursym = textp; cursym != nil; cursym = cursym->next)
        for(p = cursym->text; p != P; p = p->link) {
+               if(HEADTYPE == 10) { 
+                       // Windows
+                       // Convert
+                       //   op   n(GS), reg
+                       // to
+                       //   MOVL 0x58(GS), reg
+                       //   op   n(reg), reg
+                       // The purpose of this patch is to fix some accesses
+                       // to extern register variables (TLS) on Windows, as
+                       // a different method is used to access them.
+                       if(p->from.type == D_INDIR+D_GS
+                       && p->to.type >= D_AX && p->to.type <= D_DI 
+                       && p->from.offset != 0x58) {
+                               q = appendp(p);
+                               q->from = p->from;
+                               q->from.type = D_INDIR + p->to.type;
+                               q->to = p->to;
+                               q->as = p->as;
+                               p->as = AMOVQ;
+                               p->from.type = D_INDIR+D_GS;
+                               p->from.offset = 0x58;
+                       }
+               }
                if(HEADTYPE == 7 || HEADTYPE == 9) {
                        // ELF uses FS instead of GS.
                        if(p->from.type == D_INDIR+D_GS)
@@ -411,6 +434,21 @@ dostkoff(void)
                                p->from.type = D_INDIR+D_GS;
                        p->from.offset = tlsoffset+0;
                        p->to.type = D_CX;
+                       if(HEADTYPE == 10) { // Windows
+                               // movq %gs:0x58, %rcx
+                               // movq (%rcx), %rcx
+                               p->as = AMOVQ;
+                               p->from.type = D_INDIR+D_GS;
+                               p->from.offset = 0x58;
+                               p->to.type = D_CX;
+
+                       
+                               p = appendp(p);
+                               p->as = AMOVQ;
+                               p->from.type = D_INDIR+D_CX;
+                               p->from.offset = 0;
+                               p->to.type = D_CX;
+                       }
 
                        if(debug['K']) {
                                // 6l -K means check not only for stack
index 210f10ab5696c09e255481f3e1081255624520e2..27e0078d7466ffe1ea9b8d0229ef2bc1ac398112 100644 (file)
@@ -871,7 +871,7 @@ address(void)
        segdata.rwx = 06;
        segdata.vaddr = va;
        segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
-       if(thechar == '8' && HEADTYPE == 10)    // Windows PE
+       if((thechar == '6' || thechar == '8') && HEADTYPE == 10)        // Windows PE
                segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
        if(thechar == '8' && HEADTYPE == 2) {   // Plan 9               
                segdata.vaddr = va = rnd(va, 4096);
index 661d3071855a332b45a7d9bd7d1d75c35740eaf9..b8ce99e3e577c711653d70cf6432b7b72af4bfd2 100644 (file)
@@ -43,6 +43,7 @@ static int nextfileoff;
 
 static IMAGE_FILE_HEADER fh;
 static IMAGE_OPTIONAL_HEADER oh;
+static PE64_IMAGE_OPTIONAL_HEADER oh64;
 static IMAGE_SECTION_HEADER sh[16];
 
 typedef struct Imp Imp;
@@ -102,13 +103,14 @@ peinit(void)
        // 64-bit architectures
        case '6':
                pe64 = 1;
+               PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh64)+sizeof(sh), PEFILEALIGN);
                break;
        // 32-bit architectures
        default:
+               PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh)+sizeof(sh), PEFILEALIGN);
                break;
        }
-
-       PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh)+sizeof(sh), PEFILEALIGN);
+       
        PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN);
        nextsectoff = PESECTHEADR;
        nextfileoff = PEFILEHEADR;
@@ -125,8 +127,13 @@ pewrite(void)
 
        for (i=0; i<sizeof(fh); i++)
                cput(((char*)&fh)[i]);
-       for (i=0; i<sizeof(oh); i++)
-               cput(((char*)&oh)[i]);
+       if(pe64) { 
+               for (i=0; i<sizeof(oh64); i++)
+                       cput(((char*)&oh64)[i]);
+       } else {
+               for (i=0; i<sizeof(oh); i++)
+                       cput(((char*)&oh)[i]);
+       }
        for (i=0; i<nsect; i++)
                for (j=0; j<sizeof(sh[i]); j++)
                        cput(((char*)&sh[i])[j]);
@@ -187,9 +194,9 @@ initdynimport(void)
                        m->s->sub = dynamic->sub;
                        dynamic->sub = m->s;
                        m->s->value = dynamic->size;
-                       dynamic->size += 4;
+                       dynamic->size += PtrSize;
                }
-               dynamic->size += 4;
+               dynamic->size += PtrSize;
        }
                
        return dr;
@@ -233,8 +240,8 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
        for(d = dr; d != nil; d = d->next) {
                d->thunkoff = cpos() - n;
                for(m = d->ms; m != nil; m = m->next)
-                       lputl(m->off);
-               lputl(0);
+                       pe64 ? vputl(m->off) : lputl(m->off);
+               pe64 ? vputl(0): lputl(0);
        }
 
        // add pe section and pad it at the end
@@ -250,11 +257,11 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
        seek(cout, datsect->PointerToRawData + ftbase, 0);
        for(d = dr; d != nil; d = d->next) {
                for(m = d->ms; m != nil; m = m->next)
-                       lputl(m->off);
-               lputl(0);
+                       pe64 ? vputl(m->off) : lputl(m->off);
+               pe64 ? vputl(0): lputl(0);
        }
        cflush();
-
+       
        // finally write import descriptor table
        seek(cout, fileoff, 0);
        for(d = dr; d != nil; d = d->next) {
@@ -272,10 +279,17 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
        cflush();
        
        // update data directory
-       oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress;
-       oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize;
-       oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE;
-       oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size;
+       if(pe64) {
+               oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress;
+               oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize;
+               oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE;
+               oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size;
+       } else {
+               oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress;
+               oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize;
+               oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE;
+               oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size;
+       }
 
        seek(cout, 0, 2);
 }
@@ -308,7 +322,7 @@ asmbpe(void)
                IMAGE_SCN_CNT_INITIALIZED_DATA|
                IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
 
-       d = addpesection(".data", segdata.len, segdata.filelen, &segdata);
+       d = addpesection(".data", segdata.len, pe64 ? segdata.len : segdata.filelen, &segdata);
        d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
                IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
 
@@ -316,39 +330,68 @@ asmbpe(void)
 
        fh.NumberOfSections = nsect;
        fh.TimeDateStamp = time(0);
-       fh.SizeOfOptionalHeader = sizeof(oh);
        fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED|
                IMAGE_FILE_EXECUTABLE_IMAGE|IMAGE_FILE_DEBUG_STRIPPED;
-       if(thechar == '8')
-               fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE;
 
-       oh.Magic = 0x10b;       // PE32
-       oh.MajorLinkerVersion = 1;
-       oh.MinorLinkerVersion = 0;
-       oh.SizeOfCode = t->SizeOfRawData;
-       oh.SizeOfInitializedData = d->SizeOfRawData;
-       oh.SizeOfUninitializedData = 0;
-       oh.AddressOfEntryPoint = entryvalue()-PEBASE;
-       oh.BaseOfCode = t->VirtualAddress;
-       oh.BaseOfData = d->VirtualAddress;
-
-       oh.ImageBase = PEBASE;
-       oh.SectionAlignment = PESECTALIGN;
-       oh.FileAlignment = PEFILEALIGN;
-       oh.MajorOperatingSystemVersion = 4;
-       oh.MinorOperatingSystemVersion = 0;
-       oh.MajorImageVersion = 1;
-       oh.MinorImageVersion = 0;
-       oh.MajorSubsystemVersion = 4;
-       oh.MinorSubsystemVersion = 0;
-       oh.SizeOfImage = nextsectoff;
-       oh.SizeOfHeaders = PEFILEHEADR;
-       oh.Subsystem = 3;       // WINDOWS_CUI
-       oh.SizeOfStackReserve = 0x00200000;
-       oh.SizeOfStackCommit = 0x00001000;
-       oh.SizeOfHeapReserve = 0x00100000;
-       oh.SizeOfHeapCommit = 0x00001000;
-       oh.NumberOfRvaAndSizes = 16;
+       if (pe64) {
+               fh.SizeOfOptionalHeader = sizeof(oh64);
+               oh64.Magic = 0x20b;     // PE32+
+               oh64.MajorLinkerVersion = 1;
+               oh64.MinorLinkerVersion = 0;
+               oh64.SizeOfCode = t->SizeOfRawData;
+               oh64.SizeOfInitializedData = d->SizeOfRawData;
+               oh64.SizeOfUninitializedData = 0;
+               oh64.AddressOfEntryPoint = entryvalue()-PEBASE;
+               oh64.BaseOfCode = t->VirtualAddress;
+
+               oh64.ImageBase = PEBASE;
+               oh64.SectionAlignment = PESECTALIGN;
+               oh64.FileAlignment = PEFILEALIGN;
+               oh64.MajorOperatingSystemVersion = 4;
+               oh64.MinorOperatingSystemVersion = 0;
+               oh64.MajorImageVersion = 1;
+               oh64.MinorImageVersion = 0;
+               oh64.MajorSubsystemVersion = 4;
+               oh64.MinorSubsystemVersion = 0;
+               oh64.SizeOfImage = nextsectoff;
+               oh64.SizeOfHeaders = PEFILEHEADR;
+               oh64.Subsystem = 3;     // WINDOWS_CUI
+               oh64.SizeOfStackReserve = 0x00200000;
+               oh64.SizeOfStackCommit = 0x00001000;
+               oh64.SizeOfHeapReserve = 0x00100000;
+               oh64.SizeOfHeapCommit = 0x00001000;
+               oh64.NumberOfRvaAndSizes = 16;
+       } else {
+               fh.SizeOfOptionalHeader = sizeof(oh);
+               fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE;
+               oh.Magic = 0x10b;       // PE32
+               oh.MajorLinkerVersion = 1;
+               oh.MinorLinkerVersion = 0;
+               oh.SizeOfCode = t->SizeOfRawData;
+               oh.SizeOfInitializedData = d->SizeOfRawData;
+               oh.SizeOfUninitializedData = 0;
+               oh.AddressOfEntryPoint = entryvalue()-PEBASE;
+               oh.BaseOfCode = t->VirtualAddress;
+               oh.BaseOfData = d->VirtualAddress;
+
+               oh.ImageBase = PEBASE;
+               oh.SectionAlignment = PESECTALIGN;
+               oh.FileAlignment = PEFILEALIGN;
+               oh.MajorOperatingSystemVersion = 4;
+               oh.MinorOperatingSystemVersion = 0;
+               oh.MajorImageVersion = 1;
+               oh.MinorImageVersion = 0;
+               oh.MajorSubsystemVersion = 4;
+               oh.MinorSubsystemVersion = 0;
+               oh.SizeOfImage = nextsectoff;
+               oh.SizeOfHeaders = PEFILEHEADR;
+               oh.Subsystem = 3;       // WINDOWS_CUI
+               oh.SizeOfStackReserve = 0x00200000;
+               oh.SizeOfStackCommit = 0x00001000;
+               oh.SizeOfHeapReserve = 0x00100000;
+               oh.SizeOfHeapCommit = 0x00001000;
+               oh.NumberOfRvaAndSizes = 16;
+       }
 
        pewrite();
 }
index f8161cc4a67a87d5ca6d110a1232c16fec54f9e3..7c19630f41093a922e17f0cc653d61fa1b6dc552 100644 (file)
@@ -122,3 +122,36 @@ void peinit(void);
 void asmbpe(void);
 void dope(void);
 
+// X64
+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;