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)
{
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 */
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 */
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 */
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 */
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 */
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: */
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;
} u0;
Prog* cond;
Prog* link;
+ Prog* pcrel;
int32 pc;
int32 line;
int32 spadj;
Reloc* r;
int32 nr;
int32 maxr;
+ int rel_ro;
};
#define SIGNINTERN (1729*325*1729)
char size;
char param;
char flag;
+ uchar pcrelsiz;
};
struct Oprang
{
LFROM = 1<<0,
LTO = 1<<1,
LPOOL = 1<<2,
+ LPCREL = 1<<3,
C_NONE = 0,
C_REG,
C_NCON, /* ~RCON */
C_SCON, /* 0xffff */
C_LCON,
+ C_LCONADDR,
C_ZFCON,
C_SFCON,
C_LFCON,
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;
[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",
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)
{
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;
INITDAT = -1;
INITRND = -1;
INITENTRY = 0;
+ LIBINITENTRY = 0;
nuxiinit();
p = getgoarm();
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);
{ 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 },
{ 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 },
{ 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 },
{ 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 },
{ 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 },
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:
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;
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;
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;
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)
{
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,
Reloc* r;
int32 nr;
int32 maxr;
+ int rel_ro;
};
struct Optab
{
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;
INITDAT = -1;
INITRND = -1;
INITENTRY = 0;
+ LIBINITENTRY = 0;
nuxiinit();
flagcount("1", "use alternate profiling code", &debug['1']);
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);
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;
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;
goto bad;
case D_STATIC:
case D_EXTERN:
+ if(flag_shared)
+ goto bad;
t = D_NONE;
v = vaddr(a, &rel);
break;
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;
}
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);
+ }
}
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)
{
Reloc* r;
int32 nr;
int32 maxr;
+ int rel_ro;
};
struct Optab
{
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;
INITDAT = -1;
INITRND = -1;
INITENTRY = 0;
+ LIBINITENTRY = 0;
nuxiinit();
flagcount("1", "use alternate profiling code", &debug['1']);
dynrelocsym(Sym *s)
{
Reloc *r;
-
+ Sym *rel;
+ Sym *got;
+
if(HEADTYPE == Hwindows) {
Sym *rel, *targ;
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
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)
{
}
*l = nil;
+ if(flag_shared) {
+ for(s=datap; s != nil; s = s->next) {
+ if(s->rel_ro)
+ s->type = SDATARELRO;
+ }
+ }
datap = datsort(datap);
/*
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);
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);
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) {
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;
noptr = nil;
bss = nil;
noptrbss = nil;
+ datarelro = nil;
for(s=segdata.sect; s != nil; s=s->next) {
s->vaddr = va;
va += s->len;
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
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);
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");
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.
}
}
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();
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));
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
//
// 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();
SELFROSECT,
SELFSECT,
SNOPTRDATA,
+ SDATARELRO,
SDATA,
SMACHO, /* Mach-O __nl_symbol_ptr */
SMACHOGOT,
EXTERN int iscgo;
EXTERN int elfglobalsymndx;
EXTERN int flag_race;
+EXTERN int flag_shared;
EXTERN char* tracksym;
EXTERN char* interpreter;
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*);
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);