mirror of
https://github.com/golang/go
synced 2024-11-19 01:54:39 -07:00
liblink: introduce way to avoid pc-relative addressing
For Solaris. Sigh. LGTM=dave R=aram, iant, dave CC=golang-codereviews https://golang.org/cl/129540043
This commit is contained in:
parent
236cf308c2
commit
4516a60062
@ -1535,6 +1535,19 @@ static Optab optab[] =
|
||||
static Optab* opindex[ALAST+1];
|
||||
static vlong vaddr(Link*, Addr*, Reloc*);
|
||||
|
||||
// isextern reports whether s describes an external symbol that must avoid pc-relative addressing.
|
||||
// This happens on systems like Solaris that call .so functions instead of system calls.
|
||||
// It does not seem to be necessary for any other systems. This is probably working
|
||||
// around a Solaris-specific bug that should be fixed differently, but we don't know
|
||||
// what that bug is. And this does fix it.
|
||||
static int
|
||||
isextern(LSym *s)
|
||||
{
|
||||
// All the Solaris dynamic imports from libc.so begin with "libc·", which
|
||||
// the compiler rewrites to "libc." by the time liblink gets it.
|
||||
return strncmp(s->name, "libc.", 5) == 0;
|
||||
}
|
||||
|
||||
// single-instruction no-ops of various lengths.
|
||||
// constructed by hand and disassembled with gdb to verify.
|
||||
// see http://www.agner.org/optimize/optimizing_assembly.pdf for discussion.
|
||||
@ -1932,6 +1945,8 @@ oclass(Link *ctxt, Addr *a)
|
||||
switch(a->index) {
|
||||
case D_EXTERN:
|
||||
case D_STATIC:
|
||||
if(a->sym != nil && isextern(a->sym))
|
||||
return Yi32;
|
||||
return Yiauto; // use pc-relative addressing
|
||||
case D_AUTO:
|
||||
case D_PARAM:
|
||||
@ -2109,7 +2124,7 @@ oclass(Link *ctxt, Addr *a)
|
||||
return Yi32; /* unsigned */
|
||||
return Yi64;
|
||||
}
|
||||
return Yi32; /* TO DO: D_ADDR as Yi64 */
|
||||
return Yi32;
|
||||
|
||||
case D_BRANCH:
|
||||
return Ybr;
|
||||
@ -2282,12 +2297,17 @@ vaddr(Link *ctxt, Addr *a, Reloc *r)
|
||||
ctxt->diag("need reloc for %D", a);
|
||||
sysfatal("reloc");
|
||||
}
|
||||
r->siz = 4; // TODO: 8 for external symbols
|
||||
if(isextern(s)) {
|
||||
r->siz = 4;
|
||||
r->type = R_ADDR;
|
||||
} else {
|
||||
r->siz = 4;
|
||||
r->type = R_PCREL;
|
||||
}
|
||||
r->off = -1; // caller must fill in
|
||||
r->sym = s;
|
||||
r->add = v;
|
||||
v = 0;
|
||||
r->type = R_PCREL;
|
||||
if(s->type == STLSBSS) {
|
||||
r->xadd = r->add - r->siz;
|
||||
r->type = R_TLS;
|
||||
@ -2327,6 +2347,13 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64)
|
||||
switch(t) {
|
||||
default:
|
||||
goto bad;
|
||||
case D_EXTERN:
|
||||
case D_STATIC:
|
||||
if(!isextern(a->sym))
|
||||
goto bad;
|
||||
t = D_NONE;
|
||||
v = vaddr(ctxt, a, &rel);
|
||||
break;
|
||||
case D_AUTO:
|
||||
case D_PARAM:
|
||||
t = D_SP;
|
||||
@ -2386,7 +2413,7 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64)
|
||||
|
||||
ctxt->rexflag |= (regrex[t] & Rxb) | rex;
|
||||
if(t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS) {
|
||||
if(t == D_NONE && (a->type == D_STATIC || a->type == D_EXTERN) || ctxt->asmode != 64) {
|
||||
if((a->sym == nil || !isextern(a->sym)) && t == D_NONE && (a->type == D_STATIC || a->type == D_EXTERN) || ctxt->asmode != 64) {
|
||||
*ctxt->andptr++ = (0 << 6) | (5 << 0) | (r << 3);
|
||||
goto putrelv;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user