summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei Guangjing <vcc.163@gmail.com>2011-01-20 10:22:20 -0500
committerWei Guangjing <vcc.163@gmail.com>2011-01-20 10:22:20 -0500
commit66ed133062855ea8b18094f6ae36927c2977d071 (patch)
treece478731000234a0f92bf99a66c95108da890276
parent8d3edcce4fd9ecec79bc589e4788dcbbebeca6cf (diff)
downloadgo-66ed133062855ea8b18094f6ae36927c2977d071.tar.gz
cgo: windows/386 port
R=rsc, peterGo, brainman CC=golang-dev http://codereview.appspot.com/3733046 Committer: Russ Cox <rsc@golang.org>
-rw-r--r--src/cmd/5l/Makefile1
-rw-r--r--src/cmd/6l/Makefile1
-rw-r--r--src/cmd/8l/Makefile1
-rw-r--r--src/cmd/cgo/main.go8
-rw-r--r--src/cmd/cgo/out.go11
-rw-r--r--src/cmd/gopack/ar.c1
-rw-r--r--src/cmd/ld/data.c27
-rw-r--r--src/cmd/ld/ldpe.c404
-rw-r--r--src/cmd/ld/lib.c4
-rw-r--r--src/cmd/ld/pe.c7
-rw-r--r--src/pkg/Makefile4
-rw-r--r--src/pkg/debug/pe/file.go78
-rw-r--r--src/pkg/runtime/386/asm.s5
-rw-r--r--src/pkg/runtime/cgo/Makefile4
-rwxr-xr-xsrc/pkg/runtime/cgo/windows_386.c13
-rw-r--r--src/pkg/runtime/runtime.c1
-rw-r--r--src/pkg/runtime/windows/386/rt0.s3
17 files changed, 559 insertions, 14 deletions
diff --git a/src/cmd/5l/Makefile b/src/cmd/5l/Makefile
index 71798724b..c11ebe990 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 f7d2a550c..abe204d4f 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 84976ba18..a85e3ffa7 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 942bda5f4..14bb7ec2b 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 c76616677..d5fc63409 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 063967bd7..a16e98cfe 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 27e0078d7..0551232cf 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; 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
index 000000000..66b122bb3
--- /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; 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;
+}
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index ae77247c3..b1a62f25e 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 b8ce99e3e..7ce6767a2 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 b9031d359..3494e1c13 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 904d2f863..82c02407b 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 101a0cf52..58ca712ef 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 dc9ffb411..a2ce902d6 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 5f5235bd2..f39309cb1 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 513675240..8d3675070 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 4b67a9f42..3b023de2f 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