]> Cypherpunks repositories - gostls13.git/commitdiff
linker work
authorRuss Cox <rsc@golang.org>
Mon, 24 Aug 2009 17:19:31 +0000 (10:19 -0700)
committerRuss Cox <rsc@golang.org>
Mon, 24 Aug 2009 17:19:31 +0000 (10:19 -0700)
  * use //ffi comments in package import data
    to generate relocation entries and library loads.
  * call initffi in rt0.s if present

R=r
DELTA=117  (91 added, 3 deleted, 23 changed)
OCL=33739
CL=33750

src/cmd/5l/l.h
src/cmd/6l/asm.c
src/cmd/6l/l.h
src/cmd/8l/l.h
src/cmd/ld/go.c
src/pkg/runtime/linux/amd64/rt0.s

index 25cffd0c2c05f559bc88ad4036fe0692457e6e25..1ba95e0a2edb1d1a1082e99c0bd8c2fa6a843003 100644 (file)
@@ -119,6 +119,7 @@ struct      Sym
        short   frame;
        uchar   subtype;
        uchar   reachable;
+       uchar   ffitype;
        ushort  file;
        int32   value;
        int32   sig;
@@ -131,6 +132,8 @@ struct      Sym
        Prog*   text;
        Prog*   data;
        Sym*    gotype;
+       char*   ffiname;
+       char*   ffilib;
 };
 
 #define SIGNINTERN     (1729*325*1729)
index d40b71674794535e08079b70f614705c56c5702a..6232a5a9025068134b88d6ef37096a58d6f4c919 100644 (file)
@@ -258,10 +258,27 @@ enum {
 
 vlong elfstr[NElfStr];
 
+static int
+needlib(char *name)
+{
+       char *p;
+       Sym *s;
+
+       /* reuse hash code in symbol table */
+       p = smprint(".elfload.%s", name);
+       s = lookup(p, 0);
+       if(s->type == 0) {
+               s->type = 100;  // avoid SDATA, etc.
+               return 1;
+       }
+       return 0;
+}
+
 void
 doelf(void)
 {
-       Sym *s, *shstrtab;
+       Sym *s, *shstrtab, *dynamic, *dynstr, *d;
+       int h, nsym, t;
 
        if(HEADTYPE != 7)
                return;
@@ -279,8 +296,6 @@ doelf(void)
        elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
 
        if(!debug['d']) {       /* -d suppresses dynamic loader format */
-               Sym *dynamic, *dynstr;
-
                elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
                elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
                elfstr[ElfStrGot] = addstring(shstrtab, ".got");
@@ -338,28 +353,45 @@ doelf(void)
                dynamic = s;
 
                /*
-                * relocation demo - overwrite go func
-                * var main.extern_c_fib with fib symbol from fib.so
+                * relocation entries for extern ffi symbols
                 */
-               Sym *fib;
-               fib = lookup("main·extern_c_fib", 0);
-               if(fib->type == SDATA || fib->type == SBSS) {
-                       s = lookup(".rela", 0);
-                       addaddr(s, fib);
-                       adduint64(s, ELF64_R_INFO(1, R_X86_64_64));     // 1 = first symbol in dynsym
-                       adduint64(s, 0);
-
-                       s = lookup(".dynsym", 0);
-                       adduint32(s, addstring(lookup(".dynstr", 0), "fib"));
-                       adduint8(s, (STB_GLOBAL<<4) | STT_FUNC);
-                       adduint8(s, 0);         /* reserved */
-                       adduint16(s, SHN_UNDEF);        /* section where symbol is defined */
-                       adduint64(s, 0);        /* value */
-                       adduint64(s, 0);        /* size of object */
-
-                       elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, "fib.so"));
+               nsym = 1;       // sym 0 is reserved
+               for(h=0; h<NHASH; h++) {
+                       for(s=hash[h]; s!=S; s=s->link) {
+                               if(!s->reachable || (s->type != SDATA && s->type != SBSS) || s->ffiname == nil)
+                                       continue;
+
+                               d = lookup(".rela", 0);
+                               addaddr(d, s);
+                               adduint64(d, ELF64_R_INFO(nsym, R_X86_64_64));
+                               adduint64(d, 0);
+                               nsym++;
+
+                               d = lookup(".dynsym", 0);
+                               adduint32(d, addstring(lookup(".dynstr", 0), s->ffiname));
+                               t = STB_GLOBAL << 4;
+                               switch(s->ffitype) {
+                               case 'T':
+                                       t |= STT_FUNC;
+                                       break;
+                               case 'D':
+                                       t |= STT_OBJECT;
+                                       break;
+                               }
+                               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->ffilib))
+                                       elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->ffilib));
+                       }
                }
 
+               /*
+                * .dynamic table
+                */
                s = dynamic;
                elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
                elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
index 271ea412dc3203e57581c6366d571a34af01c60f..a0794a62272ec1c6d6f81c3a201bc3cd264554db 100644 (file)
@@ -119,6 +119,7 @@ struct      Sym
        uchar   subtype;
        uchar   dupok;
        uchar   reachable;
+       uchar   ffitype;
        vlong   value;
        vlong   size;
        int32   sig;
@@ -126,6 +127,8 @@ struct      Sym
        Prog*   text;
        Prog*   data;
        Sym*    gotype;
+       char*   ffiname;
+       char*   ffilib;
 };
 struct Optab
 {
index 3452598c52ea12354122c9e1c7dcd8714eff9e42..e58c2796943a1cecea6dd4da8a479c51af155013 100644 (file)
@@ -116,6 +116,7 @@ struct      Sym
        uchar   subtype;
        uchar   dupok;
        uchar   reachable;
+       uchar   ffitype;
        ushort  file;
        int32   value;
        int32   sig;
@@ -123,6 +124,9 @@ struct      Sym
        Prog*   text;
        Prog*   data;
        Sym*    gotype;
+       char*   ffiname;
+       char*   ffilib;
+
 };
 struct Optab
 {
index 0ced9a1ac9cc8c03179c1090e9a6d69fe1783cf7..4bad524133f6a1ab9c87d9b6f866a313eb55764f 100644 (file)
@@ -190,6 +190,7 @@ parsepkgdata(char *file, char **pp, char *ep, char **prefixp, char **namep, char
        char *p, *prefix, *name, *def, *edef, *meth;
        int n;
 
+again:
        // skip white space
        p = *pp;
        while(p < ep && (*p == ' ' || *p == '\t' || *p == '\n'))
@@ -211,8 +212,46 @@ parsepkgdata(char *file, char **pp, char *ep, char **prefixp, char **namep, char
                p += 5;
        else if(strncmp(p, "const ", 6) == 0)
                p += 6;
-       else{
-               fprint(2, "%s: confused in pkg data near <<%.20s>>\n", argv0, p);
+       else if(strncmp(p, "//ffi ", 6) == 0) {
+               Sym *s;
+               char type, *lib;
+
+               p += 6;
+               if(*p == 0 || *(p+1) != ' ')
+                       goto err;
+               type = *p;
+               p += 2;
+               name = p;
+               p = strchr(name, ' ');
+               if(p == nil)
+                       goto err;
+               while(*p == ' ')
+                       p++;
+               def = p;
+               p = strchr(def, ' ');
+               if(p == nil)
+                       goto err;
+               while(*p == ' ')
+                       p++;
+               lib = p;
+               p = strchr(lib, '\n');
+               if(p == nil)
+                       goto err;
+
+               // successful parse: now can edit the line
+               *strchr(name, ' ') = 0;
+               *strchr(def, ' ') = 0;
+               *strchr(lib, '\n') = 0;
+               *pp = p+1;
+
+               s = lookup(name, 0);
+               s->ffitype = type;
+               s->ffilib = lib;
+               s->ffiname = def;
+               goto again;
+       } else {
+       err:
+               fprint(2, "%s: confused in pkg data near <<%.20s>>\n", argv0, prefix);
                nerrors++;
                return -1;
        }
index 55be5bceef01ee1c1b135eb19403ddc2470fe776..83b68881d1ad0f7d795d7d92cdc479e176a270d1 100644 (file)
@@ -5,5 +5,12 @@
 // Darwin and Linux use the same linkage to main
 
 TEXT   _rt0_amd64_linux(SB),7,$-8
+       MOVQ    _initffi(SB), AX
+       TESTQ   AX, AX
+       JZ      2(PC)
+       CALL    AX
+
        MOVQ    $_rt0_amd64(SB), AX
        JMP     AX
+
+GLOBL _initffi(SB), $8