mirror of
https://github.com/golang/go
synced 2024-11-25 14:07:56 -07:00
cgo: windows/386 port
R=rsc, peterGo, brainman CC=golang-dev https://golang.org/cl/3733046
This commit is contained in:
parent
3aec5516ed
commit
1aa2d88739
@ -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)
|
||||
|
404
src/cmd/ld/ldpe.c
Normal file
404
src/cmd/ld/ldpe.c
Normal file
@ -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;
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user