cgo: windows/386 port R=rsc, peterGo, brainman CC=golang-dev https://golang.org/cl/3733046
diff --git a/src/pkg/Makefile b/src/pkg/Makefile index b9031d3..3494e1c 100644 --- a/src/pkg/Makefile +++ b/src/pkg/Makefile
@@ -151,10 +151,6 @@ 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 904d2f8..82c0240 100644 --- a/src/pkg/debug/pe/file.go +++ b/src/pkg/debug/pe/file.go
@@ -49,6 +49,17 @@ 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 @@ 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 101a0cf..58ca712 100644 --- a/src/pkg/runtime/386/asm.s +++ b/src/pkg/runtime/386/asm.s
@@ -18,9 +18,10 @@ // 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 dc9ffb4..a2ce902 100644 --- a/src/pkg/runtime/cgo/Makefile +++ b/src/pkg/runtime/cgo/Makefile
@@ -30,7 +30,11 @@ _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 5f5235b..f39309c 100755 --- a/src/pkg/runtime/cgo/windows_386.c +++ b/src/pkg/runtime/cgo/windows_386.c
@@ -30,6 +30,7 @@ threadentry(void *v) { ThreadStart ts; + void *tls0; ts = *(ThreadStart*)v; free(v); @@ -45,13 +46,17 @@ /* * 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 5136752..8d36750 100644 --- a/src/pkg/runtime/runtime.c +++ b/src/pkg/runtime/runtime.c
@@ -153,6 +153,7 @@ } 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 4b67a9f..3b023de 100644 --- a/src/pkg/runtime/windows/386/rt0.s +++ b/src/pkg/runtime/windows/386/rt0.s
@@ -9,3 +9,6 @@ MOVL SP, 0(FS) JMP _rt0_386(SB) + +DATA runtime·iswindows(SB)/4, $1 +GLOBL runtime·iswindows(SB), $4