Commit 1aa2d887 authored by Wei Guangjing's avatar Wei Guangjing Committed by Russ Cox

cgo: windows/386 port

R=rsc, peterGo, brainman
CC=golang-dev
https://golang.org/cl/3733046
parent 3aec5516
......@@ -14,6 +14,7 @@ OFILES=\
enam.$O\
ldelf.$O\
ldmacho.$O\
ldpe.$O\
lib.$O\
list.$O\
noop.$O\
......
......@@ -16,6 +16,7 @@ OFILES=\
go.$O\
ldelf.$O\
ldmacho.$O\
ldpe.$O\
lib.$O\
list.$O\
macho.$O\
......
......@@ -16,6 +16,7 @@ OFILES=\
go.$O\
ldelf.$O\
ldmacho.$O\
ldpe.$O\
lib.$O\
list.$O\
macho.$O\
......
......@@ -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, "")
}
......
......@@ -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
......
......@@ -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);
......
......@@ -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)
......
This diff is collapsed.
......@@ -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');
......
......@@ -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();
}
......
......@@ -151,10 +151,6 @@ DIRS+=\
endif
ifeq ($(GOOS),windows)
DIRS:=$(filter-out runtime/cgo,$(DIRS))
endif
NOTEST=\
debug/proc\
exp/draw/x11\
......
......@@ -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
}
......@@ -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)
......
......@@ -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+=\
......
......@@ -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;
}
......@@ -153,6 +153,7 @@ runtime·args(int32 c, uint8 **v)
}
int32 runtime·isplan9;
int32 runtime·iswindows;
void
runtime·goargs(void)
......
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment