Commit 9e13803a authored by Russ Cox's avatar Russ Cox

cmd/ld: avoid redundant external relocation calculations

R=ken2, ken
CC=golang-dev
https://golang.org/cl/7483045
parent cea78cb5
...@@ -240,12 +240,13 @@ adddynrel(Sym *s, Reloc *r) ...@@ -240,12 +240,13 @@ adddynrel(Sym *s, Reloc *r)
} }
int int
elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add) elfreloc1(Reloc *r, vlong sectoff)
{ {
USED(add); // written to obj file by ../ld/data.c's reloc int32 elfsym;
LPUT(off); LPUT(sectoff);
elfsym = r->xsym->elfsym;
switch(r->type) { switch(r->type) {
default: default:
return -1; return -1;
......
...@@ -96,9 +96,12 @@ struct Reloc ...@@ -96,9 +96,12 @@ struct Reloc
{ {
int32 off; int32 off;
uchar siz; uchar siz;
uchar done;
int16 type; int16 type;
int32 add; int32 add;
int32 xadd;
Sym* sym; Sym* sym;
Sym* xsym;
}; };
struct Prog struct Prog
......
...@@ -284,10 +284,13 @@ adddynrel(Sym *s, Reloc *r) ...@@ -284,10 +284,13 @@ adddynrel(Sym *s, Reloc *r)
} }
int int
elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add) elfreloc1(Reloc *r, vlong sectoff)
{ {
VPUT(off); int32 elfsym;
VPUT(sectoff);
elfsym = r->xsym->elfsym;
switch(r->type) { switch(r->type) {
default: default:
return -1; return -1;
...@@ -306,11 +309,10 @@ elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add) ...@@ -306,11 +309,10 @@ elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
VPUT(R_X86_64_PC32 | (uint64)elfsym<<32); VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
else else
return -1; return -1;
add -= r->siz;
break; break;
} }
VPUT(add); VPUT(r->xadd);
return 0; return 0;
} }
......
...@@ -101,9 +101,12 @@ struct Reloc ...@@ -101,9 +101,12 @@ struct Reloc
{ {
int32 off; int32 off;
uchar siz; uchar siz;
uchar done;
int32 type; int32 type;
int64 add; int64 add;
int64 xadd;
Sym* sym; Sym* sym;
Sym* xsym;
}; };
struct Prog struct Prog
......
...@@ -270,12 +270,13 @@ adddynrel(Sym *s, Reloc *r) ...@@ -270,12 +270,13 @@ adddynrel(Sym *s, Reloc *r)
} }
int int
elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add) elfreloc1(Reloc *r, vlong sectoff)
{ {
USED(add); // written to obj file by ../ld/data.c's reloc int32 elfsym;
LPUT(off); LPUT(sectoff);
elfsym = r->xsym->elfsym;
switch(r->type) { switch(r->type) {
default: default:
return -1; return -1;
......
...@@ -84,9 +84,12 @@ struct Reloc ...@@ -84,9 +84,12 @@ struct Reloc
{ {
int32 off; int32 off;
uchar siz; uchar siz;
uchar done;
int32 type; int32 type;
int32 add; int32 add;
int32 xadd;
Sym* sym; Sym* sym;
Sym* xsym;
}; };
struct Prog struct Prog
......
...@@ -155,6 +155,7 @@ relocsym(Sym *s) ...@@ -155,6 +155,7 @@ relocsym(Sym *s)
cursym = s; cursym = s;
memset(&p, 0, sizeof p); memset(&p, 0, sizeof p);
for(r=s->r; r<s->r+s->nr; r++) { for(r=s->r; r<s->r+s->nr; r++) {
r->done = 1;
off = r->off; off = r->off;
siz = r->siz; siz = r->siz;
if(off < 0 || off+siz > s->np) { if(off < 0 || off+siz > s->np) {
...@@ -181,31 +182,51 @@ relocsym(Sym *s) ...@@ -181,31 +182,51 @@ relocsym(Sym *s)
diag("unknown reloc %d", r->type); diag("unknown reloc %d", r->type);
break; break;
case D_ADDR: case D_ADDR:
o = symaddr(r->sym) + r->add;
if(isobj && r->sym->type != SCONST) { if(isobj && r->sym->type != SCONST) {
r->done = 0;
// set up addend for eventual relocation via outer symbol.
rs = r->sym;
r->xadd = r->add;
while(rs->outer != nil) {
r->xadd += symaddr(rs) - symaddr(rs->outer);
rs = rs->outer;
}
r->xsym = rs;
if(thechar == '6') if(thechar == '6')
o = 0; o = 0;
else { else
// set up addend for eventual relocation via outer symbol o = r->xadd;
rs = r->sym; break;
while(rs->outer != nil)
rs = rs->outer;
o -= symaddr(rs);
}
} }
o = symaddr(r->sym) + r->add;
break; break;
case D_PCREL: case D_PCREL:
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call. // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
o = 0; if(isobj && r->sym && r->sym->type != SCONST && r->sym->sect != cursym->sect) {
if(r->sym) r->done = 0;
o += symaddr(r->sym);
o += r->add - (s->value + r->off + r->siz); // set up addend for eventual relocation via outer symbol.
if(isobj && r->sym->type != SCONST && r->sym->sect != cursym->sect) { rs = r->sym;
r->xadd = r->add;
while(rs->outer != nil) {
r->xadd += symaddr(rs) - symaddr(rs->outer);
rs = rs->outer;
}
r->xsym = rs;
r->xadd -= r->siz;
if(thechar == '6') if(thechar == '6')
o = 0; o = 0;
else else
o = r->add - r->siz; o = r->xadd;
break;
} }
o = 0;
if(r->sym)
o += symaddr(r->sym);
o += r->add - (s->value + r->off + r->siz);
break; break;
case D_SIZE: case D_SIZE:
o = r->sym->size + r->add; o = r->sym->size + r->add;
......
...@@ -805,10 +805,9 @@ elfshreloc(Section *sect) ...@@ -805,10 +805,9 @@ elfshreloc(Section *sect)
void void
elfrelocsect(Section *sect, Sym *first) elfrelocsect(Section *sect, Sym *first)
{ {
Sym *sym, *rs; Sym *sym;
int32 eaddr; int32 eaddr;
Reloc *r; Reloc *r;
int64 add;
// If main section is SHT_NOBITS, nothing to relocate. // If main section is SHT_NOBITS, nothing to relocate.
// Also nothing to relocate in .shstrtab. // Also nothing to relocate in .shstrtab.
...@@ -834,30 +833,15 @@ elfrelocsect(Section *sect, Sym *first) ...@@ -834,30 +833,15 @@ elfrelocsect(Section *sect, Sym *first)
cursym = sym; cursym = sym;
for(r = sym->r; r < sym->r+sym->nr; r++) { for(r = sym->r; r < sym->r+sym->nr; r++) {
// Ignore relocations handled by reloc already. if(r->done)
switch(r->type) { continue;
case D_SIZE: if(r->xsym == nil) {
diag("missing xsym in relocation");
continue; continue;
case D_ADDR:
case D_PCREL:
if(r->sym->type == SCONST)
continue; // handled in data.c:/^relocsym
if(r->type == D_PCREL && r->sym->sect == sym->sect)
continue; // handled in data.c:/^relocsym
break;
}
add = r->add;
rs = r->sym;
while(rs->outer != nil) {
add += rs->value - rs->outer->value;
rs = rs->outer;
} }
if(r->xsym->elfsym == 0)
if(rs->elfsym == 0) diag("reloc %d to non-elf symbol %s (outer=%s) %d", r->type, r->sym->name, r->xsym->name, r->sym->type);
diag("reloc %d to non-elf symbol %s (rs=%s) %d", r->type, r->sym->name, rs->name, rs->type); if(elfreloc1(r, sym->value+r->off - sect->vaddr) < 0)
if(elfreloc1(r, sym->value - sect->vaddr + r->off, rs->elfsym, add) < 0)
diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name); diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
} }
} }
......
...@@ -1005,7 +1005,7 @@ extern char linuxdynld[]; ...@@ -1005,7 +1005,7 @@ extern char linuxdynld[];
extern char freebsddynld[]; extern char freebsddynld[];
extern char netbsddynld[]; extern char netbsddynld[];
extern char openbsddynld[]; extern char openbsddynld[];
int elfreloc1(Reloc*, vlong off, int32 elfsym, vlong add); int elfreloc1(Reloc*, vlong sectoff);
EXTERN int elfstrsize; EXTERN int elfstrsize;
EXTERN char* elfstrdat; EXTERN char* elfstrdat;
......
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