diff options
Diffstat (limited to 'src/cmd/ld/data.c')
-rw-r--r-- | src/cmd/ld/data.c | 96 |
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; } |