]> Cypherpunks repositories - gostls13.git/commitdiff
cgo: windows/386 port
authorWei Guangjing <vcc.163@gmail.com>
Thu, 20 Jan 2011 15:22:20 +0000 (10:22 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 20 Jan 2011 15:22:20 +0000 (10:22 -0500)
R=rsc, peterGo, brainman
CC=golang-dev
https://golang.org/cl/3733046

17 files changed:
src/cmd/5l/Makefile
src/cmd/6l/Makefile
src/cmd/8l/Makefile
src/cmd/cgo/main.go
src/cmd/cgo/out.go
src/cmd/gopack/ar.c
src/cmd/ld/data.c
src/cmd/ld/ldpe.c [new file with mode: 0644]
src/cmd/ld/lib.c
src/cmd/ld/pe.c
src/pkg/Makefile
src/pkg/debug/pe/file.go
src/pkg/runtime/386/asm.s
src/pkg/runtime/cgo/Makefile
src/pkg/runtime/cgo/windows_386.c
src/pkg/runtime/runtime.c
src/pkg/runtime/windows/386/rt0.s

index 71798724b8e5472674cb216b425a4d1acc93b7bb..c11ebe9908e685a7458a74d9ed6ad51f8bfa4145 100644 (file)
@@ -14,6 +14,7 @@ OFILES=\
        enam.$O\
        ldelf.$O\
        ldmacho.$O\
+       ldpe.$O\
        lib.$O\
        list.$O\
        noop.$O\
index f7d2a550c348b37df17472b12bc86486afff99d5..abe204d4f5a8b589802cda709db5cb2d1b1194b5 100644 (file)
@@ -16,6 +16,7 @@ OFILES=\
        go.$O\
        ldelf.$O\
        ldmacho.$O\
+       ldpe.$O\
        lib.$O\
        list.$O\
        macho.$O\
index 84976ba18b49d68bd74f9cc9f69abe8174cb47bf..a85e3ffa7c1cea8ba5a54b0b13226a85f7bdcb11 100644 (file)
@@ -16,6 +16,7 @@ OFILES=\
        go.$O\
        ldelf.$O\
        ldmacho.$O\
+       ldpe.$O\
        lib.$O\
        list.$O\
        macho.$O\
index 942bda5f4da44eb23cbd48dfd5e3c0c4d67de1a8..14bb7ec2b08b626c8ed7ca5a03c1b75ec5b1a274 100644 (file)
@@ -20,6 +20,7 @@ import (
        "os"
        "reflect"
        "strings"
+       "runtime"
 )
 
 // A Package collects information about the package we're going to write.
@@ -127,6 +128,13 @@ func main() {
                // specialized knowledge gcc has about where to look for imported
                // symbols and which ones to use.
                syms, imports := dynimport(*dynobj)
+               if runtime.GOOS == "windows" {
+                       for _, sym := range syms {
+                               ss := strings.Split(sym, ":", -1)
+                               fmt.Printf("#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1]))
+                       }
+                       return
+               }
                for _, sym := range syms {
                        fmt.Printf("#pragma dynimport %s %s %q\n", sym, sym, "")
                }
index c76616677520bb4fd8477dfc4c5a220575bce808..d5fc63409fda6453ef89e408c1808c129caf6a23 100644 (file)
@@ -8,6 +8,7 @@ import (
        "bytes"
        "debug/elf"
        "debug/macho"
+       "debug/pe"
        "fmt"
        "go/ast"
        "go/printer"
@@ -103,12 +104,14 @@ func dynimport(obj string) (syms, imports []string) {
                ImportedSymbols() ([]string, os.Error)
        }
        var isMacho bool
-       var err1, err2 os.Error
+       var err1, err2, err3 os.Error
        if f, err1 = elf.Open(obj); err1 != nil {
-               if f, err2 = macho.Open(obj); err2 != nil {
-                       fatal("cannot parse %s as ELF (%v) or Mach-O (%v)", obj, err1, err2)
+               if f, err2 = pe.Open(obj); err2 != nil {
+                       if f, err3 = macho.Open(obj); err3 != nil {
+                               fatal("cannot parse %s as ELF (%v) or PE (%v) or Mach-O (%v)", obj, err1, err2, err3)
+                       }
+                       isMacho = true
                }
-               isMacho = true
        }
 
        var err os.Error
index 063967bd70bc80fb69f138b02405a0acb2caeead..a16e98cfe54996783c4e2bda88ba3a7b8754e4a7 100644 (file)
@@ -607,6 +607,7 @@ scanobj(Biobuf *b, Arfile *ap, long size)
                
                /* maybe a foreign object file?  that's okay */
                if((buf[0] == 0x7F && buf[1] == 'E' && buf[2] == 'L' && buf[3] == 'F') ||   // ELF
+                  (buf[0] == 0x4c && buf[1] == 0x01 || buf[0] == 0x64 && buf[1] == 0x86) || // Windows PE
                   (buf[0] == 0xFE && buf[1] == 0xED && buf[2] == 0xFA && (buf[3]&~1) == 0xCE) ||  // Mach-O big-endian
                   (buf[3] == 0xFE && buf[2] == 0xED && buf[1] == 0xFA && (buf[0]&~1) == 0xCE)) {  // Mach-O little-endian
                        Bseek(b, offset, 0);
index 27e0078d7466ffe1ea9b8d0229ef2bc1ac398112..0551232cfc9e68357aed1d3af22b99f47192c254 100644 (file)
@@ -240,6 +240,33 @@ void
 dynrelocsym(Sym *s)
 {
        Reloc *r;
+       
+       if(thechar == '8' && HEADTYPE == 10) { // Windows PE
+               Sym *rel, *targ;
+               
+               rel = lookup(".rel", 0);
+               if(s == rel)
+                       return;
+               for(r=s->r; r<s->r+s->nr; r++) {
+                       targ = r->sym;
+                       if(r->sym->plt == -2) { // make dynimport JMP table for PE object files.
+                               targ->plt = rel->size;
+                               r->sym = rel;
+                               r->add = targ->plt;
+                               
+                               // jmp *addr
+                               adduint8(rel, 0xff);
+                               adduint8(rel, 0x25);
+                               addaddr(rel, targ);
+                               adduint8(rel, 0x90);
+                               adduint8(rel, 0x90);
+                       } else if(r->sym->plt >= 0) {
+                               r->sym = rel;
+                               r->add = targ->plt;
+                       }
+               }
+               return;
+       }
 
        for(r=s->r; r<s->r+s->nr; r++)
                if(r->sym->type == SDYNIMPORT || r->type >= 256)
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
new file mode 100644 (file)
index 0000000..66b122b
--- /dev/null
@@ -0,0 +1,404 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include       "l.h"
+#include       "lib.h"
+#include       "../ld/pe.h"
+
+#define IMAGE_SCN_MEM_DISCARDABLE 0x2000000
+
+#define IMAGE_SYM_UNDEFINED    0
+#define IMAGE_SYM_ABSOLUTE (-1)
+#define IMAGE_SYM_DEBUG        (-2)
+#define IMAGE_SYM_TYPE_NULL 0
+#define IMAGE_SYM_TYPE_VOID 1
+#define IMAGE_SYM_TYPE_CHAR 2
+#define IMAGE_SYM_TYPE_SHORT 3
+#define IMAGE_SYM_TYPE_INT 4
+#define IMAGE_SYM_TYPE_LONG 5
+#define IMAGE_SYM_TYPE_FLOAT 6
+#define IMAGE_SYM_TYPE_DOUBLE 7
+#define IMAGE_SYM_TYPE_STRUCT 8
+#define IMAGE_SYM_TYPE_UNION 9
+#define IMAGE_SYM_TYPE_ENUM 10
+#define IMAGE_SYM_TYPE_MOE 11
+#define IMAGE_SYM_TYPE_BYTE 12
+#define IMAGE_SYM_TYPE_WORD 13
+#define IMAGE_SYM_TYPE_UINT 14
+#define IMAGE_SYM_TYPE_DWORD 15
+#define IMAGE_SYM_TYPE_PCODE 32768
+#define IMAGE_SYM_DTYPE_NULL 0
+#define IMAGE_SYM_DTYPE_POINTER 0x10
+#define IMAGE_SYM_DTYPE_FUNCTION 0x20
+#define IMAGE_SYM_DTYPE_ARRAY 0x30
+#define IMAGE_SYM_CLASS_END_OF_FUNCTION        (-1)
+#define IMAGE_SYM_CLASS_NULL 0
+#define IMAGE_SYM_CLASS_AUTOMATIC 1
+#define IMAGE_SYM_CLASS_EXTERNAL 2
+#define IMAGE_SYM_CLASS_STATIC 3
+#define IMAGE_SYM_CLASS_REGISTER 4
+#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5
+#define IMAGE_SYM_CLASS_LABEL 6
+#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
+#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
+#define IMAGE_SYM_CLASS_ARGUMENT 9
+#define IMAGE_SYM_CLASS_STRUCT_TAG 10
+#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
+#define IMAGE_SYM_CLASS_UNION_TAG 12
+#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13
+#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
+#define IMAGE_SYM_CLASS_ENUM_TAG 15
+#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
+#define IMAGE_SYM_CLASS_REGISTER_PARAM 17
+#define IMAGE_SYM_CLASS_BIT_FIELD 18
+#define IMAGE_SYM_CLASS_FAR_EXTERNAL 68 /* Not in PECOFF v8 spec */
+#define IMAGE_SYM_CLASS_BLOCK 100
+#define IMAGE_SYM_CLASS_FUNCTION 101
+#define IMAGE_SYM_CLASS_END_OF_STRUCT 102
+#define IMAGE_SYM_CLASS_FILE 103
+#define IMAGE_SYM_CLASS_SECTION 104
+#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
+#define IMAGE_SYM_CLASS_CLR_TOKEN 107
+
+#define IMAGE_REL_I386_ABSOLUTE        0x0000
+#define IMAGE_REL_I386_DIR16   0x0001
+#define IMAGE_REL_I386_REL16   0x0002
+#define IMAGE_REL_I386_DIR32   0x0006
+#define IMAGE_REL_I386_DIR32NB 0x0007
+#define IMAGE_REL_I386_SEG12   0x0009
+#define IMAGE_REL_I386_SECTION 0x000A
+#define IMAGE_REL_I386_SECREL  0x000B
+#define IMAGE_REL_I386_TOKEN   0x000C
+#define IMAGE_REL_I386_SECREL7 0x000D
+#define IMAGE_REL_I386_REL32   0x0014
+
+typedef struct PeSym PeSym;
+typedef struct PeSect PeSect;
+typedef struct PeObj PeObj;
+
+struct PeSym {
+       char* name;
+       uint32 value;
+       uint16 sectnum;
+       uint16 type;
+       uint8 sclass;
+       uint8 aux;
+       Sym* sym;
+};
+
+struct PeSect {
+       char* name;
+       uchar* base;
+       uint64 size;
+       Sym* sym;
+       IMAGE_SECTION_HEADER sh;
+};
+
+struct PeObj {
+       Biobuf  *f;
+       char    *name;
+       uint32 base;
+       
+       PeSect  *sect;
+       uint    nsect;
+       PeSym   *pesym;
+       uint npesym;
+       
+       IMAGE_FILE_HEADER fh;
+       char* snames;
+};
+
+static int map(PeObj *obj, PeSect *sect);
+static int readsym(PeObj *obj, int i, PeSym **sym);
+
+void
+ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
+{
+       char *name;
+       int32 base;
+       int i, j, l, numaux;
+       PeObj *obj;
+       PeSect *sect, *rsect;
+       IMAGE_SECTION_HEADER sh;
+       uchar symbuf[18];
+       Sym *s;
+       Reloc *r, *rp;
+       PeSym *sym;
+       
+       if(debug['v'])
+               Bprint(&bso, "%5.2f ldpe %s\n", cputime(), pn);
+       
+       version++;
+       base = Boffset(f);
+       
+       obj = mal(sizeof *obj);
+       obj->f = f;
+       obj->base = base;
+       obj->name = pn;
+       // read header
+       if(Bread(f, &obj->fh, sizeof obj->fh) != sizeof obj->fh)
+               goto bad;
+       // load section list
+       obj->sect = mal(obj->fh.NumberOfSections*sizeof obj->sect[0]);
+       obj->nsect = obj->fh.NumberOfSections;
+       for(i=0; i < obj->fh.NumberOfSections; i++) {
+               if(Bread(f, &obj->sect[i].sh, sizeof sh) != sizeof sh)
+                       goto bad;
+               obj->sect[i].size = obj->sect[i].sh.SizeOfRawData;
+               obj->sect[i].name = (char*)obj->sect[i].sh.Name;
+               // TODO return error if found .cormeta .rsrc
+       }
+       // load string table
+       Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
+       if(Bread(f, &l, sizeof l) != sizeof l) 
+               goto bad;
+       obj->snames = mal(l);
+       Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
+       if(Bread(f, obj->snames, l) != l)
+               goto bad;
+       // read symbols
+       obj->pesym = mal(obj->fh.NumberOfSymbols*sizeof obj->pesym[0]);
+       obj->npesym = obj->fh.NumberOfSymbols;
+       Bseek(f, base+obj->fh.PointerToSymbolTable, 0);
+       for(i=0; i<obj->fh.NumberOfSymbols; i+=numaux+1) {
+               Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*i, 0);
+               if(Bread(f, symbuf, sizeof symbuf) != sizeof symbuf)
+                       goto bad;
+               
+               if((symbuf[0] == 0) && (symbuf[1] == 0) &&
+                        (symbuf[2] == 0) && (symbuf[3] == 0)) {
+                       l = le32(&symbuf[4]);
+                       obj->pesym[i].name = (char*)&obj->snames[l];
+               } else {
+                       obj->pesym[i].name = strdup((char*)symbuf);
+               }
+               obj->pesym[i].value = le32(&symbuf[8]);
+               obj->pesym[i].sectnum = le16(&symbuf[12]);
+               obj->pesym[i].sclass = symbuf[16];
+               obj->pesym[i].aux = symbuf[17];
+               obj->pesym[i].type = le16(&symbuf[14]);
+               numaux = obj->pesym[i].aux; 
+               if (numaux < 0) 
+                       numaux = 0;
+       }
+       // create symbols for mapped sections
+       for(i=0; i<obj->nsect; i++) {
+               sect = &obj->sect[i];
+               if(sect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE)
+                       continue;
+               if(map(obj, sect) < 0)
+                       goto bad;
+               
+               name = smprint("%s(%s)", pn, sect->name);
+               s = lookup(name, version);
+               free(name);
+               switch(sect->sh.Characteristics&(IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_CNT_INITIALIZED_DATA|
+                       IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE)) {
+                       case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ: //.rdata
+                               s->type = SRODATA;
+                               break;
+                       case IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.bss
+                       case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.data
+                               s->type = SDATA;
+                               break;
+                       case IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ: //.text
+                               s->type = STEXT;
+                               break;
+                       default:
+                               werrstr("unexpected flags for PE section %s", sect->name);
+                               goto bad;
+               }
+               s->p = sect->base;
+               s->np = sect->size;
+               s->size = sect->size;
+               if(s->type == STEXT) {
+                       if(etextp)
+                               etextp->next = s;
+                       else
+                               textp = s;
+                       etextp = s;
+               }
+               sect->sym = s;
+       }
+       
+       // load relocations
+       for(i=0; i<obj->nsect; i++) {
+               rsect = &obj->sect[i];
+               if(rsect->sym == 0 || rsect->sh.NumberOfRelocations == 0)
+                       continue;
+               if(rsect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE)
+                       continue;
+               r = mal(rsect->sh.NumberOfRelocations*sizeof r[0]);
+               Bseek(f, obj->base+rsect->sh.PointerToRelocations, 0);
+               for(j=0; j<rsect->sh.NumberOfRelocations; j++) {
+                       rp = &r[j];
+                       if(Bread(f, symbuf, 10) != 10)
+                               goto bad;
+                       
+                       uint32 rva, symindex;
+                       uint16 type;
+                       rva = le32(&symbuf[0]);
+                       symindex = le32(&symbuf[4]);
+                       type = le16(&symbuf[8]);
+                       if(readsym(obj, symindex, &sym) < 0)
+                               goto bad;
+                       if(sym->sym == nil) {
+                               werrstr("reloc of invalid sym %s idx=%d type=%d", sym->name, symindex, sym->type);
+                               goto bad;
+                       }
+                       rp->sym = sym->sym;
+                       rp->siz = 4;
+                       rp->off = rva;
+                       switch(type) {
+                               default:
+                                       diag("%s: unknown relocation type %d;", pn, type);
+                               case IMAGE_REL_I386_REL32:
+                                       rp->type = D_PCREL;
+                                       rp->add = 0;
+                                       break;
+                               case IMAGE_REL_I386_DIR32:
+                                       rp->type = D_ADDR;
+                                       // load addend from image
+                                       rp->add = le32(rsect->base+rp->off);
+                                       break;
+                       }
+               }
+               qsort(r, rsect->sh.NumberOfRelocations, sizeof r[0], rbyoff);
+               
+               s = rsect->sym;
+               s->r = r;
+               s->nr = rsect->sh.NumberOfRelocations;
+       }
+       
+       // enter sub-symbols into symbol table.
+       // frist 2 entry is file name.
+       for(i=2; i<obj->npesym; i++) {
+               if(obj->pesym[i].name == 0)
+                       continue;
+               if(obj->pesym[i].name[0] == '.') //skip section
+                       continue;
+               if(obj->pesym[i].sectnum > 0) {
+                       sect = &obj->sect[obj->pesym[i].sectnum-1];
+                       if(sect->sym == 0)
+                               continue;
+               }
+               if(readsym(obj, i, &sym) < 0)
+                       goto bad;
+       
+               s = sym->sym;
+               if(sym->sectnum == 0) {// extern
+                       if(s->type == SDYNIMPORT)
+                               s->plt = -2; // flag for dynimport in PE object files.
+                       continue;
+               } else if (sym->sectnum > 0) {
+                       sect = &obj->sect[sym->sectnum-1];
+                       if(sect->sym == 0)
+                               diag("%s: %s sym == 0!", pn, s->name);
+               } else {
+                       diag("%s: %s sectnum <0!", pn, s->name, sym->sectnum);
+               }
+
+               s->sub = sect->sym->sub;
+               sect->sym->sub = s;
+               s->type = sect->sym->type | SSUB;
+               s->value = sym->value;
+               s->size = 4;
+               s->outer = sect->sym;
+               if(sect->sym->type == STEXT) {
+                       Prog *p;
+       
+                       if(s->text != P)
+                               diag("%s: duplicate definition of %s", pn, s->name);
+                       // build a TEXT instruction with a unique pc
+                       // just to make the rest of the linker happy.
+                       p = prg();
+                       p->as = ATEXT;
+                       p->from.type = D_EXTERN;
+                       p->from.sym = s;
+                       p->textflag = 7;
+                       p->to.type = D_CONST;
+                       p->link = nil;
+                       p->pc = pc++;
+                       s->text = p;
+       
+                       etextp->next = s;
+                       etextp = s;
+               }
+       }
+
+       return;
+bad:
+       diag("%s: malformed pe file: %r", pn);
+}
+
+static int
+map(PeObj *obj, PeSect *sect)
+{
+       if(sect->base != nil)
+               return 0;
+
+       sect->base = mal(sect->sh.SizeOfRawData);
+       werrstr("short read");
+       if(Bseek(obj->f, obj->base+sect->sh.PointerToRawData, 0) < 0 || 
+                       Bread(obj->f, sect->base, sect->sh.SizeOfRawData) != sect->sh.SizeOfRawData)
+               return -1;
+       
+       return 0;
+}
+
+static int
+readsym(PeObj *obj, int i, PeSym **y)
+{
+       Sym *s;
+       PeSym *sym;
+       char *name, *p;
+
+       if(i >= obj->npesym || i < 0) {
+               werrstr("invalid pe symbol index");
+               return -1;
+       }
+
+       sym = &obj->pesym[i];
+       *y = sym;
+       s = nil;
+       
+       name = sym->name;
+       if(sym->sclass == IMAGE_SYM_CLASS_STATIC && sym->value == 0) // section
+               name = obj->sect[sym->sectnum-1].sym->name;
+       if(strncmp(sym->name, "__imp__", 6) == 0)
+               name = &sym->name[7]; // __imp__Name => Name
+       else if(sym->name[0] == '_') 
+               name = &sym->name[1]; // _Name => Name
+       // remove last @XXX
+       p = strchr(name, '@');
+       if(p)
+               *p = 0;
+       
+       switch(sym->type) {
+       default:
+               werrstr("%s: invalid symbol type %d", sym->name, sym->type);
+               return -1;
+       case IMAGE_SYM_DTYPE_FUNCTION:
+       case IMAGE_SYM_DTYPE_NULL:
+               switch(sym->sclass) {
+               case IMAGE_SYM_CLASS_EXTERNAL: //global
+                       s = lookup(name, 0);
+                       break;
+               case IMAGE_SYM_CLASS_NULL:
+               case IMAGE_SYM_CLASS_STATIC:
+                       s = lookup(name, version);
+                       break;
+               default:
+                       werrstr("%s: invalid symbol binding %d", sym->name, sym->sclass);
+                       return -1;
+               }
+               break;
+       }
+
+       if(s != nil && s->type == 0 && !(sym->sclass == IMAGE_SYM_CLASS_STATIC && sym->value == 0))
+               s->type = SXREF;
+       sym->sym = s;
+
+       return 0;
+}
index ae77247c343b5b40ed67bf34ded5621588709ba1..b1a62f25ee7f25c70afeebfdd59dd30757eb8bef 100644 (file)
@@ -406,6 +406,10 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
                ldmacho(f, pkg, len, pn);
                return;
        }
+       if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) {
+               ldpe(f, pkg, len, pn);
+               return;
+       }
 
        /* check the header */
        line = Brdline(f, '\n');
index b8ce99e3e577c711653d70cf6432b7b72af4bfd2..7ce6767a2fd441eb35f8ad1439b98fe8abb78704 100644 (file)
@@ -297,6 +297,13 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
 void
 dope(void)
 {
+       Sym *rel;
+
+       /* relocation table */
+       rel = lookup(".rel", 0);
+       rel->reachable = 1;
+       rel->type = SELFDATA;
+
        initdynimport();
 }
 
index b9031d359aa45e90f5560dba935f5e2b4537e47a..3494e1c13aefee1c9d6c44e3549f23e6356082cb 100644 (file)
@@ -151,10 +151,6 @@ DIRS+=\
 
 endif
 
-ifeq ($(GOOS),windows)
-DIRS:=$(filter-out runtime/cgo,$(DIRS))
-endif
-
 NOTEST=\
        debug/proc\
        exp/draw/x11\
index 904d2f863c1b76afe8198c92a5769516dd61bc3a..82c02407bbe3a2587ad3010e5521aee193fb3e04 100644 (file)
@@ -49,6 +49,17 @@ type Section struct {
        sr *io.SectionReader
 }
 
+type ImportDirectory struct {
+       OriginalFirstThunk uint32
+       TimeDateStamp      uint32
+       ForwarderChain     uint32
+       Name               uint32
+       FirstThunk         uint32
+
+       dll string
+       rva []uint32
+}
+
 // Data reads and returns the contents of the PE section.
 func (s *Section) Data() ([]byte, os.Error) {
        dat := make([]byte, s.sr.Size())
@@ -229,3 +240,70 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
        abbrev, info, str := dat[0], dat[1], dat[2]
        return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str)
 }
+
+// ImportedSymbols returns the names of all symbols
+// referred to by the binary f that are expected to be
+// satisfied by other libraries at dynamic load time.
+// It does not return weak symbols.
+func (f *File) ImportedSymbols() ([]string, os.Error) {
+       ds := f.Section(".idata")
+       if ds == nil {
+               // not dynamic, so no libraries
+               return nil, nil
+       }
+       d, err := ds.Data()
+       if err != nil {
+               return nil, err
+       }
+       var ida []ImportDirectory
+       for len(d) > 0 {
+               var dt ImportDirectory
+               dt.OriginalFirstThunk = binary.LittleEndian.Uint32(d[0:4])
+               dt.Name = binary.LittleEndian.Uint32(d[12:16])
+               dt.FirstThunk = binary.LittleEndian.Uint32(d[16:20])
+               d = d[20:]
+               if dt.OriginalFirstThunk == 0 {
+                       break
+               }
+               ida = append(ida, dt)
+       }
+       for i, _ := range ida {
+               for len(d) > 0 {
+                       va := binary.LittleEndian.Uint32(d[0:4])
+                       d = d[4:]
+                       if va == 0 {
+                               break
+                       }
+                       ida[i].rva = append(ida[i].rva, va)
+               }
+       }
+       for _, _ = range ida {
+               for len(d) > 0 {
+                       va := binary.LittleEndian.Uint32(d[0:4])
+                       d = d[4:]
+                       if va == 0 {
+                               break
+                       }
+               }
+       }
+       names, _ := ds.Data()
+       var all []string
+       for _, dt := range ida {
+               dt.dll, _ = getString(names, int(dt.Name-ds.VirtualAddress))
+               for _, va := range dt.rva {
+                       fn, _ := getString(names, int(va-ds.VirtualAddress+2))
+                       all = append(all, fn+":"+dt.dll)
+               }
+       }
+
+       return all, nil
+}
+
+// ImportedLibraries returns the names of all libraries
+// referred to by the binary f that are expected to be
+// linked with the binary at dynamic link time.
+func (f *File) ImportedLibraries() ([]string, os.Error) {
+       // TODO
+       // cgo -dynimport don't use this for windows PE, so just return.
+       return nil, nil
+}
index 101a0cf5223c05b5c3ad9286e0e74d358228ade7..58ca712ef7744976e4f1a9cad9d2f27d5306f2ab 100644 (file)
@@ -18,9 +18,10 @@ TEXT _rt0_386(SB),7,$0
        // we set up GS ourselves.
        MOVL    initcgo(SB), AX
        TESTL   AX, AX
-       JZ      3(PC)
+       JZ      4(PC)
        CALL    AX
-       JMP     ok
+       CMPL runtime·iswindows(SB), $0
+       JEQ ok
 
        // set up %gs
        CALL    runtime·ldt0setup(SB)
index dc9ffb41190228edc451bfa4344f15444142c4e1..a2ce902d68f1e24666655999f13d70ea7c144552 100644 (file)
@@ -30,7 +30,11 @@ OFILES=\
        _cgo_import.$O\
        $(CGO_OFILES)\
 
+ifeq ($(GOOS),windows)
+CGO_LDFLAGS=-lm -mthreads
+else
 CGO_LDFLAGS=-lpthread
+endif
 
 ifeq ($(GOOS),freebsd)
 OFILES+=\
index 5f5235bd2dafa8ab98e4bc154888dbad0f30cb0e..f39309cb1b19063e602002f54cdc7b5c8de27712 100755 (executable)
@@ -30,6 +30,7 @@ static void*
 threadentry(void *v)
 {
        ThreadStart ts;
+       void *tls0;
 
        ts = *(ThreadStart*)v;
        free(v);
@@ -45,13 +46,17 @@ threadentry(void *v)
        /*
         * Set specific keys in thread local storage.
         */
+       tls0 = (void*)LocalAlloc(LPTR, 32);
        asm volatile (
-               "MOVL %%fs:0x2c, %%eax\n"       // MOVL 0x24(FS), tmp
-               "movl %0, 0(%%eax)\n"   // MOVL g, 0(FS)
-               "movl %1, 4(%%eax)\n"   // MOVL m, 4(FS)
-               :: "r"(ts.g), "r"(ts.m) : "%eax"
+               "movl %0, %%fs:0x2c\n"  // MOVL tls0, 0x2c(FS)
+               "movl %%fs:0x2c, %%eax\n"       // MOVL 0x2c(FS), tmp
+               "movl %1, 0(%%eax)\n"   // MOVL g, 0(FS)
+               "movl %2, 4(%%eax)\n"   // MOVL m, 4(FS)
+               :: "r"(tls0), "r"(ts.g), "r"(ts.m) : "%eax"
        );
        
        crosscall_386(ts.fn);
+       
+       LocalFree(tls0);
        return nil;
 }
index 513675240f5127a4972d098f8172b9051bd7e24f..8d3675070c52c2600721c978ed5acc9004cbc6a6 100644 (file)
@@ -153,6 +153,7 @@ runtime·args(int32 c, uint8 **v)
 }
 
 int32 runtime·isplan9;
+int32 runtime·iswindows;
 
 void
 runtime·goargs(void)
index 4b67a9f42eddf3b959f244363634cd24b94986c9..3b023de2f6a536d8e3f9b894d02e9ffeaa18281e 100644 (file)
@@ -9,3 +9,6 @@ TEXT _rt0_386_windows(SB),7,$0
        MOVL    SP, 0(FS)
 
        JMP     _rt0_386(SB)
+
+DATA  runtime·iswindows(SB)/4, $1
+GLOBL runtime·iswindows(SB), $4