]> Cypherpunks repositories - gostls13.git/commitdiff
cgo working on linux/386
authorRuss Cox <rsc@golang.org>
Wed, 30 Sep 2009 20:47:15 +0000 (13:47 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 30 Sep 2009 20:47:15 +0000 (13:47 -0700)
R=r
DELTA=70  (47 added, 4 deleted, 19 changed)
OCL=35167
CL=35171

misc/cgo/gmp/Makefile
src/Make.pkg
src/cmd/8c/swt.c
src/cmd/8l/asm.c
src/cmd/cgo/ast.go
src/cmd/cgo/gcc.go
src/cmd/cgo/main.go
src/cmd/cgo/out.go
src/libcgo/Makefile
src/pkg/runtime/linux/386/rt0.s

index 1e521ab7da113de6e72015e44559b2052f3fb3e3..b261ff2352afe663aa0a1b4fe9138c44bf487855 100644 (file)
@@ -10,6 +10,12 @@ CGOFILES=\
 
 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.
 
 include $(GOROOT)/src/Make.pkg
index fadd78e3ddec42183bf2d9900bd62e1b08309dce..bc00eeaefd54793591d11f9ead1c4eb78d8bb55a 100644 (file)
@@ -93,18 +93,21 @@ RUNTIME_CFLAGS=-I$(GOROOT)/src/pkg/runtime $(RUNTIME_CFLAGS_$(GOARCH))
 %.cgo3.$O: %.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.
 %.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
-       gcc -shared -o $@ $*.cgo4.o $(CGO_LDFLAGS)
+       gcc $(_CGO_CFLAGS_$(GOARCH)) -shared -o $@ $*.cgo4.o $(CGO_LDFLAGS)
 
 $(pkgdir)/$(dir)/$(elem)_%.so: $(elem)_%.so
        @test -d $(GOROOT)/pkg && mkdir -p $(pkgdir)/$(dir)
        cp $(elem)_$*.so $@
 
-
 # Generic build rules.
 # These come last so that the rules above can override them
 # for more specific file names.
index dc7caf3ece25e9520ab4a458cd61d8daf630c84c..76dc1994723dfc5b30caea0823e96204003277c1 100644 (file)
@@ -231,6 +231,17 @@ outcode(void)
        Binit(&b, f, OWRITE);
 
        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");
 
        outhist(&b);
index f5a73884d2a942d7978618198bef3d0fb6b695e6..627bd25e89f1992b09ec942133bc56a75459bedb 100644 (file)
@@ -333,7 +333,7 @@ doelf(void)
                s = lookup(".dynsym", 0);
                s->type = SDATA;
                s->reachable = 1;
-               s->value += ELF64SYMSIZE;
+               s->value += ELF32SYMSIZE;
 
                /* dynamic string table */
                s = lookup(".dynstr", 0);
@@ -368,21 +368,20 @@ doelf(void)
                                if(!s->reachable || (s->type != SDATA && s->type != SBSS) || s->dynldname == nil)
                                        continue;
 
-                               d = lookup(".rela", 0);
+                               d = lookup(".rel", 0);
                                addaddr(d, s);
-                               adduint64(d, ELF64_R_INFO(nsym, R_X86_64_64));
-                               adduint64(d, 0);
+                               adduint32(d, ELF32_R_INFO(nsym, R_386_32));
                                nsym++;
 
                                d = lookup(".dynsym", 0);
                                adduint32(d, addstring(lookup(".dynstr", 0), s->dynldname));
+                               adduint32(d, 0);        /* value */
+                               adduint32(d, 0);        /* size of object */
                                t = STB_GLOBAL << 4;
                                t |= STT_OBJECT;        // works for func too, empirically
                                adduint8(d, t);
                                adduint8(d, 0); /* reserved */
                                adduint16(d, SHN_UNDEF);        /* section where symbol is defined */
-                               adduint64(d, 0);        /* value */
-                               adduint64(d, 0);        /* size of object */
 
                                if(needlib(s->dynldlib))
                                        elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->dynldlib));
index 29fe55240d7d4422e0de25143ac5ef02f7726508..9b122676c845149c7c0e5f8f5bd0e1ee6e252eeb 100644 (file)
@@ -35,6 +35,7 @@ type Prog struct {
        Typedef map[string]ast.Expr;
        Vardef map[string]*Type;
        Funcdef map[string]*FuncType;
+       PtrSize int64;
 }
 
 // A Type collects information about a type in both the C and Go worlds.
index 27090fdf4f6951e1861f3129f6592cabf5710fdd..e3f5268458c2c13576cb80c1696be35c6a03aa43 100644 (file)
@@ -20,7 +20,7 @@ import (
        "strings";
 )
 
-func (p *Prog) loadDebugInfo(ptrSize int64) {
+func (p *Prog) loadDebugInfo() {
        // Construct a slice of unique names from p.Crefs.
        m := make(map[string]int);
        for _, c := range p.Crefs {
@@ -57,7 +57,7 @@ func (p *Prog) loadDebugInfo(ptrSize int64) {
        b.WriteString("}\n");
 
        kind := make(map[string]string);
-       _, stderr := gccDebug(b.Bytes());
+       _, stderr := p.gccDebug(b.Bytes());
        if stderr == "" {
                fatal("gcc produced no output");
        }
@@ -109,7 +109,7 @@ func (p *Prog) loadDebugInfo(ptrSize int64) {
        for i, n := range names {
                fmt.Fprintf(&b, "typeof(%s) *__cgo__%d;\n", n, i);
        }
-       d, stderr := gccDebug(b.Bytes());
+       d, stderr := p.gccDebug(b.Bytes());
        if d == nil {
                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.
        var conv typeConv;
-       conv.Init(ptrSize);
+       conv.Init(p.PtrSize);
        for _, c := range p.Crefs {
                i := m[c.Name];
                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
 // returns the corresponding DWARF data and any messages
 // printed to standard error.
-func gccDebug(stdin []byte) (*dwarf.Data, string) {
+func (p *Prog) gccDebug(stdin []byte) (*dwarf.Data, string) {
        machine := "-m32";
-       if os.Getenv("GOARCH") == "amd64" {
+       if p.PtrSize == 8 {
                machine = "-m64";
        }
 
index 0832b3f40824c08aede7337f932dda1138c4a4a5..b629f0a22c46140e35d19a1282c486abd598a96a 100644 (file)
@@ -22,20 +22,34 @@ func usage() {
        flag.PrintDefaults();
 }
 
-const ptrSize = 8      // TODO
+var ptrSizeMap = map[string]int64 {
+       "386": 4,
+       "amd64": 8,
+       "arm": 4
+}
 
 func main() {
        flag.Usage = usage;
        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();
        if len(args) != 1 {
                usage();
                os.Exit(2);
        }
        p := openProg(args[0]);
+       p.PtrSize = ptrSize;
        p.Preamble = p.Preamble + "\n" + builtinProlog;
-       p.loadDebugInfo(ptrSize);
+       p.loadDebugInfo();
        p.Vardef = make(map[string]*Type);
        p.Funcdef = make(map[string]*FuncType);
 
index 36fbe03490a308b6957ec194d9d9d82d407e076a..91473abeb54a69a85000377792c4f03d42a4ac29 100644 (file)
@@ -100,8 +100,8 @@ func (p *Prog) writeOutput(srcfile string) {
                        structType += fmt.Sprintf("\t\t%s p%d;\n", t.C, i);
                        off += t.Size;
                }
-               if off%ptrSize != 0 {
-                       pad := ptrSize - off%ptrSize;
+               if off%p.PtrSize != 0 {
+                       pad := p.PtrSize - off%p.PtrSize;
                        structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
                        off += pad;
                        npad++;
@@ -116,8 +116,8 @@ func (p *Prog) writeOutput(srcfile string) {
                        structType += fmt.Sprintf("\t\t%s r;\n", t.C);
                        off += t.Size;
                }
-               if off%ptrSize != 0 {
-                       pad := ptrSize - off%ptrSize;
+               if off%p.PtrSize != 0 {
+                       pad := p.PtrSize - off%p.PtrSize;
                        structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
                        off += pad;
                        npad++;
index 6fbfeb0670d33a6f8ec10a8973d3742615f9eba8..ea4ccc7ef7be2d506693541f4ff30028d37ac44f 100644 (file)
@@ -4,15 +4,17 @@
 
 # not linked into build for now
 
+CFLAGS_386=-m32
+
 TARG=libcgo.so
 
 all: libcgo.so
 
 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
-       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
 
index 7717c37e86215c606853919267af68f7c72595cd..d5d270be20c34f8cde0391425a09a7136731a6cc 100755 (executable)
@@ -5,4 +5,11 @@
 // Darwin and Linux use the same linkage to main
 
 TEXT   _rt0_386_linux(SB),7,$0
+       MOVL    initcgo(SB), AX
+       TESTL   AX, AX
+       JZ      2(PC)
+       CALL    AX
+
        JMP     _rt0_386(SB)
+
+GLOBL initcgo(SB), $4