1
0
mirror of https://github.com/golang/go synced 2024-11-26 00:57:56 -07:00

cmd/ld: avoid redundant external relocation calculations

R=ken2, ken
CC=golang-dev
https://golang.org/cl/7483045
This commit is contained in:
Russ Cox 2013-03-10 19:07:16 -07:00
parent cea78cb58e
commit 9e13803ae1
9 changed files with 68 additions and 50 deletions

View File

@ -240,12 +240,13 @@ adddynrel(Sym *s, Reloc *r)
}
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
LPUT(off);
int32 elfsym;
LPUT(sectoff);
elfsym = r->xsym->elfsym;
switch(r->type) {
default:
return -1;

View File

@ -96,9 +96,12 @@ struct Reloc
{
int32 off;
uchar siz;
uchar done;
int16 type;
int32 add;
int32 xadd;
Sym* sym;
Sym* xsym;
};
struct Prog

View File

@ -284,10 +284,13 @@ adddynrel(Sym *s, Reloc *r)
}
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) {
default:
return -1;
@ -306,11 +309,10 @@ elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
else
return -1;
add -= r->siz;
break;
}
VPUT(add);
VPUT(r->xadd);
return 0;
}

View File

@ -101,9 +101,12 @@ struct Reloc
{
int32 off;
uchar siz;
uchar done;
int32 type;
int64 add;
int64 xadd;
Sym* sym;
Sym* xsym;
};
struct Prog

View File

@ -270,12 +270,13 @@ adddynrel(Sym *s, Reloc *r)
}
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) {
default:
return -1;

View File

@ -84,9 +84,12 @@ struct Reloc
{
int32 off;
uchar siz;
uchar done;
int32 type;
int32 add;
int32 xadd;
Sym* sym;
Sym* xsym;
};
struct Prog

View File

@ -155,6 +155,7 @@ relocsym(Sym *s)
cursym = s;
memset(&p, 0, sizeof p);
for(r=s->r; r<s->r+s->nr; r++) {
r->done = 1;
off = r->off;
siz = r->siz;
if(off < 0 || off+siz > s->np) {
@ -181,31 +182,51 @@ relocsym(Sym *s)
diag("unknown reloc %d", r->type);
break;
case D_ADDR:
o = symaddr(r->sym) + r->add;
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')
o = 0;
else {
// set up addend for eventual relocation via outer symbol
rs = r->sym;
while(rs->outer != nil)
rs = rs->outer;
o -= symaddr(rs);
}
else
o = r->xadd;
break;
}
o = symaddr(r->sym) + r->add;
break;
case D_PCREL:
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
if(isobj && r->sym && r->sym->type != SCONST && r->sym->sect != cursym->sect) {
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;
r->xadd -= r->siz;
if(thechar == '6')
o = 0;
else
o = r->xadd;
break;
}
o = 0;
if(r->sym)
o += symaddr(r->sym);
o += r->add - (s->value + r->off + r->siz);
if(isobj && r->sym->type != SCONST && r->sym->sect != cursym->sect) {
if(thechar == '6')
o = 0;
else
o = r->add - r->siz;
}
break;
case D_SIZE:
o = r->sym->size + r->add;

View File

@ -805,10 +805,9 @@ elfshreloc(Section *sect)
void
elfrelocsect(Section *sect, Sym *first)
{
Sym *sym, *rs;
Sym *sym;
int32 eaddr;
Reloc *r;
int64 add;
// If main section is SHT_NOBITS, nothing to relocate.
// Also nothing to relocate in .shstrtab.
@ -834,30 +833,15 @@ elfrelocsect(Section *sect, Sym *first)
cursym = sym;
for(r = sym->r; r < sym->r+sym->nr; r++) {
// Ignore relocations handled by reloc already.
switch(r->type) {
case D_SIZE:
if(r->done)
continue;
if(r->xsym == nil) {
diag("missing xsym in relocation");
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(rs->elfsym == 0)
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 - sect->vaddr + r->off, rs->elfsym, add) < 0)
if(r->xsym->elfsym == 0)
diag("reloc %d to non-elf symbol %s (outer=%s) %d", r->type, r->sym->name, r->xsym->name, r->sym->type);
if(elfreloc1(r, sym->value+r->off - sect->vaddr) < 0)
diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
}
}

View File

@ -1005,7 +1005,7 @@ extern char linuxdynld[];
extern char freebsddynld[];
extern char netbsddynld[];
extern char openbsddynld[];
int elfreloc1(Reloc*, vlong off, int32 elfsym, vlong add);
int elfreloc1(Reloc*, vlong sectoff);
EXTERN int elfstrsize;
EXTERN char* elfstrdat;