mirror of https://github.com/golang/go.git
6l/5l: PIC and shared library support for the linkers.
Added the -shared flag to 5l/6l to output a PIC executable with the required dynamic relocations and RIP-relative addressing in machine code. Added dummy support to 8l to avoid compilation errors See also: https://golang.org/cl/6822078 https://golang.org/cl/7064048 and https://groups.google.com/d/topic/golang-nuts/P05BDjLcQ5k/discussion R=rsc, iant CC=golang-dev https://golang.org/cl/6926049
This commit is contained in:
parent
6adbc545f6
commit
3bdeaf2a64
|
|
@ -93,6 +93,19 @@ braddoff(int32 a, int32 b)
|
|||
return (((uint32)a) & 0xff000000U) | (0x00ffffffU & (uint32)(a + b));
|
||||
}
|
||||
|
||||
Sym *
|
||||
lookuprel(void)
|
||||
{
|
||||
return lookup(".rel", 0);
|
||||
}
|
||||
|
||||
void
|
||||
adddynrela(Sym *rel, Sym *s, Reloc *r)
|
||||
{
|
||||
addaddrplus(rel, s, r->off);
|
||||
adduint32(rel, R_ARM_RELATIVE);
|
||||
}
|
||||
|
||||
void
|
||||
adddynrel(Sym *s, Reloc *r)
|
||||
{
|
||||
|
|
@ -859,15 +872,22 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
|
|||
rel = addrel(cursym);
|
||||
rel->off = pc - cursym->value;
|
||||
rel->siz = 4;
|
||||
rel->type = D_ADDR;
|
||||
rel->sym = p->to.sym;
|
||||
rel->add = p->to.offset;
|
||||
if(flag_shared) {
|
||||
rel->type = D_PCREL;
|
||||
rel->add += pc - p->pcrel->pc - 8;
|
||||
} else
|
||||
rel->type = D_ADDR;
|
||||
o1 = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 12: /* movw $lcon, reg */
|
||||
o1 = omvl(p, &p->from, p->to.reg);
|
||||
if(o->flag & LPCREL) {
|
||||
o2 = oprrr(AADD, p->scond) | p->to.reg | REGPC << 16 | p->to.reg << 12;
|
||||
}
|
||||
break;
|
||||
|
||||
case 13: /* op $lcon, [R], R */
|
||||
|
|
@ -1172,13 +1192,23 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
|
|||
break;
|
||||
|
||||
case 62: /* case R -> movw R<<2(PC),PC */
|
||||
o1 = olrr(p->from.reg, REGPC, REGPC, p->scond);
|
||||
o1 |= 2<<7;
|
||||
if(o->flag & LPCREL) {
|
||||
o1 = oprrr(AADD, p->scond) | immrot(1) | p->from.reg << 16 | REGTMP << 12;
|
||||
o2 = olrr(REGTMP, REGPC, REGTMP, p->scond);
|
||||
o2 |= 2<<7;
|
||||
o3 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGPC << 12;
|
||||
} else {
|
||||
o1 = olrr(p->from.reg, REGPC, REGPC, p->scond);
|
||||
o1 |= 2<<7;
|
||||
}
|
||||
break;
|
||||
|
||||
case 63: /* bcase */
|
||||
if(p->cond != P)
|
||||
if(p->cond != P) {
|
||||
o1 = p->cond->pc;
|
||||
if(flag_shared)
|
||||
o1 = o1 - p->pcrel->pc - 16;
|
||||
}
|
||||
break;
|
||||
|
||||
/* reloc ops */
|
||||
|
|
@ -1187,6 +1217,10 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
|
|||
if(!o1)
|
||||
break;
|
||||
o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
|
||||
if(o->flag & LPCREL) {
|
||||
o3 = o2;
|
||||
o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
|
||||
}
|
||||
break;
|
||||
|
||||
case 65: /* mov/movbu addr,R */
|
||||
|
|
@ -1196,6 +1230,10 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
|
|||
o2 = olr(0, REGTMP, p->to.reg, p->scond);
|
||||
if(p->as == AMOVBU || p->as == AMOVB)
|
||||
o2 |= 1<<22;
|
||||
if(o->flag & LPCREL) {
|
||||
o3 = o2;
|
||||
o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
|
||||
}
|
||||
break;
|
||||
|
||||
case 68: /* floating point store -> ADDR */
|
||||
|
|
@ -1203,6 +1241,10 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
|
|||
if(!o1)
|
||||
break;
|
||||
o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p);
|
||||
if(o->flag & LPCREL) {
|
||||
o3 = o2;
|
||||
o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
|
||||
}
|
||||
break;
|
||||
|
||||
case 69: /* floating point load <- ADDR */
|
||||
|
|
@ -1210,6 +1252,10 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
|
|||
if(!o1)
|
||||
break;
|
||||
o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
|
||||
if(o->flag & LPCREL) {
|
||||
o3 = o2;
|
||||
o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
|
||||
}
|
||||
break;
|
||||
|
||||
/* ArmV4 ops: */
|
||||
|
|
@ -1406,12 +1452,20 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
|
|||
o2 ^= (1<<5)|(1<<6);
|
||||
else if(p->as == AMOVH)
|
||||
o2 ^= (1<<6);
|
||||
if(o->flag & LPCREL) {
|
||||
o3 = o2;
|
||||
o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
|
||||
}
|
||||
break;
|
||||
case 94: /* movh/movhu R,addr -> strh */
|
||||
o1 = omvl(p, &p->to, REGTMP);
|
||||
if(!o1)
|
||||
break;
|
||||
o2 = oshr(p->from.reg, 0, REGTMP, p->scond);
|
||||
if(o->flag & LPCREL) {
|
||||
o3 = o2;
|
||||
o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
|
||||
}
|
||||
break;
|
||||
case 95: /* PLD off(reg) */
|
||||
o1 = 0xf5d0f000;
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ struct Prog
|
|||
} u0;
|
||||
Prog* cond;
|
||||
Prog* link;
|
||||
Prog* pcrel;
|
||||
int32 pc;
|
||||
int32 line;
|
||||
int32 spadj;
|
||||
|
|
@ -175,6 +176,7 @@ struct Sym
|
|||
Reloc* r;
|
||||
int32 nr;
|
||||
int32 maxr;
|
||||
int rel_ro;
|
||||
};
|
||||
|
||||
#define SIGNINTERN (1729*325*1729)
|
||||
|
|
@ -197,6 +199,7 @@ struct Optab
|
|||
char size;
|
||||
char param;
|
||||
char flag;
|
||||
uchar pcrelsiz;
|
||||
};
|
||||
struct Oprang
|
||||
{
|
||||
|
|
@ -214,6 +217,7 @@ enum
|
|||
LFROM = 1<<0,
|
||||
LTO = 1<<1,
|
||||
LPOOL = 1<<2,
|
||||
LPCREL = 1<<3,
|
||||
|
||||
C_NONE = 0,
|
||||
C_REG,
|
||||
|
|
@ -228,6 +232,7 @@ enum
|
|||
C_NCON, /* ~RCON */
|
||||
C_SCON, /* 0xffff */
|
||||
C_LCON,
|
||||
C_LCONADDR,
|
||||
C_ZFCON,
|
||||
C_SFCON,
|
||||
C_LFCON,
|
||||
|
|
@ -281,6 +286,7 @@ EXTERN int32 INITDAT; /* data location */
|
|||
EXTERN int32 INITRND; /* data round above text location */
|
||||
EXTERN int32 INITTEXT; /* text location */
|
||||
EXTERN char* INITENTRY; /* entry point */
|
||||
EXTERN char* LIBINITENTRY; /* shared library entry point */
|
||||
EXTERN int32 autosize;
|
||||
EXTERN Auto* curauto;
|
||||
EXTERN Auto* curhist;
|
||||
|
|
|
|||
|
|
@ -435,6 +435,7 @@ cnames[] =
|
|||
[C_LAUTO] = "C_LAUTO",
|
||||
[C_LBRA] = "C_LBRA",
|
||||
[C_LCON] = "C_LCON",
|
||||
[C_LCONADDR] = "C_LCONADDR",
|
||||
[C_LOREG] = "C_LOREG",
|
||||
[C_NCON] = "C_NCON",
|
||||
[C_NONE] = "C_NONE",
|
||||
|
|
|
|||
|
|
@ -45,6 +45,20 @@ static Sym* sym_divu;
|
|||
static Sym* sym_mod;
|
||||
static Sym* sym_modu;
|
||||
|
||||
static void
|
||||
linkcase(Prog *casep)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
for(p = casep; p != P; p = p->link){
|
||||
if(p->as == ABCASE) {
|
||||
for(; p != P && p->as == ABCASE; p = p->link)
|
||||
p->pcrel = casep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
noops(void)
|
||||
{
|
||||
|
|
@ -76,6 +90,11 @@ noops(void)
|
|||
for(cursym = textp; cursym != nil; cursym = cursym->next) {
|
||||
for(p = cursym->text; p != P; p = p->link) {
|
||||
switch(p->as) {
|
||||
case ACASE:
|
||||
if(flag_shared)
|
||||
linkcase(p);
|
||||
break;
|
||||
|
||||
case ATEXT:
|
||||
p->mark |= LEAF;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ main(int argc, char *argv[])
|
|||
INITDAT = -1;
|
||||
INITRND = -1;
|
||||
INITENTRY = 0;
|
||||
LIBINITENTRY = 0;
|
||||
nuxiinit();
|
||||
|
||||
p = getgoarm();
|
||||
|
|
@ -123,6 +124,7 @@ main(int argc, char *argv[])
|
|||
flagcount("u", "reject unsafe packages", &debug['u']);
|
||||
flagcount("v", "print link trace", &debug['v']);
|
||||
flagcount("w", "disable DWARF generation", &debug['w']);
|
||||
flagcount("shared", "generate shared object", &flag_shared);
|
||||
|
||||
flagparse(&argc, &argv, usage);
|
||||
|
||||
|
|
|
|||
|
|
@ -77,10 +77,12 @@ Optab optab[] =
|
|||
{ ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0 },
|
||||
|
||||
{ AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0 },
|
||||
{ AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0 },
|
||||
{ AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0 },
|
||||
|
||||
{ AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0 },
|
||||
{ AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM },
|
||||
{ AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4},
|
||||
|
||||
{ AADD, C_NCON, C_REG, C_REG, 13, 8, 0 },
|
||||
{ AADD, C_NCON, C_NONE, C_REG, 13, 8, 0 },
|
||||
|
|
@ -119,20 +121,20 @@ Optab optab[] =
|
|||
|
||||
{ AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO },
|
||||
{ AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO },
|
||||
{ AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO },
|
||||
{ AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4 },
|
||||
{ AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO },
|
||||
{ AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO },
|
||||
{ AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO },
|
||||
{ AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4 },
|
||||
{ AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO },
|
||||
{ AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO },
|
||||
{ AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO },
|
||||
{ AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4 },
|
||||
|
||||
{ AMOVW, C_LAUTO,C_NONE, C_REG, 31, 8, REGSP, LFROM },
|
||||
{ AMOVW, C_LOREG,C_NONE, C_REG, 31, 8, 0, LFROM },
|
||||
{ AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM },
|
||||
{ AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4 },
|
||||
{ AMOVBU, C_LAUTO,C_NONE, C_REG, 31, 8, REGSP, LFROM },
|
||||
{ AMOVBU, C_LOREG,C_NONE, C_REG, 31, 8, 0, LFROM },
|
||||
{ AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM },
|
||||
{ AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4 },
|
||||
|
||||
{ AMOVW, C_LACON,C_NONE, C_REG, 34, 8, REGSP, LFROM },
|
||||
|
||||
|
|
@ -159,8 +161,8 @@ Optab optab[] =
|
|||
{ AMOVF, C_LAUTO,C_NONE, C_FREG, 53, 12, REGSP, LFROM },
|
||||
{ AMOVF, C_LOREG,C_NONE, C_FREG, 53, 12, 0, LFROM },
|
||||
|
||||
{ AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO },
|
||||
{ AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM },
|
||||
{ AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4 },
|
||||
{ AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4},
|
||||
|
||||
{ AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0 },
|
||||
{ AADDF, C_FREG, C_REG, C_FREG, 54, 4, 0 },
|
||||
|
|
@ -178,7 +180,7 @@ Optab optab[] =
|
|||
{ AMOVB, C_REG, C_NONE, C_SHIFT, 61, 4, 0 },
|
||||
{ AMOVBU, C_REG, C_NONE, C_SHIFT, 61, 4, 0 },
|
||||
|
||||
{ ACASE, C_REG, C_NONE, C_NONE, 62, 4, 0 },
|
||||
{ ACASE, C_REG, C_NONE, C_NONE, 62, 4, 0, LPCREL, 8 },
|
||||
{ ABCASE, C_NONE, C_NONE, C_SBRA, 63, 4, 0 },
|
||||
|
||||
{ AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0 },
|
||||
|
|
@ -195,20 +197,20 @@ Optab optab[] =
|
|||
|
||||
{ AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO },
|
||||
{ AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO },
|
||||
{ AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO },
|
||||
{ AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4 },
|
||||
{ AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO },
|
||||
{ AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO },
|
||||
{ AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO },
|
||||
{ AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4 },
|
||||
|
||||
{ AMOVB, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM },
|
||||
{ AMOVB, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM },
|
||||
{ AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM },
|
||||
{ AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4 },
|
||||
{ AMOVH, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM },
|
||||
{ AMOVH, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM },
|
||||
{ AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM },
|
||||
{ AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4 },
|
||||
{ AMOVHU, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM },
|
||||
{ AMOVHU, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM },
|
||||
{ AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM },
|
||||
{ AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4 },
|
||||
|
||||
{ ALDREX, C_SOREG,C_NONE, C_REG, 77, 4, 0 },
|
||||
{ ASTREX, C_SOREG,C_REG, C_REG, 78, 4, 0 },
|
||||
|
|
|
|||
|
|
@ -330,9 +330,11 @@ addpool(Prog *p, Adr *a)
|
|||
switch(c) {
|
||||
default:
|
||||
t.to = *a;
|
||||
if(flag_shared && t.to.sym != S)
|
||||
t.pcrel = p;
|
||||
break;
|
||||
|
||||
case C_SROREG:
|
||||
case C_SROREG:
|
||||
case C_LOREG:
|
||||
case C_ROREG:
|
||||
case C_FOREG:
|
||||
|
|
@ -347,11 +349,13 @@ addpool(Prog *p, Adr *a)
|
|||
break;
|
||||
}
|
||||
|
||||
for(q = blitrl; q != P; q = q->link) /* could hash on t.t0.offset */
|
||||
if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) {
|
||||
p->cond = q;
|
||||
return;
|
||||
}
|
||||
if(t.pcrel == P) {
|
||||
for(q = blitrl; q != P; q = q->link) /* could hash on t.t0.offset */
|
||||
if(q->pcrel == P && memcmp(&q->to, &t.to, sizeof(t.to)) == 0) {
|
||||
p->cond = q;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
q = prg();
|
||||
*q = t;
|
||||
|
|
@ -570,7 +574,10 @@ aclass(Adr *a)
|
|||
if(s == S)
|
||||
break;
|
||||
instoffset = 0; // s.b. unused but just in case
|
||||
return C_LCON;
|
||||
if(flag_shared)
|
||||
return C_LCONADDR;
|
||||
else
|
||||
return C_LCON;
|
||||
|
||||
case D_AUTO:
|
||||
instoffset = autosize + a->offset;
|
||||
|
|
@ -736,8 +743,14 @@ buildop(void)
|
|||
for(i=0; i<C_GOK; i++)
|
||||
for(n=0; n<C_GOK; n++)
|
||||
xcmp[i][n] = cmp(n, i);
|
||||
for(n=0; optab[n].as != AXXX; n++)
|
||||
;
|
||||
for(n=0; optab[n].as != AXXX; n++) {
|
||||
if((optab[n].flag & LPCREL) != 0) {
|
||||
if(flag_shared)
|
||||
optab[n].size += optab[n].pcrelsiz;
|
||||
else
|
||||
optab[n].flag &= ~LPCREL;
|
||||
}
|
||||
}
|
||||
qsort(optab, n, sizeof(optab[0]), ocmp);
|
||||
for(i=0; i<n; i++) {
|
||||
r = optab[i].as;
|
||||
|
|
|
|||
|
|
@ -99,6 +99,20 @@ int nelfsym = 1;
|
|||
static void addpltsym(Sym*);
|
||||
static void addgotsym(Sym*);
|
||||
|
||||
Sym *
|
||||
lookuprel(void)
|
||||
{
|
||||
return lookup(".rela", 0);
|
||||
}
|
||||
|
||||
void
|
||||
adddynrela(Sym *rela, Sym *s, Reloc *r)
|
||||
{
|
||||
addaddrplus(rela, s, r->off);
|
||||
adduint64(rela, R_X86_64_RELATIVE);
|
||||
addaddrplus(rela, r->sym, r->add); // Addend
|
||||
}
|
||||
|
||||
void
|
||||
adddynrel(Sym *s, Reloc *r)
|
||||
{
|
||||
|
|
@ -463,7 +477,7 @@ adddynsym(Sym *s)
|
|||
addaddr(d, s);
|
||||
|
||||
/* size of object */
|
||||
adduint64(d, 0);
|
||||
adduint64(d, s->size);
|
||||
|
||||
if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) {
|
||||
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ struct Sym
|
|||
Reloc* r;
|
||||
int32 nr;
|
||||
int32 maxr;
|
||||
int rel_ro;
|
||||
};
|
||||
struct Optab
|
||||
{
|
||||
|
|
@ -320,6 +321,7 @@ EXTERN int32 INITRND;
|
|||
EXTERN int64 INITTEXT;
|
||||
EXTERN int64 INITDAT;
|
||||
EXTERN char* INITENTRY; /* entry point */
|
||||
EXTERN char* LIBINITENTRY; /* shared library entry point */
|
||||
EXTERN char* pcstr;
|
||||
EXTERN Auto* curauto;
|
||||
EXTERN Auto* curhist;
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ main(int argc, char *argv[])
|
|||
INITDAT = -1;
|
||||
INITRND = -1;
|
||||
INITENTRY = 0;
|
||||
LIBINITENTRY = 0;
|
||||
nuxiinit();
|
||||
|
||||
flagcount("1", "use alternate profiling code", &debug['1']);
|
||||
|
|
@ -117,6 +118,7 @@ main(int argc, char *argv[])
|
|||
flagcount("u", "reject unsafe packages", &debug['u']);
|
||||
flagcount("v", "print link trace", &debug['v']);
|
||||
flagcount("w", "disable DWARF generation", &debug['w']);
|
||||
flagcount("shared", "generate shared object", &flag_shared);
|
||||
|
||||
flagparse(&argc, &argv, usage);
|
||||
|
||||
|
|
|
|||
|
|
@ -372,7 +372,10 @@ oclass(Adr *a)
|
|||
switch(a->index) {
|
||||
case D_EXTERN:
|
||||
case D_STATIC:
|
||||
return Yi32; /* TO DO: Yi64 */
|
||||
if(flag_shared)
|
||||
return Yiauto;
|
||||
else
|
||||
return Yi32; /* TO DO: Yi64 */
|
||||
case D_AUTO:
|
||||
case D_PARAM:
|
||||
return Yiauto;
|
||||
|
|
@ -731,7 +734,10 @@ vaddr(Adr *a, Reloc *r)
|
|||
diag("need reloc for %D", a);
|
||||
errorexit();
|
||||
}
|
||||
r->type = D_ADDR;
|
||||
if(flag_shared)
|
||||
r->type = D_PCREL;
|
||||
else
|
||||
r->type = D_ADDR;
|
||||
r->siz = 4; // TODO: 8 for external symbols
|
||||
r->off = -1; // caller must fill in
|
||||
r->sym = s;
|
||||
|
|
@ -760,6 +766,8 @@ asmandsz(Adr *a, int r, int rex, int m64)
|
|||
goto bad;
|
||||
case D_STATIC:
|
||||
case D_EXTERN:
|
||||
if(flag_shared)
|
||||
goto bad;
|
||||
t = D_NONE;
|
||||
v = vaddr(a, &rel);
|
||||
break;
|
||||
|
|
@ -820,7 +828,7 @@ asmandsz(Adr *a, int r, int rex, int m64)
|
|||
|
||||
rexflag |= (regrex[t] & Rxb) | rex;
|
||||
if(t == D_NONE || (D_CS <= t && t <= D_GS)) {
|
||||
if(asmode != 64){
|
||||
if(flag_shared && t == D_NONE && (a->type == D_STATIC || a->type == D_EXTERN) || asmode != 64) {
|
||||
*andptr++ = (0 << 6) | (5 << 0) | (r << 3);
|
||||
goto putrelv;
|
||||
}
|
||||
|
|
@ -1776,13 +1784,17 @@ asmins(Prog *p)
|
|||
if(c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26)
|
||||
break;
|
||||
}
|
||||
for(r=cursym->r+cursym->nr; r-- > cursym->r; ) {
|
||||
if(r->off < p->pc)
|
||||
break;
|
||||
r->off++;
|
||||
}
|
||||
memmove(and+np+1, and+np, n-np);
|
||||
and[np] = 0x40 | rexflag;
|
||||
andptr++;
|
||||
}
|
||||
n = andptr - and;
|
||||
for(r=cursym->r+cursym->nr; r-- > cursym->r; ) {
|
||||
if(r->off < p->pc)
|
||||
break;
|
||||
if(rexflag)
|
||||
r->off++;
|
||||
if(r->type == D_PCREL)
|
||||
r->add -= p->pc + n - (r->off + r->siz);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,18 @@ int nelfsym = 1;
|
|||
static void addpltsym(Sym*);
|
||||
static void addgotsym(Sym*);
|
||||
|
||||
Sym *
|
||||
lookuprel(void)
|
||||
{
|
||||
return lookup(".rel", 0);
|
||||
}
|
||||
|
||||
void
|
||||
adddynrela(Sym *rela, Sym *s, Reloc *r)
|
||||
{
|
||||
sysfatal("adddynrela not implemented");
|
||||
}
|
||||
|
||||
void
|
||||
adddynrel(Sym *s, Reloc *r)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ struct Sym
|
|||
Reloc* r;
|
||||
int32 nr;
|
||||
int32 maxr;
|
||||
int rel_ro;
|
||||
};
|
||||
struct Optab
|
||||
{
|
||||
|
|
@ -275,6 +276,7 @@ EXTERN int32 INITRND;
|
|||
EXTERN int32 INITTEXT;
|
||||
EXTERN int32 INITDAT;
|
||||
EXTERN char* INITENTRY; /* entry point */
|
||||
EXTERN char* LIBINITENTRY; /* shared library entry point */
|
||||
EXTERN int32 casepc;
|
||||
EXTERN char* pcstr;
|
||||
EXTERN Auto* curauto;
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ main(int argc, char *argv[])
|
|||
INITDAT = -1;
|
||||
INITRND = -1;
|
||||
INITENTRY = 0;
|
||||
LIBINITENTRY = 0;
|
||||
nuxiinit();
|
||||
|
||||
flagcount("1", "use alternate profiling code", &debug['1']);
|
||||
|
|
|
|||
|
|
@ -232,7 +232,9 @@ void
|
|||
dynrelocsym(Sym *s)
|
||||
{
|
||||
Reloc *r;
|
||||
|
||||
Sym *rel;
|
||||
Sym *got;
|
||||
|
||||
if(HEADTYPE == Hwindows) {
|
||||
Sym *rel, *targ;
|
||||
|
||||
|
|
@ -268,9 +270,23 @@ dynrelocsym(Sym *s)
|
|||
return;
|
||||
}
|
||||
|
||||
for(r=s->r; r<s->r+s->nr; r++)
|
||||
got = rel = nil;
|
||||
if(flag_shared) {
|
||||
rel = lookuprel();
|
||||
got = lookup(".got", 0);
|
||||
}
|
||||
s->rel_ro = 0;
|
||||
for(r=s->r; r<s->r+s->nr; r++) {
|
||||
if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256)
|
||||
adddynrel(s, r);
|
||||
if(flag_shared && r->sym != S && (r->sym->dynimpname == nil || r->sym->dynexport) && r->type == D_ADDR
|
||||
&& (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) {
|
||||
// Create address based RELATIVE relocation
|
||||
adddynrela(rel, s, r);
|
||||
if(s->type < SNOPTRDATA)
|
||||
s->rel_ro = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -714,6 +730,29 @@ setuint64(Sym *s, vlong r, uint64 v)
|
|||
setuintxx(s, r, v, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
static vlong
|
||||
addaddrpcrelplus(Sym *s, Sym *t, int32 add)
|
||||
{
|
||||
vlong i;
|
||||
Reloc *r;
|
||||
|
||||
if(s->type == 0)
|
||||
s->type = SDATA;
|
||||
s->reachable = 1;
|
||||
i = s->size;
|
||||
s->size += PtrSize;
|
||||
symgrow(s, s->size);
|
||||
r = addrel(s);
|
||||
r->sym = t;
|
||||
r->off = i;
|
||||
r->siz = PtrSize;
|
||||
r->type = D_PCREL;
|
||||
r->add = add;
|
||||
return i;
|
||||
}
|
||||
*/
|
||||
|
||||
vlong
|
||||
addaddrplus(Sym *s, Sym *t, int32 add)
|
||||
{
|
||||
|
|
@ -968,6 +1007,12 @@ dodata(void)
|
|||
}
|
||||
*l = nil;
|
||||
|
||||
if(flag_shared) {
|
||||
for(s=datap; s != nil; s = s->next) {
|
||||
if(s->rel_ro)
|
||||
s->type = SDATARELRO;
|
||||
}
|
||||
}
|
||||
datap = datsort(datap);
|
||||
|
||||
/*
|
||||
|
|
@ -1004,7 +1049,7 @@ dodata(void)
|
|||
sect->vaddr = datsize;
|
||||
lookup("noptrdata", 0)->sect = sect;
|
||||
lookup("enoptrdata", 0)->sect = sect;
|
||||
for(; s != nil && s->type < SDATA; s = s->next) {
|
||||
for(; s != nil && s->type < SDATARELRO; s = s->next) {
|
||||
s->sect = sect;
|
||||
s->type = SDATA;
|
||||
t = alignsymsize(s->size);
|
||||
|
|
@ -1015,12 +1060,34 @@ dodata(void)
|
|||
sect->len = datsize - sect->vaddr;
|
||||
datsize = rnd(datsize, PtrSize);
|
||||
|
||||
/* dynamic relocated rodata */
|
||||
if(flag_shared) {
|
||||
sect = addsection(&segdata, ".data.rel.ro", 06);
|
||||
sect->vaddr = datsize;
|
||||
lookup("datarelro", 0)->sect = sect;
|
||||
lookup("edatarelro", 0)->sect = sect;
|
||||
for(; s != nil && s->type == SDATARELRO; s = s->next) {
|
||||
if(s->align != 0)
|
||||
datsize = rnd(datsize, s->align);
|
||||
s->sect = sect;
|
||||
s->type = SDATA;
|
||||
s->value = datsize;
|
||||
datsize += rnd(s->size, PtrSize);
|
||||
}
|
||||
sect->len = datsize - sect->vaddr;
|
||||
datsize = rnd(datsize, PtrSize);
|
||||
}
|
||||
|
||||
/* data */
|
||||
sect = addsection(&segdata, ".data", 06);
|
||||
sect->vaddr = datsize;
|
||||
lookup("data", 0)->sect = sect;
|
||||
lookup("edata", 0)->sect = sect;
|
||||
for(; s != nil && s->type < SBSS; s = s->next) {
|
||||
if(s->type == SDATARELRO) {
|
||||
cursym = s;
|
||||
diag("unexpected symbol type %d", s->type);
|
||||
}
|
||||
s->sect = sect;
|
||||
s->type = SDATA;
|
||||
t = alignsymsize(s->size);
|
||||
|
|
@ -1080,6 +1147,7 @@ dodata(void)
|
|||
sect->vaddr = 0;
|
||||
lookup("rodata", 0)->sect = sect;
|
||||
lookup("erodata", 0)->sect = sect;
|
||||
lookup("reloffset", 0)->sect = sect;
|
||||
datsize = 0;
|
||||
s = datap;
|
||||
for(; s != nil && s->type < STYPELINK; s = s->next) {
|
||||
|
|
@ -1227,7 +1295,7 @@ textaddress(void)
|
|||
void
|
||||
address(void)
|
||||
{
|
||||
Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
|
||||
Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
|
||||
Section *gcdata, *gcbss, *typelink;
|
||||
Sym *sym, *sub;
|
||||
uvlong va;
|
||||
|
|
@ -1257,6 +1325,7 @@ address(void)
|
|||
noptr = nil;
|
||||
bss = nil;
|
||||
noptrbss = nil;
|
||||
datarelro = nil;
|
||||
for(s=segdata.sect; s != nil; s=s->next) {
|
||||
s->vaddr = va;
|
||||
va += s->len;
|
||||
|
|
@ -1270,6 +1339,8 @@ address(void)
|
|||
bss = s;
|
||||
if(strcmp(s->name, ".noptrbss") == 0)
|
||||
noptrbss = s;
|
||||
if(strcmp(s->name, ".data.rel.ro") == 0)
|
||||
datarelro = s;
|
||||
}
|
||||
segdata.filelen -= bss->len + noptrbss->len; // deduct .bss
|
||||
|
||||
|
|
@ -1297,6 +1368,10 @@ address(void)
|
|||
xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
|
||||
xdefine("typelink", SRODATA, typelink->vaddr);
|
||||
xdefine("etypelink", SRODATA, typelink->vaddr + typelink->len);
|
||||
if(datarelro != nil) {
|
||||
xdefine("datarelro", SRODATA, datarelro->vaddr);
|
||||
xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
|
||||
}
|
||||
xdefine("gcdata", SGCDATA, gcdata->vaddr);
|
||||
xdefine("egcdata", SGCDATA, gcdata->vaddr + gcdata->len);
|
||||
xdefine("gcbss", SGCBSS, gcbss->vaddr);
|
||||
|
|
|
|||
|
|
@ -794,6 +794,8 @@ doelf(void)
|
|||
addstring(shstrtab, ".elfdata");
|
||||
addstring(shstrtab, ".rodata");
|
||||
addstring(shstrtab, ".typelink");
|
||||
if(flag_shared)
|
||||
addstring(shstrtab, ".data.rel.ro");
|
||||
addstring(shstrtab, ".gcdata");
|
||||
addstring(shstrtab, ".gcbss");
|
||||
addstring(shstrtab, ".gosymtab");
|
||||
|
|
@ -927,6 +929,13 @@ doelf(void)
|
|||
|
||||
elfwritedynent(s, DT_DEBUG, 0);
|
||||
|
||||
if(flag_shared) {
|
||||
Sym *init_sym = lookup(LIBINITENTRY, 0);
|
||||
if(init_sym->type != STEXT)
|
||||
diag("entry not text: %s", init_sym->name);
|
||||
elfwritedynentsym(s, DT_INIT, init_sym);
|
||||
}
|
||||
|
||||
// Do not write DT_NULL. elfdynhash will finish it.
|
||||
}
|
||||
}
|
||||
|
|
@ -1277,7 +1286,11 @@ asmbelf(vlong symo)
|
|||
eh->ident[EI_DATA] = ELFDATA2LSB;
|
||||
eh->ident[EI_VERSION] = EV_CURRENT;
|
||||
|
||||
eh->type = ET_EXEC;
|
||||
if(flag_shared)
|
||||
eh->type = ET_DYN;
|
||||
else
|
||||
eh->type = ET_EXEC;
|
||||
|
||||
eh->version = EV_CURRENT;
|
||||
eh->entry = entryvalue();
|
||||
|
||||
|
|
|
|||
|
|
@ -732,6 +732,8 @@ deadcode(void)
|
|||
Bprint(&bso, "%5.2f deadcode\n", cputime());
|
||||
|
||||
mark(lookup(INITENTRY, 0));
|
||||
if(flag_shared)
|
||||
mark(lookup(LIBINITENTRY, 0));
|
||||
for(i=0; i<nelem(morename); i++)
|
||||
mark(lookup(morename[i], 0));
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,13 @@ libinit(void)
|
|||
sprint(INITENTRY, "_rt0_%s_%s", goarch, goos);
|
||||
}
|
||||
lookup(INITENTRY, 0)->type = SXREF;
|
||||
if(flag_shared) {
|
||||
if(LIBINITENTRY == nil) {
|
||||
LIBINITENTRY = mal(strlen(goarch)+strlen(goos)+20);
|
||||
sprint(LIBINITENTRY, "_rt0_%s_%s_lib", goarch, goos);
|
||||
}
|
||||
lookup(LIBINITENTRY, 0)->type = SXREF;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -305,7 +312,7 @@ loadlib(void)
|
|||
//
|
||||
// Exception: on OS X, programs such as Shark only work with dynamic
|
||||
// binaries, so leave it enabled on OS X (Mach-O) binaries.
|
||||
if(!havedynamic && HEADTYPE != Hdarwin)
|
||||
if(!flag_shared && !havedynamic && HEADTYPE != Hdarwin)
|
||||
debug['d'] = 1;
|
||||
|
||||
importcycles();
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ enum
|
|||
SELFROSECT,
|
||||
SELFSECT,
|
||||
SNOPTRDATA,
|
||||
SDATARELRO,
|
||||
SDATA,
|
||||
SMACHO, /* Mach-O __nl_symbol_ptr */
|
||||
SMACHOGOT,
|
||||
|
|
@ -138,6 +139,7 @@ EXTERN int havedynamic;
|
|||
EXTERN int iscgo;
|
||||
EXTERN int elfglobalsymndx;
|
||||
EXTERN int flag_race;
|
||||
EXTERN int flag_shared;
|
||||
EXTERN char* tracksym;
|
||||
EXTERN char* interpreter;
|
||||
|
||||
|
|
@ -176,6 +178,8 @@ void symtab(void);
|
|||
void Lflag(char *arg);
|
||||
void usage(void);
|
||||
void adddynrel(Sym*, Reloc*);
|
||||
void adddynrela(Sym*, Sym*, Reloc*);
|
||||
Sym* lookuprel();
|
||||
void ldobj1(Biobuf *f, char*, int64 len, char *pn);
|
||||
void ldobj(Biobuf*, char*, int64, char*, int);
|
||||
void ldelf(Biobuf*, char*, int64, char*);
|
||||
|
|
|
|||
|
|
@ -387,6 +387,11 @@ symtab(void)
|
|||
xdefine("etypelink", SRODATA, 0);
|
||||
xdefine("rodata", SRODATA, 0);
|
||||
xdefine("erodata", SRODATA, 0);
|
||||
xdefine("reloffset", SRODATA, 0);
|
||||
if(flag_shared) {
|
||||
xdefine("datarelro", SDATARELRO, 0);
|
||||
xdefine("edatarelro", SDATARELRO, 0);
|
||||
}
|
||||
xdefine("gcdata", SGCDATA, 0);
|
||||
xdefine("egcdata", SGCDATA, 0);
|
||||
xdefine("gcbss", SGCBSS, 0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue