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:
parent
cea78cb58e
commit
9e13803ae1
@ -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;
|
||||
|
@ -96,9 +96,12 @@ struct Reloc
|
||||
{
|
||||
int32 off;
|
||||
uchar siz;
|
||||
uchar done;
|
||||
int16 type;
|
||||
int32 add;
|
||||
int32 xadd;
|
||||
Sym* sym;
|
||||
Sym* xsym;
|
||||
};
|
||||
|
||||
struct Prog
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -101,9 +101,12 @@ struct Reloc
|
||||
{
|
||||
int32 off;
|
||||
uchar siz;
|
||||
uchar done;
|
||||
int32 type;
|
||||
int64 add;
|
||||
int64 xadd;
|
||||
Sym* sym;
|
||||
Sym* xsym;
|
||||
};
|
||||
|
||||
struct Prog
|
||||
|
@ -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;
|
||||
|
@ -84,9 +84,12 @@ struct Reloc
|
||||
{
|
||||
int32 off;
|
||||
uchar siz;
|
||||
uchar done;
|
||||
int32 type;
|
||||
int32 add;
|
||||
int32 xadd;
|
||||
Sym* sym;
|
||||
Sym* xsym;
|
||||
};
|
||||
|
||||
struct Prog
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user