mirror of
https://github.com/golang/go
synced 2024-11-12 03:10:22 -07:00
cgo working on linux/386
R=r DELTA=70 (47 added, 4 deleted, 19 changed) OCL=35167 CL=35171
This commit is contained in:
parent
0632bb4ae5
commit
e67a5084b8
@ -10,6 +10,12 @@ CGOFILES=\
|
|||||||
|
|
||||||
CGO_LDFLAGS=-lgmp
|
CGO_LDFLAGS=-lgmp
|
||||||
|
|
||||||
|
# To add flags necessary for locating the library or its include files,
|
||||||
|
# set CGO_CFLAGS or CGO_LDFLAGS. For example, to use an
|
||||||
|
# alternate installation of the library:
|
||||||
|
# CGO_CFLAGS=-I/home/rsc/gmp32/include
|
||||||
|
# CGO_LDFLAGS+=-L/home/rsc/gmp32/lib
|
||||||
|
|
||||||
# Can have plain GOFILES too, but this example doesn't.
|
# Can have plain GOFILES too, but this example doesn't.
|
||||||
|
|
||||||
include $(GOROOT)/src/Make.pkg
|
include $(GOROOT)/src/Make.pkg
|
||||||
|
@ -93,18 +93,21 @@ RUNTIME_CFLAGS=-I$(GOROOT)/src/pkg/runtime $(RUNTIME_CFLAGS_$(GOARCH))
|
|||||||
%.cgo3.$O: %.cgo3.c
|
%.cgo3.$O: %.cgo3.c
|
||||||
$(CC) $(CFLAGS) $(RUNTIME_CFLAGS) $*.cgo3.c
|
$(CC) $(CFLAGS) $(RUNTIME_CFLAGS) $*.cgo3.c
|
||||||
|
|
||||||
|
# Have to run gcc with the right size argument on hybrid 32/64 machines.
|
||||||
|
_CGO_CFLAGS_386=-m32
|
||||||
|
_CGO_CFLAGS_amd64=-m64
|
||||||
|
|
||||||
# Compile x.cgo4.c with gcc to make package_x.so.
|
# Compile x.cgo4.c with gcc to make package_x.so.
|
||||||
%.cgo4.o: %.cgo4.c
|
%.cgo4.o: %.cgo4.c
|
||||||
gcc -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $*.cgo4.c
|
gcc $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $*.cgo4.c
|
||||||
|
|
||||||
$(elem)_%.so: %.cgo4.o
|
$(elem)_%.so: %.cgo4.o
|
||||||
gcc -shared -o $@ $*.cgo4.o $(CGO_LDFLAGS)
|
gcc $(_CGO_CFLAGS_$(GOARCH)) -shared -o $@ $*.cgo4.o $(CGO_LDFLAGS)
|
||||||
|
|
||||||
$(pkgdir)/$(dir)/$(elem)_%.so: $(elem)_%.so
|
$(pkgdir)/$(dir)/$(elem)_%.so: $(elem)_%.so
|
||||||
@test -d $(GOROOT)/pkg && mkdir -p $(pkgdir)/$(dir)
|
@test -d $(GOROOT)/pkg && mkdir -p $(pkgdir)/$(dir)
|
||||||
cp $(elem)_$*.so $@
|
cp $(elem)_$*.so $@
|
||||||
|
|
||||||
|
|
||||||
# Generic build rules.
|
# Generic build rules.
|
||||||
# These come last so that the rules above can override them
|
# These come last so that the rules above can override them
|
||||||
# for more specific file names.
|
# for more specific file names.
|
||||||
|
@ -231,6 +231,17 @@ outcode(void)
|
|||||||
Binit(&b, f, OWRITE);
|
Binit(&b, f, OWRITE);
|
||||||
|
|
||||||
Bprint(&b, "%s\n", thestring);
|
Bprint(&b, "%s\n", thestring);
|
||||||
|
if(ndynld > 0) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Bprint(&b, "\n");
|
||||||
|
Bprint(&b, "$$ // exports\n\n");
|
||||||
|
Bprint(&b, "$$ // local types\n\n");
|
||||||
|
Bprint(&b, "$$ // dynld\n", thestring);
|
||||||
|
for(i=0; i<ndynld; i++)
|
||||||
|
Bprint(&b, "dynld %s %s %s\n", dynld[i].local, dynld[i].remote, dynld[i].path);
|
||||||
|
Bprint(&b, "$$\n\n");
|
||||||
|
}
|
||||||
Bprint(&b, "!\n");
|
Bprint(&b, "!\n");
|
||||||
|
|
||||||
outhist(&b);
|
outhist(&b);
|
||||||
|
@ -333,7 +333,7 @@ doelf(void)
|
|||||||
s = lookup(".dynsym", 0);
|
s = lookup(".dynsym", 0);
|
||||||
s->type = SDATA;
|
s->type = SDATA;
|
||||||
s->reachable = 1;
|
s->reachable = 1;
|
||||||
s->value += ELF64SYMSIZE;
|
s->value += ELF32SYMSIZE;
|
||||||
|
|
||||||
/* dynamic string table */
|
/* dynamic string table */
|
||||||
s = lookup(".dynstr", 0);
|
s = lookup(".dynstr", 0);
|
||||||
@ -368,21 +368,20 @@ doelf(void)
|
|||||||
if(!s->reachable || (s->type != SDATA && s->type != SBSS) || s->dynldname == nil)
|
if(!s->reachable || (s->type != SDATA && s->type != SBSS) || s->dynldname == nil)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
d = lookup(".rela", 0);
|
d = lookup(".rel", 0);
|
||||||
addaddr(d, s);
|
addaddr(d, s);
|
||||||
adduint64(d, ELF64_R_INFO(nsym, R_X86_64_64));
|
adduint32(d, ELF32_R_INFO(nsym, R_386_32));
|
||||||
adduint64(d, 0);
|
|
||||||
nsym++;
|
nsym++;
|
||||||
|
|
||||||
d = lookup(".dynsym", 0);
|
d = lookup(".dynsym", 0);
|
||||||
adduint32(d, addstring(lookup(".dynstr", 0), s->dynldname));
|
adduint32(d, addstring(lookup(".dynstr", 0), s->dynldname));
|
||||||
|
adduint32(d, 0); /* value */
|
||||||
|
adduint32(d, 0); /* size of object */
|
||||||
t = STB_GLOBAL << 4;
|
t = STB_GLOBAL << 4;
|
||||||
t |= STT_OBJECT; // works for func too, empirically
|
t |= STT_OBJECT; // works for func too, empirically
|
||||||
adduint8(d, t);
|
adduint8(d, t);
|
||||||
adduint8(d, 0); /* reserved */
|
adduint8(d, 0); /* reserved */
|
||||||
adduint16(d, SHN_UNDEF); /* section where symbol is defined */
|
adduint16(d, SHN_UNDEF); /* section where symbol is defined */
|
||||||
adduint64(d, 0); /* value */
|
|
||||||
adduint64(d, 0); /* size of object */
|
|
||||||
|
|
||||||
if(needlib(s->dynldlib))
|
if(needlib(s->dynldlib))
|
||||||
elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->dynldlib));
|
elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->dynldlib));
|
||||||
|
@ -35,6 +35,7 @@ type Prog struct {
|
|||||||
Typedef map[string]ast.Expr;
|
Typedef map[string]ast.Expr;
|
||||||
Vardef map[string]*Type;
|
Vardef map[string]*Type;
|
||||||
Funcdef map[string]*FuncType;
|
Funcdef map[string]*FuncType;
|
||||||
|
PtrSize int64;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Type collects information about a type in both the C and Go worlds.
|
// A Type collects information about a type in both the C and Go worlds.
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"strings";
|
"strings";
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *Prog) loadDebugInfo(ptrSize int64) {
|
func (p *Prog) loadDebugInfo() {
|
||||||
// Construct a slice of unique names from p.Crefs.
|
// Construct a slice of unique names from p.Crefs.
|
||||||
m := make(map[string]int);
|
m := make(map[string]int);
|
||||||
for _, c := range p.Crefs {
|
for _, c := range p.Crefs {
|
||||||
@ -57,7 +57,7 @@ func (p *Prog) loadDebugInfo(ptrSize int64) {
|
|||||||
b.WriteString("}\n");
|
b.WriteString("}\n");
|
||||||
|
|
||||||
kind := make(map[string]string);
|
kind := make(map[string]string);
|
||||||
_, stderr := gccDebug(b.Bytes());
|
_, stderr := p.gccDebug(b.Bytes());
|
||||||
if stderr == "" {
|
if stderr == "" {
|
||||||
fatal("gcc produced no output");
|
fatal("gcc produced no output");
|
||||||
}
|
}
|
||||||
@ -109,7 +109,7 @@ func (p *Prog) loadDebugInfo(ptrSize int64) {
|
|||||||
for i, n := range names {
|
for i, n := range names {
|
||||||
fmt.Fprintf(&b, "typeof(%s) *__cgo__%d;\n", n, i);
|
fmt.Fprintf(&b, "typeof(%s) *__cgo__%d;\n", n, i);
|
||||||
}
|
}
|
||||||
d, stderr := gccDebug(b.Bytes());
|
d, stderr := p.gccDebug(b.Bytes());
|
||||||
if d == nil {
|
if d == nil {
|
||||||
fatal("gcc failed:\n%s\non input:\n%s", stderr, b.Bytes());
|
fatal("gcc failed:\n%s\non input:\n%s", stderr, b.Bytes());
|
||||||
}
|
}
|
||||||
@ -158,7 +158,7 @@ func (p *Prog) loadDebugInfo(ptrSize int64) {
|
|||||||
|
|
||||||
// Record types and typedef information in Crefs.
|
// Record types and typedef information in Crefs.
|
||||||
var conv typeConv;
|
var conv typeConv;
|
||||||
conv.Init(ptrSize);
|
conv.Init(p.PtrSize);
|
||||||
for _, c := range p.Crefs {
|
for _, c := range p.Crefs {
|
||||||
i := m[c.Name];
|
i := m[c.Name];
|
||||||
c.TypeName = kind[c.Name] == "type";
|
c.TypeName = kind[c.Name] == "type";
|
||||||
@ -175,9 +175,9 @@ func (p *Prog) loadDebugInfo(ptrSize int64) {
|
|||||||
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
|
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
|
||||||
// returns the corresponding DWARF data and any messages
|
// returns the corresponding DWARF data and any messages
|
||||||
// printed to standard error.
|
// printed to standard error.
|
||||||
func gccDebug(stdin []byte) (*dwarf.Data, string) {
|
func (p *Prog) gccDebug(stdin []byte) (*dwarf.Data, string) {
|
||||||
machine := "-m32";
|
machine := "-m32";
|
||||||
if os.Getenv("GOARCH") == "amd64" {
|
if p.PtrSize == 8 {
|
||||||
machine = "-m64";
|
machine = "-m64";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,20 +22,34 @@ func usage() {
|
|||||||
flag.PrintDefaults();
|
flag.PrintDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ptrSize = 8 // TODO
|
var ptrSizeMap = map[string]int64 {
|
||||||
|
"386": 4,
|
||||||
|
"amd64": 8,
|
||||||
|
"arm": 4
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Usage = usage;
|
flag.Usage = usage;
|
||||||
flag.Parse();
|
flag.Parse();
|
||||||
|
|
||||||
|
arch := os.Getenv("GOARCH");
|
||||||
|
if arch == "" {
|
||||||
|
fatal("$GOARCH is not set");
|
||||||
|
}
|
||||||
|
ptrSize, ok := ptrSizeMap[arch];
|
||||||
|
if !ok {
|
||||||
|
fatal("unknown architecture %s", arch);
|
||||||
|
}
|
||||||
|
|
||||||
args := flag.Args();
|
args := flag.Args();
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
usage();
|
usage();
|
||||||
os.Exit(2);
|
os.Exit(2);
|
||||||
}
|
}
|
||||||
p := openProg(args[0]);
|
p := openProg(args[0]);
|
||||||
|
p.PtrSize = ptrSize;
|
||||||
p.Preamble = p.Preamble + "\n" + builtinProlog;
|
p.Preamble = p.Preamble + "\n" + builtinProlog;
|
||||||
p.loadDebugInfo(ptrSize);
|
p.loadDebugInfo();
|
||||||
p.Vardef = make(map[string]*Type);
|
p.Vardef = make(map[string]*Type);
|
||||||
p.Funcdef = make(map[string]*FuncType);
|
p.Funcdef = make(map[string]*FuncType);
|
||||||
|
|
||||||
|
@ -100,8 +100,8 @@ func (p *Prog) writeOutput(srcfile string) {
|
|||||||
structType += fmt.Sprintf("\t\t%s p%d;\n", t.C, i);
|
structType += fmt.Sprintf("\t\t%s p%d;\n", t.C, i);
|
||||||
off += t.Size;
|
off += t.Size;
|
||||||
}
|
}
|
||||||
if off%ptrSize != 0 {
|
if off%p.PtrSize != 0 {
|
||||||
pad := ptrSize - off%ptrSize;
|
pad := p.PtrSize - off%p.PtrSize;
|
||||||
structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
|
structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
|
||||||
off += pad;
|
off += pad;
|
||||||
npad++;
|
npad++;
|
||||||
@ -116,8 +116,8 @@ func (p *Prog) writeOutput(srcfile string) {
|
|||||||
structType += fmt.Sprintf("\t\t%s r;\n", t.C);
|
structType += fmt.Sprintf("\t\t%s r;\n", t.C);
|
||||||
off += t.Size;
|
off += t.Size;
|
||||||
}
|
}
|
||||||
if off%ptrSize != 0 {
|
if off%p.PtrSize != 0 {
|
||||||
pad := ptrSize - off%ptrSize;
|
pad := p.PtrSize - off%p.PtrSize;
|
||||||
structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
|
structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
|
||||||
off += pad;
|
off += pad;
|
||||||
npad++;
|
npad++;
|
||||||
|
@ -4,15 +4,17 @@
|
|||||||
|
|
||||||
# not linked into build for now
|
# not linked into build for now
|
||||||
|
|
||||||
|
CFLAGS_386=-m32
|
||||||
|
|
||||||
TARG=libcgo.so
|
TARG=libcgo.so
|
||||||
|
|
||||||
all: libcgo.so
|
all: libcgo.so
|
||||||
|
|
||||||
cgocall.o: cgocall.c
|
cgocall.o: cgocall.c
|
||||||
gcc -O2 -fPIC -o cgocall.o -c cgocall.c
|
gcc $(CFLAGS_$(GOARCH)) -O2 -fPIC -o cgocall.o -c cgocall.c
|
||||||
|
|
||||||
libcgo.so: cgocall.o
|
libcgo.so: cgocall.o
|
||||||
gcc -shared -o libcgo.so cgocall.o -lpthread -lm
|
gcc $(CFLAGS_$(GOARCH)) -shared -o libcgo.so cgocall.o -lpthread -lm
|
||||||
|
|
||||||
install: $(GOROOT)/pkg/$(GOOS)_$(GOARCH)/libcgo.so
|
install: $(GOROOT)/pkg/$(GOOS)_$(GOARCH)/libcgo.so
|
||||||
|
|
||||||
|
@ -5,4 +5,11 @@
|
|||||||
// Darwin and Linux use the same linkage to main
|
// Darwin and Linux use the same linkage to main
|
||||||
|
|
||||||
TEXT _rt0_386_linux(SB),7,$0
|
TEXT _rt0_386_linux(SB),7,$0
|
||||||
|
MOVL initcgo(SB), AX
|
||||||
|
TESTL AX, AX
|
||||||
|
JZ 2(PC)
|
||||||
|
CALL AX
|
||||||
|
|
||||||
JMP _rt0_386(SB)
|
JMP _rt0_386(SB)
|
||||||
|
|
||||||
|
GLOBL initcgo(SB), $4
|
||||||
|
Loading…
Reference in New Issue
Block a user