summaryrefslogtreecommitdiff
path: root/src/cmd/ld/data.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ld/data.c')
-rw-r--r--src/cmd/ld/data.c96
1 files changed, 76 insertions, 20 deletions
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index f1132fc8b..e7269169e 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -36,6 +36,7 @@
#include "../ld/pe.h"
void dynreloc(void);
+static vlong addaddrplus4(Sym *s, Sym *t, int32 add);
/*
* divide-and-conquer list-link
@@ -255,11 +256,19 @@ dynrelocsym(Sym *s)
r->add = targ->plt;
// jmp *addr
- adduint8(rel, 0xff);
- adduint8(rel, 0x25);
- addaddr(rel, targ);
- adduint8(rel, 0x90);
- adduint8(rel, 0x90);
+ if(thechar == '8') {
+ adduint8(rel, 0xff);
+ adduint8(rel, 0x25);
+ addaddr(rel, targ);
+ adduint8(rel, 0x90);
+ adduint8(rel, 0x90);
+ } else {
+ adduint8(rel, 0xff);
+ adduint8(rel, 0x24);
+ adduint8(rel, 0x25);
+ addaddrplus4(rel, targ, 0);
+ adduint8(rel, 0x90);
+ }
} else if(r->sym->plt >= 0) {
r->sym = rel;
r->add = targ->plt;
@@ -451,7 +460,7 @@ codeblk(int32 addr, int32 size)
uchar *q;
if(debug['a'])
- Bprint(&bso, "codeblk [%#x,%#x) at offset %#llx\n", addr, addr+size, seek(cout, 0, 1));
+ Bprint(&bso, "codeblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos());
blk(textp, addr, size);
@@ -503,7 +512,7 @@ codeblk(int32 addr, int32 size)
epc = p->link->pc;
else
epc = sym->value + sym->size;
- Bprint(&bso, "%.6ux\t", p->pc);
+ Bprint(&bso, "%.6llux\t", (uvlong)p->pc);
q = sym->p + p->pc - sym->value;
n = epc - p->pc;
Bprint(&bso, "%-20.*I | %P\n", (int)n, q, p);
@@ -527,7 +536,7 @@ datblk(int32 addr, int32 size)
uchar *p, *ep;
if(debug['a'])
- Bprint(&bso, "datblk [%#x,%#x) at offset %#llx\n", addr, addr+size, seek(cout, 0, 1));
+ Bprint(&bso, "datblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos());
blk(datap, addr, size);
@@ -678,6 +687,27 @@ addaddrplus(Sym *s, Sym *t, int32 add)
return i;
}
+static vlong
+addaddrplus4(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 += 4;
+ symgrow(s, s->size);
+ r = addrel(s);
+ r->sym = t;
+ r->off = i;
+ r->siz = 4;
+ r->type = D_ADDR;
+ r->add = add;
+ return i;
+}
+
vlong
addpcrelplus(Sym *s, Sym *t, int32 add)
{
@@ -791,9 +821,8 @@ dodata(void)
s = datap;
for(; s != nil && s->type < SSYMTAB; s = s->next) {
s->type = SRODATA;
- t = rnd(s->size, PtrSize);
s->value = datsize;
- datsize += t;
+ datsize += rnd(s->size, PtrSize);
}
sect->len = datsize - sect->vaddr;
@@ -806,21 +835,43 @@ dodata(void)
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
+ datsize = rnd(datsize, PtrSize);
/* gopclntab */
sect = addsection(&segtext, ".gopclntab", 04);
sect->vaddr = datsize;
- for(; s != nil && s->type < SDATA; s = s->next) {
+ for(; s != nil && s->type < SELFROSECT; s = s->next) {
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
+ datsize = rnd(datsize, PtrSize);
- /* data */
+ /* read-only ELF sections */
+ for(; s != nil && s->type < SELFSECT; s = s->next) {
+ sect = addsection(&segtext, s->name, 04);
+ sect->vaddr = datsize;
+ s->type = SRODATA;
+ s->value = datsize;
+ datsize += rnd(s->size, PtrSize);
+ sect->len = datsize - sect->vaddr;
+ }
+
+ /* writable ELF sections */
datsize = 0;
+ for(; s != nil && s->type < SDATA; s = s->next) {
+ sect = addsection(&segdata, s->name, 06);
+ sect->vaddr = datsize;
+ s->type = SDATA;
+ s->value = datsize;
+ datsize += rnd(s->size, PtrSize);
+ sect->len = datsize - sect->vaddr;
+ }
+
+ /* data */
sect = addsection(&segdata, ".data", 06);
- sect->vaddr = 0;
+ sect->vaddr = datsize;
for(; s != nil && s->type < SBSS; s = s->next) {
s->type = SDATA;
t = s->size;
@@ -920,38 +971,43 @@ address(void)
segtext.fileoff = HEADR;
for(s=segtext.sect; s != nil; s=s->next) {
s->vaddr = va;
- va += s->len;
- segtext.len = va - INITTEXT;
- va = rnd(va, INITRND);
+ va += rnd(s->len, PtrSize);
}
+ segtext.len = va - INITTEXT;
segtext.filelen = segtext.len;
+ va = rnd(va, INITRND);
+
segdata.rwx = 06;
segdata.vaddr = va;
segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
+ segdata.filelen = 0;
if(HEADTYPE == Hwindows)
segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
if(HEADTYPE == Hplan9x32)
segdata.fileoff = segtext.fileoff + segtext.filelen;
+ data = nil;
for(s=segdata.sect; s != nil; s=s->next) {
s->vaddr = va;
va += s->len;
+ segdata.filelen += s->len;
segdata.len = va - segdata.vaddr;
+ if(strcmp(s->name, ".data") == 0)
+ data = s;
}
- segdata.filelen = segdata.sect->len; // assume .data is first
-
+ segdata.filelen -= data->next->len; // deduct .bss
+
text = segtext.sect;
rodata = text->next;
symtab = rodata->next;
pclntab = symtab->next;
- data = segdata.sect;
for(sym = datap; sym != nil; sym = sym->next) {
cursym = sym;
if(sym->type < SDATA)
sym->value += rodata->vaddr;
else
- sym->value += data->vaddr;
+ sym->value += segdata.sect->vaddr;
for(sub = sym->sub; sub != nil; sub = sub->sub)
sub->value += sym->value;
}