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
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)
......
......@@ -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));
......
......@@ -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
{
......
......@@ -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
{
......
......@@ -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;
}
......
......@@ -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
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