From 1aa2d887395b55a5967e0c519c479ef95743404d Mon Sep 17 00:00:00 2001 From: Wei Guangjing Date: Thu, 20 Jan 2011 10:22:20 -0500 Subject: [PATCH] cgo: windows/386 port R=rsc, peterGo, brainman CC=golang-dev https://golang.org/cl/3733046 --- src/cmd/5l/Makefile | 1 + src/cmd/6l/Makefile | 1 + src/cmd/8l/Makefile | 1 + src/cmd/cgo/main.go | 8 + src/cmd/cgo/out.go | 11 +- src/cmd/gopack/ar.c | 1 + src/cmd/ld/data.c | 27 ++ src/cmd/ld/ldpe.c | 404 ++++++++++++++++++++++++++++++ src/cmd/ld/lib.c | 4 + src/cmd/ld/pe.c | 7 + src/pkg/Makefile | 4 - src/pkg/debug/pe/file.go | 78 ++++++ src/pkg/runtime/386/asm.s | 5 +- src/pkg/runtime/cgo/Makefile | 4 + src/pkg/runtime/cgo/windows_386.c | 13 +- src/pkg/runtime/runtime.c | 1 + src/pkg/runtime/windows/386/rt0.s | 3 + 17 files changed, 559 insertions(+), 14 deletions(-) create mode 100644 src/cmd/ld/ldpe.c diff --git a/src/cmd/5l/Makefile b/src/cmd/5l/Makefile index 71798724b8e..c11ebe9908e 100644 --- a/src/cmd/5l/Makefile +++ b/src/cmd/5l/Makefile @@ -14,6 +14,7 @@ OFILES=\ enam.$O\ ldelf.$O\ ldmacho.$O\ + ldpe.$O\ lib.$O\ list.$O\ noop.$O\ diff --git a/src/cmd/6l/Makefile b/src/cmd/6l/Makefile index f7d2a550c34..abe204d4f5a 100644 --- a/src/cmd/6l/Makefile +++ b/src/cmd/6l/Makefile @@ -16,6 +16,7 @@ OFILES=\ go.$O\ ldelf.$O\ ldmacho.$O\ + ldpe.$O\ lib.$O\ list.$O\ macho.$O\ diff --git a/src/cmd/8l/Makefile b/src/cmd/8l/Makefile index 84976ba18b4..a85e3ffa7c1 100644 --- a/src/cmd/8l/Makefile +++ b/src/cmd/8l/Makefile @@ -16,6 +16,7 @@ OFILES=\ go.$O\ ldelf.$O\ ldmacho.$O\ + ldpe.$O\ lib.$O\ list.$O\ macho.$O\ diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index 942bda5f4da..14bb7ec2b08 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -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, "") } diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index c7661667752..d5fc63409fd 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -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 diff --git a/src/cmd/gopack/ar.c b/src/cmd/gopack/ar.c index 063967bd70b..a16e98cfe54 100644 --- a/src/cmd/gopack/ar.c +++ b/src/cmd/gopack/ar.c @@ -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); diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index 27e0078d746..0551232cfc9 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -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; rr+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; rr+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 index 00000000000..66b122bb339 --- /dev/null +++ b/src/cmd/ld/ldpe.c @@ -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; ifh.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; insect; 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; insect; 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; jsh.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; inpesym; 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; +} diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index ae77247c343..b1a62f25ee7 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -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'); diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c index b8ce99e3e57..7ce6767a2fd 100644 --- a/src/cmd/ld/pe.c +++ b/src/cmd/ld/pe.c @@ -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(); } diff --git a/src/pkg/Makefile b/src/pkg/Makefile index b9031d359aa..3494e1c13ae 100644 --- a/src/pkg/Makefile +++ b/src/pkg/Makefile @@ -151,10 +151,6 @@ DIRS+=\ endif -ifeq ($(GOOS),windows) -DIRS:=$(filter-out runtime/cgo,$(DIRS)) -endif - NOTEST=\ debug/proc\ exp/draw/x11\ diff --git a/src/pkg/debug/pe/file.go b/src/pkg/debug/pe/file.go index 904d2f863c1..82c02407bbe 100644 --- a/src/pkg/debug/pe/file.go +++ b/src/pkg/debug/pe/file.go @@ -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 +} diff --git a/src/pkg/runtime/386/asm.s b/src/pkg/runtime/386/asm.s index 101a0cf5223..58ca712ef77 100644 --- a/src/pkg/runtime/386/asm.s +++ b/src/pkg/runtime/386/asm.s @@ -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) diff --git a/src/pkg/runtime/cgo/Makefile b/src/pkg/runtime/cgo/Makefile index dc9ffb41190..a2ce902d68f 100644 --- a/src/pkg/runtime/cgo/Makefile +++ b/src/pkg/runtime/cgo/Makefile @@ -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+=\ diff --git a/src/pkg/runtime/cgo/windows_386.c b/src/pkg/runtime/cgo/windows_386.c index 5f5235bd2da..f39309cb1b1 100755 --- a/src/pkg/runtime/cgo/windows_386.c +++ b/src/pkg/runtime/cgo/windows_386.c @@ -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; } diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c index 513675240f5..8d3675070c5 100644 --- a/src/pkg/runtime/runtime.c +++ b/src/pkg/runtime/runtime.c @@ -153,6 +153,7 @@ runtime·args(int32 c, uint8 **v) } int32 runtime·isplan9; +int32 runtime·iswindows; void runtime·goargs(void) diff --git a/src/pkg/runtime/windows/386/rt0.s b/src/pkg/runtime/windows/386/rt0.s index 4b67a9f42ed..3b023de2f6a 100644 --- a/src/pkg/runtime/windows/386/rt0.s +++ b/src/pkg/runtime/windows/386/rt0.s @@ -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