mirror of
https://github.com/golang/go
synced 2024-11-22 17:54:45 -07:00
cmd/ld: external linking fixes for linux/386
The sticking point on 386 has been the "PC relative" relocations used to point the garbage collection metadata at the type info. These aren't in the code segment, and I don't trust that the linker isn't doing something special that would be okay in code but not when interpreting the pointers as data (for example, a PLT jump table would be terrible). Solve the problem in two steps: 1. Handle "PC relative" relocations within a section internally, so that the external linker never sees them. 2. Move the gcdata and gcbss tables into the rodata section, where the type information lives, so that the relocations can be handled internally. (To answer the obvious question, we make the gc->type references relative so that they need not be relocated individually when generating a shared object file.) R=golang-dev, iant CC=golang-dev https://golang.org/cl/7629043
This commit is contained in:
parent
0406c63ea3
commit
cd94cabad6
@ -199,7 +199,7 @@ relocsym(Sym *s)
|
|||||||
if(r->sym)
|
if(r->sym)
|
||||||
o += symaddr(r->sym);
|
o += symaddr(r->sym);
|
||||||
o += r->add - (s->value + r->off + r->siz);
|
o += r->add - (s->value + r->off + r->siz);
|
||||||
if(isobj && r->sym->type != SCONST) {
|
if(isobj && r->sym->type != SCONST && r->sym->sect != cursym->sect) {
|
||||||
if(thechar == '6')
|
if(thechar == '6')
|
||||||
o = 0;
|
o = 0;
|
||||||
else
|
else
|
||||||
@ -950,11 +950,11 @@ dodata(void)
|
|||||||
Bflush(&bso);
|
Bflush(&bso);
|
||||||
|
|
||||||
// define garbage collection symbols
|
// define garbage collection symbols
|
||||||
gcdata1 = lookup("gcdata1", 0);
|
gcdata1 = lookup("gcdata", 0);
|
||||||
gcdata1->type = SGCDATA;
|
gcdata1->type = STYPE;
|
||||||
gcdata1->reachable = 1;
|
gcdata1->reachable = 1;
|
||||||
gcbss1 = lookup("gcbss1", 0);
|
gcbss1 = lookup("gcbss", 0);
|
||||||
gcbss1->type = SGCBSS;
|
gcbss1->type = STYPE;
|
||||||
gcbss1->reachable = 1;
|
gcbss1->reachable = 1;
|
||||||
|
|
||||||
// size of .data and .bss section. the zero value is later replaced by the actual size of the section.
|
// size of .data and .bss section. the zero value is later replaced by the actual size of the section.
|
||||||
@ -1154,7 +1154,7 @@ dodata(void)
|
|||||||
}
|
}
|
||||||
sect->len = datsize - sect->vaddr;
|
sect->len = datsize - sect->vaddr;
|
||||||
|
|
||||||
/* type */
|
/* typelink */
|
||||||
sect = addsection(&segtext, ".typelink", 04);
|
sect = addsection(&segtext, ".typelink", 04);
|
||||||
sect->align = maxalign(s, STYPELINK);
|
sect->align = maxalign(s, STYPELINK);
|
||||||
datsize = rnd(datsize, sect->align);
|
datsize = rnd(datsize, sect->align);
|
||||||
@ -1170,38 +1170,6 @@ dodata(void)
|
|||||||
}
|
}
|
||||||
sect->len = datsize - sect->vaddr;
|
sect->len = datsize - sect->vaddr;
|
||||||
|
|
||||||
/* gcdata */
|
|
||||||
sect = addsection(&segtext, ".gcdata", 04);
|
|
||||||
sect->align = maxalign(s, SGCDATA);
|
|
||||||
datsize = rnd(datsize, sect->align);
|
|
||||||
sect->vaddr = datsize;
|
|
||||||
lookup("gcdata", 0)->sect = sect;
|
|
||||||
lookup("egcdata", 0)->sect = sect;
|
|
||||||
for(; s != nil && s->type == SGCDATA; s = s->next) {
|
|
||||||
datsize = aligndatsize(datsize, s);
|
|
||||||
s->sect = sect;
|
|
||||||
s->type = SRODATA;
|
|
||||||
s->value = datsize;
|
|
||||||
datsize += s->size;
|
|
||||||
}
|
|
||||||
sect->len = datsize - sect->vaddr;
|
|
||||||
|
|
||||||
/* gcbss */
|
|
||||||
sect = addsection(&segtext, ".gcbss", 04);
|
|
||||||
sect->align = maxalign(s, SGCBSS);
|
|
||||||
datsize = rnd(datsize, sect->align);
|
|
||||||
sect->vaddr = datsize;
|
|
||||||
lookup("gcbss", 0)->sect = sect;
|
|
||||||
lookup("egcbss", 0)->sect = sect;
|
|
||||||
for(; s != nil && s->type == SGCBSS; s = s->next) {
|
|
||||||
datsize = aligndatsize(datsize, s);
|
|
||||||
s->sect = sect;
|
|
||||||
s->type = SRODATA;
|
|
||||||
s->value = datsize;
|
|
||||||
datsize += s->size;
|
|
||||||
}
|
|
||||||
sect->len = datsize - sect->vaddr;
|
|
||||||
|
|
||||||
/* gosymtab */
|
/* gosymtab */
|
||||||
sect = addsection(&segtext, ".gosymtab", 04);
|
sect = addsection(&segtext, ".gosymtab", 04);
|
||||||
sect->align = maxalign(s, SPCLNTAB-1);
|
sect->align = maxalign(s, SPCLNTAB-1);
|
||||||
@ -1295,7 +1263,7 @@ void
|
|||||||
address(void)
|
address(void)
|
||||||
{
|
{
|
||||||
Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
|
Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
|
||||||
Section *gcdata, *gcbss, *typelink;
|
Section *typelink;
|
||||||
Sym *sym, *sub;
|
Sym *sym, *sub;
|
||||||
uvlong va;
|
uvlong va;
|
||||||
|
|
||||||
@ -1349,9 +1317,7 @@ address(void)
|
|||||||
text = segtext.sect;
|
text = segtext.sect;
|
||||||
rodata = text->next;
|
rodata = text->next;
|
||||||
typelink = rodata->next;
|
typelink = rodata->next;
|
||||||
gcdata = typelink->next;
|
symtab = typelink->next;
|
||||||
gcbss = gcdata->next;
|
|
||||||
symtab = gcbss->next;
|
|
||||||
pclntab = symtab->next;
|
pclntab = symtab->next;
|
||||||
|
|
||||||
for(sym = datap; sym != nil; sym = sym->next) {
|
for(sym = datap; sym != nil; sym = sym->next) {
|
||||||
@ -1374,10 +1340,15 @@ address(void)
|
|||||||
xdefine("datarelro", SRODATA, datarelro->vaddr);
|
xdefine("datarelro", SRODATA, datarelro->vaddr);
|
||||||
xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
|
xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
|
||||||
}
|
}
|
||||||
xdefine("gcdata", SGCDATA, gcdata->vaddr);
|
|
||||||
xdefine("egcdata", SGCDATA, gcdata->vaddr + gcdata->len);
|
sym = lookup("gcdata", 0);
|
||||||
xdefine("gcbss", SGCBSS, gcbss->vaddr);
|
xdefine("egcdata", STYPE, symaddr(sym) + sym->size);
|
||||||
xdefine("egcbss", SGCBSS, gcbss->vaddr + gcbss->len);
|
lookup("egcdata", 0)->sect = sym->sect;
|
||||||
|
|
||||||
|
sym = lookup("gcbss", 0);
|
||||||
|
xdefine("egcbss", STYPE, symaddr(sym) + sym->size);
|
||||||
|
lookup("egcbss", 0)->sect = sym->sect;
|
||||||
|
|
||||||
xdefine("symtab", SRODATA, symtab->vaddr);
|
xdefine("symtab", SRODATA, symtab->vaddr);
|
||||||
xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
|
xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
|
||||||
xdefine("pclntab", SRODATA, pclntab->vaddr);
|
xdefine("pclntab", SRODATA, pclntab->vaddr);
|
||||||
|
@ -843,7 +843,9 @@ elfrelocsect(Section *sect, Sym *first)
|
|||||||
case D_ADDR:
|
case D_ADDR:
|
||||||
case D_PCREL:
|
case D_PCREL:
|
||||||
if(r->sym->type == SCONST)
|
if(r->sym->type == SCONST)
|
||||||
continue;
|
continue; // handled in data.c:/^relocsym
|
||||||
|
if(r->type == D_PCREL && r->sym->sect == sym->sect)
|
||||||
|
continue; // handled in data.c:/^relocsym
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1805,8 +1805,6 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
|||||||
case SSTRING:
|
case SSTRING:
|
||||||
case SGOSTRING:
|
case SGOSTRING:
|
||||||
case SWINDOWS:
|
case SWINDOWS:
|
||||||
case SGCDATA:
|
|
||||||
case SGCBSS:
|
|
||||||
if(!s->reachable)
|
if(!s->reachable)
|
||||||
continue;
|
continue;
|
||||||
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
|
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
|
||||||
|
@ -40,8 +40,6 @@ enum
|
|||||||
SGOSTRING,
|
SGOSTRING,
|
||||||
SRODATA,
|
SRODATA,
|
||||||
STYPELINK,
|
STYPELINK,
|
||||||
SGCDATA,
|
|
||||||
SGCBSS,
|
|
||||||
SSYMTAB,
|
SSYMTAB,
|
||||||
SPCLNTAB,
|
SPCLNTAB,
|
||||||
SELFROSECT,
|
SELFROSECT,
|
||||||
|
@ -434,10 +434,8 @@ symtab(void)
|
|||||||
xdefine("datarelro", SDATARELRO, 0);
|
xdefine("datarelro", SDATARELRO, 0);
|
||||||
xdefine("edatarelro", SDATARELRO, 0);
|
xdefine("edatarelro", SDATARELRO, 0);
|
||||||
}
|
}
|
||||||
xdefine("gcdata", SGCDATA, 0);
|
xdefine("egcdata", STYPE, 0);
|
||||||
xdefine("egcdata", SGCDATA, 0);
|
xdefine("egcbss", STYPE, 0);
|
||||||
xdefine("gcbss", SGCBSS, 0);
|
|
||||||
xdefine("egcbss", SGCBSS, 0);
|
|
||||||
xdefine("noptrdata", SNOPTRDATA, 0);
|
xdefine("noptrdata", SNOPTRDATA, 0);
|
||||||
xdefine("enoptrdata", SNOPTRDATA, 0);
|
xdefine("enoptrdata", SNOPTRDATA, 0);
|
||||||
xdefine("data", SDATA, 0);
|
xdefine("data", SDATA, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user