Commit 452a9e45 authored by Shenghou Ma's avatar Shenghou Ma

cmd/5l, cmd/ld: dynamic linking library support

        Part 1 of CL 5601044 (cgo: Linux/ARM support)
        Limitation: doesn't support thumb library yet.

R=golang-dev, dave, rsc
CC=golang-dev
https://golang.org/cl/5991065
parent c44a22cc
......@@ -254,6 +254,12 @@ enum as
/* internal only */
#define D_SIZE (D_NONE+40)
#define D_PCREL (D_NONE+41)
#define D_GOTOFF (D_NONE+42) // R_ARM_GOTOFF
#define D_PLT0 (D_NONE+43) // R_ARM_PLT32, 1st inst: add ip, pc, #0xNN00000
#define D_PLT1 (D_NONE+44) // R_ARM_PLT32, 2nd inst: add ip, ip, #0xNN000
#define D_PLT2 (D_NONE+45) // R_ARM_PLT32, 3rd inst: ldr pc, [ip, #0xNNN]!
#define D_PLT32 (D_NONE+46) // R_ARM_PLT32, bl xxxxx
#define D_CALL (D_NONE+47) // R_ARM_CALL, bl xxxxx
/*
* this is the ranlib header
......
This diff is collapsed.
......@@ -303,6 +303,7 @@ EXTERN int version;
EXTERN char xcmp[C_GOK+1][C_GOK+1];
EXTERN Prog zprg;
EXTERN int dtype;
EXTERN int tlsoffset;
EXTERN int armsize;
extern char* anames[];
......
......@@ -205,7 +205,9 @@ main(int argc, char *argv[])
INITRND = 1024;
break;
case Hlinux: /* arm elf */
debug['d'] = 1; // no dynamic linking
debug['d'] = 0; // with dynamic linking
tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then 4-byte word for m
// this number is known to ../../pkg/runtime/cgo/gcc_linux_arm.c
elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1)
......@@ -263,6 +265,8 @@ main(int argc, char *argv[])
noops();
dostkcheck();
span();
addexport();
// textaddress() functionality is handled in span()
pclntab();
symtab();
dodata();
......
......@@ -215,7 +215,7 @@ patch(void)
s = p->to.sym;
if(s->text == nil)
continue;
switch(s->type) {
switch(s->type&~SSUB) {
default:
diag("undefined: %s", s->name);
s->type = STEXT;
......@@ -231,7 +231,7 @@ patch(void)
if(p->to.type != D_BRANCH)
continue;
c = p->to.offset;
for(q = textp->text; q != P;) {
for(q = cursym->text; q != P;) {
if(c == q->pc)
break;
if(q->forwd != P && c >= q->forwd->pc)
......
......@@ -90,6 +90,7 @@ span(void)
int32 c, otxt, out[6];
Section *sect;
uchar *bp;
Sym *sub;
if(debug['v'])
Bprint(&bso, "%5.2f span\n", cputime());
......@@ -100,6 +101,20 @@ span(void)
otxt = c;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
if(p == P || p->link == P) { // handle external functions and ELF section symbols
if(cursym->type & SSUB)
continue;
if(cursym->align != 0)
c = rnd(c, cursym->align);
cursym->value = 0;
for(sub = cursym; sub != S; sub = sub->sub) {
sub->value += c;
for(p = sub->text; p != P; p = p->link)
p->pc += sub->value;
}
c += cursym->size;
continue;
}
p->pc = c;
cursym->value = c;
......@@ -160,6 +175,8 @@ span(void)
bflag = 0;
c = INITTEXT;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
if(!cursym->text || !cursym->text->link)
continue;
cursym->value = c;
for(p = cursym->text; p != P; p = p->link) {
curp = p;
......@@ -217,6 +234,8 @@ span(void)
*/
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
if(p == P || p->link == P)
continue;
autosize = p->to.offset + 4;
symgrow(cursym, cursym->size);
......@@ -407,25 +426,9 @@ immhalf(int32 v)
int32
symaddr(Sym *s)
{
int32 v;
v = s->value;
switch(s->type) {
default:
diag("unexpected type %d in symaddr(%s)", s->type, s->name);
return 0;
case STEXT:
case SELFROSECT:
case SRODATA:
case SDATA:
case SBSS:
case SCONST:
case SNOPTRDATA:
case SNOPTRBSS:
break;
}
return v;
if(!s->reachable)
diag("unreachable symbol in symaddr - %s", s->name);
return s->value;
}
int
......
......@@ -282,7 +282,7 @@ dynrelocsym(Sym *s)
}
for(r=s->r; r<s->r+s->nr; r++)
if(r->sym->type == SDYNIMPORT || r->type >= 256)
if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256)
adddynrel(s, r);
}
......
......@@ -562,6 +562,8 @@ typedef struct {
#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */
#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */
#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */
#define R_ARM_CALL 28
#define R_ARM_V4BX 40
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
#define R_ARM_RSBREL32 250
......
......@@ -588,14 +588,18 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
p += 4;
}
}
if(readsym(obj, info>>32, &sym) < 0)
goto bad;
if(sym.sym == nil) {
werrstr("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d",
sect->sym->name, j, (int)(info>>32), sym.name, sym.shndx, sym.type);
goto bad;
if((info >> 32) == 0) { // absolute relocation, don't bother reading the null symbol
rp->sym = S;
} else {
if(readsym(obj, info>>32, &sym) < 0)
goto bad;
if(sym.sym == nil) {
werrstr("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d",
sect->sym->name, j, (int)(info>>32), sym.name, sym.shndx, sym.type);
goto bad;
}
rp->sym = sym.sym;
}
rp->sym = sym.sym;
rp->type = reltype(pn, (uint32)info, &rp->siz);
if(rela)
rp->add = add;
......@@ -633,6 +637,8 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
}
if(sym.shndx >= obj->nsect || sym.shndx == 0)
continue;
if(thechar == '5' && (strcmp(sym.name, "$a") == 0 || strcmp(sym.name, "$d") == 0)) // binutils for arm generate these mapping symbols, skip these
continue;
sect = obj->sect+sym.shndx;
if(sect->sym == nil) {
diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type);
......@@ -715,6 +721,9 @@ readsym(ElfObj *obj, int i, ElfSym *sym)
werrstr("invalid elf symbol index");
return -1;
}
if(i == 0) {
diag("readym: read null symbol!");
}
if(obj->is64) {
ElfSymBytes64 *b;
......@@ -760,7 +769,8 @@ readsym(ElfObj *obj, int i, ElfSym *sym)
}
// fall through
case ElfSymBindLocal:
s = lookup(sym->name, version);
if(!(thechar == '5' && (strcmp(sym->name, "$a") == 0 || strcmp(sym->name, "$d") == 0))) // binutils for arm generate these mapping symbols, ignore these
s = lookup(sym->name, version);
break;
default:
werrstr("%s: invalid symbol binding %d", sym->name, sym->bind);
......@@ -797,6 +807,15 @@ reltype(char *pn, int elftype, uchar *siz)
switch(R(thechar, elftype)) {
default:
diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype);
case R('5', R_ARM_ABS32):
case R('5', R_ARM_GOT32):
case R('5', R_ARM_PLT32):
case R('5', R_ARM_GOTOFF):
case R('5', R_ARM_GOTPC):
case R('5', R_ARM_THM_PC22):
case R('5', R_ARM_REL32):
case R('5', R_ARM_CALL):
case R('5', R_ARM_V4BX):
case R('6', R_X86_64_PC32):
case R('6', R_X86_64_PLT32):
case R('6', R_X86_64_GOTPCREL):
......
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