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 ...@@ -254,6 +254,12 @@ enum as
/* internal only */ /* internal only */
#define D_SIZE (D_NONE+40) #define D_SIZE (D_NONE+40)
#define D_PCREL (D_NONE+41) #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 is the ranlib header
......
This diff is collapsed.
...@@ -303,6 +303,7 @@ EXTERN int version; ...@@ -303,6 +303,7 @@ EXTERN int version;
EXTERN char xcmp[C_GOK+1][C_GOK+1]; EXTERN char xcmp[C_GOK+1][C_GOK+1];
EXTERN Prog zprg; EXTERN Prog zprg;
EXTERN int dtype; EXTERN int dtype;
EXTERN int tlsoffset;
EXTERN int armsize; EXTERN int armsize;
extern char* anames[]; extern char* anames[];
......
...@@ -205,7 +205,9 @@ main(int argc, char *argv[]) ...@@ -205,7 +205,9 @@ main(int argc, char *argv[])
INITRND = 1024; INITRND = 1024;
break; break;
case Hlinux: /* arm elf */ 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(); elfinit();
HEADR = ELFRESERVE; HEADR = ELFRESERVE;
if(INITTEXT == -1) if(INITTEXT == -1)
...@@ -263,6 +265,8 @@ main(int argc, char *argv[]) ...@@ -263,6 +265,8 @@ main(int argc, char *argv[])
noops(); noops();
dostkcheck(); dostkcheck();
span(); span();
addexport();
// textaddress() functionality is handled in span()
pclntab(); pclntab();
symtab(); symtab();
dodata(); dodata();
......
...@@ -215,7 +215,7 @@ patch(void) ...@@ -215,7 +215,7 @@ patch(void)
s = p->to.sym; s = p->to.sym;
if(s->text == nil) if(s->text == nil)
continue; continue;
switch(s->type) { switch(s->type&~SSUB) {
default: default:
diag("undefined: %s", s->name); diag("undefined: %s", s->name);
s->type = STEXT; s->type = STEXT;
...@@ -231,7 +231,7 @@ patch(void) ...@@ -231,7 +231,7 @@ patch(void)
if(p->to.type != D_BRANCH) if(p->to.type != D_BRANCH)
continue; continue;
c = p->to.offset; c = p->to.offset;
for(q = textp->text; q != P;) { for(q = cursym->text; q != P;) {
if(c == q->pc) if(c == q->pc)
break; break;
if(q->forwd != P && c >= q->forwd->pc) if(q->forwd != P && c >= q->forwd->pc)
......
...@@ -90,6 +90,7 @@ span(void) ...@@ -90,6 +90,7 @@ span(void)
int32 c, otxt, out[6]; int32 c, otxt, out[6];
Section *sect; Section *sect;
uchar *bp; uchar *bp;
Sym *sub;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f span\n", cputime()); Bprint(&bso, "%5.2f span\n", cputime());
...@@ -100,6 +101,20 @@ span(void) ...@@ -100,6 +101,20 @@ span(void)
otxt = c; otxt = c;
for(cursym = textp; cursym != nil; cursym = cursym->next) { for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text; 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; p->pc = c;
cursym->value = c; cursym->value = c;
...@@ -160,6 +175,8 @@ span(void) ...@@ -160,6 +175,8 @@ span(void)
bflag = 0; bflag = 0;
c = INITTEXT; c = INITTEXT;
for(cursym = textp; cursym != nil; cursym = cursym->next) { for(cursym = textp; cursym != nil; cursym = cursym->next) {
if(!cursym->text || !cursym->text->link)
continue;
cursym->value = c; cursym->value = c;
for(p = cursym->text; p != P; p = p->link) { for(p = cursym->text; p != P; p = p->link) {
curp = p; curp = p;
...@@ -217,6 +234,8 @@ span(void) ...@@ -217,6 +234,8 @@ span(void)
*/ */
for(cursym = textp; cursym != nil; cursym = cursym->next) { for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text; p = cursym->text;
if(p == P || p->link == P)
continue;
autosize = p->to.offset + 4; autosize = p->to.offset + 4;
symgrow(cursym, cursym->size); symgrow(cursym, cursym->size);
...@@ -407,25 +426,9 @@ immhalf(int32 v) ...@@ -407,25 +426,9 @@ immhalf(int32 v)
int32 int32
symaddr(Sym *s) symaddr(Sym *s)
{ {
int32 v; if(!s->reachable)
diag("unreachable symbol in symaddr - %s", s->name);
v = s->value; return 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;
} }
int int
......
...@@ -282,7 +282,7 @@ dynrelocsym(Sym *s) ...@@ -282,7 +282,7 @@ dynrelocsym(Sym *s)
} }
for(r=s->r; r<s->r+s->nr; r++) 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); adddynrel(s, r);
} }
......
...@@ -562,6 +562,8 @@ typedef struct { ...@@ -562,6 +562,8 @@ typedef struct {
#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ #define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */
#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ #define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */
#define R_ARM_PLT32 27 /* Add PC-relative PLT 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_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101 #define R_ARM_GNU_VTINHERIT 101
#define R_ARM_RSBREL32 250 #define R_ARM_RSBREL32 250
......
...@@ -588,14 +588,18 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn) ...@@ -588,14 +588,18 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
p += 4; p += 4;
} }
} }
if(readsym(obj, info>>32, &sym) < 0) if((info >> 32) == 0) { // absolute relocation, don't bother reading the null symbol
goto bad; rp->sym = S;
if(sym.sym == nil) { } else {
werrstr("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", if(readsym(obj, info>>32, &sym) < 0)
sect->sym->name, j, (int)(info>>32), sym.name, sym.shndx, sym.type); goto bad;
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); rp->type = reltype(pn, (uint32)info, &rp->siz);
if(rela) if(rela)
rp->add = add; rp->add = add;
...@@ -633,6 +637,8 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn) ...@@ -633,6 +637,8 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
} }
if(sym.shndx >= obj->nsect || sym.shndx == 0) if(sym.shndx >= obj->nsect || sym.shndx == 0)
continue; 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; sect = obj->sect+sym.shndx;
if(sect->sym == nil) { if(sect->sym == nil) {
diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type); 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) ...@@ -715,6 +721,9 @@ readsym(ElfObj *obj, int i, ElfSym *sym)
werrstr("invalid elf symbol index"); werrstr("invalid elf symbol index");
return -1; return -1;
} }
if(i == 0) {
diag("readym: read null symbol!");
}
if(obj->is64) { if(obj->is64) {
ElfSymBytes64 *b; ElfSymBytes64 *b;
...@@ -760,7 +769,8 @@ readsym(ElfObj *obj, int i, ElfSym *sym) ...@@ -760,7 +769,8 @@ readsym(ElfObj *obj, int i, ElfSym *sym)
} }
// fall through // fall through
case ElfSymBindLocal: 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; break;
default: default:
werrstr("%s: invalid symbol binding %d", sym->name, sym->bind); werrstr("%s: invalid symbol binding %d", sym->name, sym->bind);
...@@ -797,6 +807,15 @@ reltype(char *pn, int elftype, uchar *siz) ...@@ -797,6 +807,15 @@ reltype(char *pn, int elftype, uchar *siz)
switch(R(thechar, elftype)) { switch(R(thechar, elftype)) {
default: default:
diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype); 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_PC32):
case R('6', R_X86_64_PLT32): case R('6', R_X86_64_PLT32):
case R('6', R_X86_64_GOTPCREL): 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