Commit 1f177cd8 authored by Russ Cox's avatar Russ Cox

linker work

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