summaryrefslogtreecommitdiff
path: root/src/cmd/ld
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ld')
-rw-r--r--src/cmd/ld/data.c970
-rw-r--r--src/cmd/ld/doc.go11
-rw-r--r--src/cmd/ld/dwarf.c2598
-rw-r--r--src/cmd/ld/dwarf.h30
-rw-r--r--src/cmd/ld/dwarf_defs.h503
-rw-r--r--src/cmd/ld/elf.c558
-rw-r--r--src/cmd/ld/elf.h989
-rw-r--r--src/cmd/ld/go.c710
-rw-r--r--src/cmd/ld/ldelf.c816
-rw-r--r--src/cmd/ld/ldmacho.c821
-rw-r--r--src/cmd/ld/ldpe.c415
-rw-r--r--src/cmd/ld/lib.c1361
-rw-r--r--src/cmd/ld/lib.h281
-rw-r--r--src/cmd/ld/macho.c518
-rw-r--r--src/cmd/ld/macho.h94
-rw-r--r--src/cmd/ld/pe.c583
-rw-r--r--src/cmd/ld/pe.h179
-rw-r--r--src/cmd/ld/symtab.c378
18 files changed, 0 insertions, 11815 deletions
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
deleted file mode 100644
index f1132fc8b..000000000
--- a/src/cmd/ld/data.c
+++ /dev/null
@@ -1,970 +0,0 @@
-// Inferno utils/8l/asm.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Data layout and relocation.
-
-#include "l.h"
-#include "../ld/lib.h"
-#include "../ld/elf.h"
-#include "../ld/pe.h"
-
-void dynreloc(void);
-
-/*
- * divide-and-conquer list-link
- * sort of Sym* structures.
- * Used for the data block.
- */
-int
-datcmp(Sym *s1, Sym *s2)
-{
- if(s1->type != s2->type)
- return (int)s1->type - (int)s2->type;
- if(s1->size != s2->size) {
- if(s1->size < s2->size)
- return -1;
- return +1;
- }
- return strcmp(s1->name, s2->name);
-}
-
-Sym*
-datsort(Sym *l)
-{
- Sym *l1, *l2, *le;
-
- if(l == 0 || l->next == 0)
- return l;
-
- l1 = l;
- l2 = l;
- for(;;) {
- l2 = l2->next;
- if(l2 == 0)
- break;
- l2 = l2->next;
- if(l2 == 0)
- break;
- l1 = l1->next;
- }
-
- l2 = l1->next;
- l1->next = 0;
- l1 = datsort(l);
- l2 = datsort(l2);
-
- /* set up lead element */
- if(datcmp(l1, l2) < 0) {
- l = l1;
- l1 = l1->next;
- } else {
- l = l2;
- l2 = l2->next;
- }
- le = l;
-
- for(;;) {
- if(l1 == 0) {
- while(l2) {
- le->next = l2;
- le = l2;
- l2 = l2->next;
- }
- le->next = 0;
- break;
- }
- if(l2 == 0) {
- while(l1) {
- le->next = l1;
- le = l1;
- l1 = l1->next;
- }
- break;
- }
- if(datcmp(l1, l2) < 0) {
- le->next = l1;
- le = l1;
- l1 = l1->next;
- } else {
- le->next = l2;
- le = l2;
- l2 = l2->next;
- }
- }
- le->next = 0;
- return l;
-}
-
-Reloc*
-addrel(Sym *s)
-{
- if(s->nr >= s->maxr) {
- if(s->maxr == 0)
- s->maxr = 4;
- else
- s->maxr <<= 1;
- s->r = realloc(s->r, s->maxr*sizeof s->r[0]);
- if(s->r == 0) {
- diag("out of memory");
- errorexit();
- }
- memset(s->r+s->nr, 0, (s->maxr-s->nr)*sizeof s->r[0]);
- }
- return &s->r[s->nr++];
-}
-
-void
-relocsym(Sym *s)
-{
- Reloc *r;
- Prog p;
- int32 i, off, siz, fl;
- vlong o;
- uchar *cast;
-
- cursym = s;
- memset(&p, 0, sizeof p);
- for(r=s->r; r<s->r+s->nr; r++) {
- off = r->off;
- siz = r->siz;
- if(off < 0 || off+(siz&~Rbig) > s->np) {
- diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz&~Rbig, 0, s->np);
- continue;
- }
- if(r->sym != S && (r->sym->type == 0 || r->sym->type == SXREF)) {
- diag("%s: not defined", r->sym->name);
- continue;
- }
- if(r->type >= 256)
- continue;
-
- if(r->sym != S && r->sym->type == SDYNIMPORT)
- diag("unhandled relocation for %s (type %d rtype %d)", r->sym->name, r->sym->type, r->type);
-
- if(r->sym != S && !r->sym->reachable)
- diag("unreachable sym in relocation: %s %s", s->name, r->sym->name);
-
- switch(r->type) {
- default:
- o = 0;
- if(archreloc(r, s, &o) < 0)
- diag("unknown reloc %d", r->type);
- break;
- case D_ADDR:
- o = symaddr(r->sym) + r->add;
- break;
- case D_PCREL:
- o = symaddr(r->sym) + r->add - (s->value + r->off + r->siz);
- break;
- case D_SIZE:
- o = r->sym->size + r->add;
- break;
- }
-//print("relocate %s %p %s => %p %p %p %p [%p]\n", s->name, s->value+off, r->sym ? r->sym->name : "<nil>", (void*)symaddr(r->sym), (void*)s->value, (void*)r->off, (void*)r->siz, (void*)o);
- switch(siz) {
- default:
- cursym = s;
- diag("bad reloc size %#ux for %s", siz, r->sym->name);
- case 4 + Rbig:
- fl = o;
- s->p[off] = fl>>24;
- s->p[off+1] = fl>>16;
- s->p[off+2] = fl>>8;
- s->p[off+3] = fl;
- break;
- case 4 + Rlittle:
- fl = o;
- s->p[off] = fl;
- s->p[off+1] = fl>>8;
- s->p[off+2] = fl>>16;
- s->p[off+3] = fl>>24;
- break;
- case 4:
- fl = o;
- cast = (uchar*)&fl;
- for(i=0; i<4; i++)
- s->p[off+i] = cast[inuxi4[i]];
- break;
- case 8:
- cast = (uchar*)&o;
- for(i=0; i<8; i++)
- s->p[off+i] = cast[inuxi8[i]];
- break;
- }
- }
-}
-
-void
-reloc(void)
-{
- Sym *s;
-
- if(debug['v'])
- Bprint(&bso, "%5.2f reloc\n", cputime());
- Bflush(&bso);
-
- for(s=textp; s!=S; s=s->next)
- relocsym(s);
- for(s=datap; s!=S; s=s->next)
- relocsym(s);
-}
-
-void
-dynrelocsym(Sym *s)
-{
- Reloc *r;
-
- if(HEADTYPE == Hwindows) {
- Sym *rel, *targ;
-
- rel = lookup(".rel", 0);
- if(s == rel)
- return;
- for(r=s->r; r<s->r+s->nr; r++) {
- targ = r->sym;
- if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files.
- targ->plt = rel->size;
- r->sym = rel;
- r->add = targ->plt;
-
- // jmp *addr
- adduint8(rel, 0xff);
- adduint8(rel, 0x25);
- addaddr(rel, targ);
- adduint8(rel, 0x90);
- adduint8(rel, 0x90);
- } else if(r->sym->plt >= 0) {
- r->sym = rel;
- r->add = targ->plt;
- }
- }
- return;
- }
-
- for(r=s->r; r<s->r+s->nr; r++)
- if(r->sym->type == SDYNIMPORT || r->type >= 256)
- adddynrel(s, r);
-}
-
-void
-dynreloc(void)
-{
- Sym *s;
-
- // -d supresses dynamic loader format, so we may as well not
- // compute these sections or mark their symbols as reachable.
- if(debug['d'] && HEADTYPE != Hwindows)
- return;
- if(debug['v'])
- Bprint(&bso, "%5.2f reloc\n", cputime());
- Bflush(&bso);
-
- for(s=textp; s!=S; s=s->next)
- dynrelocsym(s);
- for(s=datap; s!=S; s=s->next)
- dynrelocsym(s);
- if(iself)
- elfdynhash();
-}
-
-void
-symgrow(Sym *s, int32 siz)
-{
- if(s->np >= siz)
- return;
-
- if(s->maxp < siz) {
- if(s->maxp == 0)
- s->maxp = 8;
- while(s->maxp < siz)
- s->maxp <<= 1;
- s->p = realloc(s->p, s->maxp);
- if(s->p == nil) {
- diag("out of memory");
- errorexit();
- }
- memset(s->p+s->np, 0, s->maxp-s->np);
- }
- s->np = siz;
-}
-
-void
-savedata(Sym *s, Prog *p, char *pn)
-{
- int32 off, siz, i, fl;
- uchar *cast;
- vlong o;
- Reloc *r;
-
- off = p->from.offset;
- siz = p->datasize;
- if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100)
- mangle(pn);
- symgrow(s, off+siz);
-
- switch(p->to.type) {
- default:
- diag("bad data: %P", p);
- break;
-
- case D_FCONST:
- switch(siz) {
- default:
- case 4:
- fl = ieeedtof(&p->to.ieee);
- cast = (uchar*)&fl;
- for(i=0; i<4; i++)
- s->p[off+i] = cast[fnuxi4[i]];
- break;
- case 8:
- cast = (uchar*)&p->to.ieee;
- for(i=0; i<8; i++)
- s->p[off+i] = cast[fnuxi8[i]];
- break;
- }
- break;
-
- case D_SCONST:
- for(i=0; i<siz; i++)
- s->p[off+i] = p->to.scon[i];
- break;
-
- case D_CONST:
- if(p->to.sym)
- goto Addr;
- o = p->to.offset;
- fl = o;
- cast = (uchar*)&fl;
- switch(siz) {
- default:
- diag("bad nuxi %d\n%P", siz, p);
- break;
- case 1:
- s->p[off] = cast[inuxi1[0]];
- break;
- case 2:
- for(i=0; i<2; i++)
- s->p[off+i] = cast[inuxi2[i]];
- break;
- case 4:
- for(i=0; i<4; i++)
- s->p[off+i] = cast[inuxi4[i]];
- break;
- case 8:
- cast = (uchar*)&o;
- for(i=0; i<8; i++)
- s->p[off+i] = cast[inuxi8[i]];
- break;
- }
- break;
-
- case D_ADDR:
- case D_SIZE:
- Addr:
- r = addrel(s);
- r->off = off;
- r->siz = siz;
- r->sym = p->to.sym;
- r->type = p->to.type;
- if(r->type != D_SIZE)
- r->type = D_ADDR;
- r->add = p->to.offset;
- break;
- }
-}
-
-static void
-blk(Sym *allsym, int32 addr, int32 size)
-{
- Sym *sym;
- int32 eaddr;
- uchar *p, *ep;
-
- for(sym = allsym; sym != nil; sym = sym->next)
- if(!(sym->type&SSUB) && sym->value >= addr)
- break;
-
- eaddr = addr+size;
- for(; sym != nil; sym = sym->next) {
- if(sym->type&SSUB)
- continue;
- if(sym->value >= eaddr)
- break;
- if(sym->value < addr) {
- diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type);
- errorexit();
- }
- cursym = sym;
- for(; addr < sym->value; addr++)
- cput(0);
- p = sym->p;
- ep = p + sym->np;
- while(p < ep)
- cput(*p++);
- addr += sym->np;
- for(; addr < sym->value+sym->size; addr++)
- cput(0);
- if(addr != sym->value+sym->size) {
- diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size);
- errorexit();
- }
- }
-
- for(; addr < eaddr; addr++)
- cput(0);
- cflush();
-}
-
-void
-codeblk(int32 addr, int32 size)
-{
- Sym *sym;
- int32 eaddr, n, epc;
- Prog *p;
- uchar *q;
-
- if(debug['a'])
- Bprint(&bso, "codeblk [%#x,%#x) at offset %#llx\n", addr, addr+size, seek(cout, 0, 1));
-
- blk(textp, addr, size);
-
- /* again for printing */
- if(!debug['a'])
- return;
-
- for(sym = textp; sym != nil; sym = sym->next) {
- if(!sym->reachable)
- continue;
- if(sym->value >= addr)
- break;
- }
-
- eaddr = addr + size;
- for(; sym != nil; sym = sym->next) {
- if(!sym->reachable)
- continue;
- if(sym->value >= eaddr)
- break;
-
- if(addr < sym->value) {
- Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr);
- for(; addr < sym->value; addr++)
- Bprint(&bso, " %.2ux", 0);
- Bprint(&bso, "\n");
- }
- p = sym->text;
- if(p == nil) {
- Bprint(&bso, "%.6llux\t%-20s | foreign text\n", (vlong)addr, sym->name);
- n = sym->size;
- q = sym->p;
-
- while(n >= 16) {
- Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q);
- addr += 16;
- q += 16;
- n -= 16;
- }
- if(n > 0)
- Bprint(&bso, "%.6ux\t%-20.*I\n", addr, (int)n, q);
- addr += n;
- continue;
- }
-
- Bprint(&bso, "%.6llux\t%-20s | %P\n", (vlong)sym->value, sym->name, p);
- for(p = p->link; p != P; p = p->link) {
- if(p->link != P)
- epc = p->link->pc;
- else
- epc = sym->value + sym->size;
- Bprint(&bso, "%.6ux\t", p->pc);
- q = sym->p + p->pc - sym->value;
- n = epc - p->pc;
- Bprint(&bso, "%-20.*I | %P\n", (int)n, q, p);
- addr += n;
- }
- }
-
- if(addr < eaddr) {
- Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr);
- for(; addr < eaddr; addr++)
- Bprint(&bso, " %.2ux", 0);
- }
- Bflush(&bso);
-}
-
-void
-datblk(int32 addr, int32 size)
-{
- Sym *sym;
- int32 eaddr;
- uchar *p, *ep;
-
- if(debug['a'])
- Bprint(&bso, "datblk [%#x,%#x) at offset %#llx\n", addr, addr+size, seek(cout, 0, 1));
-
- blk(datap, addr, size);
-
- /* again for printing */
- if(!debug['a'])
- return;
-
- for(sym = datap; sym != nil; sym = sym->next)
- if(sym->value >= addr)
- break;
-
- eaddr = addr + size;
- for(; sym != nil; sym = sym->next) {
- if(sym->value >= eaddr)
- break;
- if(addr < sym->value) {
- Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(pre-pad)", addr);
- addr = sym->value;
- }
- Bprint(&bso, "%-20s %.8ux|", sym->name, (uint)addr);
- p = sym->p;
- ep = p + sym->np;
- while(p < ep)
- Bprint(&bso, " %.2ux", *p++);
- addr += sym->np;
- for(; addr < sym->value+sym->size; addr++)
- Bprint(&bso, " %.2ux", 0);
- Bprint(&bso, "\n");
- }
-
- if(addr < eaddr)
- Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(post-pad)", (uint)addr);
- Bprint(&bso, "%-20s %.8ux|\n", "", (uint)eaddr);
-}
-
-void
-strnput(char *s, int n)
-{
- for(; *s && n > 0; s++) {
- cput(*s);
- n--;
- }
- while(n > 0) {
- cput(0);
- n--;
- }
-}
-
-vlong
-addstring(Sym *s, char *str)
-{
- int n;
- int32 r;
-
- if(s->type == 0)
- s->type = SDATA;
- s->reachable = 1;
- r = s->size;
- n = strlen(str)+1;
- if(strcmp(s->name, ".shstrtab") == 0)
- elfsetstring(str, r);
- symgrow(s, r+n);
- memmove(s->p+r, str, n);
- s->size += n;
- return r;
-}
-
-vlong
-adduintxx(Sym *s, uint64 v, int wid)
-{
- int32 i, r, fl;
- vlong o;
- uchar *cast;
-
- if(s->type == 0)
- s->type = SDATA;
- s->reachable = 1;
- r = s->size;
- s->size += wid;
- symgrow(s, s->size);
- assert(r+wid <= s->size);
- fl = v;
- cast = (uchar*)&fl;
- switch(wid) {
- case 1:
- s->p[r] = cast[inuxi1[0]];
- break;
- case 2:
- for(i=0; i<2; i++)
- s->p[r+i] = cast[inuxi2[i]];
- break;
- case 4:
- for(i=0; i<4; i++)
- s->p[r+i] = cast[inuxi4[i]];
- break;
- case 8:
- o = v;
- cast = (uchar*)&o;
- for(i=0; i<8; i++)
- s->p[r+i] = cast[inuxi8[i]];
- break;
- }
- return r;
-}
-
-vlong
-adduint8(Sym *s, uint8 v)
-{
- return adduintxx(s, v, 1);
-}
-
-vlong
-adduint16(Sym *s, uint16 v)
-{
- return adduintxx(s, v, 2);
-}
-
-vlong
-adduint32(Sym *s, uint32 v)
-{
- return adduintxx(s, v, 4);
-}
-
-vlong
-adduint64(Sym *s, uint64 v)
-{
- return adduintxx(s, v, 8);
-}
-
-vlong
-addaddrplus(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_ADDR;
- r->add = add;
- return i;
-}
-
-vlong
-addpcrelplus(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->add = add;
- r->type = D_PCREL;
- r->siz = 4;
- return i;
-}
-
-vlong
-addaddr(Sym *s, Sym *t)
-{
- return addaddrplus(s, t, 0);
-}
-
-vlong
-addsize(Sym *s, Sym *t)
-{
- 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_SIZE;
- return i;
-}
-
-void
-dodata(void)
-{
- int32 t, datsize;
- Section *sect;
- Sym *s, *last, **l;
-
- if(debug['v'])
- Bprint(&bso, "%5.2f dodata\n", cputime());
- Bflush(&bso);
-
- last = nil;
- datap = nil;
-
- for(s=allsym; s!=S; s=s->allsym) {
- if(!s->reachable || s->special)
- continue;
- if(STEXT < s->type && s->type < SXREF) {
- if(last == nil)
- datap = s;
- else
- last->next = s;
- s->next = nil;
- last = s;
- }
- }
-
- for(s = datap; s != nil; s = s->next) {
- if(s->np > 0 && s->type == SBSS)
- s->type = SDATA;
- if(s->np > s->size)
- diag("%s: initialize bounds (%lld < %d)",
- s->name, (vlong)s->size, s->np);
- }
-
- /*
- * now that we have the datap list, but before we start
- * to assign addresses, record all the necessary
- * dynamic relocations. these will grow the relocation
- * symbol, which is itself data.
- */
- dynreloc();
-
- /* some symbols may no longer belong in datap (Mach-O) */
- for(l=&datap; (s=*l) != nil; ) {
- if(s->type <= STEXT || SXREF <= s->type)
- *l = s->next;
- else
- l = &s->next;
- }
- *l = nil;
-
- datap = datsort(datap);
-
- /*
- * allocate data sections. list is sorted by type,
- * so we can just walk it for each piece we want to emit.
- */
-
- /* read-only data */
- sect = addsection(&segtext, ".rodata", 04);
- sect->vaddr = 0;
- datsize = 0;
- s = datap;
- for(; s != nil && s->type < SSYMTAB; s = s->next) {
- s->type = SRODATA;
- t = rnd(s->size, PtrSize);
- s->value = datsize;
- datsize += t;
- }
- sect->len = datsize - sect->vaddr;
-
- /* gosymtab */
- sect = addsection(&segtext, ".gosymtab", 04);
- sect->vaddr = datsize;
- for(; s != nil && s->type < SPCLNTAB; s = s->next) {
- s->type = SRODATA;
- s->value = datsize;
- datsize += s->size;
- }
- sect->len = datsize - sect->vaddr;
-
- /* gopclntab */
- sect = addsection(&segtext, ".gopclntab", 04);
- sect->vaddr = datsize;
- for(; s != nil && s->type < SDATA; s = s->next) {
- s->type = SRODATA;
- s->value = datsize;
- datsize += s->size;
- }
- sect->len = datsize - sect->vaddr;
-
- /* data */
- datsize = 0;
- sect = addsection(&segdata, ".data", 06);
- sect->vaddr = 0;
- for(; s != nil && s->type < SBSS; s = s->next) {
- s->type = SDATA;
- t = s->size;
- if(t == 0 && s->name[0] != '.') {
- diag("%s: no size", s->name);
- t = 1;
- }
- if(t >= PtrSize)
- t = rnd(t, PtrSize);
- else if(t > 2)
- t = rnd(t, 4);
- if(t & 1) {
- ;
- } else if(t & 2)
- datsize = rnd(datsize, 2);
- else if(t & 4)
- datsize = rnd(datsize, 4);
- else
- datsize = rnd(datsize, 8);
- s->value = datsize;
- datsize += t;
- }
- sect->len = datsize - sect->vaddr;
-
- /* bss */
- sect = addsection(&segdata, ".bss", 06);
- sect->vaddr = datsize;
- for(; s != nil; s = s->next) {
- if(s->type != SBSS) {
- cursym = s;
- diag("unexpected symbol type %d", s->type);
- }
- t = s->size;
- if(t >= PtrSize)
- t = rnd(t, PtrSize);
- else if(t > 2)
- t = rnd(t, 4);
- if(t & 1) {
- ;
- } else if(t & 2)
- datsize = rnd(datsize, 2);
- else if(t & 4)
- datsize = rnd(datsize, 4);
- else
- datsize = rnd(datsize, 8);
- s->value = datsize;
- datsize += t;
- }
- sect->len = datsize - sect->vaddr;
-}
-
-// assign addresses to text
-void
-textaddress(void)
-{
- uvlong va;
- Prog *p;
- Section *sect;
- Sym *sym, *sub;
-
- addsection(&segtext, ".text", 05);
-
- // Assign PCs in text segment.
- // Could parallelize, by assigning to text
- // and then letting threads copy down, but probably not worth it.
- sect = segtext.sect;
- va = INITTEXT;
- sect->vaddr = va;
- for(sym = textp; sym != nil; sym = sym->next) {
- if(sym->type & SSUB)
- continue;
- sym->value = 0;
- for(sub = sym; sub != S; sub = sub->sub) {
- sub->value += va;
- for(p = sub->text; p != P; p = p->link)
- p->pc += sub->value;
- }
- if(sym->size == 0 && sym->sub != S) {
- cursym = sym;
- }
- va += sym->size;
- }
- sect->len = va - sect->vaddr;
-}
-
-// assign addresses
-void
-address(void)
-{
- Section *s, *text, *data, *rodata, *symtab, *pclntab;
- Sym *sym, *sub;
- uvlong va;
-
- va = INITTEXT;
- segtext.rwx = 05;
- segtext.vaddr = va;
- 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);
- }
- segtext.filelen = segtext.len;
-
- segdata.rwx = 06;
- segdata.vaddr = va;
- segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
- if(HEADTYPE == Hwindows)
- segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
- if(HEADTYPE == Hplan9x32)
- segdata.fileoff = segtext.fileoff + segtext.filelen;
- for(s=segdata.sect; s != nil; s=s->next) {
- s->vaddr = va;
- va += s->len;
- segdata.len = va - segdata.vaddr;
- }
- segdata.filelen = segdata.sect->len; // assume .data is first
-
- 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;
- for(sub = sym->sub; sub != nil; sub = sub->sub)
- sub->value += sym->value;
- }
-
- xdefine("text", STEXT, text->vaddr);
- xdefine("etext", STEXT, text->vaddr + text->len);
- xdefine("rodata", SRODATA, rodata->vaddr);
- xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
- xdefine("symtab", SRODATA, symtab->vaddr);
- xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
- xdefine("pclntab", SRODATA, pclntab->vaddr);
- xdefine("epclntab", SRODATA, pclntab->vaddr + pclntab->len);
- xdefine("data", SBSS, data->vaddr);
- xdefine("edata", SBSS, data->vaddr + data->len);
- xdefine("end", SBSS, segdata.vaddr + segdata.len);
-}
diff --git a/src/cmd/ld/doc.go b/src/cmd/ld/doc.go
deleted file mode 100644
index 972e2a32c..000000000
--- a/src/cmd/ld/doc.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-
-This directory contains the portable section of the Plan 9 C linkers.
-See ../6l, ../8l, and ../5l for more information.
-
-*/
-package documentation
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
deleted file mode 100644
index 1c10dc796..000000000
--- a/src/cmd/ld/dwarf.c
+++ /dev/null
@@ -1,2598 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// TODO/NICETOHAVE:
-// - eliminate DW_CLS_ if not used
-// - package info in compilation units
-// - assign global variables and types to their packages
-// - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg
-// ptype struct '[]uint8' and qualifiers need to be quoted away
-// - lexical scoping is lost, so gdb gets confused as to which 'main.i' you mean.
-// - file:line info for variables
-// - make strings a typedef so prettyprinters can see the underlying string type
-//
-#include "l.h"
-#include "lib.h"
-#include "../ld/dwarf.h"
-#include "../ld/dwarf_defs.h"
-#include "../ld/elf.h"
-#include "../ld/macho.h"
-#include "../ld/pe.h"
-
-/*
- * Offsets and sizes of the debug_* sections in the cout file.
- */
-
-static vlong abbrevo;
-static vlong abbrevsize;
-static vlong lineo;
-static vlong linesize;
-static vlong infoo; // also the base for DWDie->offs and reference attributes.
-static vlong infosize;
-static vlong frameo;
-static vlong framesize;
-static vlong pubnameso;
-static vlong pubnamessize;
-static vlong pubtypeso;
-static vlong pubtypessize;
-static vlong arangeso;
-static vlong arangessize;
-static vlong gdbscripto;
-static vlong gdbscriptsize;
-
-static char gdbscript[1024];
-
-/*
- * Basic I/O
- */
-
-static void
-addrput(vlong addr)
-{
- switch(PtrSize) {
- case 4:
- LPUT(addr);
- break;
- case 8:
- VPUT(addr);
- break;
- }
-}
-
-static int
-uleb128enc(uvlong v, char* dst)
-{
- uint8 c, len;
-
- len = 0;
- do {
- c = v & 0x7f;
- v >>= 7;
- if (v)
- c |= 0x80;
- if (dst)
- *dst++ = c;
- len++;
- } while (c & 0x80);
- return len;
-};
-
-static int
-sleb128enc(vlong v, char *dst)
-{
- uint8 c, s, len;
-
- len = 0;
- do {
- c = v & 0x7f;
- s = v & 0x40;
- v >>= 7;
- if ((v != -1 || !s) && (v != 0 || s))
- c |= 0x80;
- if (dst)
- *dst++ = c;
- len++;
- } while(c & 0x80);
- return len;
-}
-
-static void
-uleb128put(vlong v)
-{
- char buf[10];
- strnput(buf, uleb128enc(v, buf));
-}
-
-static void
-sleb128put(vlong v)
-{
- char buf[10];
- strnput(buf, sleb128enc(v, buf));
-}
-
-/*
- * Defining Abbrevs. This is hardcoded, and there will be
- * only a handful of them. The DWARF spec places no restriction on
- * the ordering of atributes in the Abbrevs and DIEs, and we will
- * always write them out in the order of declaration in the abbrev.
- * This implementation relies on tag, attr < 127, so they serialize as
- * a char. Higher numbered user-defined tags or attributes can be used
- * for storing internal data but won't be serialized.
- */
-typedef struct DWAttrForm DWAttrForm;
-struct DWAttrForm {
- uint8 attr;
- uint8 form;
-};
-
-// Index into the abbrevs table below.
-// Keep in sync with ispubname() and ispubtype() below.
-// ispubtype considers >= NULLTYPE public
-enum
-{
- DW_ABRV_NULL,
- DW_ABRV_COMPUNIT,
- DW_ABRV_FUNCTION,
- DW_ABRV_VARIABLE,
- DW_ABRV_AUTO,
- DW_ABRV_PARAM,
- DW_ABRV_STRUCTFIELD,
- DW_ABRV_FUNCTYPEPARAM,
- DW_ABRV_DOTDOTDOT,
- DW_ABRV_ARRAYRANGE,
- DW_ABRV_NULLTYPE,
- DW_ABRV_BASETYPE,
- DW_ABRV_ARRAYTYPE,
- DW_ABRV_CHANTYPE,
- DW_ABRV_FUNCTYPE,
- DW_ABRV_IFACETYPE,
- DW_ABRV_MAPTYPE,
- DW_ABRV_PTRTYPE,
- DW_ABRV_SLICETYPE,
- DW_ABRV_STRINGTYPE,
- DW_ABRV_STRUCTTYPE,
- DW_ABRV_TYPEDECL,
- DW_NABRV
-};
-
-typedef struct DWAbbrev DWAbbrev;
-static struct DWAbbrev {
- uint8 tag;
- uint8 children;
- DWAttrForm attr[30];
-} abbrevs[DW_NABRV] = {
- /* The mandatory DW_ABRV_NULL entry. */
- { 0 },
- /* COMPUNIT */
- {
- DW_TAG_compile_unit, DW_CHILDREN_yes,
- DW_AT_name, DW_FORM_string,
- DW_AT_language, DW_FORM_data1,
- DW_AT_low_pc, DW_FORM_addr,
- DW_AT_high_pc, DW_FORM_addr,
- DW_AT_stmt_list, DW_FORM_data4,
- 0, 0
- },
- /* FUNCTION */
- {
- DW_TAG_subprogram, DW_CHILDREN_yes,
- DW_AT_name, DW_FORM_string,
- DW_AT_low_pc, DW_FORM_addr,
- DW_AT_high_pc, DW_FORM_addr,
- DW_AT_external, DW_FORM_flag,
- 0, 0
- },
- /* VARIABLE */
- {
- DW_TAG_variable, DW_CHILDREN_no,
- DW_AT_name, DW_FORM_string,
- DW_AT_location, DW_FORM_block1,
- DW_AT_type, DW_FORM_ref_addr,
- DW_AT_external, DW_FORM_flag,
- 0, 0
- },
- /* AUTO */
- {
- DW_TAG_variable, DW_CHILDREN_no,
- DW_AT_name, DW_FORM_string,
- DW_AT_location, DW_FORM_block1,
- DW_AT_type, DW_FORM_ref_addr,
- 0, 0
- },
- /* PARAM */
- {
- DW_TAG_formal_parameter, DW_CHILDREN_no,
- DW_AT_name, DW_FORM_string,
- DW_AT_location, DW_FORM_block1,
- DW_AT_type, DW_FORM_ref_addr,
- 0, 0
- },
- /* STRUCTFIELD */
- {
- DW_TAG_member, DW_CHILDREN_no,
- DW_AT_name, DW_FORM_string,
- DW_AT_data_member_location, DW_FORM_block1,
- DW_AT_type, DW_FORM_ref_addr,
- 0, 0
- },
- /* FUNCTYPEPARAM */
- {
- DW_TAG_formal_parameter, DW_CHILDREN_no,
- // No name!
- DW_AT_type, DW_FORM_ref_addr,
- 0, 0
- },
-
- /* DOTDOTDOT */
- {
- DW_TAG_unspecified_parameters, DW_CHILDREN_no,
- 0, 0
- },
- /* ARRAYRANGE */
- {
- DW_TAG_subrange_type, DW_CHILDREN_no,
- // No name!
- DW_AT_type, DW_FORM_ref_addr,
- DW_AT_upper_bound, DW_FORM_data1,
- 0, 0
- },
-
- // Below here are the types considered public by ispubtype
- /* NULLTYPE */
- {
- DW_TAG_unspecified_type, DW_CHILDREN_no,
- DW_AT_name, DW_FORM_string,
- 0, 0
- },
- /* BASETYPE */
- {
- DW_TAG_base_type, DW_CHILDREN_no,
- DW_AT_name, DW_FORM_string,
- DW_AT_encoding, DW_FORM_data1,
- DW_AT_byte_size, DW_FORM_data1,
- 0, 0
- },
- /* ARRAYTYPE */
- // child is subrange with upper bound
- {
- DW_TAG_array_type, DW_CHILDREN_yes,
- DW_AT_name, DW_FORM_string,
- DW_AT_type, DW_FORM_ref_addr,
- DW_AT_byte_size, DW_FORM_udata,
- 0, 0
- },
-
- /* CHANTYPE */
- {
- DW_TAG_typedef, DW_CHILDREN_no,
- DW_AT_name, DW_FORM_string,
- DW_AT_type, DW_FORM_ref_addr,
- 0, 0
- },
-
- /* FUNCTYPE */
- {
- DW_TAG_subroutine_type, DW_CHILDREN_yes,
- DW_AT_name, DW_FORM_string,
-// DW_AT_type, DW_FORM_ref_addr,
- 0, 0
- },
-
- /* IFACETYPE */
- {
- DW_TAG_typedef, DW_CHILDREN_yes,
- DW_AT_name, DW_FORM_string,
- DW_AT_type, DW_FORM_ref_addr,
- 0, 0
- },
-
- /* MAPTYPE */
- {
- DW_TAG_typedef, DW_CHILDREN_no,
- DW_AT_name, DW_FORM_string,
- DW_AT_type, DW_FORM_ref_addr,
- 0, 0
- },
-
- /* PTRTYPE */
- {
- DW_TAG_pointer_type, DW_CHILDREN_no,
- DW_AT_name, DW_FORM_string,
- DW_AT_type, DW_FORM_ref_addr,
- 0, 0
- },
-
- /* SLICETYPE */
- {
- DW_TAG_structure_type, DW_CHILDREN_yes,
- DW_AT_name, DW_FORM_string,
- DW_AT_byte_size, DW_FORM_udata,
- 0, 0
- },
-
- /* STRINGTYPE */
- {
- DW_TAG_structure_type, DW_CHILDREN_yes,
- DW_AT_name, DW_FORM_string,
- DW_AT_byte_size, DW_FORM_udata,
- 0, 0
- },
-
- /* STRUCTTYPE */
- {
- DW_TAG_structure_type, DW_CHILDREN_yes,
- DW_AT_name, DW_FORM_string,
- DW_AT_byte_size, DW_FORM_udata,
- 0, 0
- },
-
- /* TYPEDECL */
- {
- DW_TAG_typedef, DW_CHILDREN_no,
- DW_AT_name, DW_FORM_string,
- DW_AT_type, DW_FORM_ref_addr,
- 0, 0
- },
-};
-
-static void
-writeabbrev(void)
-{
- int i, n;
-
- abbrevo = cpos();
- for (i = 1; i < DW_NABRV; i++) {
- // See section 7.5.3
- uleb128put(i);
- uleb128put(abbrevs[i].tag);
- cput(abbrevs[i].children);
- // 0 is not a valid attr or form, and DWAbbrev.attr is
- // 0-terminated, so we can treat it as a string
- n = strlen((char*)abbrevs[i].attr) / 2;
- strnput((char*)abbrevs[i].attr,
- (n+1) * sizeof(DWAttrForm));
- }
- cput(0);
- abbrevsize = cpos() - abbrevo;
-}
-
-/*
- * Debugging Information Entries and their attributes.
- */
-
-enum
-{
- HASHSIZE = 107
-};
-
-static uint32
-hashstr(char* s)
-{
- uint32 h;
-
- h = 0;
- while (*s)
- h = h+h+h + *s++;
- return h % HASHSIZE;
-}
-
-// For DW_CLS_string and _block, value should contain the length, and
-// data the data, for _reference, value is 0 and data is a DWDie* to
-// the referenced instance, for all others, value is the whole thing
-// and data is null.
-
-typedef struct DWAttr DWAttr;
-struct DWAttr {
- DWAttr *link;
- uint8 atr; // DW_AT_
- uint8 cls; // DW_CLS_
- vlong value;
- char *data;
-};
-
-typedef struct DWDie DWDie;
-struct DWDie {
- int abbrev;
- DWDie *link;
- DWDie *child;
- DWAttr *attr;
- // offset into .debug_info section, i.e relative to
- // infoo. only valid after call to putdie()
- vlong offs;
- DWDie **hash; // optional index of children by name, enabled by mkindex()
- DWDie *hlink; // bucket chain in parent's index
-};
-
-/*
- * Root DIEs for compilation units, types and global variables.
- */
-
-static DWDie dwroot;
-static DWDie dwtypes;
-static DWDie dwglobals;
-
-static DWAttr*
-newattr(DWDie *die, uint8 attr, int cls, vlong value, char *data)
-{
- DWAttr *a;
-
- a = mal(sizeof *a);
- a->link = die->attr;
- die->attr = a;
- a->atr = attr;
- a->cls = cls;
- a->value = value;
- a->data = data;
- return a;
-}
-
-// Each DIE (except the root ones) has at least 1 attribute: its
-// name. getattr moves the desired one to the front so
-// frequently searched ones are found faster.
-static DWAttr*
-getattr(DWDie *die, uint8 attr)
-{
- DWAttr *a, *b;
-
- if (die->attr->atr == attr)
- return die->attr;
-
- a = die->attr;
- b = a->link;
- while (b != nil) {
- if (b->atr == attr) {
- a->link = b->link;
- b->link = die->attr;
- die->attr = b;
- return b;
- }
- a = b;
- b = b->link;
- }
- return nil;
-}
-
-// Every DIE has at least a DW_AT_name attribute (but it will only be
-// written out if it is listed in the abbrev). If its parent is
-// keeping an index, the new DIE will be inserted there.
-static DWDie*
-newdie(DWDie *parent, int abbrev, char *name)
-{
- DWDie *die;
- int h;
-
- die = mal(sizeof *die);
- die->abbrev = abbrev;
- die->link = parent->child;
- parent->child = die;
-
- newattr(die, DW_AT_name, DW_CLS_STRING, strlen(name), name);
-
- if (parent->hash) {
- h = hashstr(name);
- die->hlink = parent->hash[h];
- parent->hash[h] = die;
- }
-
- return die;
-}
-
-static void
-mkindex(DWDie *die)
-{
- die->hash = mal(HASHSIZE * sizeof(DWDie*));
-}
-
-// Find child by AT_name using hashtable if available or linear scan
-// if not.
-static DWDie*
-find(DWDie *die, char* name)
-{
- DWDie *a, *b;
- int h;
-
- if (die->hash == nil) {
- for (a = die->child; a != nil; a = a->link)
- if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
- return a;
- return nil;
- }
-
- h = hashstr(name);
- a = die->hash[h];
-
- if (a == nil)
- return nil;
-
-
- if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
- return a;
-
- // Move found ones to head of the list.
- b = a->hlink;
- while (b != nil) {
- if (strcmp(name, getattr(b, DW_AT_name)->data) == 0) {
- a->hlink = b->hlink;
- b->hlink = die->hash[h];
- die->hash[h] = b;
- return b;
- }
- a = b;
- b = b->hlink;
- }
- return nil;
-}
-
-static DWDie*
-find_or_diag(DWDie *die, char* name)
-{
- DWDie *r;
- r = find(die, name);
- if (r == nil) {
- diag("dwarf find: %s has no %s", getattr(die, DW_AT_name)->data, name);
- errorexit();
- }
- return r;
-}
-
-static DWAttr*
-newrefattr(DWDie *die, uint8 attr, DWDie* ref)
-{
- if (ref == nil)
- return nil;
- return newattr(die, attr, DW_CLS_REFERENCE, 0, (char*)ref);
-}
-
-static int fwdcount;
-
-static void
-putattr(int form, int cls, vlong value, char *data)
-{
- switch(form) {
- case DW_FORM_addr: // address
- addrput(value);
- break;
-
- case DW_FORM_block1: // block
- value &= 0xff;
- cput(value);
- while(value--)
- cput(*data++);
- break;
-
- case DW_FORM_block2: // block
- value &= 0xffff;
- WPUT(value);
- while(value--)
- cput(*data++);
- break;
-
- case DW_FORM_block4: // block
- value &= 0xffffffff;
- LPUT(value);
- while(value--)
- cput(*data++);
- break;
-
- case DW_FORM_block: // block
- uleb128put(value);
- while(value--)
- cput(*data++);
- break;
-
- case DW_FORM_data1: // constant
- cput(value);
- break;
-
- case DW_FORM_data2: // constant
- WPUT(value);
- break;
-
- case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
- LPUT(value);
- break;
-
- case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
- VPUT(value);
- break;
-
- case DW_FORM_sdata: // constant
- sleb128put(value);
- break;
-
- case DW_FORM_udata: // constant
- uleb128put(value);
- break;
-
- case DW_FORM_string: // string
- strnput(data, value+1);
- break;
-
- case DW_FORM_flag: // flag
- cput(value?1:0);
- break;
-
- case DW_FORM_ref_addr: // reference to a DIE in the .info section
- if (data == nil) {
- diag("dwarf: null reference");
- LPUT(0); // invalid dwarf, gdb will complain.
- } else {
- if (((DWDie*)data)->offs == 0)
- fwdcount++;
- LPUT(((DWDie*)data)->offs);
- }
- break;
-
- case DW_FORM_ref1: // reference within the compilation unit
- case DW_FORM_ref2: // reference
- case DW_FORM_ref4: // reference
- case DW_FORM_ref8: // reference
- case DW_FORM_ref_udata: // reference
-
- case DW_FORM_strp: // string
- case DW_FORM_indirect: // (see Section 7.5.3)
- default:
- diag("dwarf: unsupported attribute form %d / class %d", form, cls);
- errorexit();
- }
-}
-
-// Note that we can (and do) add arbitrary attributes to a DIE, but
-// only the ones actually listed in the Abbrev will be written out.
-static void
-putattrs(int abbrev, DWAttr* attr)
-{
- DWAttr *attrs[DW_AT_recursive + 1];
- DWAttrForm* af;
-
- memset(attrs, 0, sizeof attrs);
- for( ; attr; attr = attr->link)
- if (attr->atr < nelem(attrs))
- attrs[attr->atr] = attr;
-
- for(af = abbrevs[abbrev].attr; af->attr; af++)
- if (attrs[af->attr])
- putattr(af->form,
- attrs[af->attr]->cls,
- attrs[af->attr]->value,
- attrs[af->attr]->data);
- else
- putattr(af->form, 0, 0, 0);
-}
-
-static void putdie(DWDie* die);
-
-static void
-putdies(DWDie* die)
-{
- for(; die; die = die->link)
- putdie(die);
-}
-
-static void
-putdie(DWDie* die)
-{
- die->offs = cpos() - infoo;
- uleb128put(die->abbrev);
- putattrs(die->abbrev, die->attr);
- if (abbrevs[die->abbrev].children) {
- putdies(die->child);
- cput(0);
- }
-}
-
-static void
-reverselist(DWDie** list)
-{
- DWDie *curr, *prev;
-
- curr = *list;
- prev = nil;
- while(curr != nil) {
- DWDie* next = curr->link;
- curr->link = prev;
- prev = curr;
- curr = next;
- }
- *list = prev;
-}
-
-static void
-reversetree(DWDie** list)
-{
- DWDie *die;
-
- reverselist(list);
- for (die = *list; die != nil; die = die->link)
- if (abbrevs[die->abbrev].children)
- reversetree(&die->child);
-}
-
-static void
-newmemberoffsetattr(DWDie *die, int32 offs)
-{
- char block[10];
- int i;
-
- i = 0;
- if (offs != 0) {
- block[i++] = DW_OP_consts;
- i += sleb128enc(offs, block+i);
- block[i++] = DW_OP_plus;
- }
- newattr(die, DW_AT_data_member_location, DW_CLS_BLOCK, i, mal(i));
- memmove(die->attr->data, block, i);
-}
-
-// GDB doesn't like DW_FORM_addr for DW_AT_location, so emit a
-// location expression that evals to a const.
-static void
-newabslocexprattr(DWDie *die, vlong addr)
-{
- char block[10];
- int i;
-
- i = 0;
- block[i++] = DW_OP_constu;
- i += uleb128enc(addr, block+i);
- newattr(die, DW_AT_location, DW_CLS_BLOCK, i, mal(i));
- memmove(die->attr->data, block, i);
-}
-
-// Decoding the type.* symbols. This has to be in sync with
-// ../../pkg/runtime/type.go, or more specificaly, with what
-// ../gc/reflect.c stuffs in these.
-
-enum {
- KindBool = 1,
- KindInt,
- KindInt8,
- KindInt16,
- KindInt32,
- KindInt64,
- KindUint,
- KindUint8,
- KindUint16,
- KindUint32,
- KindUint64,
- KindUintptr,
- KindFloat32,
- KindFloat64,
- KindComplex64,
- KindComplex128,
- KindArray,
- KindChan,
- KindFunc,
- KindInterface,
- KindMap,
- KindPtr,
- KindSlice,
- KindString,
- KindStruct,
- KindUnsafePointer,
-
- KindNoPointers = 1<<7,
-
- // size of Type interface header + CommonType structure.
- CommonSize = 2*PtrSize+ 4*PtrSize + 8,
-};
-
-static Reloc*
-decode_reloc(Sym *s, int32 off)
-{
- int i;
-
- for (i = 0; i < s->nr; i++)
- if (s->r[i].off == off)
- return s->r + i;
- return nil;
-}
-
-static Sym*
-decode_reloc_sym(Sym *s, int32 off)
-{
- Reloc *r;
-
- r = decode_reloc(s,off);
- if (r == nil)
- return nil;
- return r->sym;
-}
-
-static uvlong
-decode_inuxi(uchar* p, int sz)
-{
- uint64 v;
- uint32 l;
- uchar *cast, *inuxi;
- int i;
-
- v = l = 0;
- cast = nil;
- inuxi = nil;
- switch (sz) {
- case 2:
- cast = (uchar*)&l;
- inuxi = inuxi2;
- break;
- case 4:
- cast = (uchar*)&l;
- inuxi = inuxi4;
- break;
- case 8:
- cast = (uchar*)&v;
- inuxi = inuxi8;
- break;
- default:
- diag("dwarf: decode inuxi %d", sz);
- errorexit();
- }
- for (i = 0; i < sz; i++)
- cast[inuxi[i]] = p[i];
- if (sz == 8)
- return v;
- return l;
-}
-
-// Type.commonType.kind
-static uint8
-decodetype_kind(Sym *s)
-{
- return s->p[3*PtrSize + 7] & ~KindNoPointers; // 0x13 / 0x1f
-}
-
-// Type.commonType.size
-static vlong
-decodetype_size(Sym *s)
-{
- return decode_inuxi(s->p + 2*PtrSize, PtrSize); // 0x8 / 0x10
-}
-
-// Type.ArrayType.elem and Type.SliceType.Elem
-static Sym*
-decodetype_arrayelem(Sym *s)
-{
- return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
-}
-
-static vlong
-decodetype_arraylen(Sym *s)
-{
- return decode_inuxi(s->p + CommonSize+PtrSize, PtrSize);
-}
-
-// Type.PtrType.elem
-static Sym*
-decodetype_ptrelem(Sym *s)
-{
- return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
-}
-
-// Type.MapType.key, elem
-static Sym*
-decodetype_mapkey(Sym *s)
-{
- return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
-}
-static Sym*
-decodetype_mapvalue(Sym *s)
-{
- return decode_reloc_sym(s, CommonSize+PtrSize); // 0x20 / 0x38
-}
-
-// Type.ChanType.elem
-static Sym*
-decodetype_chanelem(Sym *s)
-{
- return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
-}
-
-// Type.FuncType.dotdotdot
-static int
-decodetype_funcdotdotdot(Sym *s)
-{
- return s->p[CommonSize];
-}
-
-// Type.FuncType.in.len
-static int
-decodetype_funcincount(Sym *s)
-{
- return decode_inuxi(s->p + CommonSize+2*PtrSize, 4);
-}
-
-static int
-decodetype_funcoutcount(Sym *s)
-{
- return decode_inuxi(s->p + CommonSize+3*PtrSize + 2*4, 4);
-}
-
-static Sym*
-decodetype_funcintype(Sym *s, int i)
-{
- Reloc *r;
-
- r = decode_reloc(s, CommonSize + PtrSize);
- if (r == nil)
- return nil;
- return decode_reloc_sym(r->sym, r->add + i * PtrSize);
-}
-
-static Sym*
-decodetype_funcouttype(Sym *s, int i)
-{
- Reloc *r;
-
- r = decode_reloc(s, CommonSize + 2*PtrSize + 2*4);
- if (r == nil)
- return nil;
- return decode_reloc_sym(r->sym, r->add + i * PtrSize);
-}
-
-// Type.StructType.fields.Slice::len
-static int
-decodetype_structfieldcount(Sym *s)
-{
- return decode_inuxi(s->p + CommonSize + PtrSize, 4);
-}
-
-enum {
- StructFieldSize = 5*PtrSize
-};
-// Type.StructType.fields[]-> name, typ and offset.
-static char*
-decodetype_structfieldname(Sym *s, int i)
-{
- Reloc *r;
-
- // go.string."foo" 0x28 / 0x40
- s = decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize);
- if (s == nil) // embedded structs have a nil name.
- return nil;
- r = decode_reloc(s, 0); // s has a pointer to the string data at offset 0
- if (r == nil) // shouldn't happen.
- return nil;
- return (char*) r->sym->p + r->add; // the c-string
-}
-
-static Sym*
-decodetype_structfieldtype(Sym *s, int i)
-{
- return decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize + 2*PtrSize);
-}
-
-static vlong
-decodetype_structfieldoffs(Sym *s, int i)
-{
- return decode_inuxi(s->p + CommonSize + PtrSize + 2*4 + i*StructFieldSize + 4*PtrSize, 4);
-}
-
-// InterfaceTYpe.methods.len
-static vlong
-decodetype_ifacemethodcount(Sym *s)
-{
- return decode_inuxi(s->p + CommonSize + PtrSize, 4);
-}
-
-
-// Fake attributes for slices, maps and channel
-enum {
- DW_AT_internal_elem_type = 250, // channels and slices
- DW_AT_internal_key_type = 251, // maps
- DW_AT_internal_val_type = 252, // maps
- DW_AT_internal_location = 253, // params and locals
-};
-
-static DWDie* defptrto(DWDie *dwtype); // below
-
-// Lookup predefined types
-static Sym*
-lookup_or_diag(char *n)
-{
- Sym *s;
-
- s = rlookup(n, 0);
- if (s == nil || s->size == 0) {
- diag("dwarf: missing type: %s", n);
- errorexit();
- }
- return s;
-}
-
-// Define gotype, for composite ones recurse into constituents.
-static DWDie*
-defgotype(Sym *gotype)
-{
- DWDie *die, *fld;
- Sym *s;
- char *name, *f;
- uint8 kind;
- vlong bytesize;
- int i, nfields;
-
- if (gotype == nil)
- return find_or_diag(&dwtypes, "<unspecified>");
-
- if (strncmp("type.", gotype->name, 5) != 0) {
- diag("dwarf: type name doesn't start with \".type\": %s", gotype->name);
- return find_or_diag(&dwtypes, "<unspecified>");
- }
- name = gotype->name + 5; // could also decode from Type.string
-
- die = find(&dwtypes, name);
- if (die != nil)
- return die;
-
- if (0 && debug['v'] > 2)
- print("new type: %Y\n", gotype);
-
- kind = decodetype_kind(gotype);
- bytesize = decodetype_size(gotype);
-
- switch (kind) {
- case KindBool:
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, name);
- newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_boolean, 0);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- break;
-
- case KindInt:
- case KindInt8:
- case KindInt16:
- case KindInt32:
- case KindInt64:
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, name);
- newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_signed, 0);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- break;
-
- case KindUint:
- case KindUint8:
- case KindUint16:
- case KindUint32:
- case KindUint64:
- case KindUintptr:
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, name);
- newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- break;
-
- case KindFloat32:
- case KindFloat64:
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, name);
- newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_float, 0);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- break;
-
- case KindComplex64:
- case KindComplex128:
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, name);
- newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_complex_float, 0);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- break;
-
- case KindArray:
- die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- s = decodetype_arrayelem(gotype);
- newrefattr(die, DW_AT_type, defgotype(s));
- fld = newdie(die, DW_ABRV_ARRAYRANGE, "range");
- newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, decodetype_arraylen(gotype), 0);
- newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
- break;
-
- case KindChan:
- die = newdie(&dwtypes, DW_ABRV_CHANTYPE, name);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- s = decodetype_chanelem(gotype);
- newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
- break;
-
- case KindFunc:
- die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name);
- newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "void"));
- nfields = decodetype_funcincount(gotype);
- for (i = 0; i < nfields; i++) {
- s = decodetype_funcintype(gotype, i);
- fld = newdie(die, DW_ABRV_FUNCTYPEPARAM, s->name+5);
- newrefattr(fld, DW_AT_type, defgotype(s));
- }
- if (decodetype_funcdotdotdot(gotype))
- newdie(die, DW_ABRV_DOTDOTDOT, "...");
- nfields = decodetype_funcoutcount(gotype);
- for (i = 0; i < nfields; i++) {
- s = decodetype_funcouttype(gotype, i);
- fld = newdie(die, DW_ABRV_FUNCTYPEPARAM, s->name+5);
- newrefattr(fld, DW_AT_type, defptrto(defgotype(s)));
- }
- break;
-
- case KindInterface:
- die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- nfields = decodetype_ifacemethodcount(gotype);
- if (nfields == 0)
- s = lookup_or_diag("type.runtime.eface");
- else
- s = lookup_or_diag("type.runtime.iface");
- newrefattr(die, DW_AT_type, defgotype(s));
- break;
-
- case KindMap:
- die = newdie(&dwtypes, DW_ABRV_MAPTYPE, name);
- s = decodetype_mapkey(gotype);
- newrefattr(die, DW_AT_internal_key_type, defgotype(s));
- s = decodetype_mapvalue(gotype);
- newrefattr(die, DW_AT_internal_val_type, defgotype(s));
- break;
-
- case KindPtr:
- die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name);
- s = decodetype_ptrelem(gotype);
- newrefattr(die, DW_AT_type, defgotype(s));
- break;
-
- case KindSlice:
- die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- s = decodetype_arrayelem(gotype);
- newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
- break;
-
- case KindString:
- die = newdie(&dwtypes, DW_ABRV_STRINGTYPE, name);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- break;
-
- case KindStruct:
- die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
- nfields = decodetype_structfieldcount(gotype);
- for (i = 0; i < nfields; i++) {
- f = decodetype_structfieldname(gotype, i);
- s = decodetype_structfieldtype(gotype, i);
- if (f == nil)
- f = s->name + 5; // skip "type."
- fld = newdie(die, DW_ABRV_STRUCTFIELD, f);
- newrefattr(fld, DW_AT_type, defgotype(s));
- newmemberoffsetattr(fld, decodetype_structfieldoffs(gotype, i));
- }
- break;
-
- case KindUnsafePointer:
- die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name);
- newrefattr(die, DW_AT_type, find(&dwtypes, "void"));
- break;
-
- default:
- diag("dwarf: definition of unknown kind %d: %s", kind, gotype->name);
- die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name);
- newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "<unspecified>"));
- }
-
- return die;
-}
-
-// Find or construct *T given T.
-static DWDie*
-defptrto(DWDie *dwtype)
-{
- char ptrname[1024];
- DWDie *die;
-
- snprint(ptrname, sizeof ptrname, "*%s", getattr(dwtype, DW_AT_name)->data);
- die = find(&dwtypes, ptrname);
- if (die == nil) {
- die = newdie(&dwtypes, DW_ABRV_PTRTYPE,
- strcpy(mal(strlen(ptrname)+1), ptrname));
- newrefattr(die, DW_AT_type, dwtype);
- }
- return die;
-}
-
-// Copies src's children into dst. Copies attributes by value.
-// DWAttr.data is copied as pointer only.
-static void
-copychildren(DWDie *dst, DWDie *src)
-{
- DWDie *c;
- DWAttr *a;
-
- for (src = src->child; src != nil; src = src->link) {
- c = newdie(dst, src->abbrev, getattr(src, DW_AT_name)->data);
- for (a = src->attr; a != nil; a = a->link)
- newattr(c, a->atr, a->cls, a->value, a->data);
- copychildren(c, src);
- }
- reverselist(&dst->child);
-}
-
-// Search children (assumed to have DW_TAG_member) for the one named
-// field and set it's DW_AT_type to dwtype
-static void
-substitutetype(DWDie *structdie, char *field, DWDie* dwtype)
-{
- DWDie *child;
- DWAttr *a;
-
- child = find_or_diag(structdie, field);
- if (child == nil)
- return;
-
- a = getattr(child, DW_AT_type);
- if (a != nil)
- a->data = (char*) dwtype;
- else
- newrefattr(child, DW_AT_type, dwtype);
-}
-
-static void
-synthesizestringtypes(DWDie* die)
-{
- DWDie *prototype;
-
- prototype = defgotype(lookup_or_diag("type.runtime._string"));
- if (prototype == nil)
- return;
-
- for (; die != nil; die = die->link) {
- if (die->abbrev != DW_ABRV_STRINGTYPE)
- continue;
- copychildren(die, prototype);
- }
-}
-
-static void
-synthesizeslicetypes(DWDie *die)
-{
- DWDie *prototype, *elem;
-
- prototype = defgotype(lookup_or_diag("type.runtime.slice"));
- if (prototype == nil)
- return;
-
- for (; die != nil; die = die->link) {
- if (die->abbrev != DW_ABRV_SLICETYPE)
- continue;
- copychildren(die, prototype);
- elem = (DWDie*) getattr(die, DW_AT_internal_elem_type)->data;
- substitutetype(die, "array", defptrto(elem));
- }
-}
-
-static char*
-mkinternaltypename(char *base, char *arg1, char *arg2)
-{
- char buf[1024];
- char *n;
-
- if (arg2 == nil)
- snprint(buf, sizeof buf, "%s<%s>", base, arg1);
- else
- snprint(buf, sizeof buf, "%s<%s,%s>", base, arg1, arg2);
- n = mal(strlen(buf) + 1);
- memmove(n, buf, strlen(buf));
- return n;
-}
-
-
-// synthesizemaptypes is way too closely married to runtime/hashmap.c
-enum {
- MaxValsize = 256 - 64
-};
-
-static void
-synthesizemaptypes(DWDie *die)
-{
-
- DWDie *hash, *hash_subtable, *hash_entry,
- *dwh, *dwhs, *dwhe, *dwhash, *keytype, *valtype, *fld;
- int hashsize, keysize, valsize, datsize, valsize_in_hash, datavo;
- DWAttr *a;
-
- hash = defgotype(lookup_or_diag("type.runtime.hmap"));
- hash_subtable = defgotype(lookup_or_diag("type.runtime.hash_subtable"));
- hash_entry = defgotype(lookup_or_diag("type.runtime.hash_entry"));
-
- if (hash == nil || hash_subtable == nil || hash_entry == nil)
- return;
-
- dwhash = (DWDie*)getattr(find_or_diag(hash_entry, "hash"), DW_AT_type)->data;
- if (dwhash == nil)
- return;
-
- hashsize = getattr(dwhash, DW_AT_byte_size)->value;
-
- for (; die != nil; die = die->link) {
- if (die->abbrev != DW_ABRV_MAPTYPE)
- continue;
-
- keytype = (DWDie*) getattr(die, DW_AT_internal_key_type)->data;
- valtype = (DWDie*) getattr(die, DW_AT_internal_val_type)->data;
-
- a = getattr(keytype, DW_AT_byte_size);
- keysize = a ? a->value : PtrSize; // We don't store size with Pointers
-
- a = getattr(valtype, DW_AT_byte_size);
- valsize = a ? a->value : PtrSize;
-
- // This is what happens in hash_init and makemap_c
- valsize_in_hash = valsize;
- if (valsize > MaxValsize)
- valsize_in_hash = PtrSize;
- datavo = keysize;
- if (valsize_in_hash >= PtrSize)
- datavo = rnd(keysize, PtrSize);
- datsize = datavo + valsize_in_hash;
- if (datsize < PtrSize)
- datsize = PtrSize;
- datsize = rnd(datsize, PtrSize);
-
- // Construct struct hash_entry<K,V>
- dwhe = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("hash_entry",
- getattr(keytype, DW_AT_name)->data,
- getattr(valtype, DW_AT_name)->data));
-
- fld = newdie(dwhe, DW_ABRV_STRUCTFIELD, "hash");
- newrefattr(fld, DW_AT_type, dwhash);
- newmemberoffsetattr(fld, 0);
-
- fld = newdie(dwhe, DW_ABRV_STRUCTFIELD, "key");
- newrefattr(fld, DW_AT_type, keytype);
- newmemberoffsetattr(fld, hashsize);
-
- fld = newdie(dwhe, DW_ABRV_STRUCTFIELD, "val");
- if (valsize > MaxValsize)
- valtype = defptrto(valtype);
- newrefattr(fld, DW_AT_type, valtype);
- newmemberoffsetattr(fld, hashsize + datavo);
- newattr(dwhe, DW_AT_byte_size, DW_CLS_CONSTANT, hashsize + datsize, nil);
-
- // Construct hash_subtable<hash_entry<K,V>>
- dwhs = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("hash_subtable",
- getattr(keytype, DW_AT_name)->data,
- getattr(valtype, DW_AT_name)->data));
- copychildren(dwhs, hash_subtable);
- substitutetype(dwhs, "end", defptrto(dwhe));
- substitutetype(dwhs, "entry", dwhe); // todo: []hash_entry with dynamic size
- newattr(dwhs, DW_AT_byte_size, DW_CLS_CONSTANT,
- getattr(hash_subtable, DW_AT_byte_size)->value, nil);
-
- // Construct hash<K,V>
- dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("hash",
- getattr(keytype, DW_AT_name)->data,
- getattr(valtype, DW_AT_name)->data));
- copychildren(dwh, hash);
- substitutetype(dwh, "st", defptrto(dwhs));
- newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
- getattr(hash, DW_AT_byte_size)->value, nil);
-
- newrefattr(die, DW_AT_type, defptrto(dwh));
- }
-}
-
-static void
-synthesizechantypes(DWDie *die)
-{
- DWDie *sudog, *waitq, *hchan,
- *dws, *dww, *dwh, *elemtype;
- DWAttr *a;
- int elemsize, sudogsize;
-
- sudog = defgotype(lookup_or_diag("type.runtime.sudog"));
- waitq = defgotype(lookup_or_diag("type.runtime.waitq"));
- hchan = defgotype(lookup_or_diag("type.runtime.hchan"));
- if (sudog == nil || waitq == nil || hchan == nil)
- return;
-
- sudogsize = getattr(sudog, DW_AT_byte_size)->value;
-
- for (; die != nil; die = die->link) {
- if (die->abbrev != DW_ABRV_CHANTYPE)
- continue;
- elemtype = (DWDie*) getattr(die, DW_AT_internal_elem_type)->data;
- a = getattr(elemtype, DW_AT_byte_size);
- elemsize = a ? a->value : PtrSize;
-
- // sudog<T>
- dws = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("sudog",
- getattr(elemtype, DW_AT_name)->data, nil));
- copychildren(dws, sudog);
- substitutetype(dws, "elem", elemtype);
- newattr(dws, DW_AT_byte_size, DW_CLS_CONSTANT,
- sudogsize + (elemsize > 8 ? elemsize - 8 : 0), nil);
-
- // waitq<T>
- dww = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("waitq", getattr(elemtype, DW_AT_name)->data, nil));
- copychildren(dww, waitq);
- substitutetype(dww, "first", defptrto(dws));
- substitutetype(dww, "last", defptrto(dws));
- newattr(dww, DW_AT_byte_size, DW_CLS_CONSTANT,
- getattr(waitq, DW_AT_byte_size)->value, nil);
-
- // hchan<T>
- dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("hchan", getattr(elemtype, DW_AT_name)->data, nil));
- copychildren(dwh, hchan);
- substitutetype(dwh, "recvq", dww);
- substitutetype(dwh, "sendq", dww);
- substitutetype(dwh, "free", defptrto(dws));
- newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
- getattr(hchan, DW_AT_byte_size)->value, nil);
-
- newrefattr(die, DW_AT_type, defptrto(dwh));
- }
-}
-
-// For use with pass.c::genasmsym
-static void
-defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype)
-{
- DWDie *dv, *dt;
-
- USED(size);
- if (strncmp(s, "go.string.", 10) == 0)
- return;
-
- if (strncmp(s, "type.", 5) == 0 && strcmp(s, "type.*") != 0) {
- defgotype(sym);
- return;
- }
-
- dv = nil;
-
- switch (t) {
- default:
- return;
- case 'd':
- case 'b':
- case 'D':
- case 'B':
- dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s);
- newabslocexprattr(dv, v);
- if (ver == 0)
- newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0);
- // fallthrough
- case 'a':
- case 'p':
- dt = defgotype(gotype);
- }
-
- if (dv != nil)
- newrefattr(dv, DW_AT_type, dt);
-}
-
-// TODO(lvd) For now, just append them all to the first compilation
-// unit (that should be main), in the future distribute them to the
-// appropriate compilation units.
-static void
-movetomodule(DWDie *parent)
-{
- DWDie *die;
-
- for (die = dwroot.child->child; die->link != nil; die = die->link) /* nix */;
- die->link = parent->child;
-}
-
-/*
- * Filename fragments for the line history stack.
- */
-
-static char **ftab;
-static int ftabsize;
-
-void
-dwarfaddfrag(int n, char *frag)
-{
- int s;
-
- if (n >= ftabsize) {
- s = ftabsize;
- ftabsize = 1 + n + (n >> 2);
- ftab = realloc(ftab, ftabsize * sizeof(ftab[0]));
- memset(ftab + s, 0, (ftabsize - s) * sizeof(ftab[0]));
- }
-
- if (*frag == '<')
- frag++;
- ftab[n] = frag;
-}
-
-// Returns a malloc'ed string, piecewise copied from the ftab.
-static char *
-decodez(char *s)
-{
- int len, o;
- char *ss, *f;
- char *r, *rb, *re;
-
- len = 0;
- ss = s + 1; // first is 0
- while((o = ((uint8)ss[0] << 8) | (uint8)ss[1]) != 0) {
- if (o < 0 || o >= ftabsize) {
- diag("dwarf: corrupt z entry");
- return 0;
- }
- f = ftab[o];
- if (f == nil) {
- diag("dwarf: corrupt z entry");
- return 0;
- }
- len += strlen(f) + 1; // for the '/'
- ss += 2;
- }
-
- if (len == 0)
- return 0;
-
- r = malloc(len + 1);
- rb = r;
- re = rb + len + 1;
-
- s++;
- while((o = ((uint8)s[0] << 8) | (uint8)s[1]) != 0) {
- f = ftab[o];
- if (rb == r || rb[-1] == '/')
- rb = seprint(rb, re, "%s", f);
- else
- rb = seprint(rb, re, "/%s", f);
- s += 2;
- }
- return r;
-}
-
-/*
- * The line history itself
- */
-
-static char **histfile; // [0] holds "<eof>", DW_LNS_set_file arguments must be > 0.
-static int histfilesize;
-static int histfilecap;
-
-static void
-clearhistfile(void)
-{
- int i;
-
- // [0] holds "<eof>"
- for (i = 1; i < histfilesize; i++)
- free(histfile[i]);
- histfilesize = 0;
-}
-
-static int
-addhistfile(char *zentry)
-{
- char *fname;
-
- if (histfilesize == histfilecap) {
- histfilecap = 2 * histfilecap + 2;
- histfile = realloc(histfile, histfilecap * sizeof(char*));
- }
- if (histfilesize == 0)
- histfile[histfilesize++] = "<eof>";
-
- fname = decodez(zentry);
- if (fname == 0)
- return -1;
- // Don't fill with duplicates (check only top one).
- if (strcmp(fname, histfile[histfilesize-1]) == 0) {
- free(fname);
- return histfilesize - 1;
- }
- histfile[histfilesize++] = fname;
- return histfilesize - 1;
-}
-
-// if the histfile stack contains ..../runtime/runtime_defs.go
-// use that to set gdbscript
-static void
-finddebugruntimepath(void)
-{
- int i, l;
- char *c;
-
- for (i = 1; i < histfilesize; i++) {
- if ((c = strstr(histfile[i], "runtime/runtime_defs.go")) != nil) {
- l = c - histfile[i];
- memmove(gdbscript, histfile[i], l);
- memmove(gdbscript + l, "runtime/runtime-gdb.py", strlen("runtime/runtime-gdb.py") + 1);
- break;
- }
- }
-}
-
-// Go's runtime C sources are sane, and Go sources nest only 1 level,
-// so 16 should be plenty.
-static struct {
- int file;
- vlong line;
-} includestack[16];
-static int includetop;
-static vlong absline;
-
-typedef struct Linehist Linehist;
-struct Linehist {
- Linehist *link;
- vlong absline;
- vlong line;
- int file;
-};
-
-static Linehist *linehist;
-
-static void
-checknesting(void)
-{
- int i;
-
- if (includetop < 0) {
- diag("dwarf: corrupt z stack");
- errorexit();
- }
- if (includetop >= nelem(includestack)) {
- diag("dwarf: nesting too deep");
- for (i = 0; i < nelem(includestack); i++)
- diag("\t%s", histfile[includestack[i].file]);
- errorexit();
- }
-}
-
-/*
- * Return false if the a->link chain contains no history, otherwise
- * returns true and finds z and Z entries in the Auto list (of a
- * Prog), and resets the history stack
- */
-static int
-inithist(Auto *a)
-{
- Linehist *lh;
-
- for (; a; a = a->link)
- if (a->type == D_FILE)
- break;
- if (a==nil)
- return 0;
-
- // We have a new history. They are guaranteed to come completely
- // at the beginning of the compilation unit.
- if (a->aoffset != 1) {
- diag("dwarf: stray 'z' with offset %d", a->aoffset);
- return 0;
- }
-
- // Clear the history.
- clearhistfile();
- includetop = 0;
- includestack[includetop].file = 0;
- includestack[includetop].line = -1;
- absline = 0;
- while (linehist != nil) {
- lh = linehist->link;
- free(linehist);
- linehist = lh;
- }
-
- // Construct the new one.
- for (; a; a = a->link) {
- if (a->type == D_FILE) { // 'z'
- int f = addhistfile(a->asym->name);
- if (f < 0) { // pop file
- includetop--;
- checknesting();
- } else if(f != includestack[includetop].file) { // pushed a new file
- includestack[includetop].line += a->aoffset - absline;
- includetop++;
- checknesting();
- includestack[includetop].file = f;
- includestack[includetop].line = 1;
- }
- absline = a->aoffset;
- } else if (a->type == D_FILE1) { // 'Z'
- // We could just fixup the current
- // linehist->line, but there doesn't appear to
- // be a guarantee that every 'Z' is preceded
- // by it's own 'z', so do the safe thing and
- // update the stack and push a new Linehist
- // entry
- includestack[includetop].line = a->aoffset;
- } else
- continue;
- if (linehist == 0 || linehist->absline != absline) {
- Linehist* lh = malloc(sizeof *lh);
- lh->link = linehist;
- lh->absline = absline;
- linehist = lh;
- }
- linehist->file = includestack[includetop].file;
- linehist->line = includestack[includetop].line;
- }
- return 1;
-}
-
-static Linehist *
-searchhist(vlong absline)
-{
- Linehist *lh;
-
- for (lh = linehist; lh; lh = lh->link)
- if (lh->absline <= absline)
- break;
- return lh;
-}
-
-static int
-guesslang(char *s)
-{
- if(strlen(s) >= 3 && strcmp(s+strlen(s)-3, ".go") == 0)
- return DW_LANG_Go;
-
- return DW_LANG_C;
-}
-
-/*
- * Generate short opcodes when possible, long ones when neccesary.
- * See section 6.2.5
- */
-
-enum {
- LINE_BASE = -1,
- LINE_RANGE = 4,
- OPCODE_BASE = 5
-};
-
-static void
-putpclcdelta(vlong delta_pc, vlong delta_lc)
-{
- if (LINE_BASE <= delta_lc && delta_lc < LINE_BASE+LINE_RANGE) {
- vlong opcode = OPCODE_BASE + (delta_lc - LINE_BASE) + (LINE_RANGE * delta_pc);
- if (OPCODE_BASE <= opcode && opcode < 256) {
- cput(opcode);
- return;
- }
- }
-
- if (delta_pc) {
- cput(DW_LNS_advance_pc);
- sleb128put(delta_pc);
- }
-
- cput(DW_LNS_advance_line);
- sleb128put(delta_lc);
- cput(DW_LNS_copy);
-}
-
-static void
-newcfaoffsetattr(DWDie *die, int32 offs)
-{
- char block[10];
- int i;
-
- i = 0;
-
- block[i++] = DW_OP_call_frame_cfa;
- if (offs != 0) {
- block[i++] = DW_OP_consts;
- i += sleb128enc(offs, block+i);
- block[i++] = DW_OP_plus;
- }
- newattr(die, DW_AT_location, DW_CLS_BLOCK, i, mal(i));
- memmove(die->attr->data, block, i);
-}
-
-static char*
-mkvarname(char* name, int da)
-{
- char buf[1024];
- char *n;
-
- snprint(buf, sizeof buf, "%s#%d", name, da);
- n = mal(strlen(buf) + 1);
- memmove(n, buf, strlen(buf));
- return n;
-}
-
-/*
- * Walk prog table, emit line program and build DIE tree.
- */
-
-// flush previous compilation unit.
-static void
-flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
-{
- vlong here;
-
- if (dwinfo != nil && pc != 0) {
- newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, 0);
- }
-
- if (unitstart >= 0) {
- cput(0); // start extended opcode
- uleb128put(1);
- cput(DW_LNE_end_sequence);
- cflush();
-
- here = cpos();
- seek(cout, unitstart, 0);
- LPUT(here - unitstart - sizeof(int32)); // unit_length
- WPUT(3); // dwarf version
- LPUT(header_length); // header length starting here
- cflush();
- seek(cout, here, 0);
- }
-}
-
-static void
-writelines(void)
-{
- Prog *q;
- Sym *s;
- Auto *a;
- vlong unitstart, headerend, offs;
- vlong pc, epc, lc, llc, lline;
- int currfile;
- int i, lang, da, dt;
- Linehist *lh;
- DWDie *dwinfo, *dwfunc, *dwvar, **dws;
- DWDie *varhash[HASHSIZE];
- char *n, *nn;
-
- unitstart = -1;
- headerend = -1;
- pc = 0;
- epc = 0;
- lc = 1;
- llc = 1;
- currfile = -1;
- lineo = cpos();
- dwinfo = nil;
-
- for(cursym = textp; cursym != nil; cursym = cursym->next) {
- s = cursym;
- if(s->text == P)
- continue;
-
- // Look for history stack. If we find one,
- // we're entering a new compilation unit
-
- if (inithist(s->autom)) {
- flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
- unitstart = cpos();
-
- if(debug['v'] > 1) {
- print("dwarf writelines found %s\n", histfile[1]);
- Linehist* lh;
- for (lh = linehist; lh; lh = lh->link)
- print("\t%8lld: [%4lld]%s\n",
- lh->absline, lh->line, histfile[lh->file]);
- }
-
- lang = guesslang(histfile[1]);
- finddebugruntimepath();
-
- dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, strdup(histfile[1]));
- newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT,lang, 0);
- newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart - lineo, 0);
- newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, 0);
-
- // Write .debug_line Line Number Program Header (sec 6.2.4)
- // Fields marked with (*) must be changed for 64-bit dwarf
- LPUT(0); // unit_length (*), will be filled in by flushunit.
- WPUT(3); // dwarf version (appendix F)
- LPUT(0); // header_length (*), filled in by flushunit.
- // cpos == unitstart + 4 + 2 + 4
- cput(1); // minimum_instruction_length
- cput(1); // default_is_stmt
- cput(LINE_BASE); // line_base
- cput(LINE_RANGE); // line_range
- cput(OPCODE_BASE); // opcode_base (we only use 1..4)
- cput(0); // standard_opcode_lengths[1]
- cput(1); // standard_opcode_lengths[2]
- cput(1); // standard_opcode_lengths[3]
- cput(1); // standard_opcode_lengths[4]
- cput(0); // include_directories (empty)
-
- for (i=1; i < histfilesize; i++) {
- strnput(histfile[i], strlen(histfile[i]) + 4);
- // 4 zeros: the string termination + 3 fields.
- }
-
- cput(0); // terminate file_names.
- headerend = cpos();
-
- pc = s->text->pc;
- epc = pc;
- currfile = 1;
- lc = 1;
- llc = 1;
-
- cput(0); // start extended opcode
- uleb128put(1 + PtrSize);
- cput(DW_LNE_set_address);
- addrput(pc);
- }
- if(s->text == nil)
- continue;
-
- if (unitstart < 0) {
- diag("dwarf: reachable code before seeing any history: %P", s->text);
- continue;
- }
-
- dwfunc = newdie(dwinfo, DW_ABRV_FUNCTION, s->name);
- newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, 0);
- epc = s->value + s->size;
- newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, 0);
- if (s->version == 0)
- newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0);
-
- if(s->text->link == nil)
- continue;
-
- for(q = s->text; q != P; q = q->link) {
- lh = searchhist(q->line);
- if (lh == nil) {
- diag("dwarf: corrupt history or bad absolute line: %P", q);
- continue;
- }
-
- if (lh->file < 1) { // 0 is the past-EOF entry.
- // diag("instruction with line number past EOF in %s: %P", histfile[1], q);
- continue;
- }
-
- lline = lh->line + q->line - lh->absline;
- if (debug['v'] > 1)
- print("%6llux %s[%lld] %P\n", (vlong)q->pc, histfile[lh->file], lline, q);
-
- if (q->line == lc)
- continue;
- if (currfile != lh->file) {
- currfile = lh->file;
- cput(DW_LNS_set_file);
- uleb128put(currfile);
- }
- putpclcdelta(q->pc - pc, lline - llc);
- pc = q->pc;
- lc = q->line;
- llc = lline;
- }
-
- da = 0;
- dwfunc->hash = varhash; // enable indexing of children by name
- memset(varhash, 0, sizeof varhash);
- for(a = s->autom; a; a = a->link) {
- switch (a->type) {
- case D_AUTO:
- dt = DW_ABRV_AUTO;
- offs = a->aoffset - PtrSize;
- break;
- case D_PARAM:
- dt = DW_ABRV_PARAM;
- offs = a->aoffset;
- break;
- default:
- continue;
- }
- if (strstr(a->asym->name, ".autotmp_"))
- continue;
- if (find(dwfunc, a->asym->name) != nil)
- n = mkvarname(a->asym->name, da);
- else
- n = a->asym->name;
- // Drop the package prefix from locals and arguments.
- nn = strrchr(n, '.');
- if (nn)
- n = nn + 1;
-
- dwvar = newdie(dwfunc, dt, n);
- newcfaoffsetattr(dwvar, offs);
- newrefattr(dwvar, DW_AT_type, defgotype(a->gotype));
-
- // push dwvar down dwfunc->child to preserve order
- newattr(dwvar, DW_AT_internal_location, DW_CLS_CONSTANT, offs, nil);
- dwfunc->child = dwvar->link; // take dwvar out from the top of the list
- for (dws = &dwfunc->child; *dws != nil; dws = &(*dws)->link)
- if (offs > getattr(*dws, DW_AT_internal_location)->value)
- break;
- dwvar->link = *dws;
- *dws = dwvar;
-
- da++;
- }
-
- dwfunc->hash = nil;
- }
-
- flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
- linesize = cpos() - lineo;
-}
-
-/*
- * Emit .debug_frame
- */
-enum
-{
- CIERESERVE = 16,
- DATAALIGNMENTFACTOR = -4, // TODO -PtrSize?
- FAKERETURNCOLUMN = 16 // TODO gdb6 doesnt like > 15?
-};
-
-static void
-putpccfadelta(vlong deltapc, vlong cfa)
-{
- if (deltapc < 0x40) {
- cput(DW_CFA_advance_loc + deltapc);
- } else if (deltapc < 0x100) {
- cput(DW_CFA_advance_loc1);
- cput(deltapc);
- } else if (deltapc < 0x10000) {
- cput(DW_CFA_advance_loc2);
- WPUT(deltapc);
- } else {
- cput(DW_CFA_advance_loc4);
- LPUT(deltapc);
- }
-
- cput(DW_CFA_def_cfa_offset_sf);
- sleb128put(cfa / DATAALIGNMENTFACTOR);
-}
-
-static void
-writeframes(void)
-{
- Prog *p, *q;
- Sym *s;
- vlong fdeo, fdesize, pad, cfa, pc;
-
- frameo = cpos();
-
- // Emit the CIE, Section 6.4.1
- LPUT(CIERESERVE); // initial length, must be multiple of PtrSize
- LPUT(0xffffffff); // cid.
- cput(3); // dwarf version (appendix F)
- cput(0); // augmentation ""
- uleb128put(1); // code_alignment_factor
- sleb128put(DATAALIGNMENTFACTOR); // guess
- uleb128put(FAKERETURNCOLUMN); // return_address_register
-
- cput(DW_CFA_def_cfa);
- uleb128put(DWARFREGSP); // register SP (**ABI-dependent, defined in l.h)
- uleb128put(PtrSize); // offset
-
- cput(DW_CFA_offset + FAKERETURNCOLUMN); // return address
- uleb128put(-PtrSize / DATAALIGNMENTFACTOR); // at cfa - x*4
-
- // 4 is to exclude the length field.
- pad = CIERESERVE + frameo + 4 - cpos();
- if (pad < 0) {
- diag("dwarf: CIERESERVE too small by %lld bytes.", -pad);
- errorexit();
- }
- strnput("", pad);
-
- for(cursym = textp; cursym != nil; cursym = cursym->next) {
- s = cursym;
- if(s->text == nil)
- continue;
-
- fdeo = cpos();
- // Emit a FDE, Section 6.4.1, starting wit a placeholder.
- LPUT(0); // length, must be multiple of PtrSize
- LPUT(0); // Pointer to the CIE above, at offset 0
- addrput(0); // initial location
- addrput(0); // address range
-
- cfa = PtrSize; // CFA starts at sp+PtrSize
- p = s->text;
- pc = p->pc;
-
- for(q = p; q->link != P; q = q->link) {
- if (q->spadj == 0)
- continue;
- cfa += q->spadj;
- putpccfadelta(q->link->pc - pc, cfa);
- pc = q->link->pc;
- }
-
- fdesize = cpos() - fdeo - 4; // exclude the length field.
- pad = rnd(fdesize, PtrSize) - fdesize;
- strnput("", pad);
- fdesize += pad;
- cflush();
-
- // Emit the FDE header for real, Section 6.4.1.
- seek(cout, fdeo, 0);
- LPUT(fdesize);
- LPUT(0);
- addrput(p->pc);
- addrput(s->size);
-
- cflush();
- seek(cout, fdeo + 4 + fdesize, 0);
- }
-
- cflush();
- framesize = cpos() - frameo;
-}
-
-/*
- * Walk DWarfDebugInfoEntries, and emit .debug_info
- */
-enum
-{
- COMPUNITHEADERSIZE = 4+2+4+1
-};
-
-static void
-writeinfo(void)
-{
- DWDie *compunit;
- vlong unitstart, here;
-
- fwdcount = 0;
-
- for (compunit = dwroot.child; compunit; compunit = compunit->link) {
- unitstart = cpos();
-
- // Write .debug_info Compilation Unit Header (sec 7.5.1)
- // Fields marked with (*) must be changed for 64-bit dwarf
- // This must match COMPUNITHEADERSIZE above.
- LPUT(0); // unit_length (*), will be filled in later.
- WPUT(3); // dwarf version (appendix F)
- LPUT(0); // debug_abbrev_offset (*)
- cput(PtrSize); // address_size
-
- putdie(compunit);
-
- cflush();
- here = cpos();
- seek(cout, unitstart, 0);
- LPUT(here - unitstart - 4); // exclude the length field.
- cflush();
- seek(cout, here, 0);
- }
-
-}
-
-/*
- * Emit .debug_pubnames/_types. _info must have been written before,
- * because we need die->offs and infoo/infosize;
- */
-static int
-ispubname(DWDie *die) {
- DWAttr *a;
-
- switch(die->abbrev) {
- case DW_ABRV_FUNCTION:
- case DW_ABRV_VARIABLE:
- a = getattr(die, DW_AT_external);
- return a && a->value;
- }
- return 0;
-}
-
-static int
-ispubtype(DWDie *die) {
- return die->abbrev >= DW_ABRV_NULLTYPE;
-}
-
-static vlong
-writepub(int (*ispub)(DWDie*))
-{
- DWDie *compunit, *die;
- DWAttr *dwa;
- vlong unitstart, unitend, sectionstart, here;
-
- sectionstart = cpos();
-
- for (compunit = dwroot.child; compunit != nil; compunit = compunit->link) {
- unitstart = compunit->offs - COMPUNITHEADERSIZE;
- if (compunit->link != nil)
- unitend = compunit->link->offs - COMPUNITHEADERSIZE;
- else
- unitend = infoo + infosize;
-
- // Write .debug_pubnames/types Header (sec 6.1.1)
- LPUT(0); // unit_length (*), will be filled in later.
- WPUT(2); // dwarf version (appendix F)
- LPUT(unitstart); // debug_info_offset (of the Comp unit Header)
- LPUT(unitend - unitstart); // debug_info_length
-
- for (die = compunit->child; die != nil; die = die->link) {
- if (!ispub(die)) continue;
- LPUT(die->offs - unitstart);
- dwa = getattr(die, DW_AT_name);
- strnput(dwa->data, dwa->value + 1);
- }
- LPUT(0);
-
- cflush();
- here = cpos();
- seek(cout, sectionstart, 0);
- LPUT(here - sectionstart - 4); // exclude the length field.
- cflush();
- seek(cout, here, 0);
-
- }
-
- return sectionstart;
-}
-
-/*
- * emit .debug_aranges. _info must have been written before,
- * because we need die->offs of dw_globals.
- */
-static vlong
-writearanges(void)
-{
- DWDie *compunit;
- DWAttr *b, *e;
- int headersize;
- vlong sectionstart;
-
- sectionstart = cpos();
- headersize = rnd(4+2+4+1+1, PtrSize); // don't count unit_length field itself
-
- for (compunit = dwroot.child; compunit != nil; compunit = compunit->link) {
- b = getattr(compunit, DW_AT_low_pc);
- if (b == nil)
- continue;
- e = getattr(compunit, DW_AT_high_pc);
- if (e == nil)
- continue;
-
- // Write .debug_aranges Header + entry (sec 6.1.2)
- LPUT(headersize + 4*PtrSize - 4); // unit_length (*)
- WPUT(2); // dwarf version (appendix F)
- LPUT(compunit->offs - COMPUNITHEADERSIZE); // debug_info_offset
- cput(PtrSize); // address_size
- cput(0); // segment_size
- strnput("", headersize - (4+2+4+1+1)); // align to PtrSize
-
- addrput(b->value);
- addrput(e->value - b->value);
- addrput(0);
- addrput(0);
- }
- cflush();
- return sectionstart;
-}
-
-static vlong
-writegdbscript(void)
-{
- vlong sectionstart;
-
- sectionstart = cpos();
-
- if (gdbscript[0]) {
- cput(1); // magic 1 byte?
- strnput(gdbscript, strlen(gdbscript)+1);
- cflush();
- }
- return sectionstart;
-}
-
-static void
-align(vlong size)
-{
- if(HEADTYPE == Hwindows) // Only Windows PE need section align.
- strnput("", rnd(size, PEFILEALIGN) - size);
-}
-
-/*
- * This is the main entry point for generating dwarf. After emitting
- * the mandatory debug_abbrev section, it calls writelines() to set up
- * the per-compilation unit part of the DIE tree, while simultaneously
- * emitting the debug_line section. When the final tree contains
- * forward references, it will write the debug_info section in 2
- * passes.
- *
- */
-void
-dwarfemitdebugsections(void)
-{
- vlong infoe;
- DWDie* die;
-
- if(debug['w']) // disable dwarf
- return;
-
- // For diagnostic messages.
- newattr(&dwtypes, DW_AT_name, DW_CLS_STRING, strlen("dwtypes"), "dwtypes");
-
- mkindex(&dwroot);
- mkindex(&dwtypes);
- mkindex(&dwglobals);
-
- // Some types that must exist to define other ones.
- newdie(&dwtypes, DW_ABRV_NULLTYPE, "<unspecified>");
- newdie(&dwtypes, DW_ABRV_NULLTYPE, "void");
- newrefattr(newdie(&dwtypes, DW_ABRV_PTRTYPE, "unsafe.Pointer"),
- DW_AT_type, find(&dwtypes, "void"));
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, "uintptr"); // needed for array size
- newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0);
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, PtrSize, 0);
-
- // Needed by the prettyprinter code for interface inspection.
- defgotype(lookup_or_diag("type.runtime.commonType"));
- defgotype(lookup_or_diag("type.runtime.InterfaceType"));
- defgotype(lookup_or_diag("type.runtime.itab"));
-
- genasmsym(defdwsymb);
-
- writeabbrev();
- align(abbrevsize);
- writelines();
- align(linesize);
- writeframes();
- align(framesize);
-
- synthesizestringtypes(dwtypes.child);
- synthesizeslicetypes(dwtypes.child);
- synthesizemaptypes(dwtypes.child);
- synthesizechantypes(dwtypes.child);
-
- reversetree(&dwroot.child);
- reversetree(&dwtypes.child);
- reversetree(&dwglobals.child);
-
- movetomodule(&dwtypes);
- movetomodule(&dwglobals);
-
- infoo = cpos();
- writeinfo();
- infoe = cpos();
- pubnameso = infoe;
- pubtypeso = infoe;
- arangeso = infoe;
- gdbscripto = infoe;
-
- if (fwdcount > 0) {
- if (debug['v'])
- Bprint(&bso, "%5.2f dwarf pass 2.\n", cputime());
- seek(cout, infoo, 0);
- writeinfo();
- if (fwdcount > 0) {
- diag("dwarf: unresolved references after first dwarf info pass");
- errorexit();
- }
- if (infoe != cpos()) {
- diag("dwarf: inconsistent second dwarf info pass");
- errorexit();
- }
- }
- infosize = infoe - infoo;
- align(infosize);
-
- pubnameso = writepub(ispubname);
- pubnamessize = cpos() - pubnameso;
- align(pubnamessize);
-
- pubtypeso = writepub(ispubtype);
- pubtypessize = cpos() - pubtypeso;
- align(pubtypessize);
-
- arangeso = writearanges();
- arangessize = cpos() - arangeso;
- align(arangessize);
-
- gdbscripto = writegdbscript();
- gdbscriptsize = cpos() - gdbscripto;
- align(gdbscriptsize);
-}
-
-/*
- * Elf.
- */
-enum
-{
- ElfStrDebugAbbrev,
- ElfStrDebugAranges,
- ElfStrDebugFrame,
- ElfStrDebugInfo,
- ElfStrDebugLine,
- ElfStrDebugLoc,
- ElfStrDebugMacinfo,
- ElfStrDebugPubNames,
- ElfStrDebugPubTypes,
- ElfStrDebugRanges,
- ElfStrDebugStr,
- ElfStrGDBScripts,
- NElfStrDbg
-};
-
-vlong elfstrdbg[NElfStrDbg];
-
-void
-dwarfaddshstrings(Sym *shstrtab)
-{
- if(debug['w']) // disable dwarf
- return;
-
- elfstrdbg[ElfStrDebugAbbrev] = addstring(shstrtab, ".debug_abbrev");
- elfstrdbg[ElfStrDebugAranges] = addstring(shstrtab, ".debug_aranges");
- elfstrdbg[ElfStrDebugFrame] = addstring(shstrtab, ".debug_frame");
- elfstrdbg[ElfStrDebugInfo] = addstring(shstrtab, ".debug_info");
- elfstrdbg[ElfStrDebugLine] = addstring(shstrtab, ".debug_line");
- elfstrdbg[ElfStrDebugLoc] = addstring(shstrtab, ".debug_loc");
- elfstrdbg[ElfStrDebugMacinfo] = addstring(shstrtab, ".debug_macinfo");
- elfstrdbg[ElfStrDebugPubNames] = addstring(shstrtab, ".debug_pubnames");
- elfstrdbg[ElfStrDebugPubTypes] = addstring(shstrtab, ".debug_pubtypes");
- elfstrdbg[ElfStrDebugRanges] = addstring(shstrtab, ".debug_ranges");
- elfstrdbg[ElfStrDebugStr] = addstring(shstrtab, ".debug_str");
- elfstrdbg[ElfStrGDBScripts] = addstring(shstrtab, ".debug_gdb_scripts");
-}
-
-void
-dwarfaddelfheaders(void)
-{
- ElfShdr *sh;
-
- if(debug['w']) // disable dwarf
- return;
-
- sh = newElfShdr(elfstrdbg[ElfStrDebugAbbrev]);
- sh->type = SHT_PROGBITS;
- sh->off = abbrevo;
- sh->size = abbrevsize;
- sh->addralign = 1;
-
- sh = newElfShdr(elfstrdbg[ElfStrDebugLine]);
- sh->type = SHT_PROGBITS;
- sh->off = lineo;
- sh->size = linesize;
- sh->addralign = 1;
-
- sh = newElfShdr(elfstrdbg[ElfStrDebugFrame]);
- sh->type = SHT_PROGBITS;
- sh->off = frameo;
- sh->size = framesize;
- sh->addralign = 1;
-
- sh = newElfShdr(elfstrdbg[ElfStrDebugInfo]);
- sh->type = SHT_PROGBITS;
- sh->off = infoo;
- sh->size = infosize;
- sh->addralign = 1;
-
- if (pubnamessize > 0) {
- sh = newElfShdr(elfstrdbg[ElfStrDebugPubNames]);
- sh->type = SHT_PROGBITS;
- sh->off = pubnameso;
- sh->size = pubnamessize;
- sh->addralign = 1;
- }
-
- if (pubtypessize > 0) {
- sh = newElfShdr(elfstrdbg[ElfStrDebugPubTypes]);
- sh->type = SHT_PROGBITS;
- sh->off = pubtypeso;
- sh->size = pubtypessize;
- sh->addralign = 1;
- }
-
- if (arangessize) {
- sh = newElfShdr(elfstrdbg[ElfStrDebugAranges]);
- sh->type = SHT_PROGBITS;
- sh->off = arangeso;
- sh->size = arangessize;
- sh->addralign = 1;
- }
-
- if (gdbscriptsize) {
- sh = newElfShdr(elfstrdbg[ElfStrGDBScripts]);
- sh->type = SHT_PROGBITS;
- sh->off = gdbscripto;
- sh->size = gdbscriptsize;
- sh->addralign = 1;
- }
-}
-
-/*
- * Macho
- */
-void
-dwarfaddmachoheaders(void)
-{
- MachoSect *msect;
- MachoSeg *ms;
- vlong fakestart;
- int nsect;
-
- if(debug['w']) // disable dwarf
- return;
-
- // Zero vsize segments won't be loaded in memory, even so they
- // have to be page aligned in the file.
- fakestart = abbrevo & ~0xfff;
-
- nsect = 4;
- if (pubnamessize > 0)
- nsect++;
- if (pubtypessize > 0)
- nsect++;
- if (arangessize > 0)
- nsect++;
- if (gdbscriptsize > 0)
- nsect++;
-
- ms = newMachoSeg("__DWARF", nsect);
- ms->fileoffset = fakestart;
- ms->filesize = abbrevo-fakestart;
-
- msect = newMachoSect(ms, "__debug_abbrev");
- msect->off = abbrevo;
- msect->size = abbrevsize;
- ms->filesize += msect->size;
-
- msect = newMachoSect(ms, "__debug_line");
- msect->off = lineo;
- msect->size = linesize;
- ms->filesize += msect->size;
-
- msect = newMachoSect(ms, "__debug_frame");
- msect->off = frameo;
- msect->size = framesize;
- ms->filesize += msect->size;
-
- msect = newMachoSect(ms, "__debug_info");
- msect->off = infoo;
- msect->size = infosize;
- ms->filesize += msect->size;
-
- if (pubnamessize > 0) {
- msect = newMachoSect(ms, "__debug_pubnames");
- msect->off = pubnameso;
- msect->size = pubnamessize;
- ms->filesize += msect->size;
- }
-
- if (pubtypessize > 0) {
- msect = newMachoSect(ms, "__debug_pubtypes");
- msect->off = pubtypeso;
- msect->size = pubtypessize;
- ms->filesize += msect->size;
- }
-
- if (arangessize > 0) {
- msect = newMachoSect(ms, "__debug_aranges");
- msect->off = arangeso;
- msect->size = arangessize;
- ms->filesize += msect->size;
- }
-
- // TODO(lvd) fix gdb/python to load MachO (16 char section name limit)
- if (gdbscriptsize > 0) {
- msect = newMachoSect(ms, "__debug_gdb_scripts");
- msect->off = gdbscripto;
- msect->size = gdbscriptsize;
- ms->filesize += msect->size;
- }
-}
-
-/*
- * Windows PE
- */
-void
-dwarfaddpeheaders(void)
-{
- if(debug['w']) // disable dwarf
- return;
-
- newPEDWARFSection(".debug_abbrev", abbrevsize);
- newPEDWARFSection(".debug_line", linesize);
- newPEDWARFSection(".debug_frame", framesize);
- newPEDWARFSection(".debug_info", infosize);
- newPEDWARFSection(".debug_pubnames", pubnamessize);
- newPEDWARFSection(".debug_pubtypes", pubtypessize);
- newPEDWARFSection(".debug_aranges", arangessize);
- newPEDWARFSection(".debug_gdb_scripts", gdbscriptsize);
-}
diff --git a/src/cmd/ld/dwarf.h b/src/cmd/ld/dwarf.h
deleted file mode 100644
index f0df2f9b1..000000000
--- a/src/cmd/ld/dwarf.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Register 'f' symbol file fragments. Doing this while parsing the
- * .6 input saves a pass over the symbol table later.
- */
-void dwarfaddfrag(int n, char* frag);
-
-/*
- * Emit debug_abbrevs, debug_info and debug_line sections to current
- * offset in cout.
- */
-void dwarfemitdebugsections(void);
-
-/*
- * Add the dwarf section names to the ELF
- * s[ection]h[eader]str[ing]tab. Prerequisite for
- * dwarfaddelfheaders().
- */
-void dwarfaddshstrings(Sym *shstrtab);
-
-/*
- * Add section headers pointing to the sections emitted in
- * dwarfemitdebugsections.
- */
-void dwarfaddelfheaders(void);
-void dwarfaddmachoheaders(void);
-void dwarfaddpeheaders(void);
diff --git a/src/cmd/ld/dwarf_defs.h b/src/cmd/ld/dwarf_defs.h
deleted file mode 100644
index eed143dff..000000000
--- a/src/cmd/ld/dwarf_defs.h
+++ /dev/null
@@ -1,503 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Cut, pasted, tr-and-awk'ed from tables in
-// http://dwarfstd.org/doc/Dwarf3.pdf
-
-// Table 18
-enum
-{
- DW_TAG_array_type = 0x01,
- DW_TAG_class_type = 0x02,
- DW_TAG_entry_point = 0x03,
- DW_TAG_enumeration_type = 0x04,
- DW_TAG_formal_parameter = 0x05,
- DW_TAG_imported_declaration = 0x08,
- DW_TAG_label = 0x0a,
- DW_TAG_lexical_block = 0x0b,
- DW_TAG_member = 0x0d,
- DW_TAG_pointer_type = 0x0f,
- DW_TAG_reference_type = 0x10,
- DW_TAG_compile_unit = 0x11,
- DW_TAG_string_type = 0x12,
- DW_TAG_structure_type = 0x13,
- DW_TAG_subroutine_type = 0x15,
- DW_TAG_typedef = 0x16,
- DW_TAG_union_type = 0x17,
- DW_TAG_unspecified_parameters = 0x18,
- DW_TAG_variant = 0x19,
- DW_TAG_common_block = 0x1a,
- DW_TAG_common_inclusion = 0x1b,
- DW_TAG_inheritance = 0x1c,
- DW_TAG_inlined_subroutine = 0x1d,
- DW_TAG_module = 0x1e,
- DW_TAG_ptr_to_member_type = 0x1f,
- DW_TAG_set_type = 0x20,
- DW_TAG_subrange_type = 0x21,
- DW_TAG_with_stmt = 0x22,
- DW_TAG_access_declaration = 0x23,
- DW_TAG_base_type = 0x24,
- DW_TAG_catch_block = 0x25,
- DW_TAG_const_type = 0x26,
- DW_TAG_constant = 0x27,
- DW_TAG_enumerator = 0x28,
- DW_TAG_file_type = 0x29,
- DW_TAG_friend = 0x2a,
- DW_TAG_namelist = 0x2b,
- DW_TAG_namelist_item = 0x2c,
- DW_TAG_packed_type = 0x2d,
- DW_TAG_subprogram = 0x2e,
- DW_TAG_template_type_parameter = 0x2f,
- DW_TAG_template_value_parameter = 0x30,
- DW_TAG_thrown_type = 0x31,
- DW_TAG_try_block = 0x32,
- DW_TAG_variant_part = 0x33,
- DW_TAG_variable = 0x34,
- DW_TAG_volatile_type = 0x35,
- // Dwarf3
- DW_TAG_dwarf_procedure = 0x36,
- DW_TAG_restrict_type = 0x37,
- DW_TAG_interface_type = 0x38,
- DW_TAG_namespace = 0x39,
- DW_TAG_imported_module = 0x3a,
- DW_TAG_unspecified_type = 0x3b,
- DW_TAG_partial_unit = 0x3c,
- DW_TAG_imported_unit = 0x3d,
- DW_TAG_condition = 0x3f,
- DW_TAG_shared_type = 0x40,
- // Dwarf4
- DW_TAG_type_unit = 0x41,
- DW_TAG_rvalue_reference_type = 0x42,
- DW_TAG_template_alias = 0x43,
-
- // User defined
- DW_TAG_lo_user = 0x4080,
- DW_TAG_hi_user = 0xffff,
-
-};
-
-// Table 19
-enum
-{
- DW_CHILDREN_no = 0x00,
- DW_CHILDREN_yes = 0x01,
-};
-
-// Not from the spec, but logicaly belongs here
-enum
-{
- DW_CLS_ADDRESS = 0x01,
- DW_CLS_BLOCK,
- DW_CLS_CONSTANT,
- DW_CLS_FLAG,
- DW_CLS_PTR, // lineptr, loclistptr, macptr, rangelistptr
- DW_CLS_REFERENCE,
- DW_CLS_STRING
-};
-
-// Table 20
-enum
-{
- DW_AT_sibling = 0x01, // reference
- DW_AT_location = 0x02, // block, loclistptr
- DW_AT_name = 0x03, // string
- DW_AT_ordering = 0x09, // constant
- DW_AT_byte_size = 0x0b, // block, constant, reference
- DW_AT_bit_offset = 0x0c, // block, constant, reference
- DW_AT_bit_size = 0x0d, // block, constant, reference
- DW_AT_stmt_list = 0x10, // lineptr
- DW_AT_low_pc = 0x11, // address
- DW_AT_high_pc = 0x12, // address
- DW_AT_language = 0x13, // constant
- DW_AT_discr = 0x15, // reference
- DW_AT_discr_value = 0x16, // constant
- DW_AT_visibility = 0x17, // constant
- DW_AT_import = 0x18, // reference
- DW_AT_string_length = 0x19, // block, loclistptr
- DW_AT_common_reference = 0x1a, // reference
- DW_AT_comp_dir = 0x1b, // string
- DW_AT_const_value = 0x1c, // block, constant, string
- DW_AT_containing_type = 0x1d, // reference
- DW_AT_default_value = 0x1e, // reference
- DW_AT_inline = 0x20, // constant
- DW_AT_is_optional = 0x21, // flag
- DW_AT_lower_bound = 0x22, // block, constant, reference
- DW_AT_producer = 0x25, // string
- DW_AT_prototyped = 0x27, // flag
- DW_AT_return_addr = 0x2a, // block, loclistptr
- DW_AT_start_scope = 0x2c, // constant
- DW_AT_bit_stride = 0x2e, // constant
- DW_AT_upper_bound = 0x2f, // block, constant, reference
- DW_AT_abstract_origin = 0x31, // reference
- DW_AT_accessibility = 0x32, // constant
- DW_AT_address_class = 0x33, // constant
- DW_AT_artificial = 0x34, // flag
- DW_AT_base_types = 0x35, // reference
- DW_AT_calling_convention = 0x36, // constant
- DW_AT_count = 0x37, // block, constant, reference
- DW_AT_data_member_location = 0x38, // block, constant, loclistptr
- DW_AT_decl_column = 0x39, // constant
- DW_AT_decl_file = 0x3a, // constant
- DW_AT_decl_line = 0x3b, // constant
- DW_AT_declaration = 0x3c, // flag
- DW_AT_discr_list = 0x3d, // block
- DW_AT_encoding = 0x3e, // constant
- DW_AT_external = 0x3f, // flag
- DW_AT_frame_base = 0x40, // block, loclistptr
- DW_AT_friend = 0x41, // reference
- DW_AT_identifier_case = 0x42, // constant
- DW_AT_macro_info = 0x43, // macptr
- DW_AT_namelist_item = 0x44, // block
- DW_AT_priority = 0x45, // reference
- DW_AT_segment = 0x46, // block, loclistptr
- DW_AT_specification = 0x47, // reference
- DW_AT_static_link = 0x48, // block, loclistptr
- DW_AT_type = 0x49, // reference
- DW_AT_use_location = 0x4a, // block, loclistptr
- DW_AT_variable_parameter = 0x4b, // flag
- DW_AT_virtuality = 0x4c, // constant
- DW_AT_vtable_elem_location = 0x4d, // block, loclistptr
- // Dwarf3
- DW_AT_allocated = 0x4e, // block, constant, reference
- DW_AT_associated = 0x4f, // block, constant, reference
- DW_AT_data_location = 0x50, // block
- DW_AT_byte_stride = 0x51, // block, constant, reference
- DW_AT_entry_pc = 0x52, // address
- DW_AT_use_UTF8 = 0x53, // flag
- DW_AT_extension = 0x54, // reference
- DW_AT_ranges = 0x55, // rangelistptr
- DW_AT_trampoline = 0x56, // address, flag, reference, string
- DW_AT_call_column = 0x57, // constant
- DW_AT_call_file = 0x58, // constant
- DW_AT_call_line = 0x59, // constant
- DW_AT_description = 0x5a, // string
- DW_AT_binary_scale = 0x5b, // constant
- DW_AT_decimal_scale = 0x5c, // constant
- DW_AT_small = 0x5d, // reference
- DW_AT_decimal_sign = 0x5e, // constant
- DW_AT_digit_count = 0x5f, // constant
- DW_AT_picture_string = 0x60, // string
- DW_AT_mutable = 0x61, // flag
- DW_AT_threads_scaled = 0x62, // flag
- DW_AT_explicit = 0x63, // flag
- DW_AT_object_pointer = 0x64, // reference
- DW_AT_endianity = 0x65, // constant
- DW_AT_elemental = 0x66, // flag
- DW_AT_pure = 0x67, // flag
- DW_AT_recursive = 0x68, // flag
-
- DW_AT_lo_user = 0x2000, // ---
- DW_AT_hi_user = 0x3fff, // ---
-
-};
-
-// Table 21
-enum
-{
- DW_FORM_addr = 0x01, // address
- DW_FORM_block2 = 0x03, // block
- DW_FORM_block4 = 0x04, // block
- DW_FORM_data2 = 0x05, // constant
- DW_FORM_data4 = 0x06, // constant, lineptr, loclistptr, macptr, rangelistptr
- DW_FORM_data8 = 0x07, // constant, lineptr, loclistptr, macptr, rangelistptr
- DW_FORM_string = 0x08, // string
- DW_FORM_block = 0x09, // block
- DW_FORM_block1 = 0x0a, // block
- DW_FORM_data1 = 0x0b, // constant
- DW_FORM_flag = 0x0c, // flag
- DW_FORM_sdata = 0x0d, // constant
- DW_FORM_strp = 0x0e, // string
- DW_FORM_udata = 0x0f, // constant
- DW_FORM_ref_addr = 0x10, // reference
- DW_FORM_ref1 = 0x11, // reference
- DW_FORM_ref2 = 0x12, // reference
- DW_FORM_ref4 = 0x13, // reference
- DW_FORM_ref8 = 0x14, // reference
- DW_FORM_ref_udata = 0x15, // reference
- DW_FORM_indirect = 0x16, // (see Section 7.5.3)
-};
-
-// Table 24 (#operands, notes)
-enum
-{
- DW_OP_addr = 0x03, // 1 constant address (size target specific)
- DW_OP_deref = 0x06, // 0
- DW_OP_const1u = 0x08, // 1 1-byte constant
- DW_OP_const1s = 0x09, // 1 1-byte constant
- DW_OP_const2u = 0x0a, // 1 2-byte constant
- DW_OP_const2s = 0x0b, // 1 2-byte constant
- DW_OP_const4u = 0x0c, // 1 4-byte constant
- DW_OP_const4s = 0x0d, // 1 4-byte constant
- DW_OP_const8u = 0x0e, // 1 8-byte constant
- DW_OP_const8s = 0x0f, // 1 8-byte constant
- DW_OP_constu = 0x10, // 1 ULEB128 constant
- DW_OP_consts = 0x11, // 1 SLEB128 constant
- DW_OP_dup = 0x12, // 0
- DW_OP_drop = 0x13, // 0
- DW_OP_over = 0x14, // 0
- DW_OP_pick = 0x15, // 1 1-byte stack index
- DW_OP_swap = 0x16, // 0
- DW_OP_rot = 0x17, // 0
- DW_OP_xderef = 0x18, // 0
- DW_OP_abs = 0x19, // 0
- DW_OP_and = 0x1a, // 0
- DW_OP_div = 0x1b, // 0
- DW_OP_minus = 0x1c, // 0
- DW_OP_mod = 0x1d, // 0
- DW_OP_mul = 0x1e, // 0
- DW_OP_neg = 0x1f, // 0
- DW_OP_not = 0x20, // 0
- DW_OP_or = 0x21, // 0
- DW_OP_plus = 0x22, // 0
- DW_OP_plus_uconst = 0x23, // 1 ULEB128 addend
- DW_OP_shl = 0x24, // 0
- DW_OP_shr = 0x25, // 0
- DW_OP_shra = 0x26, // 0
- DW_OP_xor = 0x27, // 0
- DW_OP_skip = 0x2f, // 1 signed 2-byte constant
- DW_OP_bra = 0x28, // 1 signed 2-byte constant
- DW_OP_eq = 0x29, // 0
- DW_OP_ge = 0x2a, // 0
- DW_OP_gt = 0x2b, // 0
- DW_OP_le = 0x2c, // 0
- DW_OP_lt = 0x2d, // 0
- DW_OP_ne = 0x2e, // 0
- DW_OP_lit0 = 0x30, // 0 ...
- DW_OP_lit31 = 0x4f, // 0 literals 0..31 = (DW_OP_lit0 +
- // literal)
- DW_OP_reg0 = 0x50, // 0 ..
- DW_OP_reg31 = 0x6f, // 0 reg 0..31 = (DW_OP_reg0 + regnum)
- DW_OP_breg0 = 0x70, // 1 ...
- DW_OP_breg31 = 0x8f, // 1 SLEB128 offset base register 0..31 = (DW_OP_breg0 + regnum)
- DW_OP_regx = 0x90, // 1 ULEB128 register
- DW_OP_fbreg = 0x91, // 1 SLEB128 offset
- DW_OP_bregx = 0x92, // 2 ULEB128 register followed by SLEB128 offset
- DW_OP_piece = 0x93, // 1 ULEB128 size of piece addressed
- DW_OP_deref_size = 0x94, // 1 1-byte size of data retrieved
- DW_OP_xderef_size = 0x95, // 1 1-byte size of data retrieved
- DW_OP_nop = 0x96, // 0
- DW_OP_push_object_address = 0x97, // 0
- DW_OP_call2 = 0x98, // 1 2-byte offset of DIE
- DW_OP_call4 = 0x99, // 1 4-byte offset of DIE
- DW_OP_call_ref = 0x9a, // 1 4- or 8-byte offset of DIE
- DW_OP_form_tls_address = 0x9b, // 0
- DW_OP_call_frame_cfa = 0x9c, // 0
- DW_OP_bit_piece = 0x9d, // 2
- DW_OP_lo_user = 0xe0,
- DW_OP_hi_user = 0xff,
-};
-
-// Table 25
-enum
-{
- DW_ATE_address = 0x01,
- DW_ATE_boolean = 0x02,
- DW_ATE_complex_float = 0x03,
- DW_ATE_float = 0x04,
- DW_ATE_signed = 0x05,
- DW_ATE_signed_char = 0x06,
- DW_ATE_unsigned = 0x07,
- DW_ATE_unsigned_char = 0x08,
- DW_ATE_imaginary_float = 0x09,
- DW_ATE_packed_decimal = 0x0a,
- DW_ATE_numeric_string = 0x0b,
- DW_ATE_edited = 0x0c,
- DW_ATE_signed_fixed = 0x0d,
- DW_ATE_unsigned_fixed = 0x0e,
- DW_ATE_decimal_float = 0x0f,
- DW_ATE_lo_user = 0x80,
- DW_ATE_hi_user = 0xff,
-};
-
-// Table 26
-enum
-{
- DW_DS_unsigned = 0x01,
- DW_DS_leading_overpunch = 0x02,
- DW_DS_trailing_overpunch = 0x03,
- DW_DS_leading_separate = 0x04,
- DW_DS_trailing_separate = 0x05,
-};
-
-// Table 27
-enum
-{
- DW_END_default = 0x00,
- DW_END_big = 0x01,
- DW_END_little = 0x02,
- DW_END_lo_user = 0x40,
- DW_END_hi_user = 0xff,
-};
-
-// Table 28
-enum
-{
- DW_ACCESS_public = 0x01,
- DW_ACCESS_protected = 0x02,
- DW_ACCESS_private = 0x03,
-};
-
-// Table 29
-enum
-{
- DW_VIS_local = 0x01,
- DW_VIS_exported = 0x02,
- DW_VIS_qualified = 0x03,
-};
-
-// Table 30
-enum
-{
- DW_VIRTUALITY_none = 0x00,
- DW_VIRTUALITY_virtual = 0x01,
- DW_VIRTUALITY_pure_virtual = 0x02,
-};
-
-// Table 31
-enum
-{
- DW_LANG_C89 = 0x0001,
- DW_LANG_C = 0x0002,
- DW_LANG_Ada83 = 0x0003,
- DW_LANG_C_plus_plus = 0x0004,
- DW_LANG_Cobol74 = 0x0005,
- DW_LANG_Cobol85 = 0x0006,
- DW_LANG_Fortran77 = 0x0007,
- DW_LANG_Fortran90 = 0x0008,
- DW_LANG_Pascal83 = 0x0009,
- DW_LANG_Modula2 = 0x000a,
- // Dwarf3
- DW_LANG_Java = 0x000b,
- DW_LANG_C99 = 0x000c,
- DW_LANG_Ada95 = 0x000d,
- DW_LANG_Fortran95 = 0x000e,
- DW_LANG_PLI = 0x000f,
- DW_LANG_ObjC = 0x0010,
- DW_LANG_ObjC_plus_plus = 0x0011,
- DW_LANG_UPC = 0x0012,
- DW_LANG_D = 0x0013,
- // Dwarf4
- DW_LANG_Python = 0x0014,
- // Dwarf5
- DW_LANG_Go = 0x0016,
-
- DW_LANG_lo_user = 0x8000,
- DW_LANG_hi_user = 0xffff,
-};
-
-// Table 32
-enum
-{
- DW_ID_case_sensitive = 0x00,
- DW_ID_up_case = 0x01,
- DW_ID_down_case = 0x02,
- DW_ID_case_insensitive = 0x03,
-};
-
-// Table 33
-enum
-{
- DW_CC_normal = 0x01,
- DW_CC_program = 0x02,
- DW_CC_nocall = 0x03,
- DW_CC_lo_user = 0x40,
- DW_CC_hi_user = 0xff,
-};
-
-// Table 34
-enum
-{
- DW_INL_not_inlined = 0x00,
- DW_INL_inlined = 0x01,
- DW_INL_declared_not_inlined = 0x02,
- DW_INL_declared_inlined = 0x03,
-};
-
-// Table 35
-enum
-{
- DW_ORD_row_major = 0x00,
- DW_ORD_col_major = 0x01,
-};
-
-// Table 36
-enum
-{
- DW_DSC_label = 0x00,
- DW_DSC_range = 0x01,
-};
-
-// Table 37
-enum
-{
- DW_LNS_copy = 0x01,
- DW_LNS_advance_pc = 0x02,
- DW_LNS_advance_line = 0x03,
- DW_LNS_set_file = 0x04,
- DW_LNS_set_column = 0x05,
- DW_LNS_negate_stmt = 0x06,
- DW_LNS_set_basic_block = 0x07,
- DW_LNS_const_add_pc = 0x08,
- DW_LNS_fixed_advance_pc = 0x09,
- // Dwarf3
- DW_LNS_set_prologue_end = 0x0a,
- DW_LNS_set_epilogue_begin = 0x0b,
- DW_LNS_set_isa = 0x0c,
-};
-
-// Table 38
-enum
-{
- DW_LNE_end_sequence = 0x01,
- DW_LNE_set_address = 0x02,
- DW_LNE_define_file = 0x03,
- DW_LNE_lo_user = 0x80,
- DW_LNE_hi_user = 0xff,
-};
-
-// Table 39
-enum
-{
- DW_MACINFO_define = 0x01,
- DW_MACINFO_undef = 0x02,
- DW_MACINFO_start_file = 0x03,
- DW_MACINFO_end_file = 0x04,
- DW_MACINFO_vendor_ext = 0xff,
-};
-
-// Table 40.
-enum
-{ // operand,...
- DW_CFA_nop = 0x00,
- DW_CFA_set_loc = 0x01, // address
- DW_CFA_advance_loc1 = 0x02, // 1-byte delta
- DW_CFA_advance_loc2 = 0x03, // 2-byte delta
- DW_CFA_advance_loc4 = 0x04, // 4-byte delta
- DW_CFA_offset_extended = 0x05, // ULEB128 register, ULEB128 offset
- DW_CFA_restore_extended = 0x06, // ULEB128 register
- DW_CFA_undefined = 0x07, // ULEB128 register
- DW_CFA_same_value = 0x08, // ULEB128 register
- DW_CFA_register = 0x09, // ULEB128 register, ULEB128 register
- DW_CFA_remember_state = 0x0a,
- DW_CFA_restore_state = 0x0b,
- DW_CFA_def_cfa = 0x0c, // ULEB128 register, ULEB128 offset
- DW_CFA_def_cfa_register = 0x0d, // ULEB128 register
- DW_CFA_def_cfa_offset = 0x0e, // ULEB128 offset
- DW_CFA_def_cfa_expression = 0x0f, // BLOCK
- DW_CFA_expression = 0x10, // ULEB128 register, BLOCK
- DW_CFA_offset_extended_sf = 0x11, // ULEB128 register, SLEB128 offset
- DW_CFA_def_cfa_sf = 0x12, // ULEB128 register, SLEB128 offset
- DW_CFA_def_cfa_offset_sf = 0x13, // SLEB128 offset
- DW_CFA_val_offset = 0x14, // ULEB128, ULEB128
- DW_CFA_val_offset_sf = 0x15, // ULEB128, SLEB128
- DW_CFA_val_expression = 0x16, // ULEB128, BLOCK
-
- DW_CFA_lo_user = 0x1c,
- DW_CFA_hi_user = 0x3f,
-
- // Opcodes that take an addend operand.
- DW_CFA_advance_loc = 0x1<<6, // +delta
- DW_CFA_offset = 0x2<<6, // +register (ULEB128 offset)
- DW_CFA_restore = 0x3<<6, // +register
-};
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
deleted file mode 100644
index fc917b203..000000000
--- a/src/cmd/ld/elf.c
+++ /dev/null
@@ -1,558 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "l.h"
-#include "lib.h"
-#include "../ld/elf.h"
-
-/*
- * We use the 64-bit data structures on both 32- and 64-bit machines
- * in order to write the code just once. The 64-bit data structure is
- * written in the 32-bit format on the 32-bit machines.
- */
-#define NSECT 32
-
-int iself;
-
-static int elf64;
-static ElfEhdr hdr;
-static ElfPhdr *phdr[NSECT];
-static ElfShdr *shdr[NSECT];
-static char *interp;
-
-typedef struct Elfstring Elfstring;
-struct Elfstring
-{
- char *s;
- int off;
-};
-
-static Elfstring elfstr[100];
-static int nelfstr;
-
-/*
- Initialize the global variable that describes the ELF header. It will be updated as
- we write section and prog headers.
- */
-void
-elfinit(void)
-{
- iself = 1;
-
- switch(thechar) {
- // 64-bit architectures
- case '6':
- elf64 = 1;
- hdr.phoff = ELF64HDRSIZE; /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
- hdr.shoff = ELF64HDRSIZE; /* Will move as we add PHeaders */
- hdr.ehsize = ELF64HDRSIZE; /* Must be ELF64HDRSIZE */
- hdr.phentsize = ELF64PHDRSIZE; /* Must be ELF64PHDRSIZE */
- hdr.shentsize = ELF64SHDRSIZE; /* Must be ELF64SHDRSIZE */
- break;
-
- // 32-bit architectures
- default:
- hdr.phoff = ELF32HDRSIZE; /* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */
- hdr.shoff = ELF32HDRSIZE; /* Will move as we add PHeaders */
- hdr.ehsize = ELF32HDRSIZE; /* Must be ELF32HDRSIZE */
- hdr.phentsize = ELF32PHDRSIZE; /* Must be ELF32PHDRSIZE */
- hdr.shentsize = ELF32SHDRSIZE; /* Must be ELF32SHDRSIZE */
- }
-}
-
-void
-elf64phdr(ElfPhdr *e)
-{
- LPUT(e->type);
- LPUT(e->flags);
- VPUT(e->off);
- VPUT(e->vaddr);
- VPUT(e->paddr);
- VPUT(e->filesz);
- VPUT(e->memsz);
- VPUT(e->align);
-}
-
-void
-elf32phdr(ElfPhdr *e)
-{
- LPUT(e->type);
- LPUT(e->off);
- LPUT(e->vaddr);
- LPUT(e->paddr);
- LPUT(e->filesz);
- LPUT(e->memsz);
- LPUT(e->flags);
- LPUT(e->align);
-}
-
-void
-elf64shdr(ElfShdr *e)
-{
- LPUT(e->name);
- LPUT(e->type);
- VPUT(e->flags);
- VPUT(e->addr);
- VPUT(e->off);
- VPUT(e->size);
- LPUT(e->link);
- LPUT(e->info);
- VPUT(e->addralign);
- VPUT(e->entsize);
-}
-
-void
-elf32shdr(ElfShdr *e)
-{
- LPUT(e->name);
- LPUT(e->type);
- LPUT(e->flags);
- LPUT(e->addr);
- LPUT(e->off);
- LPUT(e->size);
- LPUT(e->link);
- LPUT(e->info);
- LPUT(e->addralign);
- LPUT(e->entsize);
-}
-
-uint32
-elfwriteshdrs(void)
-{
- int i;
-
- if (elf64) {
- for (i = 0; i < hdr.shnum; i++)
- elf64shdr(shdr[i]);
- return hdr.shnum * ELF64SHDRSIZE;
- }
- for (i = 0; i < hdr.shnum; i++)
- elf32shdr(shdr[i]);
- return hdr.shnum * ELF32SHDRSIZE;
-}
-
-void
-elfsetstring(char *s, int off)
-{
- if(nelfstr >= nelem(elfstr)) {
- diag("too many elf strings");
- errorexit();
- }
- elfstr[nelfstr].s = s;
- elfstr[nelfstr].off = off;
- nelfstr++;
-}
-
-uint32
-elfwritephdrs(void)
-{
- int i;
-
- if (elf64) {
- for (i = 0; i < hdr.phnum; i++)
- elf64phdr(phdr[i]);
- return hdr.phnum * ELF64PHDRSIZE;
- }
- for (i = 0; i < hdr.phnum; i++)
- elf32phdr(phdr[i]);
- return hdr.phnum * ELF32PHDRSIZE;
-}
-
-ElfPhdr*
-newElfPhdr(void)
-{
- ElfPhdr *e;
-
- e = mal(sizeof *e);
- if (hdr.phnum >= NSECT)
- diag("too many phdrs");
- else
- phdr[hdr.phnum++] = e;
- if (elf64)
- hdr.shoff += ELF64PHDRSIZE;
- else
- hdr.shoff += ELF32PHDRSIZE;
- return e;
-}
-
-ElfShdr*
-newElfShstrtab(vlong name)
-{
- hdr.shstrndx = hdr.shnum;
- return newElfShdr(name);
-}
-
-ElfShdr*
-newElfShdr(vlong name)
-{
- ElfShdr *e;
-
- e = mal(sizeof *e);
- e->name = name;
- if (hdr.shnum >= NSECT) {
- diag("too many shdrs");
- } else {
- shdr[hdr.shnum++] = e;
- }
- return e;
-}
-
-ElfEhdr*
-getElfEhdr(void)
-{
- return &hdr;
-}
-
-uint32
-elf64writehdr(void)
-{
- int i;
-
- for (i = 0; i < EI_NIDENT; i++)
- cput(hdr.ident[i]);
- WPUT(hdr.type);
- WPUT(hdr.machine);
- LPUT(hdr.version);
- VPUT(hdr.entry);
- VPUT(hdr.phoff);
- VPUT(hdr.shoff);
- LPUT(hdr.flags);
- WPUT(hdr.ehsize);
- WPUT(hdr.phentsize);
- WPUT(hdr.phnum);
- WPUT(hdr.shentsize);
- WPUT(hdr.shnum);
- WPUT(hdr.shstrndx);
- return ELF64HDRSIZE;
-}
-
-uint32
-elf32writehdr(void)
-{
- int i;
-
- for (i = 0; i < EI_NIDENT; i++)
- cput(hdr.ident[i]);
- WPUT(hdr.type);
- WPUT(hdr.machine);
- LPUT(hdr.version);
- LPUT(hdr.entry);
- LPUT(hdr.phoff);
- LPUT(hdr.shoff);
- LPUT(hdr.flags);
- WPUT(hdr.ehsize);
- WPUT(hdr.phentsize);
- WPUT(hdr.phnum);
- WPUT(hdr.shentsize);
- WPUT(hdr.shnum);
- WPUT(hdr.shstrndx);
- return ELF32HDRSIZE;
-}
-
-uint32
-elfwritehdr(void)
-{
- if(elf64)
- return elf64writehdr();
- return elf32writehdr();
-}
-
-/* Taken directly from the definition document for ELF64 */
-uint32
-elfhash(uchar *name)
-{
- uint32 h = 0, g;
- while (*name) {
- h = (h << 4) + *name++;
- if (g = h & 0xf0000000)
- h ^= g >> 24;
- h &= 0x0fffffff;
- }
- return h;
-}
-
-void
-elfwritedynent(Sym *s, int tag, uint64 val)
-{
- if(elf64) {
- adduint64(s, tag);
- adduint64(s, val);
- } else {
- adduint32(s, tag);
- adduint32(s, val);
- }
-}
-
-void
-elfwritedynentsym(Sym *s, int tag, Sym *t)
-{
- if(elf64)
- adduint64(s, tag);
- else
- adduint32(s, tag);
- addaddr(s, t);
-}
-
-void
-elfwritedynentsymsize(Sym *s, int tag, Sym *t)
-{
- if(elf64)
- adduint64(s, tag);
- else
- adduint32(s, tag);
- addsize(s, t);
-}
-
-int
-elfwriteinterp(void)
-{
- int n;
-
- if(interp == nil)
- return 0;
-
- n = strlen(interp)+1;
- seek(cout, ELFRESERVE-n, 0);
- ewrite(cout, interp, n);
- return n;
-}
-
-void
-elfinterp(ElfShdr *sh, uint64 startva, char *p)
-{
- int n;
-
- interp = p;
- n = strlen(interp)+1;
- sh->addr = startva + ELFRESERVE - n;
- sh->off = ELFRESERVE - n;
- sh->size = n;
-}
-
-extern int nelfsym;
-int elfverneed;
-
-typedef struct Elfaux Elfaux;
-typedef struct Elflib Elflib;
-
-struct Elflib
-{
- Elflib *next;
- Elfaux *aux;
- char *file;
-};
-
-struct Elfaux
-{
- Elfaux *next;
- int num;
- char *vers;
-};
-
-Elfaux*
-addelflib(Elflib **list, char *file, char *vers)
-{
- Elflib *lib;
- Elfaux *aux;
-
- for(lib=*list; lib; lib=lib->next)
- if(strcmp(lib->file, file) == 0)
- goto havelib;
- lib = mal(sizeof *lib);
- lib->next = *list;
- lib->file = file;
- *list = lib;
-havelib:
- for(aux=lib->aux; aux; aux=aux->next)
- if(strcmp(aux->vers, vers) == 0)
- goto haveaux;
- aux = mal(sizeof *aux);
- aux->next = lib->aux;
- aux->vers = vers;
- lib->aux = aux;
-haveaux:
- return aux;
-}
-
-void
-elfdynhash(void)
-{
- Sym *s, *sy, *dynstr;
- int i, j, nbucket, b, nfile;
- uint32 hc, *chain, *buckets;
- int nsym;
- char *name;
- Elfaux **need;
- Elflib *needlib;
- Elflib *l;
- Elfaux *x;
-
- if(!iself)
- return;
-
- nsym = nelfsym;
- s = lookup(".hash", 0);
- s->type = SELFDATA;
- s->reachable = 1;
-
- i = nsym;
- nbucket = 1;
- while(i > 0) {
- ++nbucket;
- i >>= 1;
- }
-
- needlib = nil;
- need = malloc(nsym * sizeof need[0]);
- chain = malloc(nsym * sizeof chain[0]);
- buckets = malloc(nbucket * sizeof buckets[0]);
- if(need == nil || chain == nil || buckets == nil) {
- cursym = nil;
- diag("out of memory");
- errorexit();
- }
- memset(need, 0, nsym * sizeof need[0]);
- memset(chain, 0, nsym * sizeof chain[0]);
- memset(buckets, 0, nbucket * sizeof buckets[0]);
- for(sy=allsym; sy!=S; sy=sy->allsym) {
- if (sy->dynid <= 0)
- continue;
-
- if(sy->dynimpvers)
- need[sy->dynid] = addelflib(&needlib, sy->dynimplib, sy->dynimpvers);
-
- name = sy->dynimpname;
- if(name == nil)
- name = sy->name;
- hc = elfhash((uchar*)name);
-
- b = hc % nbucket;
- chain[sy->dynid] = buckets[b];
- buckets[b] = sy->dynid;
- }
-
- adduint32(s, nbucket);
- adduint32(s, nsym);
- for(i = 0; i<nbucket; i++)
- adduint32(s, buckets[i]);
- for(i = 0; i<nsym; i++)
- adduint32(s, chain[i]);
-
- free(chain);
- free(buckets);
-
- // version symbols
- dynstr = lookup(".dynstr", 0);
- s = lookup(".gnu.version_r", 0);
- i = 2;
- nfile = 0;
- for(l=needlib; l; l=l->next) {
- nfile++;
- // header
- adduint16(s, 1); // table version
- j = 0;
- for(x=l->aux; x; x=x->next)
- j++;
- adduint16(s, j); // aux count
- adduint32(s, addstring(dynstr, l->file)); // file string offset
- adduint32(s, 16); // offset from header to first aux
- if(l->next)
- adduint32(s, 16+j*16); // offset from this header to next
- else
- adduint32(s, 0);
-
- for(x=l->aux; x; x=x->next) {
- x->num = i++;
- // aux struct
- adduint32(s, elfhash((uchar*)x->vers)); // hash
- adduint16(s, 0); // flags
- adduint16(s, x->num); // other - index we refer to this by
- adduint32(s, addstring(dynstr, x->vers)); // version string offset
- if(x->next)
- adduint32(s, 16); // offset from this aux to next
- else
- adduint32(s, 0);
- }
- }
-
- // version references
- s = lookup(".gnu.version", 0);
- for(i=0; i<nsym; i++) {
- if(i == 0)
- adduint16(s, 0); // first entry - no symbol
- else if(need[i] == nil)
- adduint16(s, 1); // global
- else
- adduint16(s, need[i]->num);
- }
-
- free(need);
-
- s = lookup(".dynamic", 0);
- elfverneed = nfile;
- if(elfverneed) {
- elfwritedynentsym(s, DT_VERNEED, lookup(".gnu.version_r", 0));
- elfwritedynent(s, DT_VERNEEDNUM, nfile);
- elfwritedynentsym(s, DT_VERSYM, lookup(".gnu.version", 0));
- }
- elfwritedynent(s, DT_NULL, 0);
-}
-
-ElfPhdr*
-elfphload(Segment *seg)
-{
- ElfPhdr *ph;
-
- ph = newElfPhdr();
- ph->type = PT_LOAD;
- if(seg->rwx & 4)
- ph->flags |= PF_R;
- if(seg->rwx & 2)
- ph->flags |= PF_W;
- if(seg->rwx & 1)
- ph->flags |= PF_X;
- ph->vaddr = seg->vaddr;
- ph->paddr = seg->vaddr;
- ph->memsz = seg->len;
- ph->off = seg->fileoff;
- ph->filesz = seg->filelen;
- ph->align = INITRND;
-
- return ph;
-}
-
-ElfShdr*
-elfshbits(Section *sect)
-{
- int i, off;
- ElfShdr *sh;
-
- for(i=0; i<nelfstr; i++) {
- if(strcmp(sect->name, elfstr[i].s) == 0) {
- off = elfstr[i].off;
- goto found;
- }
- }
- diag("cannot find elf name %s", sect->name);
- errorexit();
- return nil;
-
-found:
- sh = newElfShdr(off);
- if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen)
- sh->type = SHT_PROGBITS;
- else
- sh->type = SHT_NOBITS;
- sh->flags = SHF_ALLOC;
- if(sect->rwx & 1)
- sh->flags |= SHF_EXECINSTR;
- if(sect->rwx & 2)
- sh->flags |= SHF_WRITE;
- sh->addr = sect->vaddr;
- sh->addralign = PtrSize;
- sh->size = sect->len;
- sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
-
- return sh;
-}
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
deleted file mode 100644
index c63df2241..000000000
--- a/src/cmd/ld/elf.h
+++ /dev/null
@@ -1,989 +0,0 @@
-/*
- * Derived from:
- * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $
- * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $
- * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $
- * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $
- * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $
- * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $
- * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $
- * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $
- * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $
- *
- * Copyright (c) 1996-1998 John D. Polstra. All rights reserved.
- * Copyright (c) 2001 David E. O'Brien
- * Portions Copyright 2009 The Go Authors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-/*
- * ELF definitions that are independent of architecture or word size.
- */
-
-/*
- * Note header. The ".note" section contains an array of notes. Each
- * begins with this header, aligned to a word boundary. Immediately
- * following the note header is n_namesz bytes of name, padded to the
- * next word boundary. Then comes n_descsz bytes of descriptor, again
- * padded to a word boundary. The values of n_namesz and n_descsz do
- * not include the padding.
- */
-
-typedef struct {
- uint32 n_namesz; /* Length of name. */
- uint32 n_descsz; /* Length of descriptor. */
- uint32 n_type; /* Type of this note. */
-} Elf_Note;
-
-/* Indexes into the e_ident array. Keep synced with
- http://www.sco.com/developer/gabi/ch4.eheader.html */
-#define EI_MAG0 0 /* Magic number, byte 0. */
-#define EI_MAG1 1 /* Magic number, byte 1. */
-#define EI_MAG2 2 /* Magic number, byte 2. */
-#define EI_MAG3 3 /* Magic number, byte 3. */
-#define EI_CLASS 4 /* Class of machine. */
-#define EI_DATA 5 /* Data format. */
-#define EI_VERSION 6 /* ELF format version. */
-#define EI_OSABI 7 /* Operating system / ABI identification */
-#define EI_ABIVERSION 8 /* ABI version */
-#define OLD_EI_BRAND 8 /* Start of architecture identification. */
-#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */
-#define EI_NIDENT 16 /* Size of e_ident array. */
-
-/* Values for the magic number bytes. */
-#define ELFMAG0 0x7f
-#define ELFMAG1 'E'
-#define ELFMAG2 'L'
-#define ELFMAG3 'F'
-#define ELFMAG "\177ELF" /* magic string */
-#define SELFMAG 4 /* magic string size */
-
-/* Values for e_ident[EI_VERSION] and e_version. */
-#define EV_NONE 0
-#define EV_CURRENT 1
-
-/* Values for e_ident[EI_CLASS]. */
-#define ELFCLASSNONE 0 /* Unknown class. */
-#define ELFCLASS32 1 /* 32-bit architecture. */
-#define ELFCLASS64 2 /* 64-bit architecture. */
-
-/* Values for e_ident[EI_DATA]. */
-#define ELFDATANONE 0 /* Unknown data format. */
-#define ELFDATA2LSB 1 /* 2's complement little-endian. */
-#define ELFDATA2MSB 2 /* 2's complement big-endian. */
-
-/* Values for e_ident[EI_OSABI]. */
-#define ELFOSABI_NONE 0 /* UNIX System V ABI */
-#define ELFOSABI_HPUX 1 /* HP-UX operating system */
-#define ELFOSABI_NETBSD 2 /* NetBSD */
-#define ELFOSABI_LINUX 3 /* GNU/Linux */
-#define ELFOSABI_HURD 4 /* GNU/Hurd */
-#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
-#define ELFOSABI_SOLARIS 6 /* Solaris */
-#define ELFOSABI_AIX 7 /* AIX */
-#define ELFOSABI_IRIX 8 /* IRIX */
-#define ELFOSABI_FREEBSD 9 /* FreeBSD */
-#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
-#define ELFOSABI_MODESTO 11 /* Novell Modesto */
-#define ELFOSABI_OPENBSD 12 /* OpenBSD */
-#define ELFOSABI_OPENVMS 13 /* Open VMS */
-#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
-#define ELFOSABI_ARM 97 /* ARM */
-#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
-
-#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */
-#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */
-
-/* e_ident */
-#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
- (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
- (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
- (ehdr).e_ident[EI_MAG3] == ELFMAG3)
-
-/* Values for e_type. */
-#define ET_NONE 0 /* Unknown type. */
-#define ET_REL 1 /* Relocatable. */
-#define ET_EXEC 2 /* Executable. */
-#define ET_DYN 3 /* Shared object. */
-#define ET_CORE 4 /* Core file. */
-#define ET_LOOS 0xfe00 /* First operating system specific. */
-#define ET_HIOS 0xfeff /* Last operating system-specific. */
-#define ET_LOPROC 0xff00 /* First processor-specific. */
-#define ET_HIPROC 0xffff /* Last processor-specific. */
-
-/* Values for e_machine. */
-#define EM_NONE 0 /* Unknown machine. */
-#define EM_M32 1 /* AT&T WE32100. */
-#define EM_SPARC 2 /* Sun SPARC. */
-#define EM_386 3 /* Intel i386. */
-#define EM_68K 4 /* Motorola 68000. */
-#define EM_88K 5 /* Motorola 88000. */
-#define EM_860 7 /* Intel i860. */
-#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */
-#define EM_S370 9 /* IBM System/370. */
-#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */
-#define EM_PARISC 15 /* HP PA-RISC. */
-#define EM_VPP500 17 /* Fujitsu VPP500. */
-#define EM_SPARC32PLUS 18 /* SPARC v8plus. */
-#define EM_960 19 /* Intel 80960. */
-#define EM_PPC 20 /* PowerPC 32-bit. */
-#define EM_PPC64 21 /* PowerPC 64-bit. */
-#define EM_S390 22 /* IBM System/390. */
-#define EM_V800 36 /* NEC V800. */
-#define EM_FR20 37 /* Fujitsu FR20. */
-#define EM_RH32 38 /* TRW RH-32. */
-#define EM_RCE 39 /* Motorola RCE. */
-#define EM_ARM 40 /* ARM. */
-#define EM_SH 42 /* Hitachi SH. */
-#define EM_SPARCV9 43 /* SPARC v9 64-bit. */
-#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */
-#define EM_ARC 45 /* Argonaut RISC Core. */
-#define EM_H8_300 46 /* Hitachi H8/300. */
-#define EM_H8_300H 47 /* Hitachi H8/300H. */
-#define EM_H8S 48 /* Hitachi H8S. */
-#define EM_H8_500 49 /* Hitachi H8/500. */
-#define EM_IA_64 50 /* Intel IA-64 Processor. */
-#define EM_MIPS_X 51 /* Stanford MIPS-X. */
-#define EM_COLDFIRE 52 /* Motorola ColdFire. */
-#define EM_68HC12 53 /* Motorola M68HC12. */
-#define EM_MMA 54 /* Fujitsu MMA. */
-#define EM_PCP 55 /* Siemens PCP. */
-#define EM_NCPU 56 /* Sony nCPU. */
-#define EM_NDR1 57 /* Denso NDR1 microprocessor. */
-#define EM_STARCORE 58 /* Motorola Star*Core processor. */
-#define EM_ME16 59 /* Toyota ME16 processor. */
-#define EM_ST100 60 /* STMicroelectronics ST100 processor. */
-#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */
-#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */
-
-/* Non-standard or deprecated. */
-#define EM_486 6 /* Intel i486. */
-#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
-#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */
-#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */
-
-/* Special section indexes. */
-#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */
-#define SHN_LORESERVE 0xff00 /* First of reserved range. */
-#define SHN_LOPROC 0xff00 /* First processor-specific. */
-#define SHN_HIPROC 0xff1f /* Last processor-specific. */
-#define SHN_LOOS 0xff20 /* First operating system-specific. */
-#define SHN_HIOS 0xff3f /* Last operating system-specific. */
-#define SHN_ABS 0xfff1 /* Absolute values. */
-#define SHN_COMMON 0xfff2 /* Common data. */
-#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */
-#define SHN_HIRESERVE 0xffff /* Last of reserved range. */
-
-/* sh_type */
-#define SHT_NULL 0 /* inactive */
-#define SHT_PROGBITS 1 /* program defined information */
-#define SHT_SYMTAB 2 /* symbol table section */
-#define SHT_STRTAB 3 /* string table section */
-#define SHT_RELA 4 /* relocation section with addends */
-#define SHT_HASH 5 /* symbol hash table section */
-#define SHT_DYNAMIC 6 /* dynamic section */
-#define SHT_NOTE 7 /* note section */
-#define SHT_NOBITS 8 /* no space section */
-#define SHT_REL 9 /* relocation section - no addends */
-#define SHT_SHLIB 10 /* reserved - purpose unknown */
-#define SHT_DYNSYM 11 /* dynamic symbol table section */
-#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */
-#define SHT_FINI_ARRAY 15 /* Termination function pointers. */
-#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */
-#define SHT_GROUP 17 /* Section group. */
-#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */
-#define SHT_LOOS 0x60000000 /* First of OS specific semantics */
-#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */
-#define SHT_GNU_VERDEF 0x6ffffffd
-#define SHT_GNU_VERNEED 0x6ffffffe
-#define SHT_GNU_VERSYM 0x6fffffff
-#define SHT_LOPROC 0x70000000 /* reserved range for processor */
-#define SHT_HIPROC 0x7fffffff /* specific section header types */
-#define SHT_LOUSER 0x80000000 /* reserved range for application */
-#define SHT_HIUSER 0xffffffff /* specific indexes */
-
-/* Flags for sh_flags. */
-#define SHF_WRITE 0x1 /* Section contains writable data. */
-#define SHF_ALLOC 0x2 /* Section occupies memory. */
-#define SHF_EXECINSTR 0x4 /* Section contains instructions. */
-#define SHF_MERGE 0x10 /* Section may be merged. */
-#define SHF_STRINGS 0x20 /* Section contains strings. */
-#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */
-#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */
-#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */
-#define SHF_GROUP 0x200 /* Member of section group. */
-#define SHF_TLS 0x400 /* Section contains TLS data. */
-#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */
-#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */
-
-/* Values for p_type. */
-#define PT_NULL 0 /* Unused entry. */
-#define PT_LOAD 1 /* Loadable segment. */
-#define PT_DYNAMIC 2 /* Dynamic linking information segment. */
-#define PT_INTERP 3 /* Pathname of interpreter. */
-#define PT_NOTE 4 /* Auxiliary information. */
-#define PT_SHLIB 5 /* Reserved (not used). */
-#define PT_PHDR 6 /* Location of program header itself. */
-#define PT_TLS 7 /* Thread local storage segment */
-#define PT_LOOS 0x60000000 /* First OS-specific. */
-#define PT_HIOS 0x6fffffff /* Last OS-specific. */
-#define PT_LOPROC 0x70000000 /* First processor-specific type. */
-#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */
-#define PT_GNU_STACK 0x6474e551
-
-/* Values for p_flags. */
-#define PF_X 0x1 /* Executable. */
-#define PF_W 0x2 /* Writable. */
-#define PF_R 0x4 /* Readable. */
-#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */
-#define PF_MASKPROC 0xf0000000 /* Processor-specific. */
-
-/* Values for d_tag. */
-#define DT_NULL 0 /* Terminating entry. */
-/* String table offset of a needed shared library. */
-#define DT_NEEDED 1
-#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */
-#define DT_PLTGOT 3 /* Processor-dependent address. */
-#define DT_HASH 4 /* Address of symbol hash table. */
-#define DT_STRTAB 5 /* Address of string table. */
-#define DT_SYMTAB 6 /* Address of symbol table. */
-#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */
-#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */
-#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */
-#define DT_STRSZ 10 /* Size of string table. */
-#define DT_SYMENT 11 /* Size of each symbol table entry. */
-#define DT_INIT 12 /* Address of initialization function. */
-#define DT_FINI 13 /* Address of finalization function. */
-/* String table offset of shared object name. */
-#define DT_SONAME 14
-#define DT_RPATH 15 /* String table offset of library path. [sup] */
-#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */
-#define DT_REL 17 /* Address of ElfNN_Rel relocations. */
-#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */
-#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */
-#define DT_PLTREL 20 /* Type of relocation used for PLT. */
-#define DT_DEBUG 21 /* Reserved (not used). */
-/* Indicates there may be relocations in non-writable segments. [sup] */
-#define DT_TEXTREL 22
-#define DT_JMPREL 23 /* Address of PLT relocations. */
-#define DT_BIND_NOW 24 /* [sup] */
-/* Address of the array of pointers to initialization functions */
-#define DT_INIT_ARRAY 25
-/* Address of the array of pointers to termination functions */
-#define DT_FINI_ARRAY 26
-/* Size in bytes of the array of initialization functions. */
-#define DT_INIT_ARRAYSZ 27
-/* Size in bytes of the array of terminationfunctions. */
-#define DT_FINI_ARRAYSZ 28
-/* String table offset of a null-terminated library search path string. */
-#define DT_RUNPATH 29
-#define DT_FLAGS 30 /* Object specific flag values. */
-/* Values greater than or equal to DT_ENCODING and less than
- DT_LOOS follow the rules for the interpretation of the d_un
- union as follows: even == 'd_ptr', even == 'd_val' or none */
-#define DT_ENCODING 32
-/* Address of the array of pointers to pre-initialization functions. */
-#define DT_PREINIT_ARRAY 32
-/* Size in bytes of the array of pre-initialization functions. */
-#define DT_PREINIT_ARRAYSZ 33
-#define DT_LOOS 0x6000000d /* First OS-specific */
-#define DT_HIOS 0x6ffff000 /* Last OS-specific */
-#define DT_LOPROC 0x70000000 /* First processor-specific type. */
-#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */
-
-#define DT_VERNEED 0x6ffffffe
-#define DT_VERNEEDNUM 0x6fffffff
-#define DT_VERSYM 0x6ffffff0
-
-/* Values for DT_FLAGS */
-/* Indicates that the object being loaded may make reference to
- the $ORIGIN substitution string */
-#define DF_ORIGIN 0x0001
-#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */
-/* Indicates there may be relocations in non-writable segments. */
-#define DF_TEXTREL 0x0004
-/* Indicates that the dynamic linker should process all
- relocations for the object containing this entry before
- transferring control to the program. */
-#define DF_BIND_NOW 0x0008
-/* Indicates that the shared object or executable contains code
- using a static thread-local storage scheme. */
-#define DF_STATIC_TLS 0x0010
-
-/* Values for n_type. Used in core files. */
-#define NT_PRSTATUS 1 /* Process status. */
-#define NT_FPREGSET 2 /* Floating point registers. */
-#define NT_PRPSINFO 3 /* Process state info. */
-
-/* Symbol Binding - ELFNN_ST_BIND - st_info */
-#define STB_LOCAL 0 /* Local symbol */
-#define STB_GLOBAL 1 /* Global symbol */
-#define STB_WEAK 2 /* like global - lower precedence */
-#define STB_LOOS 10 /* Reserved range for operating system */
-#define STB_HIOS 12 /* specific semantics. */
-#define STB_LOPROC 13 /* reserved range for processor */
-#define STB_HIPROC 15 /* specific semantics. */
-
-/* Symbol type - ELFNN_ST_TYPE - st_info */
-#define STT_NOTYPE 0 /* Unspecified type. */
-#define STT_OBJECT 1 /* Data object. */
-#define STT_FUNC 2 /* Function. */
-#define STT_SECTION 3 /* Section. */
-#define STT_FILE 4 /* Source file. */
-#define STT_COMMON 5 /* Uninitialized common block. */
-#define STT_TLS 6 /* TLS object. */
-#define STT_LOOS 10 /* Reserved range for operating system */
-#define STT_HIOS 12 /* specific semantics. */
-#define STT_LOPROC 13 /* reserved range for processor */
-#define STT_HIPROC 15 /* specific semantics. */
-
-/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */
-#define STV_DEFAULT 0x0 /* Default visibility (see binding). */
-#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */
-#define STV_HIDDEN 0x2 /* Not visible. */
-#define STV_PROTECTED 0x3 /* Visible but not preemptible. */
-
-/* Special symbol table indexes. */
-#define STN_UNDEF 0 /* Undefined symbol index. */
-
-/*
- * ELF definitions common to all 32-bit architectures.
- */
-
-typedef uint32 Elf32_Addr;
-typedef uint16 Elf32_Half;
-typedef uint32 Elf32_Off;
-typedef int32 Elf32_Sword;
-typedef uint32 Elf32_Word;
-
-typedef Elf32_Word Elf32_Hashelt;
-
-/* Non-standard class-dependent datatype used for abstraction. */
-typedef Elf32_Word Elf32_Size;
-typedef Elf32_Sword Elf32_Ssize;
-
-/*
- * ELF header.
- */
-
-typedef struct {
- unsigned char ident[EI_NIDENT]; /* File identification. */
- Elf32_Half type; /* File type. */
- Elf32_Half machine; /* Machine architecture. */
- Elf32_Word version; /* ELF format version. */
- Elf32_Addr entry; /* Entry point. */
- Elf32_Off phoff; /* Program header file offset. */
- Elf32_Off shoff; /* Section header file offset. */
- Elf32_Word flags; /* Architecture-specific flags. */
- Elf32_Half ehsize; /* Size of ELF header in bytes. */
- Elf32_Half phentsize; /* Size of program header entry. */
- Elf32_Half phnum; /* Number of program header entries. */
- Elf32_Half shentsize; /* Size of section header entry. */
- Elf32_Half shnum; /* Number of section header entries. */
- Elf32_Half shstrndx; /* Section name strings section. */
-} Elf32_Ehdr;
-
-/*
- * Section header.
- */
-
-typedef struct {
- Elf32_Word name; /* Section name (index into the
- section header string table). */
- Elf32_Word type; /* Section type. */
- Elf32_Word flags; /* Section flags. */
- Elf32_Addr vaddr; /* Address in memory image. */
- Elf32_Off off; /* Offset in file. */
- Elf32_Word size; /* Size in bytes. */
- Elf32_Word link; /* Index of a related section. */
- Elf32_Word info; /* Depends on section type. */
- Elf32_Word addralign; /* Alignment in bytes. */
- Elf32_Word entsize; /* Size of each entry in section. */
-} Elf32_Shdr;
-
-/*
- * Program header.
- */
-
-typedef struct {
- Elf32_Word type; /* Entry type. */
- Elf32_Off off; /* File offset of contents. */
- Elf32_Addr vaddr; /* Virtual address in memory image. */
- Elf32_Addr paddr; /* Physical address (not used). */
- Elf32_Word filesz; /* Size of contents in file. */
- Elf32_Word memsz; /* Size of contents in memory. */
- Elf32_Word flags; /* Access permission flags. */
- Elf32_Word align; /* Alignment in memory and file. */
-} Elf32_Phdr;
-
-/*
- * Dynamic structure. The ".dynamic" section contains an array of them.
- */
-
-typedef struct {
- Elf32_Sword d_tag; /* Entry type. */
- union {
- Elf32_Word d_val; /* Integer value. */
- Elf32_Addr d_ptr; /* Address value. */
- } d_un;
-} Elf32_Dyn;
-
-/*
- * Relocation entries.
- */
-
-/* Relocations that don't need an addend field. */
-typedef struct {
- Elf32_Addr off; /* Location to be relocated. */
- Elf32_Word info; /* Relocation type and symbol index. */
-} Elf32_Rel;
-
-/* Relocations that need an addend field. */
-typedef struct {
- Elf32_Addr off; /* Location to be relocated. */
- Elf32_Word info; /* Relocation type and symbol index. */
- Elf32_Sword addend; /* Addend. */
-} Elf32_Rela;
-
-/* Macros for accessing the fields of r_info. */
-#define ELF32_R_SYM(info) ((info) >> 8)
-#define ELF32_R_TYPE(info) ((unsigned char)(info))
-
-/* Macro for constructing r_info from field values. */
-#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type))
-
-/*
- * Relocation types.
- */
-
-#define R_X86_64_NONE 0 /* No relocation. */
-#define R_X86_64_64 1 /* Add 64 bit symbol value. */
-#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */
-#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */
-#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */
-#define R_X86_64_COPY 5 /* Copy data from shared object. */
-#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */
-#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */
-#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */
-#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */
-#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */
-#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */
-#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */
-#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */
-#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */
-#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */
-#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
-#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */
-#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */
-#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */
-#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */
-#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
-#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */
-#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */
-
-#define R_X86_64_COUNT 24 /* Count of defined relocation types. */
-
-
-#define R_ALPHA_NONE 0 /* No reloc */
-#define R_ALPHA_REFLONG 1 /* Direct 32 bit */
-#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
-#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
-#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
-#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
-#define R_ALPHA_GPDISP 6 /* Add displacement to GP */
-#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
-#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
-#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
-#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
-#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
-#define R_ALPHA_OP_PUSH 12 /* OP stack push */
-#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */
-#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */
-#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */
-#define R_ALPHA_GPVALUE 16
-#define R_ALPHA_GPRELHIGH 17
-#define R_ALPHA_GPRELLOW 18
-#define R_ALPHA_IMMED_GP_16 19
-#define R_ALPHA_IMMED_GP_HI32 20
-#define R_ALPHA_IMMED_SCN_HI32 21
-#define R_ALPHA_IMMED_BR_HI32 22
-#define R_ALPHA_IMMED_LO32 23
-#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
-#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
-#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
-#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
-
-#define R_ALPHA_COUNT 28
-
-
-#define R_ARM_NONE 0 /* No relocation. */
-#define R_ARM_PC24 1
-#define R_ARM_ABS32 2
-#define R_ARM_REL32 3
-#define R_ARM_PC13 4
-#define R_ARM_ABS16 5
-#define R_ARM_ABS12 6
-#define R_ARM_THM_ABS5 7
-#define R_ARM_ABS8 8
-#define R_ARM_SBREL32 9
-#define R_ARM_THM_PC22 10
-#define R_ARM_THM_PC8 11
-#define R_ARM_AMP_VCALL9 12
-#define R_ARM_SWI24 13
-#define R_ARM_THM_SWI8 14
-#define R_ARM_XPC25 15
-#define R_ARM_THM_XPC22 16
-#define R_ARM_COPY 20 /* Copy data from shared object. */
-#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */
-#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */
-#define R_ARM_RELATIVE 23 /* Add load address of shared object. */
-#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */
-#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */
-#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */
-#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */
-#define R_ARM_GNU_VTENTRY 100
-#define R_ARM_GNU_VTINHERIT 101
-#define R_ARM_RSBREL32 250
-#define R_ARM_THM_RPC22 251
-#define R_ARM_RREL32 252
-#define R_ARM_RABS32 253
-#define R_ARM_RPC24 254
-#define R_ARM_RBASE 255
-
-#define R_ARM_COUNT 33 /* Count of defined relocation types. */
-
-
-#define R_386_NONE 0 /* No relocation. */
-#define R_386_32 1 /* Add symbol value. */
-#define R_386_PC32 2 /* Add PC-relative symbol value. */
-#define R_386_GOT32 3 /* Add PC-relative GOT offset. */
-#define R_386_PLT32 4 /* Add PC-relative PLT offset. */
-#define R_386_COPY 5 /* Copy data from shared object. */
-#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */
-#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */
-#define R_386_RELATIVE 8 /* Add load address of shared object. */
-#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */
-#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */
-#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */
-#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */
-#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */
-#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */
-#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */
-#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */
-#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */
-#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */
-#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */
-#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */
-#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */
-#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */
-#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */
-#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */
-#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */
-#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */
-#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */
-#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */
-#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */
-#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */
-
-#define R_386_COUNT 38 /* Count of defined relocation types. */
-
-#define R_PPC_NONE 0 /* No relocation. */
-#define R_PPC_ADDR32 1
-#define R_PPC_ADDR24 2
-#define R_PPC_ADDR16 3
-#define R_PPC_ADDR16_LO 4
-#define R_PPC_ADDR16_HI 5
-#define R_PPC_ADDR16_HA 6
-#define R_PPC_ADDR14 7
-#define R_PPC_ADDR14_BRTAKEN 8
-#define R_PPC_ADDR14_BRNTAKEN 9
-#define R_PPC_REL24 10
-#define R_PPC_REL14 11
-#define R_PPC_REL14_BRTAKEN 12
-#define R_PPC_REL14_BRNTAKEN 13
-#define R_PPC_GOT16 14
-#define R_PPC_GOT16_LO 15
-#define R_PPC_GOT16_HI 16
-#define R_PPC_GOT16_HA 17
-#define R_PPC_PLTREL24 18
-#define R_PPC_COPY 19
-#define R_PPC_GLOB_DAT 20
-#define R_PPC_JMP_SLOT 21
-#define R_PPC_RELATIVE 22
-#define R_PPC_LOCAL24PC 23
-#define R_PPC_UADDR32 24
-#define R_PPC_UADDR16 25
-#define R_PPC_REL32 26
-#define R_PPC_PLT32 27
-#define R_PPC_PLTREL32 28
-#define R_PPC_PLT16_LO 29
-#define R_PPC_PLT16_HI 30
-#define R_PPC_PLT16_HA 31
-#define R_PPC_SDAREL16 32
-#define R_PPC_SECTOFF 33
-#define R_PPC_SECTOFF_LO 34
-#define R_PPC_SECTOFF_HI 35
-#define R_PPC_SECTOFF_HA 36
-
-#define R_PPC_COUNT 37 /* Count of defined relocation types. */
-
-#define R_PPC_TLS 67
-#define R_PPC_DTPMOD32 68
-#define R_PPC_TPREL16 69
-#define R_PPC_TPREL16_LO 70
-#define R_PPC_TPREL16_HI 71
-#define R_PPC_TPREL16_HA 72
-#define R_PPC_TPREL32 73
-#define R_PPC_DTPREL16 74
-#define R_PPC_DTPREL16_LO 75
-#define R_PPC_DTPREL16_HI 76
-#define R_PPC_DTPREL16_HA 77
-#define R_PPC_DTPREL32 78
-#define R_PPC_GOT_TLSGD16 79
-#define R_PPC_GOT_TLSGD16_LO 80
-#define R_PPC_GOT_TLSGD16_HI 81
-#define R_PPC_GOT_TLSGD16_HA 82
-#define R_PPC_GOT_TLSLD16 83
-#define R_PPC_GOT_TLSLD16_LO 84
-#define R_PPC_GOT_TLSLD16_HI 85
-#define R_PPC_GOT_TLSLD16_HA 86
-#define R_PPC_GOT_TPREL16 87
-#define R_PPC_GOT_TPREL16_LO 88
-#define R_PPC_GOT_TPREL16_HI 89
-#define R_PPC_GOT_TPREL16_HA 90
-
-#define R_PPC_EMB_NADDR32 101
-#define R_PPC_EMB_NADDR16 102
-#define R_PPC_EMB_NADDR16_LO 103
-#define R_PPC_EMB_NADDR16_HI 104
-#define R_PPC_EMB_NADDR16_HA 105
-#define R_PPC_EMB_SDAI16 106
-#define R_PPC_EMB_SDA2I16 107
-#define R_PPC_EMB_SDA2REL 108
-#define R_PPC_EMB_SDA21 109
-#define R_PPC_EMB_MRKREF 110
-#define R_PPC_EMB_RELSEC16 111
-#define R_PPC_EMB_RELST_LO 112
-#define R_PPC_EMB_RELST_HI 113
-#define R_PPC_EMB_RELST_HA 114
-#define R_PPC_EMB_BIT_FLD 115
-#define R_PPC_EMB_RELSDA 116
-
- /* Count of defined relocation types. */
-#define R_PPC_EMB_COUNT (R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1)
-
-
-#define R_SPARC_NONE 0
-#define R_SPARC_8 1
-#define R_SPARC_16 2
-#define R_SPARC_32 3
-#define R_SPARC_DISP8 4
-#define R_SPARC_DISP16 5
-#define R_SPARC_DISP32 6
-#define R_SPARC_WDISP30 7
-#define R_SPARC_WDISP22 8
-#define R_SPARC_HI22 9
-#define R_SPARC_22 10
-#define R_SPARC_13 11
-#define R_SPARC_LO10 12
-#define R_SPARC_GOT10 13
-#define R_SPARC_GOT13 14
-#define R_SPARC_GOT22 15
-#define R_SPARC_PC10 16
-#define R_SPARC_PC22 17
-#define R_SPARC_WPLT30 18
-#define R_SPARC_COPY 19
-#define R_SPARC_GLOB_DAT 20
-#define R_SPARC_JMP_SLOT 21
-#define R_SPARC_RELATIVE 22
-#define R_SPARC_UA32 23
-#define R_SPARC_PLT32 24
-#define R_SPARC_HIPLT22 25
-#define R_SPARC_LOPLT10 26
-#define R_SPARC_PCPLT32 27
-#define R_SPARC_PCPLT22 28
-#define R_SPARC_PCPLT10 29
-#define R_SPARC_10 30
-#define R_SPARC_11 31
-#define R_SPARC_64 32
-#define R_SPARC_OLO10 33
-#define R_SPARC_HH22 34
-#define R_SPARC_HM10 35
-#define R_SPARC_LM22 36
-#define R_SPARC_PC_HH22 37
-#define R_SPARC_PC_HM10 38
-#define R_SPARC_PC_LM22 39
-#define R_SPARC_WDISP16 40
-#define R_SPARC_WDISP19 41
-#define R_SPARC_GLOB_JMP 42
-#define R_SPARC_7 43
-#define R_SPARC_5 44
-#define R_SPARC_6 45
-#define R_SPARC_DISP64 46
-#define R_SPARC_PLT64 47
-#define R_SPARC_HIX22 48
-#define R_SPARC_LOX10 49
-#define R_SPARC_H44 50
-#define R_SPARC_M44 51
-#define R_SPARC_L44 52
-#define R_SPARC_REGISTER 53
-#define R_SPARC_UA64 54
-#define R_SPARC_UA16 55
-
-
-/*
- * Magic number for the elf trampoline, chosen wisely to be an immediate
- * value.
- */
-#define ARM_MAGIC_TRAMP_NUMBER 0x5c000003
-
-
-/*
- * Symbol table entries.
- */
-
-typedef struct {
- Elf32_Word name; /* String table index of name. */
- Elf32_Addr value; /* Symbol value. */
- Elf32_Word size; /* Size of associated object. */
- unsigned char info; /* Type and binding information. */
- unsigned char other; /* Reserved (not used). */
- Elf32_Half shndx; /* Section index of symbol. */
-} Elf32_Sym;
-
-/* Macros for accessing the fields of st_info. */
-#define ELF32_ST_BIND(info) ((info) >> 4)
-#define ELF32_ST_TYPE(info) ((info) & 0xf)
-
-/* Macro for constructing st_info from field values. */
-#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
-
-/* Macro for accessing the fields of st_other. */
-#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3)
-
-/*
- * ELF definitions common to all 64-bit architectures.
- */
-
-typedef uint64 Elf64_Addr;
-typedef uint16 Elf64_Half;
-typedef uint64 Elf64_Off;
-typedef int32 Elf64_Sword;
-typedef int64 Elf64_Sxword;
-typedef uint32 Elf64_Word;
-typedef uint64 Elf64_Xword;
-
-/*
- * Types of dynamic symbol hash table bucket and chain elements.
- *
- * This is inconsistent among 64 bit architectures, so a machine dependent
- * typedef is required.
- */
-
-#ifdef __alpha__
-typedef Elf64_Off Elf64_Hashelt;
-#else
-typedef Elf64_Word Elf64_Hashelt;
-#endif
-
-/* Non-standard class-dependent datatype used for abstraction. */
-typedef Elf64_Xword Elf64_Size;
-typedef Elf64_Sxword Elf64_Ssize;
-
-/*
- * ELF header.
- */
-
-typedef struct {
- unsigned char ident[EI_NIDENT]; /* File identification. */
- Elf64_Half type; /* File type. */
- Elf64_Half machine; /* Machine architecture. */
- Elf64_Word version; /* ELF format version. */
- Elf64_Addr entry; /* Entry point. */
- Elf64_Off phoff; /* Program header file offset. */
- Elf64_Off shoff; /* Section header file offset. */
- Elf64_Word flags; /* Architecture-specific flags. */
- Elf64_Half ehsize; /* Size of ELF header in bytes. */
- Elf64_Half phentsize; /* Size of program header entry. */
- Elf64_Half phnum; /* Number of program header entries. */
- Elf64_Half shentsize; /* Size of section header entry. */
- Elf64_Half shnum; /* Number of section header entries. */
- Elf64_Half shstrndx; /* Section name strings section. */
-} Elf64_Ehdr;
-
-/*
- * Section header.
- */
-
-typedef struct {
- Elf64_Word name; /* Section name (index into the
- section header string table). */
- Elf64_Word type; /* Section type. */
- Elf64_Xword flags; /* Section flags. */
- Elf64_Addr addr; /* Address in memory image. */
- Elf64_Off off; /* Offset in file. */
- Elf64_Xword size; /* Size in bytes. */
- Elf64_Word link; /* Index of a related section. */
- Elf64_Word info; /* Depends on section type. */
- Elf64_Xword addralign; /* Alignment in bytes. */
- Elf64_Xword entsize; /* Size of each entry in section. */
-} Elf64_Shdr;
-
-/*
- * Program header.
- */
-
-typedef struct {
- Elf64_Word type; /* Entry type. */
- Elf64_Word flags; /* Access permission flags. */
- Elf64_Off off; /* File offset of contents. */
- Elf64_Addr vaddr; /* Virtual address in memory image. */
- Elf64_Addr paddr; /* Physical address (not used). */
- Elf64_Xword filesz; /* Size of contents in file. */
- Elf64_Xword memsz; /* Size of contents in memory. */
- Elf64_Xword align; /* Alignment in memory and file. */
-} Elf64_Phdr;
-
-/*
- * Dynamic structure. The ".dynamic" section contains an array of them.
- */
-
-typedef struct {
- Elf64_Sxword d_tag; /* Entry type. */
- union {
- Elf64_Xword d_val; /* Integer value. */
- Elf64_Addr d_ptr; /* Address value. */
- } d_un;
-} Elf64_Dyn;
-
-/*
- * Relocation entries.
- */
-
-/* Relocations that don't need an addend field. */
-typedef struct {
- Elf64_Addr off; /* Location to be relocated. */
- Elf64_Xword info; /* Relocation type and symbol index. */
-} Elf64_Rel;
-
-/* Relocations that need an addend field. */
-typedef struct {
- Elf64_Addr off; /* Location to be relocated. */
- Elf64_Xword info; /* Relocation type and symbol index. */
- Elf64_Sxword addend; /* Addend. */
-} Elf64_Rela;
-
-/* Macros for accessing the fields of r_info. */
-#define ELF64_R_SYM(info) ((info) >> 32)
-#define ELF64_R_TYPE(info) ((info) & 0xffffffffL)
-
-/* Macro for constructing r_info from field values. */
-#define ELF64_R_INFO(sym, type) ((((uint64)(sym)) << 32) + (((uint64)(type)) & 0xffffffffULL))
-
-/*
- * Symbol table entries.
- */
-
-typedef struct {
- Elf64_Word name; /* String table index of name. */
- unsigned char info; /* Type and binding information. */
- unsigned char other; /* Reserved (not used). */
- Elf64_Half shndx; /* Section index of symbol. */
- Elf64_Addr value; /* Symbol value. */
- Elf64_Xword size; /* Size of associated object. */
-} Elf64_Sym;
-
-/* Macros for accessing the fields of st_info. */
-#define ELF64_ST_BIND(info) ((info) >> 4)
-#define ELF64_ST_TYPE(info) ((info) & 0xf)
-
-/* Macro for constructing st_info from field values. */
-#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
-
-/* Macro for accessing the fields of st_other. */
-#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3)
-
-/*
- * Go linker interface
- */
-
-#define ELF64HDRSIZE 64
-#define ELF64PHDRSIZE 56
-#define ELF64SHDRSIZE 64
-#define ELF64RELSIZE 16
-#define ELF64RELASIZE 24
-#define ELF64SYMSIZE sizeof(Elf64_Sym)
-
-#define ELF32HDRSIZE sizeof(Elf32_Ehdr)
-#define ELF32PHDRSIZE sizeof(Elf32_Phdr)
-#define ELF32SHDRSIZE sizeof(Elf32_Shdr)
-#define ELF32SYMSIZE sizeof(Elf32_Sym)
-#define ELF32RELSIZE 8
-
-/*
- * The interface uses the 64-bit structures always,
- * to avoid code duplication. The writers know how to
- * marshal a 32-bit representation from the 64-bit structure.
- */
-typedef Elf64_Ehdr ElfEhdr;
-typedef Elf64_Shdr ElfShdr;
-typedef Elf64_Phdr ElfPhdr;
-
-void elfinit(void);
-ElfEhdr *getElfEhdr(void);
-ElfShdr *newElfShstrtab(vlong);
-ElfShdr *newElfShdr(vlong);
-ElfPhdr *newElfPhdr(void);
-uint32 elfwritehdr(void);
-uint32 elfwritephdrs(void);
-uint32 elfwriteshdrs(void);
-void elfwritedynent(Sym*, int, uint64);
-void elfwritedynentsym(Sym*, int, Sym*);
-void elfwritedynentsymsize(Sym*, int, Sym*);
-uint32 elfhash(uchar*);
-uint64 startelf(void);
-uint64 endelf(void);
-extern int numelfphdr;
-extern int numelfshdr;
-extern int iself;
-extern int elfverneed;
-int elfwriteinterp(void);
-void elfinterp(ElfShdr*, uint64, char*);
-void elfdynhash(void);
-ElfPhdr* elfphload(Segment*);
-ElfShdr* elfshbits(Section*);
-void elfsetstring(char*, int);
-void elfaddverneed(Sym*);
-
-EXTERN int elfstrsize;
-EXTERN char* elfstrdat;
-EXTERN int elftextsh;
-
-/*
- * Total amount of space to reserve at the start of the file
- * for Header, PHeaders, SHeaders, and interp.
- * May waste some.
- * On FreeBSD, cannot be larger than a page.
- */
-#define ELFRESERVE 3072
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
deleted file mode 100644
index 05d1cc136..000000000
--- a/src/cmd/ld/go.c
+++ /dev/null
@@ -1,710 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// go-specific code shared across loaders (5l, 6l, 8l).
-
-#include "l.h"
-#include "../ld/lib.h"
-
-// accumulate all type information from .6 files.
-// check for inconsistencies.
-
-// TODO:
-// generate debugging section in binary.
-// once the dust settles, try to move some code to
-// libmach, so that other linkers and ar can share.
-
-/*
- * package import data
- */
-typedef struct Import Import;
-struct Import
-{
- Import *hash; // next in hash table
- char *prefix; // "type", "var", "func", "const"
- char *name;
- char *def;
- char *file;
-};
-enum {
- NIHASH = 1024
-};
-static Import *ihash[NIHASH];
-static int nimport;
-
-static int
-hashstr(char *name)
-{
- int h;
- char *cp;
-
- h = 0;
- for(cp = name; *cp; h += *cp++)
- h *= 1119;
- // not if(h < 0) h = ~h, because gcc 4.3 -O2 miscompiles it.
- h &= 0xffffff;
- return h;
-}
-
-static Import *
-ilookup(char *name)
-{
- int h;
- Import *x;
-
- h = hashstr(name) % NIHASH;
- for(x=ihash[h]; x; x=x->hash)
- if(x->name[0] == name[0] && strcmp(x->name, name) == 0)
- return x;
- x = mal(sizeof *x);
- x->name = strdup(name);
- x->hash = ihash[h];
- ihash[h] = x;
- nimport++;
- return x;
-}
-
-static void loadpkgdata(char*, char*, char*, int);
-static void loaddynimport(char*, char*, char*, int);
-static void loaddynexport(char*, char*, char*, int);
-static int parsemethod(char**, char*, char**);
-static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**);
-
-static Sym **dynexp;
-
-void
-ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence)
-{
- char *data, *p0, *p1, *name;
-
- if(debug['g'])
- return;
-
- if((int)len != len) {
- fprint(2, "%s: too much pkg data in %s\n", argv0, filename);
- if(debug['u'])
- errorexit();
- return;
- }
- data = mal(len+1);
- if(Bread(f, data, len) != len) {
- fprint(2, "%s: short pkg read %s\n", argv0, filename);
- if(debug['u'])
- errorexit();
- return;
- }
- data[len] = '\0';
-
- // first \n$$ marks beginning of exports - skip rest of line
- p0 = strstr(data, "\n$$");
- if(p0 == nil) {
- if(debug['u'] && whence != ArchiveObj) {
- fprint(2, "%s: cannot find export data in %s\n", argv0, filename);
- errorexit();
- }
- return;
- }
- p0 += 3;
- while(*p0 != '\n' && *p0 != '\0')
- p0++;
-
- // second marks end of exports / beginning of local data
- p1 = strstr(p0, "\n$$");
- if(p1 == nil) {
- fprint(2, "%s: cannot find end of exports in %s\n", argv0, filename);
- if(debug['u'])
- errorexit();
- return;
- }
- while(p0 < p1 && (*p0 == ' ' || *p0 == '\t' || *p0 == '\n'))
- p0++;
- if(p0 < p1) {
- if(strncmp(p0, "package ", 8) != 0) {
- fprint(2, "%s: bad package section in %s - %s\n", argv0, filename, p0);
- if(debug['u'])
- errorexit();
- return;
- }
- p0 += 8;
- while(p0 < p1 && (*p0 == ' ' || *p0 == '\t' || *p0 == '\n'))
- p0++;
- name = p0;
- while(p0 < p1 && *p0 != ' ' && *p0 != '\t' && *p0 != '\n')
- p0++;
- if(debug['u'] && whence != ArchiveObj &&
- (p0+6 > p1 || memcmp(p0, " safe\n", 6) != 0)) {
- fprint(2, "%s: load of unsafe package %s\n", argv0, filename);
- nerrors++;
- errorexit();
- }
- if(p0 < p1) {
- if(*p0 == '\n')
- *p0++ = '\0';
- else {
- *p0++ = '\0';
- while(p0 < p1 && *p0++ != '\n')
- ;
- }
- }
- if(strcmp(pkg, "main") == 0 && strcmp(name, "main") != 0)
- fprint(2, "%s: %s: not package main (package %s)\n", argv0, filename, name);
- loadpkgdata(filename, pkg, p0, p1 - p0);
- }
-
- // The __.PKGDEF archive summary has no local types.
- if(whence == Pkgdef)
- return;
-
- // local types begin where exports end.
- // skip rest of line after $$ we found above
- p0 = p1 + 3;
- while(*p0 != '\n' && *p0 != '\0')
- p0++;
-
- // local types end at next \n$$.
- p1 = strstr(p0, "\n$$");
- if(p1 == nil) {
- fprint(2, "%s: cannot find end of local types in %s\n", argv0, filename);
- if(debug['u'])
- errorexit();
- return;
- }
-
- loadpkgdata(filename, pkg, p0, p1 - p0);
-
- // look for dynimport section
- p0 = strstr(p1, "\n$$ // dynimport");
- if(p0 != nil) {
- p0 = strchr(p0+1, '\n');
- if(p0 == nil) {
- fprint(2, "%s: found $$ // dynimport but no newline in %s\n", argv0, filename);
- if(debug['u'])
- errorexit();
- return;
- }
- p1 = strstr(p0, "\n$$");
- if(p1 == nil)
- p1 = strstr(p0, "\n!\n");
- if(p1 == nil) {
- fprint(2, "%s: cannot find end of // dynimport section in %s\n", argv0, filename);
- if(debug['u'])
- errorexit();
- return;
- }
- loaddynimport(filename, pkg, p0 + 1, p1 - (p0+1));
- }
-
- // look for dynexp section
- p0 = strstr(p1, "\n$$ // dynexport");
- if(p0 != nil) {
- p0 = strchr(p0+1, '\n');
- if(p0 == nil) {
- fprint(2, "%s: found $$ // dynexporg but no newline in %s\n", argv0, filename);
- if(debug['u'])
- errorexit();
- return;
- }
- p1 = strstr(p0, "\n$$");
- if(p1 == nil)
- p1 = strstr(p0, "\n!\n");
- if(p1 == nil) {
- fprint(2, "%s: cannot find end of // dynexporg section in %s\n", argv0, filename);
- if(debug['u'])
- errorexit();
- return;
- }
- loaddynexport(filename, pkg, p0 + 1, p1 - (p0+1));
- }
-}
-
-static void
-loadpkgdata(char *file, char *pkg, char *data, int len)
-{
- char *p, *ep, *prefix, *name, *def;
- Import *x;
-
- file = strdup(file);
- p = data;
- ep = data + len;
- while(parsepkgdata(file, pkg, &p, ep, &prefix, &name, &def) > 0) {
- x = ilookup(name);
- if(x->prefix == nil) {
- x->prefix = prefix;
- x->def = def;
- x->file = file;
- } else if(strcmp(x->prefix, prefix) != 0) {
- fprint(2, "%s: conflicting definitions for %s\n", argv0, name);
- fprint(2, "%s:\t%s %s ...\n", x->file, x->prefix, name);
- fprint(2, "%s:\t%s %s ...\n", file, prefix, name);
- nerrors++;
- } else if(strcmp(x->def, def) != 0) {
- fprint(2, "%s: conflicting definitions for %s\n", argv0, name);
- fprint(2, "%s:\t%s %s %s\n", x->file, x->prefix, name, x->def);
- fprint(2, "%s:\t%s %s %s\n", file, prefix, name, def);
- nerrors++;
- }
- }
-}
-
-// replace all "". with pkg.
-char*
-expandpkg(char *t0, char *pkg)
-{
- int n;
- char *p;
- char *w, *w0, *t;
-
- n = 0;
- for(p=t0; (p=strstr(p, "\"\".")) != nil; p+=3)
- n++;
-
- if(n == 0)
- return t0;
-
- // use malloc, not mal, so that caller can free
- w0 = malloc(strlen(t0) + strlen(pkg)*n);
- if(w0 == nil) {
- diag("out of memory");
- errorexit();
- }
- w = w0;
- for(p=t=t0; (p=strstr(p, "\"\".")) != nil; p=t) {
- memmove(w, t, p - t);
- w += p-t;
- strcpy(w, pkg);
- w += strlen(pkg);
- t = p+2;
- }
- strcpy(w, t);
- return w0;
-}
-
-static int
-parsepkgdata(char *file, char *pkg, char **pp, char *ep, char **prefixp, char **namep, char **defp)
-{
- char *p, *prefix, *name, *def, *edef, *meth;
- int n, inquote;
-
- // skip white space
- p = *pp;
-loop:
- while(p < ep && (*p == ' ' || *p == '\t' || *p == '\n'))
- p++;
- if(p == ep || strncmp(p, "$$\n", 3) == 0)
- return 0;
-
- // prefix: (var|type|func|const)
- prefix = p;
- if(p + 7 > ep)
- return -1;
- if(strncmp(p, "var ", 4) == 0)
- p += 4;
- else if(strncmp(p, "type ", 5) == 0)
- p += 5;
- else if(strncmp(p, "func ", 5) == 0)
- p += 5;
- else if(strncmp(p, "const ", 6) == 0)
- p += 6;
- else if(strncmp(p, "import ", 7) == 0) {
- p += 7;
- while(p < ep && *p != '\n')
- p++;
- goto loop;
- }
- else {
- fprint(2, "%s: confused in pkg data near <<%.40s>>\n", argv0, prefix);
- nerrors++;
- return -1;
- }
- p[-1] = '\0';
-
- // name: a.b followed by space
- name = p;
- inquote = 0;
- while(p < ep) {
- if (*p == ' ' && !inquote)
- break;
-
- if(*p == '\\')
- p++;
- else if(*p == '"')
- inquote = !inquote;
-
- p++;
- }
-
- if(p >= ep)
- return -1;
- *p++ = '\0';
-
- // def: free form to new line
- def = p;
- while(p < ep && *p != '\n')
- p++;
- if(p >= ep)
- return -1;
- edef = p;
- *p++ = '\0';
-
- // include methods on successive lines in def of named type
- while(parsemethod(&p, ep, &meth) > 0) {
- *edef++ = '\n'; // overwrites '\0'
- if(edef+1 > meth) {
- // We want to indent methods with a single \t.
- // 6g puts at least one char of indent before all method defs,
- // so there will be room for the \t. If the method def wasn't
- // indented we could do something more complicated,
- // but for now just diagnose the problem and assume
- // 6g will keep indenting for us.
- fprint(2, "%s: %s: expected methods to be indented %p %p %.10s\n", argv0,
- file, edef, meth, meth);
- nerrors++;
- return -1;
- }
- *edef++ = '\t';
- n = strlen(meth);
- memmove(edef, meth, n);
- edef += n;
- }
-
- name = expandpkg(name, pkg);
- def = expandpkg(def, pkg);
-
- // done
- *pp = p;
- *prefixp = prefix;
- *namep = name;
- *defp = def;
- return 1;
-}
-
-static int
-parsemethod(char **pp, char *ep, char **methp)
-{
- char *p;
-
- // skip white space
- p = *pp;
- while(p < ep && (*p == ' ' || *p == '\t'))
- p++;
- if(p == ep)
- return 0;
-
- // if it says "func (", it's a method
- if(p + 6 >= ep || strncmp(p, "func (", 6) != 0)
- return 0;
-
- // definition to end of line
- *methp = p;
- while(p < ep && *p != '\n')
- p++;
- if(p >= ep) {
- fprint(2, "%s: lost end of line in method definition\n", argv0);
- *pp = ep;
- return -1;
- }
- *p++ = '\0';
- *pp = p;
- return 1;
-}
-
-static void
-loaddynimport(char *file, char *pkg, char *p, int n)
-{
- char *pend, *next, *name, *def, *p0, *lib, *q;
- Sym *s;
-
- USED(file);
- pend = p + n;
- for(; p<pend; p=next) {
- next = strchr(p, '\n');
- if(next == nil)
- next = "";
- else
- *next++ = '\0';
- p0 = p;
- if(strncmp(p, "dynimport ", 10) != 0)
- goto err;
- p += 10;
- name = p;
- p = strchr(name, ' ');
- if(p == nil)
- goto err;
- while(*p == ' ')
- p++;
- def = p;
- p = strchr(def, ' ');
- if(p == nil)
- goto err;
- while(*p == ' ')
- p++;
- lib = p;
-
- // successful parse: now can edit the line
- *strchr(name, ' ') = 0;
- *strchr(def, ' ') = 0;
-
- if(debug['d']) {
- fprint(2, "%s: %s: cannot use dynamic imports with -d flag\n", argv0, file);
- nerrors++;
- return;
- }
-
- if(strcmp(name, "_") == 0 && strcmp(def, "_") == 0) {
- // allow #pragma dynimport _ _ "foo.so"
- // to force a link of foo.so.
- havedynamic = 1;
- adddynlib(lib);
- continue;
- }
-
- name = expandpkg(name, pkg);
- q = strchr(def, '@');
- if(q)
- *q++ = '\0';
- s = lookup(name, 0);
- if(s->type == 0 || s->type == SXREF) {
- s->dynimplib = lib;
- s->dynimpname = def;
- s->dynimpvers = q;
- s->type = SDYNIMPORT;
- havedynamic = 1;
- }
- }
- return;
-
-err:
- fprint(2, "%s: %s: invalid dynimport line: %s\n", argv0, file, p0);
- nerrors++;
-}
-
-static void
-loaddynexport(char *file, char *pkg, char *p, int n)
-{
- char *pend, *next, *local, *elocal, *remote, *p0;
- Sym *s;
-
- USED(file);
- pend = p + n;
- for(; p<pend; p=next) {
- next = strchr(p, '\n');
- if(next == nil)
- next = "";
- else
- *next++ = '\0';
- p0 = p;
- if(strncmp(p, "dynexport ", 10) != 0)
- goto err;
- p += 10;
- local = p;
- p = strchr(local, ' ');
- if(p == nil)
- goto err;
- while(*p == ' ')
- p++;
- remote = p;
-
- // successful parse: now can edit the line
- *strchr(local, ' ') = 0;
-
- elocal = expandpkg(local, pkg);
-
- s = lookup(elocal, 0);
- if(s->dynimplib != nil) {
- fprint(2, "%s: symbol is both dynimport and dynexport %s\n", argv0, local);
- nerrors++;
- }
- s->dynimpname = remote;
- s->dynexport = 1;
-
- if(ndynexp%32 == 0)
- dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
- dynexp[ndynexp++] = s;
-
- if (elocal != local)
- free(elocal);
- }
- return;
-
-err:
- fprint(2, "%s: invalid dynexport line: %s\n", argv0, p0);
- nerrors++;
-}
-
-static int markdepth;
-
-static void
-marktext(Sym *s)
-{
- Auto *a;
- Prog *p;
-
- if(s == S)
- return;
- markdepth++;
- if(debug['v'] > 1)
- Bprint(&bso, "%d marktext %s\n", markdepth, s->name);
- for(a=s->autom; a; a=a->link)
- mark(a->gotype);
- for(p=s->text; p != P; p=p->link) {
- if(p->from.sym)
- mark(p->from.sym);
- if(p->to.sym)
- mark(p->to.sym);
- }
- markdepth--;
-}
-
-void
-mark(Sym *s)
-{
- int i;
-
- if(s == S || s->reachable)
- return;
- if(strncmp(s->name, "weak.", 5) == 0)
- return;
- s->reachable = 1;
- if(s->text)
- marktext(s);
- for(i=0; i<s->nr; i++)
- mark(s->r[i].sym);
- if(s->gotype)
- mark(s->gotype);
- if(s->sub)
- mark(s->sub);
- if(s->outer)
- mark(s->outer);
-}
-
-static char*
-morename[] =
-{
- "runtime.morestack",
- "runtime.morestackx",
-
- "runtime.morestack00",
- "runtime.morestack10",
- "runtime.morestack01",
- "runtime.morestack11",
-
- "runtime.morestack8",
- "runtime.morestack16",
- "runtime.morestack24",
- "runtime.morestack32",
- "runtime.morestack40",
- "runtime.morestack48",
-};
-
-static int
-isz(Auto *a)
-{
- for(; a; a=a->link)
- if(a->type == D_FILE || a->type == D_FILE1)
- return 1;
- return 0;
-}
-
-static void
-addz(Sym *s, Auto *z)
-{
- Auto *a, *last;
-
- // strip out non-z
- last = nil;
- for(a = z; a != nil; a = a->link) {
- if(a->type == D_FILE || a->type == D_FILE1) {
- if(last == nil)
- z = a;
- else
- last->link = a;
- last = a;
- }
- }
- if(last) {
- last->link = s->autom;
- s->autom = z;
- }
-}
-
-void
-deadcode(void)
-{
- int i;
- Sym *s, *last;
- Auto *z;
-
- if(debug['v'])
- Bprint(&bso, "%5.2f deadcode\n", cputime());
-
- mark(lookup(INITENTRY, 0));
- for(i=0; i<nelem(morename); i++)
- mark(lookup(morename[i], 0));
-
- for(i=0; i<ndynexp; i++)
- mark(dynexp[i]);
-
- // remove dead text but keep file information (z symbols).
- last = nil;
- z = nil;
- for(s = textp; s != nil; s = s->next) {
- if(!s->reachable) {
- if(isz(s->autom))
- z = s->autom;
- continue;
- }
- if(last == nil)
- textp = s;
- else
- last->next = s;
- last = s;
- if(z != nil) {
- if(!isz(s->autom))
- addz(s, z);
- z = nil;
- }
- }
- if(last == nil)
- textp = nil;
- else
- last->next = nil;
-
- for(s = allsym; s != S; s = s->allsym)
- if(strncmp(s->name, "weak.", 5) == 0) {
- s->special = 1; // do not lay out in data segment
- s->reachable = 1;
- s->hide = 1;
- }
-}
-
-void
-doweak(void)
-{
- Sym *s, *t;
-
- // resolve weak references only if
- // target symbol will be in binary anyway.
- for(s = allsym; s != S; s = s->allsym) {
- if(strncmp(s->name, "weak.", 5) == 0) {
- t = rlookup(s->name+5, s->version);
- if(t && t->type != 0 && t->reachable) {
- s->value = t->value;
- s->type = t->type;
- } else {
- s->type = SCONST;
- s->value = 0;
- }
- continue;
- }
- }
-}
-
-void
-addexport(void)
-{
- int i;
-
- for(i=0; i<ndynexp; i++)
- adddynsym(dynexp[i]);
-}
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
deleted file mode 100644
index 8334e988e..000000000
--- a/src/cmd/ld/ldelf.c
+++ /dev/null
@@ -1,816 +0,0 @@
-/*
-Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
-http://code.swtch.com/plan9port/src/tip/src/libmach/
-
- Copyright © 2004 Russ Cox.
- Portions Copyright © 2008-2010 Google Inc.
- Portions Copyright © 2010 The Go Authors.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-#include "l.h"
-#include "lib.h"
-#include "../ld/elf.h"
-
-enum
-{
- ElfClassNone = 0,
- ElfClass32,
- ElfClass64,
-
- ElfDataNone = 0,
- ElfDataLsb,
- ElfDataMsb,
-
- ElfTypeNone = 0,
- ElfTypeRelocatable,
- ElfTypeExecutable,
- ElfTypeSharedObject,
- ElfTypeCore,
- /* 0xFF00 - 0xFFFF reserved for processor-specific types */
-
- ElfMachNone = 0,
- ElfMach32100, /* AT&T WE 32100 */
- ElfMachSparc, /* SPARC */
- ElfMach386, /* Intel 80386 */
- ElfMach68000, /* Motorola 68000 */
- ElfMach88000, /* Motorola 88000 */
- ElfMach486, /* Intel 80486, no longer used */
- ElfMach860, /* Intel 80860 */
- ElfMachMips, /* MIPS RS3000 */
- ElfMachS370, /* IBM System/370 */
- ElfMachMipsLe, /* MIPS RS3000 LE */
- ElfMachParisc = 15, /* HP PA RISC */
- ElfMachVpp500 = 17, /* Fujitsu VPP500 */
- ElfMachSparc32Plus, /* SPARC V8+ */
- ElfMach960, /* Intel 80960 */
- ElfMachPower, /* PowerPC */
- ElfMachPower64, /* PowerPC 64 */
- ElfMachS390, /* IBM System/390 */
- ElfMachV800 = 36, /* NEC V800 */
- ElfMachFr20, /* Fujitsu FR20 */
- ElfMachRh32, /* TRW RH-32 */
- ElfMachRce, /* Motorola RCE */
- ElfMachArm, /* ARM */
- ElfMachAlpha, /* Digital Alpha */
- ElfMachSH, /* Hitachi SH */
- ElfMachSparc9, /* SPARC V9 */
- ElfMachAmd64 = 62,
- /* and the list goes on... */
-
- ElfAbiNone = 0,
- ElfAbiSystemV = 0, /* [sic] */
- ElfAbiHPUX,
- ElfAbiNetBSD,
- ElfAbiLinux,
- ElfAbiSolaris = 6,
- ElfAbiAix,
- ElfAbiIrix,
- ElfAbiFreeBSD,
- ElfAbiTru64,
- ElfAbiModesto,
- ElfAbiOpenBSD,
- ElfAbiARM = 97,
- ElfAbiEmbedded = 255,
-
- /* some of sections 0xFF00 - 0xFFFF reserved for various things */
- ElfSectNone = 0,
- ElfSectProgbits,
- ElfSectSymtab,
- ElfSectStrtab,
- ElfSectRela,
- ElfSectHash,
- ElfSectDynamic,
- ElfSectNote,
- ElfSectNobits,
- ElfSectRel,
- ElfSectShlib,
- ElfSectDynsym,
-
- ElfSectFlagWrite = 0x1,
- ElfSectFlagAlloc = 0x2,
- ElfSectFlagExec = 0x4,
- /* 0xF0000000 are reserved for processor specific */
-
- ElfSymBindLocal = 0,
- ElfSymBindGlobal,
- ElfSymBindWeak,
- /* 13-15 reserved */
-
- ElfSymTypeNone = 0,
- ElfSymTypeObject,
- ElfSymTypeFunc,
- ElfSymTypeSection,
- ElfSymTypeFile,
- /* 13-15 reserved */
-
- ElfSymShnNone = 0,
- ElfSymShnAbs = 0xFFF1,
- ElfSymShnCommon = 0xFFF2,
- /* 0xFF00-0xFF1F reserved for processors */
- /* 0xFF20-0xFF3F reserved for operating systems */
-
- ElfProgNone = 0,
- ElfProgLoad,
- ElfProgDynamic,
- ElfProgInterp,
- ElfProgNote,
- ElfProgShlib,
- ElfProgPhdr,
-
- ElfProgFlagExec = 0x1,
- ElfProgFlagWrite = 0x2,
- ElfProgFlagRead = 0x4,
-
- ElfNotePrStatus = 1,
- ElfNotePrFpreg = 2,
- ElfNotePrPsinfo = 3,
- ElfNotePrTaskstruct = 4,
- ElfNotePrAuxv = 6,
- ElfNotePrXfpreg = 0x46e62b7f /* for gdb/386 */
-};
-
-typedef struct ElfHdrBytes ElfHdrBytes;
-typedef struct ElfSectBytes ElfSectBytes;
-typedef struct ElfProgBytes ElfProgBytes;
-typedef struct ElfSymBytes ElfSymBytes;
-
-typedef struct ElfHdrBytes64 ElfHdrBytes64;
-typedef struct ElfSectBytes64 ElfSectBytes64;
-typedef struct ElfProgBytes64 ElfProgBytes64;
-typedef struct ElfSymBytes64 ElfSymBytes64;
-
-struct ElfHdrBytes
-{
- uchar ident[16];
- uchar type[2];
- uchar machine[2];
- uchar version[4];
- uchar entry[4];
- uchar phoff[4];
- uchar shoff[4];
- uchar flags[4];
- uchar ehsize[2];
- uchar phentsize[2];
- uchar phnum[2];
- uchar shentsize[2];
- uchar shnum[2];
- uchar shstrndx[2];
-};
-
-struct ElfHdrBytes64
-{
- uchar ident[16];
- uchar type[2];
- uchar machine[2];
- uchar version[4];
- uchar entry[8];
- uchar phoff[8];
- uchar shoff[8];
- uchar flags[4];
- uchar ehsize[2];
- uchar phentsize[2];
- uchar phnum[2];
- uchar shentsize[2];
- uchar shnum[2];
- uchar shstrndx[2];
-};
-
-struct ElfSectBytes
-{
- uchar name[4];
- uchar type[4];
- uchar flags[4];
- uchar addr[4];
- uchar off[4];
- uchar size[4];
- uchar link[4];
- uchar info[4];
- uchar align[4];
- uchar entsize[4];
-};
-
-struct ElfSectBytes64
-{
- uchar name[4];
- uchar type[4];
- uchar flags[8];
- uchar addr[8];
- uchar off[8];
- uchar size[8];
- uchar link[4];
- uchar info[4];
- uchar align[8];
- uchar entsize[8];
-};
-
-struct ElfSymBytes
-{
- uchar name[4];
- uchar value[4];
- uchar size[4];
- uchar info; /* top4: bind, bottom4: type */
- uchar other;
- uchar shndx[2];
-};
-
-struct ElfSymBytes64
-{
- uchar name[4];
- uchar info; /* top4: bind, bottom4: type */
- uchar other;
- uchar shndx[2];
- uchar value[8];
- uchar size[8];
-};
-
-typedef struct ElfSect ElfSect;
-typedef struct ElfObj ElfObj;
-typedef struct ElfSym ElfSym;
-
-struct ElfSect
-{
- char *name;
- uint32 type;
- uint64 flags;
- uint64 addr;
- uint64 off;
- uint64 size;
- uint32 link;
- uint32 info;
- uint64 align;
- uint64 entsize;
- uchar *base;
- Sym *sym;
-};
-
-struct ElfObj
-{
- Biobuf *f;
- int64 base; // offset in f where ELF begins
- int64 len; // length of ELF
- int is64;
- char *name;
-
- Endian *e;
- ElfSect *sect;
- uint nsect;
- char *shstrtab;
- int nsymtab;
- ElfSect *symtab;
- ElfSect *symstr;
-
- uint32 type;
- uint32 machine;
- uint32 version;
- uint64 entry;
- uint64 phoff;
- uint64 shoff;
- uint32 flags;
- uint32 ehsize;
- uint32 phentsize;
- uint32 phnum;
- uint32 shentsize;
- uint32 shnum;
- uint32 shstrndx;
-};
-
-struct ElfSym
-{
- char* name;
- uint64 value;
- uint64 size;
- uchar bind;
- uchar type;
- uchar other;
- uint16 shndx;
- Sym* sym;
-};
-
-uchar ElfMagic[4] = { 0x7F, 'E', 'L', 'F' };
-
-static ElfSect* section(ElfObj*, char*);
-static int map(ElfObj*, ElfSect*);
-static int readsym(ElfObj*, int i, ElfSym*);
-static int reltype(char*, int, uchar*);
-
-void
-ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
-{
- int32 base;
- uint64 add, info;
- char *name;
- int i, j, rela, is64, n;
- uchar hdrbuf[64];
- uchar *p;
- ElfHdrBytes *hdr;
- ElfObj *obj;
- ElfSect *sect, *rsect;
- ElfSym sym;
- Endian *e;
- Reloc *r, *rp;
- Sym *s;
-
- USED(pkg);
- if(debug['v'])
- Bprint(&bso, "%5.2f ldelf %s\n", cputime(), pn);
-
- version++;
- base = Boffset(f);
-
- if(Bread(f, hdrbuf, sizeof hdrbuf) != sizeof hdrbuf)
- goto bad;
- hdr = (ElfHdrBytes*)hdrbuf;
- if(memcmp(hdr->ident, ElfMagic, 4) != 0)
- goto bad;
- switch(hdr->ident[5]) {
- case ElfDataLsb:
- e = &le;
- break;
- case ElfDataMsb:
- e = &be;
- break;
- default:
- goto bad;
- }
-
- // read header
- obj = mal(sizeof *obj);
- obj->e = e;
- obj->f = f;
- obj->base = base;
- obj->len = len;
- obj->name = pn;
-
- is64 = 0;
- if(hdr->ident[4] == ElfClass64) {
- ElfHdrBytes64* hdr;
-
- is64 = 1;
- hdr = (ElfHdrBytes64*)hdrbuf;
- obj->type = e->e16(hdr->type);
- obj->machine = e->e16(hdr->machine);
- obj->version = e->e32(hdr->version);
- obj->phoff = e->e64(hdr->phoff);
- obj->shoff = e->e64(hdr->shoff);
- obj->flags = e->e32(hdr->flags);
- obj->ehsize = e->e16(hdr->ehsize);
- obj->phentsize = e->e16(hdr->phentsize);
- obj->phnum = e->e16(hdr->phnum);
- obj->shentsize = e->e16(hdr->shentsize);
- obj->shnum = e->e16(hdr->shnum);
- obj->shstrndx = e->e16(hdr->shstrndx);
- } else {
- obj->type = e->e16(hdr->type);
- obj->machine = e->e16(hdr->machine);
- obj->version = e->e32(hdr->version);
- obj->entry = e->e32(hdr->entry);
- obj->phoff = e->e32(hdr->phoff);
- obj->shoff = e->e32(hdr->shoff);
- obj->flags = e->e32(hdr->flags);
- obj->ehsize = e->e16(hdr->ehsize);
- obj->phentsize = e->e16(hdr->phentsize);
- obj->phnum = e->e16(hdr->phnum);
- obj->shentsize = e->e16(hdr->shentsize);
- obj->shnum = e->e16(hdr->shnum);
- obj->shstrndx = e->e16(hdr->shstrndx);
- }
- obj->is64 = is64;
-
- if(hdr->ident[6] != obj->version)
- goto bad;
-
- if(e->e16(hdr->type) != ElfTypeRelocatable) {
- diag("%s: elf but not elf relocatable object");
- return;
- }
-
- switch(thechar) {
- default:
- diag("%s: elf %s unimplemented", thestring);
- return;
- case '5':
- if(e != &le || obj->machine != ElfMachArm || hdr->ident[4] != ElfClass32) {
- diag("%s: elf object but not arm", pn);
- return;
- }
- break;
- case '6':
- if(e != &le || obj->machine != ElfMachAmd64 || hdr->ident[4] != ElfClass64) {
- diag("%s: elf object but not amd64", pn);
- return;
- }
- break;
- case '8':
- if(e != &le || obj->machine != ElfMach386 || hdr->ident[4] != ElfClass32) {
- diag("%s: elf object but not 386", pn);
- return;
- }
- break;
- }
-
- // load section list into memory.
- obj->sect = mal(obj->shnum*sizeof obj->sect[0]);
- obj->nsect = obj->shnum;
- for(i=0; i<obj->nsect; i++) {
- if(Bseek(f, base+obj->shoff+i*obj->shentsize, 0) < 0)
- goto bad;
- sect = &obj->sect[i];
- if(is64) {
- ElfSectBytes64 b;
-
- werrstr("short read");
- if(Bread(f, &b, sizeof b) != sizeof b)
- goto bad;
-
- sect->name = (char*)(uintptr)e->e32(b.name);
- sect->type = e->e32(b.type);
- sect->flags = e->e64(b.flags);
- sect->addr = e->e64(b.addr);
- sect->off = e->e64(b.off);
- sect->size = e->e64(b.size);
- sect->link = e->e32(b.link);
- sect->info = e->e32(b.info);
- sect->align = e->e64(b.align);
- sect->entsize = e->e64(b.entsize);
- } else {
- ElfSectBytes b;
-
- werrstr("short read");
- if(Bread(f, &b, sizeof b) != sizeof b)
- goto bad;
-
- sect->name = (char*)(uintptr)e->e32(b.name);
- sect->type = e->e32(b.type);
- sect->flags = e->e32(b.flags);
- sect->addr = e->e32(b.addr);
- sect->off = e->e32(b.off);
- sect->size = e->e32(b.size);
- sect->link = e->e32(b.link);
- sect->info = e->e32(b.info);
- sect->align = e->e32(b.align);
- sect->entsize = e->e32(b.entsize);
- }
- }
-
- // read section string table and translate names
- if(obj->shstrndx >= obj->nsect) {
- werrstr("shstrndx out of range %d >= %d", obj->shstrndx, obj->nsect);
- goto bad;
- }
- sect = &obj->sect[obj->shstrndx];
- if(map(obj, sect) < 0)
- goto bad;
- for(i=0; i<obj->nsect; i++)
- if(obj->sect[i].name != nil)
- obj->sect[i].name = (char*)sect->base + (uintptr)obj->sect[i].name;
-
- // load string table for symbols into memory.
- obj->symtab = section(obj, ".symtab");
- if(obj->symtab == nil) {
- // our work is done here - no symbols means nothing can refer to this file
- return;
- }
- if(obj->symtab->link <= 0 || obj->symtab->link >= obj->nsect) {
- diag("%s: elf object has symbol table with invalid string table link", pn);
- return;
- }
- obj->symstr = &obj->sect[obj->symtab->link];
- if(is64)
- obj->nsymtab = obj->symtab->size / sizeof(ElfSymBytes64);
- else
- obj->nsymtab = obj->symtab->size / sizeof(ElfSymBytes);
-
- if(map(obj, obj->symtab) < 0)
- goto bad;
- if(map(obj, obj->symstr) < 0)
- goto bad;
-
- // load text and data segments into memory.
- // they are not as small as the section lists, but we'll need
- // the memory anyway for the symbol images, so we might
- // as well use one large chunk.
-
- // create symbols for mapped sections
- for(i=0; i<obj->nsect; i++) {
- sect = &obj->sect[i];
- if((sect->type != ElfSectProgbits && sect->type != ElfSectNobits) || !(sect->flags&ElfSectFlagAlloc))
- continue;
- if(sect->type != ElfSectNobits && map(obj, sect) < 0)
- goto bad;
-
- name = smprint("%s(%s)", pn, sect->name);
- s = lookup(name, version);
- free(name);
- switch((int)sect->flags&(ElfSectFlagAlloc|ElfSectFlagWrite|ElfSectFlagExec)) {
- default:
- werrstr("unexpected flags for ELF section %s", sect->name);
- goto bad;
- case ElfSectFlagAlloc:
- s->type = SRODATA;
- break;
- case ElfSectFlagAlloc + ElfSectFlagWrite:
- s->type = SDATA;
- break;
- case ElfSectFlagAlloc + ElfSectFlagExec:
- s->type = STEXT;
- break;
- }
- if(sect->type == ElfSectProgbits) {
- s->p = sect->base;
- s->np = sect->size;
- }
- s->size = sect->size;
- if(s->type == STEXT) {
- if(etextp)
- etextp->next = s;
- else
- textp = s;
- etextp = s;
- }
- sect->sym = s;
- }
-
- // load relocations
- for(i=0; i<obj->nsect; i++) {
- rsect = &obj->sect[i];
- if(rsect->type != ElfSectRela && rsect->type != ElfSectRel)
- continue;
- if(rsect->info >= obj->nsect || obj->sect[rsect->info].base == nil)
- continue;
- sect = &obj->sect[rsect->info];
- if(map(obj, rsect) < 0)
- goto bad;
- rela = rsect->type == ElfSectRela;
- n = rsect->size/(4+4*is64)/(2+rela);
- r = mal(n*sizeof r[0]);
- p = rsect->base;
- for(j=0; j<n; j++) {
- add = 0;
- rp = &r[j];
- if(is64) {
- // 64-bit rel/rela
- rp->off = e->e64(p);
- p += 8;
- info = e->e64(p);
- p += 8;
- if(rela) {
- add = e->e64(p);
- p += 8;
- }
- } else {
- // 32-bit rel/rela
- rp->off = e->e32(p);
- p += 4;
- info = e->e32(p);
- info = info>>8<<32 | (info&0xff); // convert to 64-bit info
- p += 4;
- if(rela) {
- add = e->e32(p);
- p += 4;
- }
- }
- if(readsym(obj, info>>32, &sym) < 0)
- goto bad;
- if(sym.sym == nil) {
- werrstr("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d",
- sect->sym->name, j, (int)(info>>32), sym.name, sym.shndx, sym.type);
- goto bad;
- }
- rp->sym = sym.sym;
- rp->type = reltype(pn, (uint32)info, &rp->siz);
- if(rela)
- rp->add = add;
- else {
- // load addend from image
- if(rp->siz == 4)
- rp->add = e->e32(sect->base+rp->off);
- else if(rp->siz == 8)
- rp->add = e->e64(sect->base+rp->off);
- else
- diag("invalid rela size %d", rp->siz);
- }
- }
- qsort(r, n, sizeof r[0], rbyoff); // just in case
-
- s = sect->sym;
- s->r = r;
- s->nr = n;
- }
-
- // enter sub-symbols into symbol table.
- // symbol 0 is the null symbol.
- for(i=1; i<obj->nsymtab; i++) {
- if(readsym(obj, i, &sym) < 0)
- goto bad;
- if(sym.type != ElfSymTypeFunc && sym.type != ElfSymTypeObject && sym.type != ElfSymTypeNone)
- continue;
- if(sym.shndx == ElfSymShnCommon) {
- s = sym.sym;
- if(s->size < sym.size)
- s->size = sym.size;
- if(s->type == 0 || s->type == SXREF)
- s->type = SBSS;
- continue;
- }
- if(sym.shndx >= obj->nsect || sym.shndx == 0)
- continue;
- sect = obj->sect+sym.shndx;
- if(sect->sym == nil) {
- diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type);
- continue;
- }
- s = sym.sym;
- s->sub = sect->sym->sub;
- sect->sym->sub = s;
- s->type = sect->sym->type | SSUB;
- if(!s->dynexport) {
- s->dynimplib = nil; // satisfy dynimport
- s->dynimpname = nil; // satisfy dynimport
- }
- s->value = sym.value;
- s->size = sym.size;
- s->outer = sect->sym;
- if(sect->sym->type == STEXT) {
- Prog *p;
-
- if(s->text != P)
- diag("%s: duplicate definition of %s", pn, s->name);
- // build a TEXT instruction with a unique pc
- // just to make the rest of the linker happy.
- p = prg();
- p->as = ATEXT;
- p->from.type = D_EXTERN;
- p->from.sym = s;
- p->textflag = 7;
- p->to.type = D_CONST;
- p->link = nil;
- p->pc = pc++;
- s->text = p;
-
- etextp->next = s;
- etextp = s;
- }
- }
- return;
-
-bad:
- diag("%s: malformed elf file: %r", pn);
-}
-
-static ElfSect*
-section(ElfObj *obj, char *name)
-{
- int i;
-
- for(i=0; i<obj->nsect; i++)
- if(obj->sect[i].name && name && strcmp(obj->sect[i].name, name) == 0)
- return &obj->sect[i];
- return nil;
-}
-
-static int
-map(ElfObj *obj, ElfSect *sect)
-{
- if(sect->base != nil)
- return 0;
-
- if(sect->off+sect->size > obj->len) {
- werrstr("elf section past end of file");
- return -1;
- }
-
- sect->base = mal(sect->size);
- werrstr("short read");
- if(Bseek(obj->f, obj->base+sect->off, 0) < 0 || Bread(obj->f, sect->base, sect->size) != sect->size)
- return -1;
-
- return 0;
-}
-
-static int
-readsym(ElfObj *obj, int i, ElfSym *sym)
-{
- Sym *s;
-
- if(i >= obj->nsymtab || i < 0) {
- werrstr("invalid elf symbol index");
- return -1;
- }
-
- if(obj->is64) {
- ElfSymBytes64 *b;
-
- b = (ElfSymBytes64*)(obj->symtab->base + i*sizeof *b);
- sym->name = (char*)obj->symstr->base + obj->e->e32(b->name);
- sym->value = obj->e->e64(b->value);
- sym->size = obj->e->e64(b->size);
- sym->shndx = obj->e->e16(b->shndx);
- sym->bind = b->info>>4;
- sym->type = b->info&0xf;
- sym->other = b->other;
- } else {
- ElfSymBytes *b;
-
- b = (ElfSymBytes*)(obj->symtab->base + i*sizeof *b);
- sym->name = (char*)obj->symstr->base + obj->e->e32(b->name);
- sym->value = obj->e->e32(b->value);
- sym->size = obj->e->e32(b->size);
- sym->shndx = obj->e->e16(b->shndx);
- sym->bind = b->info>>4;
- sym->type = b->info&0xf;
- sym->other = b->other;
- }
-
- s = nil;
- if(strcmp(sym->name, "_GLOBAL_OFFSET_TABLE_") == 0)
- sym->name = ".got";
- if(strcmp(sym->name, "__stack_chk_fail_local") == 0)
- sym->other = 0; // rewrite hidden -> default visibility
- switch(sym->type) {
- case ElfSymTypeSection:
- s = obj->sect[sym->shndx].sym;
- break;
- case ElfSymTypeObject:
- case ElfSymTypeFunc:
- case ElfSymTypeNone:
- switch(sym->bind) {
- case ElfSymBindGlobal:
- if(sym->other != 2) {
- s = lookup(sym->name, 0);
- break;
- }
- // fall through
- case ElfSymBindLocal:
- s = lookup(sym->name, version);
- break;
- default:
- werrstr("%s: invalid symbol binding %d", sym->name, sym->bind);
- return -1;
- }
- break;
- }
- if(s != nil && s->type == 0 && sym->type != ElfSymTypeSection)
- s->type = SXREF;
- sym->sym = s;
-
- return 0;
-}
-
-int
-rbyoff(const void *va, const void *vb)
-{
- Reloc *a, *b;
-
- a = (Reloc*)va;
- b = (Reloc*)vb;
- if(a->off < b->off)
- return -1;
- if(a->off > b->off)
- return +1;
- return 0;
-}
-
-#define R(x, y) ((x)|((y)<<24))
-
-static int
-reltype(char *pn, int elftype, uchar *siz)
-{
- switch(R(thechar, elftype)) {
- default:
- diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype);
- case R('6', R_X86_64_PC32):
- case R('6', R_X86_64_PLT32):
- case R('6', R_X86_64_GOTPCREL):
- case R('8', R_386_32):
- case R('8', R_386_PC32):
- case R('8', R_386_GOT32):
- case R('8', R_386_PLT32):
- case R('8', R_386_GOTOFF):
- case R('8', R_386_GOTPC):
- *siz = 4;
- break;
- case R('6', R_X86_64_64):
- *siz = 8;
- break;
- }
-
- return 256+elftype;
-}
diff --git a/src/cmd/ld/ldmacho.c b/src/cmd/ld/ldmacho.c
deleted file mode 100644
index abbc3b3cd..000000000
--- a/src/cmd/ld/ldmacho.c
+++ /dev/null
@@ -1,821 +0,0 @@
-/*
-Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
-http://code.swtch.com/plan9port/src/tip/src/libmach/
-
- Copyright © 2004 Russ Cox.
- Portions Copyright © 2008-2010 Google Inc.
- Portions Copyright © 2010 The Go Authors.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-#include "l.h"
-#include "lib.h"
-
-enum {
- MACHO_FAKE_GOTPCREL = 100, // from macho.h
-
- N_EXT = 0x01,
- N_TYPE = 0x1e,
- N_STAB = 0xe0,
-};
-
-typedef struct MachoObj MachoObj;
-typedef struct MachoCmd MachoCmd;
-typedef struct MachoSeg MachoSeg;
-typedef struct MachoSect MachoSect;
-typedef struct MachoRel MachoRel;
-typedef struct MachoSymtab MachoSymtab;
-typedef struct MachoSym MachoSym;
-typedef struct MachoDysymtab MachoDysymtab;
-
-enum
-{
- MachoCpuVax = 1,
- MachoCpu68000 = 6,
- MachoCpu386 = 7,
- MachoCpuAmd64 = 0x1000007,
- MachoCpuMips = 8,
- MachoCpu98000 = 10,
- MachoCpuHppa = 11,
- MachoCpuArm = 12,
- MachoCpu88000 = 13,
- MachoCpuSparc = 14,
- MachoCpu860 = 15,
- MachoCpuAlpha = 16,
- MachoCpuPower = 18,
-
- MachoCmdSegment = 1,
- MachoCmdSymtab = 2,
- MachoCmdSymseg = 3,
- MachoCmdThread = 4,
- MachoCmdDysymtab = 11,
- MachoCmdSegment64 = 25,
-
- MachoFileObject = 1,
- MachoFileExecutable = 2,
- MachoFileFvmlib = 3,
- MachoFileCore = 4,
- MachoFilePreload = 5,
-};
-
-struct MachoSeg
-{
- char name[16+1];
- uint64 vmaddr;
- uint64 vmsize;
- uint32 fileoff;
- uint32 filesz;
- uint32 maxprot;
- uint32 initprot;
- uint32 nsect;
- uint32 flags;
- MachoSect *sect;
-};
-
-struct MachoSect
-{
- char name[16+1];
- char segname[16+1];
- uint64 addr;
- uint64 size;
- uint32 off;
- uint32 align;
- uint32 reloff;
- uint32 nreloc;
- uint32 flags;
- uint32 res1;
- uint32 res2;
- Sym *sym;
-
- MachoRel *rel;
-};
-
-struct MachoRel
-{
- uint32 addr;
- uint32 symnum;
- uint8 pcrel;
- uint8 length;
- uint8 extrn;
- uint8 type;
- uint8 scattered;
- uint32 value;
-};
-
-struct MachoSymtab
-{
- uint32 symoff;
- uint32 nsym;
- uint32 stroff;
- uint32 strsize;
-
- char *str;
- MachoSym *sym;
-};
-
-struct MachoSym
-{
- char *name;
- uint8 type;
- uint8 sectnum;
- uint16 desc;
- char kind;
- uint64 value;
- Sym *sym;
-};
-
-struct MachoDysymtab
-{
- uint32 ilocalsym;
- uint32 nlocalsym;
- uint32 iextdefsym;
- uint32 nextdefsym;
- uint32 iundefsym;
- uint32 nundefsym;
- uint32 tocoff;
- uint32 ntoc;
- uint32 modtaboff;
- uint32 nmodtab;
- uint32 extrefsymoff;
- uint32 nextrefsyms;
- uint32 indirectsymoff;
- uint32 nindirectsyms;
- uint32 extreloff;
- uint32 nextrel;
- uint32 locreloff;
- uint32 nlocrel;
- uint32 *indir;
-};
-
-struct MachoCmd
-{
- int type;
- uint32 off;
- uint32 size;
- MachoSeg seg;
- MachoSymtab sym;
- MachoDysymtab dsym;
-};
-
-struct MachoObj
-{
- Biobuf *f;
- int64 base; // off in f where Mach-O begins
- int64 len; // length of Mach-O
- int is64;
- char *name;
-
- Endian *e;
- uint cputype;
- uint subcputype;
- uint32 filetype;
- uint32 flags;
- MachoCmd *cmd;
- uint ncmd;
-};
-
-static int
-unpackcmd(uchar *p, MachoObj *m, MachoCmd *c, uint type, uint sz)
-{
- uint32 (*e4)(uchar*);
- uint64 (*e8)(uchar*);
- MachoSect *s;
- int i;
-
- e4 = m->e->e32;
- e8 = m->e->e64;
-
- c->type = type;
- c->size = sz;
- switch(type){
- default:
- return -1;
- case MachoCmdSegment:
- if(sz < 56)
- return -1;
- strecpy(c->seg.name, c->seg.name+sizeof c->seg.name, (char*)p+8);
- c->seg.vmaddr = e4(p+24);
- c->seg.vmsize = e4(p+28);
- c->seg.fileoff = e4(p+32);
- c->seg.filesz = e4(p+36);
- c->seg.maxprot = e4(p+40);
- c->seg.initprot = e4(p+44);
- c->seg.nsect = e4(p+48);
- c->seg.flags = e4(p+52);
- c->seg.sect = mal(c->seg.nsect * sizeof c->seg.sect[0]);
- if(sz < 56+c->seg.nsect*68)
- return -1;
- p += 56;
- for(i=0; i<c->seg.nsect; i++) {
- s = &c->seg.sect[i];
- strecpy(s->name, s->name+sizeof s->name, (char*)p+0);
- strecpy(s->segname, s->segname+sizeof s->segname, (char*)p+16);
- s->addr = e4(p+32);
- s->size = e4(p+36);
- s->off = e4(p+40);
- s->align = e4(p+44);
- s->reloff = e4(p+48);
- s->nreloc = e4(p+52);
- s->flags = e4(p+56);
- s->res1 = e4(p+60);
- s->res2 = e4(p+64);
- p += 68;
- }
- break;
- case MachoCmdSegment64:
- if(sz < 72)
- return -1;
- strecpy(c->seg.name, c->seg.name+sizeof c->seg.name, (char*)p+8);
- c->seg.vmaddr = e8(p+24);
- c->seg.vmsize = e8(p+32);
- c->seg.fileoff = e8(p+40);
- c->seg.filesz = e8(p+48);
- c->seg.maxprot = e4(p+56);
- c->seg.initprot = e4(p+60);
- c->seg.nsect = e4(p+64);
- c->seg.flags = e4(p+68);
- c->seg.sect = mal(c->seg.nsect * sizeof c->seg.sect[0]);
- if(sz < 72+c->seg.nsect*80)
- return -1;
- p += 72;
- for(i=0; i<c->seg.nsect; i++) {
- s = &c->seg.sect[i];
- strecpy(s->name, s->name+sizeof s->name, (char*)p+0);
- strecpy(s->segname, s->segname+sizeof s->segname, (char*)p+16);
- s->addr = e8(p+32);
- s->size = e8(p+40);
- s->off = e4(p+48);
- s->align = e4(p+52);
- s->reloff = e4(p+56);
- s->nreloc = e4(p+60);
- s->flags = e4(p+64);
- s->res1 = e4(p+68);
- s->res2 = e4(p+72);
- // p+76 is reserved
- p += 80;
- }
- break;
- case MachoCmdSymtab:
- if(sz < 24)
- return -1;
- c->sym.symoff = e4(p+8);
- c->sym.nsym = e4(p+12);
- c->sym.stroff = e4(p+16);
- c->sym.strsize = e4(p+20);
- break;
- case MachoCmdDysymtab:
- if(sz < 80)
- return -1;
- c->dsym.ilocalsym = e4(p+8);
- c->dsym.nlocalsym = e4(p+12);
- c->dsym.iextdefsym = e4(p+16);
- c->dsym.nextdefsym = e4(p+20);
- c->dsym.iundefsym = e4(p+24);
- c->dsym.nundefsym = e4(p+28);
- c->dsym.tocoff = e4(p+32);
- c->dsym.ntoc = e4(p+36);
- c->dsym.modtaboff = e4(p+40);
- c->dsym.nmodtab = e4(p+44);
- c->dsym.extrefsymoff = e4(p+48);
- c->dsym.nextrefsyms = e4(p+52);
- c->dsym.indirectsymoff = e4(p+56);
- c->dsym.nindirectsyms = e4(p+60);
- c->dsym.extreloff = e4(p+64);
- c->dsym.nextrel = e4(p+68);
- c->dsym.locreloff = e4(p+72);
- c->dsym.nlocrel = e4(p+76);
- break;
- }
- return 0;
-}
-
-static int
-macholoadrel(MachoObj *m, MachoSect *sect)
-{
- MachoRel *rel, *r;
- uchar *buf, *p;
- int i, n;
- uint32 v;
-
- if(sect->rel != nil || sect->nreloc == 0)
- return 0;
- rel = mal(sect->nreloc * sizeof r[0]);
- n = sect->nreloc * 8;
- buf = mal(n);
- if(Bseek(m->f, m->base + sect->reloff, 0) < 0 || Bread(m->f, buf, n) != n)
- return -1;
- for(i=0; i<sect->nreloc; i++) {
- r = &rel[i];
- p = buf+i*8;
- r->addr = m->e->e32(p);
-
- // TODO(rsc): Wrong interpretation for big-endian bitfields?
- if(r->addr & 0x80000000) {
- // scatterbrained relocation
- r->scattered = 1;
- v = r->addr >> 24;
- r->addr &= 0xFFFFFF;
- r->type = v & 0xF;
- v >>= 4;
- r->length = 1<<(v&3);
- v >>= 2;
- r->pcrel = v & 1;
- r->value = m->e->e32(p+4);
- } else {
- v = m->e->e32(p+4);
- r->symnum = v & 0xFFFFFF;
- v >>= 24;
- r->pcrel = v&1;
- v >>= 1;
- r->length = 1<<(v&3);
- v >>= 2;
- r->extrn = v&1;
- v >>= 1;
- r->type = v;
- }
- }
- sect->rel = rel;
- return 0;
-}
-
-static int
-macholoaddsym(MachoObj *m, MachoDysymtab *d)
-{
- uchar *p;
- int i, n;
-
- n = d->nindirectsyms;
-
- p = mal(n*4);
- if(Bseek(m->f, m->base + d->indirectsymoff, 0) < 0 || Bread(m->f, p, n*4) != n*4)
- return -1;
-
- d->indir = (uint32*)p;
- for(i=0; i<n; i++)
- d->indir[i] = m->e->e32(p+4*i);
- return 0;
-}
-
-static int
-macholoadsym(MachoObj *m, MachoSymtab *symtab)
-{
- char *strbuf;
- uchar *symbuf, *p;
- int i, n, symsize;
- MachoSym *sym, *s;
- uint32 v;
-
- if(symtab->sym != nil)
- return 0;
-
- strbuf = mal(symtab->strsize);
- if(Bseek(m->f, m->base + symtab->stroff, 0) < 0 || Bread(m->f, strbuf, symtab->strsize) != symtab->strsize)
- return -1;
-
- symsize = 12;
- if(m->is64)
- symsize = 16;
- n = symtab->nsym * symsize;
- symbuf = mal(n);
- if(Bseek(m->f, m->base + symtab->symoff, 0) < 0 || Bread(m->f, symbuf, n) != n)
- return -1;
- sym = mal(symtab->nsym * sizeof sym[0]);
- p = symbuf;
- for(i=0; i<symtab->nsym; i++) {
- s = &sym[i];
- v = m->e->e32(p);
- if(v >= symtab->strsize)
- return -1;
- s->name = strbuf + v;
- s->type = p[4];
- s->sectnum = p[5];
- s->desc = m->e->e16(p+6);
- if(m->is64)
- s->value = m->e->e64(p+8);
- else
- s->value = m->e->e32(p+8);
- p += symsize;
- }
- symtab->str = strbuf;
- symtab->sym = sym;
- return 0;
-}
-
-void
-ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
-{
- int i, j, is64;
- uint64 secaddr;
- uchar hdr[7*4], *cmdp;
- uchar tmp[4];
- uchar *dat;
- ulong ncmd, cmdsz, ty, sz, off;
- MachoObj *m;
- Endian *e;
- int64 base;
- MachoSect *sect;
- MachoRel *rel;
- Sym *s, *outer;
- MachoCmd *c;
- MachoSymtab *symtab;
- MachoDysymtab *dsymtab;
- MachoSym *sym;
- Reloc *r, *rp;
- char *name;
-
- USED(pkg);
- version++;
- base = Boffset(f);
- if(Bread(f, hdr, sizeof hdr) != sizeof hdr)
- goto bad;
-
- if((be.e32(hdr)&~1) == 0xFEEDFACE){
- e = &be;
- }else if((le.e32(hdr)&~1) == 0xFEEDFACE){
- e = &le;
- }else{
- werrstr("bad magic - not mach-o file");
- goto bad;
- }
-
- is64 = e->e32(hdr) == 0xFEEDFACF;
- ncmd = e->e32(hdr+4*4);
- cmdsz = e->e32(hdr+5*4);
- if(ncmd > 0x10000 || cmdsz >= 0x01000000){
- werrstr("implausible mach-o header ncmd=%lud cmdsz=%lud", ncmd, cmdsz);
- goto bad;
- }
- if(is64)
- Bread(f, tmp, 4); // skip reserved word in header
-
- m = mal(sizeof(*m)+ncmd*sizeof(MachoCmd)+cmdsz);
- m->f = f;
- m->e = e;
- m->cputype = e->e32(hdr+1*4);
- m->subcputype = e->e32(hdr+2*4);
- m->filetype = e->e32(hdr+3*4);
- m->ncmd = ncmd;
- m->flags = e->e32(hdr+6*4);
- m->is64 = is64;
- m->base = base;
- m->len = len;
- m->name = pn;
-
- switch(thechar) {
- default:
- diag("%s: mach-o %s unimplemented", thestring);
- return;
- case '6':
- if(e != &le || m->cputype != MachoCpuAmd64) {
- diag("%s: mach-o object but not amd64", pn);
- return;
- }
- break;
- case '8':
- if(e != &le || m->cputype != MachoCpu386) {
- diag("%s: mach-o object but not 386", pn);
- return;
- }
- break;
- }
-
- m->cmd = (MachoCmd*)(m+1);
- off = sizeof hdr;
- cmdp = (uchar*)(m->cmd+ncmd);
- if(Bread(f, cmdp, cmdsz) != cmdsz){
- werrstr("reading cmds: %r");
- goto bad;
- }
-
- // read and parse load commands
- c = nil;
- symtab = nil;
- dsymtab = nil;
- for(i=0; i<ncmd; i++){
- ty = e->e32(cmdp);
- sz = e->e32(cmdp+4);
- m->cmd[i].off = off;
- unpackcmd(cmdp, m, &m->cmd[i], ty, sz);
- cmdp += sz;
- off += sz;
- if(ty == MachoCmdSymtab) {
- if(symtab != nil) {
- werrstr("multiple symbol tables");
- goto bad;
- }
- symtab = &m->cmd[i].sym;
- macholoadsym(m, symtab);
- }
- if(ty == MachoCmdDysymtab) {
- dsymtab = &m->cmd[i].dsym;
- macholoaddsym(m, dsymtab);
- }
- if((is64 && ty == MachoCmdSegment64) || (!is64 && ty == MachoCmdSegment)) {
- if(c != nil) {
- werrstr("multiple load commands");
- goto bad;
- }
- c = &m->cmd[i];
- }
- }
-
- // load text and data segments into memory.
- // they are not as small as the load commands, but we'll need
- // the memory anyway for the symbol images, so we might
- // as well use one large chunk.
- if(c == nil) {
- werrstr("no load command");
- goto bad;
- }
- if(symtab == nil) {
- // our work is done here - no symbols means nothing can refer to this file
- return;
- }
-
- if(c->seg.fileoff+c->seg.filesz >= len) {
- werrstr("load segment out of range");
- goto bad;
- }
-
- dat = mal(c->seg.filesz);
- if(Bseek(f, m->base + c->seg.fileoff, 0) < 0 || Bread(f, dat, c->seg.filesz) != c->seg.filesz) {
- werrstr("cannot load object data: %r");
- goto bad;
- }
-
- for(i=0; i<c->seg.nsect; i++) {
- sect = &c->seg.sect[i];
- if(strcmp(sect->segname, "__TEXT") != 0 && strcmp(sect->segname, "__DATA") != 0)
- continue;
- if(strcmp(sect->name, "__eh_frame") == 0)
- continue;
- name = smprint("%s(%s/%s)", pn, sect->segname, sect->name);
- s = lookup(name, version);
- if(s->type != 0) {
- werrstr("duplicate %s/%s", sect->segname, sect->name);
- goto bad;
- }
- free(name);
- s->p = dat + sect->addr - c->seg.vmaddr;
- s->np = sect->size;
- s->size = s->np;
-
- if(strcmp(sect->segname, "__TEXT") == 0) {
- if(strcmp(sect->name, "__text") == 0)
- s->type = STEXT;
- else
- s->type = SRODATA;
- } else {
- if (strcmp(sect->name, "__bss") == 0) {
- s->type = SBSS;
- s->np = 0;
- } else
- s->type = SDATA;
- }
- if(s->type == STEXT) {
- if(etextp)
- etextp->next = s;
- else
- textp = s;
- etextp = s;
- }
- sect->sym = s;
- }
-
- // enter sub-symbols into symbol table.
- // have to guess sizes from next symbol.
- for(i=0; i<symtab->nsym; i++) {
- int v;
- sym = &symtab->sym[i];
- if(sym->type&N_STAB)
- continue;
- // TODO: check sym->type against outer->type.
- name = sym->name;
- if(name[0] == '_' && name[1] != '\0')
- name++;
- v = 0;
- if(!(sym->type&N_EXT))
- v = version;
- s = lookup(name, v);
- sym->sym = s;
- if(sym->sectnum == 0) // undefined
- continue;
- if(sym->sectnum > c->seg.nsect) {
- werrstr("reference to invalid section %d", sym->sectnum);
- goto bad;
- }
- sect = &c->seg.sect[sym->sectnum-1];
- outer = sect->sym;
- if(outer == nil) {
- werrstr("reference to invalid section %s/%s", sect->segname, sect->name);
- continue;
- }
- s->type = outer->type | SSUB;
- s->sub = outer->sub;
- outer->sub = s;
- s->outer = outer;
- s->value = sym->value - sect->addr;
- if(i+1 < symtab->nsym)
- s->size = (sym+1)->value - sym->value;
- else
- s->size = sect->addr + sect->size - sym->value;
- if(!s->dynexport) {
- s->dynimplib = nil; // satisfy dynimport
- s->dynimpname = nil; // satisfy dynimport
- }
- if(outer->type == STEXT) {
- Prog *p;
-
- if(s->text != P)
- diag("%s sym#%d: duplicate definition of %s", pn, i, s->name);
- // build a TEXT instruction with a unique pc
- // just to make the rest of the linker happy.
- // TODO: this is too 6l-specific ?
- p = prg();
- p->as = ATEXT;
- p->from.type = D_EXTERN;
- p->from.sym = s;
- p->textflag = 7;
- p->to.type = D_CONST;
- p->link = nil;
- p->pc = pc++;
- s->text = p;
-
- etextp->next = s;
- etextp = s;
- }
- sym->sym = s;
- }
-
- // load relocations
- for(i=0; i<c->seg.nsect; i++) {
- sect = &c->seg.sect[i];
- if((s = sect->sym) == S)
- continue;
- macholoadrel(m, sect);
- if(sect->rel == nil)
- continue;
- r = mal(sect->nreloc*sizeof r[0]);
- rp = r;
- rel = sect->rel;
- for(j=0; j<sect->nreloc; j++, rel++) {
- if(rel->scattered) {
- int k;
- MachoSect *ks;
-
- if(thechar != '8')
- diag("unexpected scattered relocation");
-
- // on 386, rewrite scattered 4/1 relocation into
- // the pseudo-pc-relative reference that it is.
- // assume that the second in the pair is in this section
- // and use that as the pc-relative base.
- if(thechar != '8' || rel->type != 4 || j+1 >= sect->nreloc ||
- !(rel+1)->scattered || (rel+1)->type != 1 ||
- (rel+1)->value < sect->addr || (rel+1)->value >= sect->addr+sect->size) {
- werrstr("unsupported scattered relocation %d/%d", (int)rel->type, (int)(rel+1)->type);
- goto bad;
- }
- rp->siz = rel->length;
- rp->off = rel->addr;
-
- // NOTE(rsc): I haven't worked out why (really when)
- // we should ignore the addend on a
- // scattered relocation, but it seems that the
- // common case is we ignore it.
- // It's likely that this is not strictly correct
- // and that the math should look something
- // like the non-scattered case below.
- rp->add = 0;
-
- // want to make it pc-relative aka relative to rp->off+4
- // but the scatter asks for relative to off = (rel+1)->value - sect->addr.
- // adjust rp->add accordingly.
- rp->type = D_PCREL;
- rp->add += (rp->off+4) - ((rel+1)->value - sect->addr);
-
- // now consider the desired symbol.
- // find the section where it lives.
- for(k=0; k<c->seg.nsect; k++) {
- ks = &c->seg.sect[k];
- if(ks->addr <= rel->value && rel->value < ks->addr+ks->size)
- goto foundk;
- }
- werrstr("unsupported scattered relocation: invalid address %#ux", rel->addr);
- goto bad;
- foundk:
- if(ks->sym != S) {
- rp->sym = ks->sym;
- rp->add += rel->value - ks->addr;
- } else if(strcmp(ks->segname, "__IMPORT") == 0 && strcmp(ks->name, "__pointers") == 0) {
- // handle reference to __IMPORT/__pointers.
- // how much worse can this get?
- // why are we supporting 386 on the mac anyway?
- rp->type = 512 + MACHO_FAKE_GOTPCREL;
- // figure out which pointer this is a reference to.
- k = ks->res1 + (rel->value - ks->addr) / 4;
- // load indirect table for __pointers
- // fetch symbol number
- if(dsymtab == nil || k < 0 || k >= dsymtab->nindirectsyms || dsymtab->indir == nil) {
- werrstr("invalid scattered relocation: indirect symbol reference out of range");
- goto bad;
- }
- k = dsymtab->indir[k];
- if(k < 0 || k >= symtab->nsym) {
- werrstr("invalid scattered relocation: symbol reference out of range");
- goto bad;
- }
- rp->sym = symtab->sym[k].sym;
- } else {
- werrstr("unsupported scattered relocation: reference to %s/%s", ks->segname, ks->name);
- goto bad;
- }
- rp++;
- // skip #1 of 2 rel; continue skips #2 of 2.
- rel++;
- j++;
- continue;
- }
-
- rp->siz = rel->length;
- rp->type = 512 + (rel->type<<1) + rel->pcrel;
- rp->off = rel->addr;
-
- // Handle X86_64_RELOC_SIGNED referencing a section (rel->extrn == 0).
- if (thechar == '6' && rel->extrn == 0 && rel->type == 1) {
- // Calculate the addend as the offset into the section.
- //
- // The rip-relative offset stored in the object file is encoded
- // as follows:
- //
- // movsd 0x00000360(%rip),%xmm0
- //
- // To get the absolute address of the value this rip-relative address is pointing
- // to, we must add the address of the next instruction to it. This is done by
- // taking the address of the relocation and adding 4 to it (since the rip-relative
- // offset can at most be 32 bits long). To calculate the offset into the section the
- // relocation is referencing, we subtract the vaddr of the start of the referenced
- // section found in the original object file.
- //
- // [For future reference, see Darwin's /usr/include/mach-o/x86_64/reloc.h]
- secaddr = c->seg.sect[rel->symnum-1].addr;
- rp->add = e->e32(s->p+rp->off) + rp->off + 4 - secaddr;
- } else
- rp->add = e->e32(s->p+rp->off);
-
- // For i386 Mach-O PC-relative, the addend is written such that
- // it *is* the PC being subtracted. Use that to make
- // it match our version of PC-relative.
- if(rel->pcrel && thechar == '8')
- rp->add += rp->off+rp->siz;
- if(!rel->extrn) {
- if(rel->symnum < 1 || rel->symnum > c->seg.nsect) {
- werrstr("invalid relocation: section reference out of range %d vs %d", rel->symnum, c->seg.nsect);
- goto bad;
- }
- rp->sym = c->seg.sect[rel->symnum-1].sym;
- if(rp->sym == nil) {
- werrstr("invalid relocation: %s", c->seg.sect[rel->symnum-1].name);
- goto bad;
- }
- // References to symbols in other sections
- // include that information in the addend.
- // We only care about the delta from the
- // section base.
- if(thechar == '8')
- rp->add -= c->seg.sect[rel->symnum-1].addr;
- } else {
- if(rel->symnum >= symtab->nsym) {
- werrstr("invalid relocation: symbol reference out of range");
- goto bad;
- }
- rp->sym = symtab->sym[rel->symnum].sym;
- }
- rp++;
- }
- qsort(r, rp - r, sizeof r[0], rbyoff);
- s->r = r;
- s->nr = rp - r;
- }
- return;
-
-bad:
- diag("%s: malformed mach-o file: %r", pn);
-}
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
deleted file mode 100644
index 98c866fee..000000000
--- a/src/cmd/ld/ldpe.c
+++ /dev/null
@@ -1,415 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "l.h"
-#include "lib.h"
-#include "../ld/pe.h"
-
-#define IMAGE_SCN_MEM_DISCARDABLE 0x2000000
-
-#define IMAGE_SYM_UNDEFINED 0
-#define IMAGE_SYM_ABSOLUTE (-1)
-#define IMAGE_SYM_DEBUG (-2)
-#define IMAGE_SYM_TYPE_NULL 0
-#define IMAGE_SYM_TYPE_VOID 1
-#define IMAGE_SYM_TYPE_CHAR 2
-#define IMAGE_SYM_TYPE_SHORT 3
-#define IMAGE_SYM_TYPE_INT 4
-#define IMAGE_SYM_TYPE_LONG 5
-#define IMAGE_SYM_TYPE_FLOAT 6
-#define IMAGE_SYM_TYPE_DOUBLE 7
-#define IMAGE_SYM_TYPE_STRUCT 8
-#define IMAGE_SYM_TYPE_UNION 9
-#define IMAGE_SYM_TYPE_ENUM 10
-#define IMAGE_SYM_TYPE_MOE 11
-#define IMAGE_SYM_TYPE_BYTE 12
-#define IMAGE_SYM_TYPE_WORD 13
-#define IMAGE_SYM_TYPE_UINT 14
-#define IMAGE_SYM_TYPE_DWORD 15
-#define IMAGE_SYM_TYPE_PCODE 32768
-#define IMAGE_SYM_DTYPE_NULL 0
-#define IMAGE_SYM_DTYPE_POINTER 0x10
-#define IMAGE_SYM_DTYPE_FUNCTION 0x20
-#define IMAGE_SYM_DTYPE_ARRAY 0x30
-#define IMAGE_SYM_CLASS_END_OF_FUNCTION (-1)
-#define IMAGE_SYM_CLASS_NULL 0
-#define IMAGE_SYM_CLASS_AUTOMATIC 1
-#define IMAGE_SYM_CLASS_EXTERNAL 2
-#define IMAGE_SYM_CLASS_STATIC 3
-#define IMAGE_SYM_CLASS_REGISTER 4
-#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5
-#define IMAGE_SYM_CLASS_LABEL 6
-#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
-#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
-#define IMAGE_SYM_CLASS_ARGUMENT 9
-#define IMAGE_SYM_CLASS_STRUCT_TAG 10
-#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
-#define IMAGE_SYM_CLASS_UNION_TAG 12
-#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13
-#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
-#define IMAGE_SYM_CLASS_ENUM_TAG 15
-#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
-#define IMAGE_SYM_CLASS_REGISTER_PARAM 17
-#define IMAGE_SYM_CLASS_BIT_FIELD 18
-#define IMAGE_SYM_CLASS_FAR_EXTERNAL 68 /* Not in PECOFF v8 spec */
-#define IMAGE_SYM_CLASS_BLOCK 100
-#define IMAGE_SYM_CLASS_FUNCTION 101
-#define IMAGE_SYM_CLASS_END_OF_STRUCT 102
-#define IMAGE_SYM_CLASS_FILE 103
-#define IMAGE_SYM_CLASS_SECTION 104
-#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
-#define IMAGE_SYM_CLASS_CLR_TOKEN 107
-
-#define IMAGE_REL_I386_ABSOLUTE 0x0000
-#define IMAGE_REL_I386_DIR16 0x0001
-#define IMAGE_REL_I386_REL16 0x0002
-#define IMAGE_REL_I386_DIR32 0x0006
-#define IMAGE_REL_I386_DIR32NB 0x0007
-#define IMAGE_REL_I386_SEG12 0x0009
-#define IMAGE_REL_I386_SECTION 0x000A
-#define IMAGE_REL_I386_SECREL 0x000B
-#define IMAGE_REL_I386_TOKEN 0x000C
-#define IMAGE_REL_I386_SECREL7 0x000D
-#define IMAGE_REL_I386_REL32 0x0014
-
-typedef struct PeSym PeSym;
-typedef struct PeSect PeSect;
-typedef struct PeObj PeObj;
-
-struct PeSym {
- char* name;
- uint32 value;
- uint16 sectnum;
- uint16 type;
- uint8 sclass;
- uint8 aux;
- Sym* sym;
-};
-
-struct PeSect {
- char* name;
- uchar* base;
- uint64 size;
- Sym* sym;
- IMAGE_SECTION_HEADER sh;
-};
-
-struct PeObj {
- Biobuf *f;
- char *name;
- uint32 base;
-
- PeSect *sect;
- uint nsect;
- PeSym *pesym;
- uint npesym;
-
- IMAGE_FILE_HEADER fh;
- char* snames;
-};
-
-static int map(PeObj *obj, PeSect *sect);
-static int readsym(PeObj *obj, int i, PeSym **sym);
-
-void
-ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
-{
- char *name;
- int32 base;
- int i, j, l, numaux;
- PeObj *obj;
- PeSect *sect, *rsect;
- IMAGE_SECTION_HEADER sh;
- uchar symbuf[18];
- Sym *s;
- Reloc *r, *rp;
- PeSym *sym;
-
- USED(len);
- USED(pkg);
- if(debug['v'])
- Bprint(&bso, "%5.2f ldpe %s\n", cputime(), pn);
-
- sect = nil;
- version++;
- base = Boffset(f);
-
- obj = mal(sizeof *obj);
- obj->f = f;
- obj->base = base;
- obj->name = pn;
- // read header
- if(Bread(f, &obj->fh, sizeof obj->fh) != sizeof obj->fh)
- goto bad;
- // load section list
- obj->sect = mal(obj->fh.NumberOfSections*sizeof obj->sect[0]);
- obj->nsect = obj->fh.NumberOfSections;
- for(i=0; i < obj->fh.NumberOfSections; i++) {
- if(Bread(f, &obj->sect[i].sh, sizeof sh) != sizeof sh)
- goto bad;
- obj->sect[i].size = obj->sect[i].sh.SizeOfRawData;
- obj->sect[i].name = (char*)obj->sect[i].sh.Name;
- // TODO return error if found .cormeta
- }
- // load string table
- Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
- if(Bread(f, &l, sizeof l) != sizeof l)
- goto bad;
- obj->snames = mal(l);
- Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
- if(Bread(f, obj->snames, l) != l)
- goto bad;
- // read symbols
- obj->pesym = mal(obj->fh.NumberOfSymbols*sizeof obj->pesym[0]);
- obj->npesym = obj->fh.NumberOfSymbols;
- Bseek(f, base+obj->fh.PointerToSymbolTable, 0);
- for(i=0; i<obj->fh.NumberOfSymbols; i+=numaux+1) {
- Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*i, 0);
- if(Bread(f, symbuf, sizeof symbuf) != sizeof symbuf)
- goto bad;
-
- if((symbuf[0] == 0) && (symbuf[1] == 0) &&
- (symbuf[2] == 0) && (symbuf[3] == 0)) {
- l = le32(&symbuf[4]);
- obj->pesym[i].name = (char*)&obj->snames[l];
- } else { // sym name length <= 8
- obj->pesym[i].name = mal(9);
- strncpy(obj->pesym[i].name, (char*)symbuf, 8);
- obj->pesym[i].name[8] = 0;
- }
- obj->pesym[i].value = le32(&symbuf[8]);
- obj->pesym[i].sectnum = le16(&symbuf[12]);
- obj->pesym[i].sclass = symbuf[16];
- obj->pesym[i].aux = symbuf[17];
- obj->pesym[i].type = le16(&symbuf[14]);
- numaux = obj->pesym[i].aux;
- if (numaux < 0)
- numaux = 0;
- }
- // create symbols for mapped sections
- for(i=0; i<obj->nsect; i++) {
- sect = &obj->sect[i];
- if(sect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE)
- continue;
- if(map(obj, sect) < 0)
- goto bad;
-
- name = smprint("%s(%s)", pn, sect->name);
- s = lookup(name, version);
- free(name);
- switch(sect->sh.Characteristics&(IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_CNT_INITIALIZED_DATA|
- IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE)) {
- case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ: //.rdata
- s->type = SRODATA;
- break;
- case IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.bss
- case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.data
- s->type = SDATA;
- break;
- case IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ: //.text
- s->type = STEXT;
- break;
- default:
- werrstr("unexpected flags for PE section %s", sect->name);
- goto bad;
- }
- s->p = sect->base;
- s->np = sect->size;
- s->size = sect->size;
- if(s->type == STEXT) {
- if(etextp)
- etextp->next = s;
- else
- textp = s;
- etextp = s;
- }
- sect->sym = s;
- if(strcmp(sect->name, ".rsrc") == 0)
- setpersrc(sect->sym);
- }
-
- // load relocations
- for(i=0; i<obj->nsect; i++) {
- rsect = &obj->sect[i];
- if(rsect->sym == 0 || rsect->sh.NumberOfRelocations == 0)
- continue;
- if(rsect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE)
- continue;
- r = mal(rsect->sh.NumberOfRelocations*sizeof r[0]);
- Bseek(f, obj->base+rsect->sh.PointerToRelocations, 0);
- for(j=0; j<rsect->sh.NumberOfRelocations; j++) {
- rp = &r[j];
- if(Bread(f, symbuf, 10) != 10)
- goto bad;
-
- uint32 rva, symindex;
- uint16 type;
- rva = le32(&symbuf[0]);
- symindex = le32(&symbuf[4]);
- type = le16(&symbuf[8]);
- if(readsym(obj, symindex, &sym) < 0)
- goto bad;
- if(sym->sym == nil) {
- werrstr("reloc of invalid sym %s idx=%d type=%d", sym->name, symindex, sym->type);
- goto bad;
- }
- rp->sym = sym->sym;
- rp->siz = 4;
- rp->off = rva;
- switch(type) {
- default:
- diag("%s: unknown relocation type %d;", pn, type);
- case IMAGE_REL_I386_REL32:
- rp->type = D_PCREL;
- rp->add = 0;
- break;
- case IMAGE_REL_I386_DIR32NB:
- case IMAGE_REL_I386_DIR32:
- rp->type = D_ADDR;
- // load addend from image
- rp->add = le32(rsect->base+rp->off);
- break;
- }
- }
- qsort(r, rsect->sh.NumberOfRelocations, sizeof r[0], rbyoff);
-
- s = rsect->sym;
- s->r = r;
- s->nr = rsect->sh.NumberOfRelocations;
- }
-
- // enter sub-symbols into symbol table.
- // frist 2 entry is file name.
- for(i=2; i<obj->npesym; i++) {
- if(obj->pesym[i].name == 0)
- continue;
- if(obj->pesym[i].name[0] == '.') //skip section
- continue;
- if(obj->pesym[i].sectnum > 0) {
- sect = &obj->sect[obj->pesym[i].sectnum-1];
- if(sect->sym == 0)
- continue;
- }
- if(readsym(obj, i, &sym) < 0)
- goto bad;
-
- s = sym->sym;
- if(sym->sectnum == 0) {// extern
- if(s->type == SDYNIMPORT)
- s->plt = -2; // flag for dynimport in PE object files.
- continue;
- } else if (sym->sectnum > 0) {
- sect = &obj->sect[sym->sectnum-1];
- if(sect->sym == 0)
- diag("%s: %s sym == 0!", pn, s->name);
- } else {
- diag("%s: %s sectnum <0!", pn, s->name, sym->sectnum);
- }
-
- if(sect == nil)
- return;
- s->sub = sect->sym->sub;
- sect->sym->sub = s;
- s->type = sect->sym->type | SSUB;
- s->value = sym->value;
- s->size = 4;
- s->outer = sect->sym;
- if(sect->sym->type == STEXT) {
- Prog *p;
-
- if(s->text != P)
- diag("%s: duplicate definition of %s", pn, s->name);
- // build a TEXT instruction with a unique pc
- // just to make the rest of the linker happy.
- p = prg();
- p->as = ATEXT;
- p->from.type = D_EXTERN;
- p->from.sym = s;
- p->textflag = 7;
- p->to.type = D_CONST;
- p->link = nil;
- p->pc = pc++;
- s->text = p;
-
- etextp->next = s;
- etextp = s;
- }
- }
-
- return;
-bad:
- diag("%s: malformed pe file: %r", pn);
-}
-
-static int
-map(PeObj *obj, PeSect *sect)
-{
- if(sect->base != nil)
- return 0;
-
- sect->base = mal(sect->sh.SizeOfRawData);
- werrstr("short read");
- if(Bseek(obj->f, obj->base+sect->sh.PointerToRawData, 0) < 0 ||
- Bread(obj->f, sect->base, sect->sh.SizeOfRawData) != sect->sh.SizeOfRawData)
- return -1;
-
- return 0;
-}
-
-static int
-readsym(PeObj *obj, int i, PeSym **y)
-{
- Sym *s;
- PeSym *sym;
- char *name, *p;
-
- if(i >= obj->npesym || i < 0) {
- werrstr("invalid pe symbol index");
- return -1;
- }
-
- sym = &obj->pesym[i];
- *y = sym;
-
- name = sym->name;
- if(sym->sclass == IMAGE_SYM_CLASS_STATIC && sym->value == 0) // section
- name = obj->sect[sym->sectnum-1].sym->name;
- if(strncmp(sym->name, "__imp__", 7) == 0)
- name = &sym->name[7]; // __imp__Name => Name
- else if(sym->name[0] == '_')
- name = &sym->name[1]; // _Name => Name
- // remove last @XXX
- p = strchr(name, '@');
- if(p)
- *p = 0;
-
- switch(sym->type) {
- default:
- werrstr("%s: invalid symbol type %d", sym->name, sym->type);
- return -1;
- case IMAGE_SYM_DTYPE_FUNCTION:
- case IMAGE_SYM_DTYPE_NULL:
- switch(sym->sclass) {
- case IMAGE_SYM_CLASS_EXTERNAL: //global
- s = lookup(name, 0);
- break;
- case IMAGE_SYM_CLASS_NULL:
- case IMAGE_SYM_CLASS_STATIC:
- s = lookup(name, version);
- break;
- default:
- werrstr("%s: invalid symbol binding %d", sym->name, sym->sclass);
- return -1;
- }
- break;
- }
-
- if(s != nil && s->type == 0 && !(sym->sclass == IMAGE_SYM_CLASS_STATIC && sym->value == 0))
- s->type = SXREF;
- if(strncmp(sym->name, "__imp__", 7) == 0)
- s->got = -2; // flag for __imp__
- sym->sym = s;
-
- return 0;
-}
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
deleted file mode 100644
index 77a62f5de..000000000
--- a/src/cmd/ld/lib.c
+++ /dev/null
@@ -1,1361 +0,0 @@
-// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "l.h"
-#include "lib.h"
-#include "../../pkg/runtime/stack.h"
-
-#include <ar.h>
-
-int iconv(Fmt*);
-
-char symname[] = SYMDEF;
-char pkgname[] = "__.PKGDEF";
-char* libdir[16];
-int nlibdir = 0;
-int cout = -1;
-
-char* goroot;
-char* goarch;
-char* goos;
-
-void
-Lflag(char *arg)
-{
- if(nlibdir >= nelem(libdir)-1) {
- print("too many -L's: %d\n", nlibdir);
- usage();
- }
- libdir[nlibdir++] = arg;
-}
-
-void
-libinit(void)
-{
- fmtinstall('i', iconv);
- fmtinstall('Y', Yconv);
- mywhatsys(); // get goroot, goarch, goos
- if(strcmp(goarch, thestring) != 0)
- print("goarch is not known: %s\n", goarch);
-
- // add goroot to the end of the libdir list.
- libdir[nlibdir++] = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
-
- remove(outfile);
- cout = create(outfile, 1, 0775);
- if(cout < 0) {
- diag("cannot create %s", outfile);
- errorexit();
- }
-
- if(INITENTRY == nil) {
- INITENTRY = mal(strlen(goarch)+strlen(goos)+10);
- sprint(INITENTRY, "_rt0_%s_%s", goarch, goos);
- }
- lookup(INITENTRY, 0)->type = SXREF;
-}
-
-void
-errorexit(void)
-{
- if(nerrors) {
- if(cout >= 0)
- remove(outfile);
- exits("error");
- }
- exits(0);
-}
-
-void
-addlib(char *src, char *obj)
-{
- char name[1024], pname[1024], comp[256], *p;
- int i, search;
-
- if(histfrogp <= 0)
- return;
-
- search = 0;
- if(histfrog[0]->name[1] == '/') {
- sprint(name, "");
- i = 1;
- } else
- if(isalpha(histfrog[0]->name[1]) && histfrog[0]->name[2] == ':') {
- strcpy(name, histfrog[0]->name+1);
- i = 1;
- } else
- if(histfrog[0]->name[1] == '.') {
- sprint(name, ".");
- i = 0;
- } else {
- sprint(name, "");
- i = 0;
- search = 1;
- }
-
- for(; i<histfrogp; i++) {
- snprint(comp, sizeof comp, "%s", histfrog[i]->name+1);
- for(;;) {
- p = strstr(comp, "$O");
- if(p == 0)
- break;
- memmove(p+1, p+2, strlen(p+2)+1);
- p[0] = thechar;
- }
- for(;;) {
- p = strstr(comp, "$M");
- if(p == 0)
- break;
- if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
- diag("library component too long");
- return;
- }
- memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
- memmove(p, thestring, strlen(thestring));
- }
- if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
- diag("library component too long");
- return;
- }
- if(i > 0 || !search)
- strcat(name, "/");
- strcat(name, comp);
- }
- cleanname(name);
-
- // runtime.a -> runtime
- p = nil;
- if(strlen(name) > 2 && name[strlen(name)-2] == '.') {
- p = name+strlen(name)-2;
- *p = '\0';
- }
-
- // already loaded?
- for(i=0; i<libraryp; i++)
- if(strcmp(library[i].pkg, name) == 0)
- return;
-
- // runtime -> runtime.a for search
- if(p != nil)
- *p = '.';
-
- if(search) {
- // try dot, -L "libdir", and then goroot.
- for(i=0; i<nlibdir; i++) {
- snprint(pname, sizeof pname, "%s/%s", libdir[i], name);
- if(access(pname, AEXIST) >= 0)
- break;
- }
- }else
- strcpy(pname, name);
- cleanname(pname);
-
- /* runtime.a -> runtime */
- if(p != nil)
- *p = '\0';
-
- if(debug['v'])
- Bprint(&bso, "%5.2f addlib: %s %s pulls in %s\n", cputime(), obj, src, pname);
-
- addlibpath(src, obj, pname, name);
-}
-
-/*
- * add library to library list.
- * srcref: src file referring to package
- * objref: object file referring to package
- * file: object file, e.g., /home/rsc/go/pkg/container/vector.a
- * pkg: package import path, e.g. container/vector
- */
-void
-addlibpath(char *srcref, char *objref, char *file, char *pkg)
-{
- int i;
- Library *l;
- char *p;
-
- for(i=0; i<libraryp; i++)
- if(strcmp(file, library[i].file) == 0)
- return;
-
- if(debug['v'] > 1)
- Bprint(&bso, "%5.2f addlibpath: srcref: %s objref: %s file: %s pkg: %s\n",
- cputime(), srcref, objref, file, pkg);
-
- if(libraryp == nlibrary){
- nlibrary = 50 + 2*libraryp;
- library = realloc(library, sizeof library[0] * nlibrary);
- }
-
- l = &library[libraryp++];
-
- p = mal(strlen(objref) + 1);
- strcpy(p, objref);
- l->objref = p;
-
- p = mal(strlen(srcref) + 1);
- strcpy(p, srcref);
- l->srcref = p;
-
- p = mal(strlen(file) + 1);
- strcpy(p, file);
- l->file = p;
-
- p = mal(strlen(pkg) + 1);
- strcpy(p, pkg);
- l->pkg = p;
-}
-
-void
-loadinternal(char *name)
-{
- char pname[1024];
- int i, found;
-
- found = 0;
- for(i=0; i<nlibdir; i++) {
- snprint(pname, sizeof pname, "%s/%s.a", libdir[i], name);
- if(debug['v'])
- Bprint(&bso, "searching for %s.a in %s\n", name, pname);
- if(access(pname, AEXIST) >= 0) {
- addlibpath("internal", "internal", pname, name);
- found = 1;
- break;
- }
- }
- if(!found)
- Bprint(&bso, "warning: unable to find %s.a\n", name);
-}
-
-void
-loadlib(void)
-{
- int i;
-
- loadinternal("runtime");
- if(thechar == '5')
- loadinternal("math");
-
- for(i=0; i<libraryp; i++) {
- if(debug['v'])
- Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i].file, library[i].objref);
- objfile(library[i].file, library[i].pkg);
- }
-
- // We've loaded all the code now.
- // If there are no dynamic libraries needed, gcc disables dynamic linking.
- // Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
- // assumes that a dynamic binary always refers to at least one dynamic library.
- // Rather than be a source of test cases for glibc, disable dynamic linking
- // the same way that gcc would.
- //
- // 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)
- debug['d'] = 1;
-}
-
-/*
- * look for the next file in an archive.
- * adapted from libmach.
- */
-int
-nextar(Biobuf *bp, int off, struct ar_hdr *a)
-{
- int r;
- int32 arsize;
-
- if (off&01)
- off++;
- Bseek(bp, off, 0);
- r = Bread(bp, a, SAR_HDR);
- if(r != SAR_HDR)
- return 0;
- if(strncmp(a->fmag, ARFMAG, sizeof(a->fmag)))
- return -1;
- arsize = strtol(a->size, 0, 0);
- if (arsize&1)
- arsize++;
- return arsize + SAR_HDR;
-}
-
-void
-objfile(char *file, char *pkg)
-{
- int32 off, l;
- Biobuf *f;
- char magbuf[SARMAG];
- char pname[150];
- struct ar_hdr arhdr;
-
- pkg = smprint("%i", pkg);
-
- if(debug['v'])
- Bprint(&bso, "%5.2f ldobj: %s (%s)\n", cputime(), file, pkg);
- Bflush(&bso);
- f = Bopen(file, 0);
- if(f == nil) {
- diag("cannot open file: %s", file);
- errorexit();
- }
- l = Bread(f, magbuf, SARMAG);
- if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
- /* load it as a regular file */
- l = Bseek(f, 0L, 2);
- Bseek(f, 0L, 0);
- ldobj(f, pkg, l, file, FileObj);
- Bterm(f);
- return;
- }
-
- /* skip over __.SYMDEF */
- off = Boffset(f);
- if((l = nextar(f, off, &arhdr)) <= 0) {
- diag("%s: short read on archive file symbol header", file);
- goto out;
- }
- if(strncmp(arhdr.name, symname, strlen(symname))) {
- diag("%s: first entry not symbol header", file);
- goto out;
- }
- off += l;
-
- /* skip over (or process) __.PKGDEF */
- if((l = nextar(f, off, &arhdr)) <= 0) {
- diag("%s: short read on archive file symbol header", file);
- goto out;
- }
- if(strncmp(arhdr.name, pkgname, strlen(pkgname))) {
- diag("%s: second entry not package header", file);
- goto out;
- }
- off += l;
-
- if(debug['u'])
- ldpkg(f, pkg, atolwhex(arhdr.size), file, Pkgdef);
-
- /*
- * load all the object files from the archive now.
- * this gives us sequential file access and keeps us
- * from needing to come back later to pick up more
- * objects. it breaks the usual C archive model, but
- * this is Go, not C. the common case in Go is that
- * we need to load all the objects, and then we throw away
- * the individual symbols that are unused.
- *
- * loading every object will also make it possible to
- * load foreign objects not referenced by __.SYMDEF.
- */
- for(;;) {
- l = nextar(f, off, &arhdr);
- if(l == 0)
- break;
- if(l < 0) {
- diag("%s: malformed archive", file);
- goto out;
- }
- off += l;
-
- l = SARNAME;
- while(l > 0 && arhdr.name[l-1] == ' ')
- l--;
- snprint(pname, sizeof pname, "%s(%.*s)", file, utfnlen(arhdr.name, l), arhdr.name);
- l = atolwhex(arhdr.size);
- ldobj(f, pkg, l, pname, ArchiveObj);
- }
-
-out:
- Bterm(f);
-}
-
-void
-ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
-{
- char *line;
- int n, c1, c2, c3, c4;
- uint32 magic;
- vlong import0, import1, eof;
- char *t;
-
- eof = Boffset(f) + len;
-
- pn = strdup(pn);
-
- c1 = Bgetc(f);
- c2 = Bgetc(f);
- c3 = Bgetc(f);
- c4 = Bgetc(f);
- Bungetc(f);
- Bungetc(f);
- Bungetc(f);
- Bungetc(f);
-
- magic = c1<<24 | c2<<16 | c3<<8 | c4;
- if(magic == 0x7f454c46) { // \x7F E L F
- ldelf(f, pkg, len, pn);
- return;
- }
- if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
- ldmacho(f, pkg, len, pn);
- return;
- }
- if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) {
- ldpe(f, pkg, len, pn);
- return;
- }
-
- /* check the header */
- line = Brdline(f, '\n');
- if(line == nil) {
- if(Blinelen(f) > 0) {
- diag("%s: not an object file", pn);
- return;
- }
- goto eof;
- }
- n = Blinelen(f) - 1;
- line[n] = '\0';
- if(strncmp(line, "go object ", 10) != 0) {
- if(strlen(pn) > 3 && strcmp(pn+strlen(pn)-3, ".go") == 0) {
- print("%cl: input %s is not .%c file (use %cg to compile .go files)\n", thechar, pn, thechar, thechar);
- errorexit();
- }
- if(strcmp(line, thestring) == 0) {
- // old header format: just $GOOS
- diag("%s: stale object file", pn);
- return;
- }
- diag("%s: not an object file", pn);
- return;
- }
- t = smprint("%s %s %s", getgoos(), thestring, getgoversion());
- if(strcmp(line+10, t) != 0 && !debug['f']) {
- diag("%s: object is [%s] expected [%s]", pn, line+10, t);
- free(t);
- return;
- }
- free(t);
- line[n] = '\n';
-
- /* skip over exports and other info -- ends with \n!\n */
- import0 = Boffset(f);
- c1 = '\n'; // the last line ended in \n
- c2 = Bgetc(f);
- c3 = Bgetc(f);
- while(c1 != '\n' || c2 != '!' || c3 != '\n') {
- c1 = c2;
- c2 = c3;
- c3 = Bgetc(f);
- if(c3 == Beof)
- goto eof;
- }
- import1 = Boffset(f);
-
- Bseek(f, import0, 0);
- ldpkg(f, pkg, import1 - import0 - 2, pn, whence); // -2 for !\n
- Bseek(f, import1, 0);
-
- ldobj1(f, pkg, eof - Boffset(f), pn);
- return;
-
-eof:
- diag("truncated object file: %s", pn);
-}
-
-static Sym*
-_lookup(char *symb, int v, int creat)
-{
- Sym *s;
- char *p;
- int32 h;
- int l, c;
-
- h = v;
- for(p=symb; c = *p; p++)
- h = h+h+h + c;
- l = (p - symb) + 1;
- // not if(h < 0) h = ~h, because gcc 4.3 -O2 miscompiles it.
- h &= 0xffffff;
- h %= NHASH;
- for(s = hash[h]; s != S; s = s->hash)
- if(memcmp(s->name, symb, l) == 0)
- return s;
- if(!creat)
- return nil;
-
- s = mal(sizeof(*s));
- if(debug['v'] > 1)
- Bprint(&bso, "lookup %s\n", symb);
-
- s->dynid = -1;
- s->plt = -1;
- s->got = -1;
- s->name = mal(l + 1);
- memmove(s->name, symb, l);
-
- s->hash = hash[h];
- s->type = 0;
- s->version = v;
- s->value = 0;
- s->sig = 0;
- s->size = 0;
- hash[h] = s;
- nsymbol++;
-
- s->allsym = allsym;
- allsym = s;
- return s;
-}
-
-Sym*
-lookup(char *name, int v)
-{
- return _lookup(name, v, 1);
-}
-
-// read-only lookup
-Sym*
-rlookup(char *name, int v)
-{
- return _lookup(name, v, 0);
-}
-
-void
-copyhistfrog(char *buf, int nbuf)
-{
- char *p, *ep;
- int i;
-
- p = buf;
- ep = buf + nbuf;
- for(i=0; i<histfrogp; i++) {
- p = seprint(p, ep, "%s", histfrog[i]->name+1);
- if(i+1<histfrogp && (p == buf || p[-1] != '/'))
- p = seprint(p, ep, "/");
- }
-}
-
-void
-addhist(int32 line, int type)
-{
- Auto *u;
- Sym *s;
- int i, j, k;
-
- u = mal(sizeof(Auto));
- s = mal(sizeof(Sym));
- s->name = mal(2*(histfrogp+1) + 1);
-
- u->asym = s;
- u->type = type;
- u->aoffset = line;
- u->link = curhist;
- curhist = u;
-
- s->name[0] = 0;
- j = 1;
- for(i=0; i<histfrogp; i++) {
- k = histfrog[i]->value;
- s->name[j+0] = k>>8;
- s->name[j+1] = k;
- j += 2;
- }
- s->name[j] = 0;
- s->name[j+1] = 0;
-}
-
-void
-histtoauto(void)
-{
- Auto *l;
-
- while(l = curhist) {
- curhist = l->link;
- l->link = curauto;
- curauto = l;
- }
-}
-
-void
-collapsefrog(Sym *s)
-{
- int i;
-
- /*
- * bad encoding of path components only allows
- * MAXHIST components. if there is an overflow,
- * first try to collapse xxx/..
- */
- for(i=1; i<histfrogp; i++)
- if(strcmp(histfrog[i]->name+1, "..") == 0) {
- memmove(histfrog+i-1, histfrog+i+1,
- (histfrogp-i-1)*sizeof(histfrog[0]));
- histfrogp--;
- goto out;
- }
-
- /*
- * next try to collapse .
- */
- for(i=0; i<histfrogp; i++)
- if(strcmp(histfrog[i]->name+1, ".") == 0) {
- memmove(histfrog+i, histfrog+i+1,
- (histfrogp-i-1)*sizeof(histfrog[0]));
- goto out;
- }
-
- /*
- * last chance, just truncate from front
- */
- memmove(histfrog+0, histfrog+1,
- (histfrogp-1)*sizeof(histfrog[0]));
-
-out:
- histfrog[histfrogp-1] = s;
-}
-
-void
-nuxiinit(void)
-{
- int i, c;
-
- for(i=0; i<4; i++) {
- c = find1(0x04030201L, i+1);
- if(i < 2)
- inuxi2[i] = c;
- if(i < 1)
- inuxi1[i] = c;
- inuxi4[i] = c;
- if(c == i) {
- inuxi8[i] = c;
- inuxi8[i+4] = c+4;
- } else {
- inuxi8[i] = c+4;
- inuxi8[i+4] = c;
- }
- fnuxi4[i] = c;
- fnuxi8[i] = c;
- fnuxi8[i+4] = c+4;
- }
- if(debug['v']) {
- Bprint(&bso, "inuxi = ");
- for(i=0; i<1; i++)
- Bprint(&bso, "%d", inuxi1[i]);
- Bprint(&bso, " ");
- for(i=0; i<2; i++)
- Bprint(&bso, "%d", inuxi2[i]);
- Bprint(&bso, " ");
- for(i=0; i<4; i++)
- Bprint(&bso, "%d", inuxi4[i]);
- Bprint(&bso, " ");
- for(i=0; i<8; i++)
- Bprint(&bso, "%d", inuxi8[i]);
- Bprint(&bso, "\nfnuxi = ");
- for(i=0; i<4; i++)
- Bprint(&bso, "%d", fnuxi4[i]);
- Bprint(&bso, " ");
- for(i=0; i<8; i++)
- Bprint(&bso, "%d", fnuxi8[i]);
- Bprint(&bso, "\n");
- }
- Bflush(&bso);
-}
-
-int
-find1(int32 l, int c)
-{
- char *p;
- int i;
-
- p = (char*)&l;
- for(i=0; i<4; i++)
- if(*p++ == c)
- return i;
- return 0;
-}
-
-int
-find2(int32 l, int c)
-{
- union {
- int32 l;
- short p[2];
- } u;
- short *p;
- int i;
-
- u.l = l;
- p = u.p;
- for(i=0; i<4; i+=2) {
- if(((*p >> 8) & 0xff) == c)
- return i;
- if((*p++ & 0xff) == c)
- return i+1;
- }
- return 0;
-}
-
-int32
-ieeedtof(Ieee *e)
-{
- int exp;
- int32 v;
-
- if(e->h == 0)
- return 0;
- exp = (e->h>>20) & ((1L<<11)-1L);
- exp -= (1L<<10) - 2L;
- v = (e->h & 0xfffffL) << 3;
- v |= (e->l >> 29) & 0x7L;
- if((e->l >> 28) & 1) {
- v++;
- if(v & 0x800000L) {
- v = (v & 0x7fffffL) >> 1;
- exp++;
- }
- }
- if(-148 <= exp && exp <= -126) {
- v |= 1<<23;
- v >>= -125 - exp;
- exp = -126;
- }
- else if(exp < -148 || exp >= 130)
- diag("double fp to single fp overflow: %.17g", ieeedtod(e));
- v |= ((exp + 126) & 0xffL) << 23;
- v |= e->h & 0x80000000L;
- return v;
-}
-
-double
-ieeedtod(Ieee *ieeep)
-{
- Ieee e;
- double fr;
- int exp;
-
- if(ieeep->h & (1L<<31)) {
- e.h = ieeep->h & ~(1L<<31);
- e.l = ieeep->l;
- return -ieeedtod(&e);
- }
- if(ieeep->l == 0 && ieeep->h == 0)
- return 0;
- exp = (ieeep->h>>20) & ((1L<<11)-1L);
- exp -= (1L<<10) - 2L;
- fr = ieeep->l & ((1L<<16)-1L);
- fr /= 1L<<16;
- fr += (ieeep->l>>16) & ((1L<<16)-1L);
- fr /= 1L<<16;
- if(exp == -(1L<<10) - 2L) {
- fr += (ieeep->h & (1L<<20)-1L);
- exp++;
- } else
- fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
- fr /= 1L<<21;
- return ldexp(fr, exp);
-}
-
-void
-zerosig(char *sp)
-{
- Sym *s;
-
- s = lookup(sp, 0);
- s->sig = 0;
-}
-
-int32
-Bget4(Biobuf *f)
-{
- uchar p[4];
-
- if(Bread(f, p, 4) != 4)
- return 0;
- return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-}
-
-void
-mywhatsys(void)
-{
- goroot = getgoroot();
- goos = getgoos();
- goarch = thestring; // ignore $GOARCH - we know who we are
-}
-
-int
-pathchar(void)
-{
- return '/';
-}
-
-static uchar* hunk;
-static uint32 nhunk;
-#define NHUNK (10UL<<20)
-
-void*
-mal(uint32 n)
-{
- void *v;
-
- n = (n+7)&~7;
- if(n > NHUNK) {
- v = malloc(n);
- if(v == nil) {
- diag("out of memory");
- errorexit();
- }
- memset(v, 0, n);
- return v;
- }
- if(n > nhunk) {
- hunk = malloc(NHUNK);
- if(hunk == nil) {
- diag("out of memory");
- errorexit();
- }
- nhunk = NHUNK;
- }
-
- v = hunk;
- nhunk -= n;
- hunk += n;
-
- memset(v, 0, n);
- return v;
-}
-
-void
-unmal(void *v, uint32 n)
-{
- n = (n+7)&~7;
- if(hunk - n == v) {
- hunk -= n;
- nhunk += n;
- }
-}
-
-// Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync.
-/*
- * Convert raw string to the prefix that will be used in the symbol table.
- * Invalid bytes turn into %xx. Right now the only bytes that need
- * escaping are %, ., and ", but we escape all control characters too.
- */
-static char*
-pathtoprefix(char *s)
-{
- static char hex[] = "0123456789abcdef";
- char *p, *r, *w;
- int n;
-
- // check for chars that need escaping
- n = 0;
- for(r=s; *r; r++)
- if(*r <= ' ' || *r == '.' || *r == '%' || *r == '"')
- n++;
-
- // quick exit
- if(n == 0)
- return s;
-
- // escape
- p = mal((r-s)+1+2*n);
- for(r=s, w=p; *r; r++) {
- if(*r <= ' ' || *r == '.' || *r == '%' || *r == '"') {
- *w++ = '%';
- *w++ = hex[(*r>>4)&0xF];
- *w++ = hex[*r&0xF];
- } else
- *w++ = *r;
- }
- *w = '\0';
- return p;
-}
-
-int
-iconv(Fmt *fp)
-{
- char *p;
-
- p = va_arg(fp->args, char*);
- if(p == nil) {
- fmtstrcpy(fp, "<nil>");
- return 0;
- }
- p = pathtoprefix(p);
- fmtstrcpy(fp, p);
- return 0;
-}
-
-void
-mangle(char *file)
-{
- fprint(2, "%s: mangled input file\n", file);
- errorexit();
-}
-
-Section*
-addsection(Segment *seg, char *name, int rwx)
-{
- Section **l;
- Section *sect;
-
- for(l=&seg->sect; *l; l=&(*l)->next)
- ;
- sect = mal(sizeof *sect);
- sect->rwx = rwx;
- sect->name = name;
- sect->seg = seg;
- *l = sect;
- return sect;
-}
-
-void
-ewrite(int fd, void *buf, int n)
-{
- if(write(fd, buf, n) < 0) {
- diag("write error: %r");
- errorexit();
- }
-}
-
-void
-pclntab(void)
-{
- vlong oldpc;
- Prog *p;
- int32 oldlc, v, s;
- Sym *sym;
- uchar *bp;
-
- sym = lookup("pclntab", 0);
- sym->type = SPCLNTAB;
- sym->reachable = 1;
- if(debug['s'])
- return;
-
- oldpc = INITTEXT;
- oldlc = 0;
- for(cursym = textp; cursym != nil; cursym = cursym->next) {
- for(p = cursym->text; p != P; p = p->link) {
- if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
- if(debug['O'])
- Bprint(&bso, "%6llux %P\n",
- (vlong)p->pc, p);
- continue;
- }
- if(debug['O'])
- Bprint(&bso, "\t\t%6d", lcsize);
- v = (p->pc - oldpc) / MINLC;
- while(v) {
- s = 127;
- if(v < 127)
- s = v;
- symgrow(sym, lcsize+1);
- bp = sym->p + lcsize;
- *bp = s+128; /* 129-255 +pc */
- if(debug['O'])
- Bprint(&bso, " pc+%d*%d(%d)", s, MINLC, s+128);
- v -= s;
- lcsize++;
- }
- s = p->line - oldlc;
- oldlc = p->line;
- oldpc = p->pc + MINLC;
- if(s > 64 || s < -64) {
- symgrow(sym, lcsize+5);
- bp = sym->p + lcsize;
- *bp++ = 0; /* 0 vv +lc */
- *bp++ = s>>24;
- *bp++ = s>>16;
- *bp++ = s>>8;
- *bp = s;
- if(debug['O']) {
- if(s > 0)
- Bprint(&bso, " lc+%d(%d,%d)\n",
- s, 0, s);
- else
- Bprint(&bso, " lc%d(%d,%d)\n",
- s, 0, s);
- Bprint(&bso, "%6llux %P\n",
- (vlong)p->pc, p);
- }
- lcsize += 5;
- continue;
- }
- symgrow(sym, lcsize+1);
- bp = sym->p + lcsize;
- if(s > 0) {
- *bp = 0+s; /* 1-64 +lc */
- if(debug['O']) {
- Bprint(&bso, " lc+%d(%d)\n", s, 0+s);
- Bprint(&bso, "%6llux %P\n",
- (vlong)p->pc, p);
- }
- } else {
- *bp = 64-s; /* 65-128 -lc */
- if(debug['O']) {
- Bprint(&bso, " lc%d(%d)\n", s, 64-s);
- Bprint(&bso, "%6llux %P\n",
- (vlong)p->pc, p);
- }
- }
- lcsize++;
- }
- }
- if(lcsize & 1) {
- symgrow(sym, lcsize+1);
- sym->p[lcsize] = 129;
- lcsize++;
- }
- sym->size = lcsize;
- lcsize = 0;
-
- if(debug['v'] || debug['O'])
- Bprint(&bso, "lcsize = %d\n", lcsize);
- Bflush(&bso);
-}
-
-#define LOG 5
-void
-mkfwd(void)
-{
- Prog *p;
- int i;
- int32 dwn[LOG], cnt[LOG];
- Prog *lst[LOG];
-
- for(i=0; i<LOG; i++) {
- if(i == 0)
- cnt[i] = 1;
- else
- cnt[i] = LOG * cnt[i-1];
- dwn[i] = 1;
- lst[i] = P;
- }
- i = 0;
- for(cursym = textp; cursym != nil; cursym = cursym->next) {
- for(p = cursym->text; p != P; p = p->link) {
- if(p->link == P) {
- if(cursym->next)
- p->forwd = cursym->next->text;
- break;
- }
- i--;
- if(i < 0)
- i = LOG-1;
- p->forwd = P;
- dwn[i]--;
- if(dwn[i] <= 0) {
- dwn[i] = cnt[i];
- if(lst[i] != P)
- lst[i]->forwd = p;
- lst[i] = p;
- }
- }
- }
-}
-
-uint16
-le16(uchar *b)
-{
- return b[0] | b[1]<<8;
-}
-
-uint32
-le32(uchar *b)
-{
- return b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;
-}
-
-uint64
-le64(uchar *b)
-{
- return le32(b) | (uint64)le32(b+4)<<32;
-}
-
-uint16
-be16(uchar *b)
-{
- return b[0]<<8 | b[1];
-}
-
-uint32
-be32(uchar *b)
-{
- return b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
-}
-
-uint64
-be64(uchar *b)
-{
- return (uvlong)be32(b)<<32 | be32(b+4);
-}
-
-Endian be = { be16, be32, be64 };
-Endian le = { le16, le32, le64 };
-
-typedef struct Chain Chain;
-struct Chain
-{
- Sym *sym;
- Chain *up;
- int limit; // limit on entry to sym
-};
-
-static int stkcheck(Chain*, int);
-static void stkprint(Chain*, int);
-static void stkbroke(Chain*, int);
-static Sym *morestack;
-static Sym *newstack;
-
-enum
-{
- HasLinkRegister = (thechar == '5'),
- CallSize = (!HasLinkRegister)*PtrSize, // bytes of stack required for a call
-};
-
-void
-dostkcheck(void)
-{
- Chain ch;
- Sym *s;
-
- morestack = lookup("runtime.morestack", 0);
- newstack = lookup("runtime.newstack", 0);
-
- // First the nosplits on their own.
- for(s = textp; s != nil; s = s->next) {
- if(s->text == nil || s->text->link == nil || (s->text->textflag & NOSPLIT) == 0)
- continue;
- cursym = s;
- ch.up = nil;
- ch.sym = s;
- ch.limit = StackLimit - CallSize;
- stkcheck(&ch, 0);
- s->stkcheck = 1;
- }
-
- // Check calling contexts.
- // Some nosplits get called a little further down,
- // like newproc and deferproc. We could hard-code
- // that knowledge but it's more robust to look at
- // the actual call sites.
- for(s = textp; s != nil; s = s->next) {
- if(s->text == nil || s->text->link == nil || (s->text->textflag & NOSPLIT) != 0)
- continue;
- cursym = s;
- ch.up = nil;
- ch.sym = s;
- ch.limit = StackLimit - CallSize;
- stkcheck(&ch, 0);
- }
-}
-
-static int
-stkcheck(Chain *up, int depth)
-{
- Chain ch, ch1;
- Prog *p;
- Sym *s;
- int limit, prolog;
-
- limit = up->limit;
- s = up->sym;
- p = s->text;
-
- // Small optimization: don't repeat work at top.
- if(s->stkcheck && limit == StackLimit-CallSize)
- return 0;
-
- if(depth > 100) {
- diag("nosplit stack check too deep");
- stkbroke(up, 0);
- return -1;
- }
-
- if(p == nil || p->link == nil) {
- // external function.
- // should never be called directly.
- // only diagnose the direct caller.
- if(depth == 1)
- diag("call to external function %s", s->name);
- return -1;
- }
-
- if(limit < 0) {
- stkbroke(up, limit);
- return -1;
- }
-
- // morestack looks like it calls functions,
- // but it switches the stack pointer first.
- if(s == morestack)
- return 0;
-
- ch.up = up;
- prolog = (s->text->textflag & NOSPLIT) == 0;
- for(p = s->text; p != P; p = p->link) {
- limit -= p->spadj;
- if(prolog && p->spadj != 0) {
- // The first stack adjustment in a function with a
- // split-checking prologue marks the end of the
- // prologue. Assuming the split check is correct,
- // after the adjustment there should still be at least
- // StackLimit bytes available below the stack pointer.
- // If this is not the top call in the chain, no need
- // to duplicate effort, so just stop.
- if(depth > 0)
- return 0;
- prolog = 0;
- limit = StackLimit;
- }
- if(limit < 0) {
- stkbroke(up, limit);
- return -1;
- }
- if(iscall(p)) {
- limit -= CallSize;
- ch.limit = limit;
- if(p->to.type == D_BRANCH) {
- // Direct call.
- ch.sym = p->to.sym;
- if(stkcheck(&ch, depth+1) < 0)
- return -1;
- } else {
- // Indirect call. Assume it is a splitting function,
- // so we have to make sure it can call morestack.
- limit -= CallSize;
- ch.sym = nil;
- ch1.limit = limit;
- ch1.up = &ch;
- ch1.sym = morestack;
- if(stkcheck(&ch1, depth+2) < 0)
- return -1;
- limit += CallSize;
- }
- limit += CallSize;
- }
-
- }
- return 0;
-}
-
-static void
-stkbroke(Chain *ch, int limit)
-{
- diag("nosplit stack overflow");
- stkprint(ch, limit);
-}
-
-static void
-stkprint(Chain *ch, int limit)
-{
- char *name;
-
- if(ch->sym)
- name = ch->sym->name;
- else
- name = "function pointer";
-
- if(ch->up == nil) {
- // top of chain. ch->sym != nil.
- if(ch->sym->text->textflag & NOSPLIT)
- print("\t%d\tassumed on entry to %s\n", ch->limit, name);
- else
- print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
- } else {
- stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize);
- if(!HasLinkRegister)
- print("\t%d\ton entry to %s\n", ch->limit, name);
- }
- if(ch->limit != limit)
- print("\t%d\tafter %s uses %d\n", limit, name, ch->limit - limit);
-}
-
-int
-headtype(char *name)
-{
- int i;
-
- for(i=0; headers[i].name; i++)
- if(strcmp(name, headers[i].name) == 0) {
- headstring = headers[i].name;
- return headers[i].val;
- }
- fprint(2, "unknown header type -H %s\n", name);
- errorexit();
- return -1; // not reached
-}
-
-void
-undef(void)
-{
- Sym *s;
-
- for(s = allsym; s != S; s = s->allsym)
- if(s->type == SXREF)
- diag("%s(%d): not defined", s->name, s->version);
-}
-
-int
-Yconv(Fmt *fp)
-{
- Sym *s;
- Fmt fmt;
- int i;
- char *str;
-
- s = va_arg(fp->args, Sym*);
- if (s == S) {
- fmtprint(fp, "<nil>");
- } else {
- fmtstrinit(&fmt);
- fmtprint(&fmt, "%s @0x%08x [%d]", s->name, s->value, s->size);
- for (i = 0; i < s->size; i++) {
- if (!(i%8)) fmtprint(&fmt, "\n\t0x%04x ", i);
- fmtprint(&fmt, "%02x ", s->p[i]);
- }
- fmtprint(&fmt, "\n");
- for (i = 0; i < s->nr; i++) {
- fmtprint(&fmt, "\t0x%04x[%x] %d %s[%llx]\n",
- s->r[i].off,
- s->r[i].siz,
- s->r[i].type,
- s->r[i].sym->name,
- (vlong)s->r[i].add);
- }
- str = fmtstrflush(&fmt);
- fmtstrcpy(fp, str);
- free(str);
- }
-
- return 0;
-}
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
deleted file mode 100644
index 347987195..000000000
--- a/src/cmd/ld/lib.h
+++ /dev/null
@@ -1,281 +0,0 @@
-// Derived from Inferno utils/6l/l.h
-// http://code.google.com/p/inferno-os/source/browse/utils/6l/l.h
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-enum
-{
- Sxxx,
-
- /* order here is order in output file */
- STEXT,
- SELFDATA,
- SMACHOPLT,
- STYPE,
- SSTRING,
- SGOSTRING,
- SRODATA,
- SSYMTAB,
- SPCLNTAB,
- SDATA,
- SMACHO, /* Mach-O __nl_symbol_ptr */
- SMACHOGOT,
- SWINDOWS,
- SBSS,
-
- SXREF,
- SMACHODYNSTR,
- SMACHODYNSYM,
- SMACHOINDIRECTPLT,
- SMACHOINDIRECTGOT,
- SFILE,
- SCONST,
- SDYNIMPORT,
-
- SSUB = 1<<8, /* sub-symbol, linked from parent via ->sub list */
-
- NHASH = 100003,
-};
-
-typedef struct Library Library;
-struct Library
-{
- char *objref; // object where we found the reference
- char *srcref; // src file where we found the reference
- char *file; // object file
- char *pkg; // import path
-};
-
-// Terrible but standard terminology.
-// A segment describes a block of file to load into memory.
-// A section further describes the pieces of that block for
-// use in debuggers and such.
-
-typedef struct Segment Segment;
-typedef struct Section Section;
-
-struct Segment
-{
- uchar rwx; // permission as usual unix bits (5 = r-x etc)
- uvlong vaddr; // virtual address
- uvlong len; // length in memory
- uvlong fileoff; // file offset
- uvlong filelen; // length on disk
- Section* sect;
-};
-
-struct Section
-{
- uchar rwx;
- char *name;
- uvlong vaddr;
- uvlong len;
- Section *next; // in segment list
- Segment *seg;
-};
-
-extern char symname[];
-extern char *libdir[];
-extern int nlibdir;
-extern int cout;
-
-EXTERN char* INITENTRY;
-EXTERN char* thestring;
-EXTERN Library* library;
-EXTERN int libraryp;
-EXTERN int nlibrary;
-EXTERN Sym* hash[NHASH];
-EXTERN Sym* allsym;
-EXTERN Sym* histfrog[MAXHIST];
-EXTERN uchar fnuxi8[8];
-EXTERN uchar fnuxi4[4];
-EXTERN int histfrogp;
-EXTERN int histgen;
-EXTERN uchar inuxi1[1];
-EXTERN uchar inuxi2[2];
-EXTERN uchar inuxi4[4];
-EXTERN uchar inuxi8[8];
-EXTERN char* outfile;
-EXTERN int32 nsymbol;
-EXTERN char* thestring;
-EXTERN int ndynexp;
-EXTERN int havedynamic;
-
-EXTERN Segment segtext;
-EXTERN Segment segdata;
-EXTERN Segment segsym;
-
-void addlib(char *src, char *obj);
-void addlibpath(char *srcref, char *objref, char *file, char *pkg);
-Section* addsection(Segment*, char*, int);
-void copyhistfrog(char *buf, int nbuf);
-void addhist(int32 line, int type);
-void asmlc(void);
-void histtoauto(void);
-void collapsefrog(Sym *s);
-Sym* lookup(char *symb, int v);
-Sym* rlookup(char *symb, int v);
-void nuxiinit(void);
-int find1(int32 l, int c);
-int find2(int32 l, int c);
-int32 ieeedtof(Ieee *e);
-double ieeedtod(Ieee *e);
-void undefsym(Sym *s);
-void zerosig(char *sp);
-void readundefs(char *f, int t);
-int32 Bget4(Biobuf *f);
-void loadlib(void);
-void errorexit(void);
-void mangle(char*);
-void objfile(char *file, char *pkg);
-void libinit(void);
-void pclntab(void);
-void symtab(void);
-void Lflag(char *arg);
-void usage(void);
-void adddynrel(Sym*, Reloc*);
-void ldobj1(Biobuf *f, char*, int64 len, char *pn);
-void ldobj(Biobuf*, char*, int64, char*, int);
-void ldelf(Biobuf*, char*, int64, char*);
-void ldmacho(Biobuf*, char*, int64, char*);
-void ldpe(Biobuf*, char*, int64, char*);
-void ldpkg(Biobuf*, char*, int64, char*, int);
-void mark(Sym *s);
-void mkfwd(void);
-char* expandpkg(char*, char*);
-void deadcode(void);
-void ewrite(int, void*, int);
-Reloc* addrel(Sym*);
-void codeblk(int32, int32);
-void datblk(int32, int32);
-Sym* datsort(Sym*);
-void reloc(void);
-void relocsym(Sym*);
-void savedata(Sym*, Prog*, char*);
-void symgrow(Sym*, int32);
-vlong addstring(Sym*, char*);
-vlong adduint32(Sym*, uint32);
-vlong adduint64(Sym*, uint64);
-vlong addaddr(Sym*, Sym*);
-vlong addaddrplus(Sym*, Sym*, int32);
-vlong addpcrelplus(Sym*, Sym*, int32);
-vlong addsize(Sym*, Sym*);
-vlong adduint8(Sym*, uint8);
-vlong adduint16(Sym*, uint16);
-void asmsym(void);
-void asmelfsym(void);
-void asmplan9sym(void);
-void strnput(char*, int);
-void dodata(void);
-void address(void);
-void textaddress(void);
-void genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*));
-vlong datoff(vlong);
-void adddynlib(char*);
-int archreloc(Reloc*, Sym*, vlong*);
-void adddynsym(Sym*);
-void addexport(void);
-void dostkcheck(void);
-void undef(void);
-void doweak(void);
-void setpersrc(Sym*);
-
-int pathchar(void);
-void* mal(uint32);
-void unmal(void*, uint32);
-void mywhatsys(void);
-int rbyoff(const void*, const void*);
-
-uint16 le16(uchar*);
-uint32 le32(uchar*);
-uint64 le64(uchar*);
-uint16 be16(uchar*);
-uint32 be32(uchar*);
-uint64 be64(uchar*);
-
-typedef struct Endian Endian;
-struct Endian
-{
- uint16 (*e16)(uchar*);
- uint32 (*e32)(uchar*);
- uint64 (*e64)(uchar*);
-};
-
-extern Endian be, le;
-
-// relocation size bits
-enum {
- Rbig = 128,
- Rlittle = 64,
-};
-
-/* set by call to mywhatsys() */
-extern char* goroot;
-extern char* goarch;
-extern char* goos;
-
-/* whence for ldpkg */
-enum {
- FileObj = 0,
- ArchiveObj,
- Pkgdef
-};
-
-/* executable header types */
-enum {
- Hgarbunix = 0, // garbage unix
- Hnoheader, // no header
- Hunixcoff, // unix coff
- Hrisc, // aif for risc os
- Hplan9x32, // plan 9 32-bit format
- Hplan9x64, // plan 9 64-bit format
- Hmsdoscom, // MS-DOS .COM
- Hnetbsd, // NetBSD
- Hmsdosexe, // fake MS-DOS .EXE
- Hixp1200, // IXP1200 (raw)
- Helf, // ELF32
- Hipaq, // ipaq
- Hdarwin, // Apple Mach-O
- Hlinux, // Linux ELF
- Hfreebsd, // FreeBSD ELF
- Hwindows, // MS Windows PE
-};
-
-typedef struct Header Header;
-struct Header {
- char *name;
- int val;
-};
-
-EXTERN char* headstring;
-extern Header headers[];
-
-int headtype(char*);
-
-int Yconv(Fmt*);
-#pragma varargck type "Y" Sym*
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
deleted file mode 100644
index 0b12ac17b..000000000
--- a/src/cmd/ld/macho.c
+++ /dev/null
@@ -1,518 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Mach-O file writing
-// http://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
-
-#include "l.h"
-#include "../ld/dwarf.h"
-#include "../ld/lib.h"
-#include "../ld/macho.h"
-
-static int macho64;
-static MachoHdr hdr;
-static MachoLoad *load;
-static MachoSeg seg[16];
-static MachoDebug xdebug[16];
-static int nload, mload, nseg, ndebug, nsect;
-
-// Amount of space left for adding load commands
-// that refer to dynamic libraries. Because these have
-// to go in the Mach-O header, we can't just pick a
-// "big enough" header size. The initial header is
-// one page, the non-dynamic library stuff takes
-// up about 1300 bytes; we overestimate that as 2k.
-static int load_budget = INITIAL_MACHO_HEADR - 2*1024;
-
-void
-machoinit(void)
-{
- switch(thechar) {
- // 64-bit architectures
- case '6':
- macho64 = 1;
- break;
-
- // 32-bit architectures
- default:
- break;
- }
-}
-
-MachoHdr*
-getMachoHdr(void)
-{
- return &hdr;
-}
-
-MachoLoad*
-newMachoLoad(uint32 type, uint32 ndata)
-{
- MachoLoad *l;
-
- if(nload >= mload) {
- if(mload == 0)
- mload = 1;
- else
- mload *= 2;
- load = realloc(load, mload*sizeof load[0]);
- if(load == nil) {
- diag("out of memory");
- errorexit();
- }
- }
-
- if(macho64 && (ndata & 1))
- ndata++;
-
- l = &load[nload++];
- l->type = type;
- l->ndata = ndata;
- l->data = mal(ndata*4);
- return l;
-}
-
-MachoSeg*
-newMachoSeg(char *name, int msect)
-{
- MachoSeg *s;
-
- if(nseg >= nelem(seg)) {
- diag("too many segs");
- errorexit();
- }
- s = &seg[nseg++];
- s->name = name;
- s->msect = msect;
- s->sect = mal(msect*sizeof s->sect[0]);
- return s;
-}
-
-MachoSect*
-newMachoSect(MachoSeg *seg, char *name)
-{
- MachoSect *s;
-
- if(seg->nsect >= seg->msect) {
- diag("too many sects in segment %s", seg->name);
- errorexit();
- }
- s = &seg->sect[seg->nsect++];
- s->name = name;
- nsect++;
- return s;
-}
-
-MachoDebug*
-newMachoDebug(void)
-{
- if(ndebug >= nelem(xdebug)) {
- diag("too many debugs");
- errorexit();
- }
- return &xdebug[ndebug++];
-}
-
-
-// Generic linking code.
-
-static char **dylib;
-static int ndylib;
-
-static vlong linkoff;
-
-int
-machowrite(void)
-{
- vlong o1;
- int loadsize;
- int i, j;
- MachoSeg *s;
- MachoSect *t;
- MachoDebug *d;
- MachoLoad *l;
-
- o1 = cpos();
-
- loadsize = 4*4*ndebug;
- for(i=0; i<nload; i++)
- loadsize += 4*(load[i].ndata+2);
- if(macho64) {
- loadsize += 18*4*nseg;
- loadsize += 20*4*nsect;
- } else {
- loadsize += 14*4*nseg;
- loadsize += 17*4*nsect;
- }
-
- if(macho64)
- LPUT(0xfeedfacf);
- else
- LPUT(0xfeedface);
- LPUT(hdr.cpu);
- LPUT(hdr.subcpu);
- LPUT(2); /* file type - mach executable */
- LPUT(nload+nseg+ndebug);
- LPUT(loadsize);
- LPUT(1); /* flags - no undefines */
- if(macho64)
- LPUT(0); /* reserved */
-
- for(i=0; i<nseg; i++) {
- s = &seg[i];
- if(macho64) {
- LPUT(25); /* segment 64 */
- LPUT(72+80*s->nsect);
- strnput(s->name, 16);
- VPUT(s->vaddr);
- VPUT(s->vsize);
- VPUT(s->fileoffset);
- VPUT(s->filesize);
- LPUT(s->prot1);
- LPUT(s->prot2);
- LPUT(s->nsect);
- LPUT(s->flag);
- } else {
- LPUT(1); /* segment 32 */
- LPUT(56+68*s->nsect);
- strnput(s->name, 16);
- LPUT(s->vaddr);
- LPUT(s->vsize);
- LPUT(s->fileoffset);
- LPUT(s->filesize);
- LPUT(s->prot1);
- LPUT(s->prot2);
- LPUT(s->nsect);
- LPUT(s->flag);
- }
- for(j=0; j<s->nsect; j++) {
- t = &s->sect[j];
- if(macho64) {
- strnput(t->name, 16);
- strnput(s->name, 16);
- VPUT(t->addr);
- VPUT(t->size);
- LPUT(t->off);
- LPUT(t->align);
- LPUT(t->reloc);
- LPUT(t->nreloc);
- LPUT(t->flag);
- LPUT(t->res1); /* reserved */
- LPUT(t->res2); /* reserved */
- LPUT(0); /* reserved */
- } else {
- strnput(t->name, 16);
- strnput(s->name, 16);
- LPUT(t->addr);
- LPUT(t->size);
- LPUT(t->off);
- LPUT(t->align);
- LPUT(t->reloc);
- LPUT(t->nreloc);
- LPUT(t->flag);
- LPUT(t->res1); /* reserved */
- LPUT(t->res2); /* reserved */
- }
- }
- }
-
- for(i=0; i<nload; i++) {
- l = &load[i];
- LPUT(l->type);
- LPUT(4*(l->ndata+2));
- for(j=0; j<l->ndata; j++)
- LPUT(l->data[j]);
- }
-
- for(i=0; i<ndebug; i++) {
- d = &xdebug[i];
- LPUT(3); /* obsolete gdb debug info */
- LPUT(16); /* size of symseg command */
- LPUT(d->fileoffset);
- LPUT(d->filesize);
- }
-
- return cpos() - o1;
-}
-
-void
-domacho(void)
-{
- Sym *s;
-
- if(debug['d'])
- return;
-
- // empirically, string table must begin with " \x00".
- s = lookup(".dynstr", 0);
- s->type = SMACHODYNSTR;
- s->reachable = 1;
- adduint8(s, ' ');
- adduint8(s, '\0');
-
- s = lookup(".dynsym", 0);
- s->type = SMACHODYNSYM;
- s->reachable = 1;
-
- s = lookup(".plt", 0); // will be __symbol_stub
- s->type = SMACHOPLT;
- s->reachable = 1;
-
- s = lookup(".got", 0); // will be __nl_symbol_ptr
- s->type = SMACHOGOT;
- s->reachable = 1;
-
- s = lookup(".linkedit.plt", 0); // indirect table for .plt
- s->type = SMACHOINDIRECTPLT;
- s->reachable = 1;
-
- s = lookup(".linkedit.got", 0); // indirect table for .got
- s->type = SMACHOINDIRECTGOT;
- s->reachable = 1;
-}
-
-void
-machoadddynlib(char *lib)
-{
- // Will need to store the library name rounded up
- // and 24 bytes of header metadata. If not enough
- // space, grab another page of initial space at the
- // beginning of the output file.
- load_budget -= (strlen(lib)+7)/8*8 + 24;
- if(load_budget < 0) {
- HEADR += 4096;
- INITTEXT += 4096;
- load_budget += 4096;
- }
-
- if(ndylib%32 == 0) {
- dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
- if(dylib == nil) {
- diag("out of memory");
- errorexit();
- }
- }
- dylib[ndylib++] = lib;
-}
-
-void
-asmbmacho(void)
-{
- vlong v, w;
- vlong va;
- int a, i;
- MachoHdr *mh;
- MachoSect *msect;
- MachoSeg *ms;
- MachoDebug *md;
- MachoLoad *ml;
- Sym *s;
-
- /* apple MACH */
- va = INITTEXT - HEADR;
- mh = getMachoHdr();
- switch(thechar){
- default:
- diag("unknown mach architecture");
- errorexit();
- case '6':
- mh->cpu = MACHO_CPU_AMD64;
- mh->subcpu = MACHO_SUBCPU_X86;
- break;
- case '8':
- mh->cpu = MACHO_CPU_386;
- mh->subcpu = MACHO_SUBCPU_X86;
- break;
- }
-
- /* segment for zero page */
- ms = newMachoSeg("__PAGEZERO", 0);
- ms->vsize = va;
-
- /* text */
- v = rnd(HEADR+segtext.len, INITRND);
- ms = newMachoSeg("__TEXT", 2);
- ms->vaddr = va;
- ms->vsize = v;
- ms->filesize = v;
- ms->prot1 = 7;
- ms->prot2 = 5;
-
- msect = newMachoSect(ms, "__text");
- msect->addr = INITTEXT;
- msect->size = segtext.sect->len;
- msect->off = INITTEXT - va;
- msect->flag = 0x400; /* flag - some instructions */
-
- s = lookup(".plt", 0);
- if(s->size > 0) {
- msect = newMachoSect(ms, "__symbol_stub1");
- msect->addr = symaddr(s);
- msect->size = s->size;
- msect->off = ms->fileoffset + msect->addr - ms->vaddr;
- msect->flag = 0x80000408; /* flag */
- msect->res1 = 0; /* index into indirect symbol table */
- msect->res2 = 6; /* size of stubs */
- }
-
- /* data */
- w = segdata.len;
- ms = newMachoSeg("__DATA", 3);
- ms->vaddr = va+v;
- ms->vsize = w;
- ms->fileoffset = v;
- ms->filesize = segdata.filelen;
- ms->prot1 = 7;
- ms->prot2 = 3;
-
- msect = newMachoSect(ms, "__data");
- msect->addr = va+v;
- msect->off = v;
- msect->size = segdata.filelen;
-
- s = lookup(".got", 0);
- if(s->size > 0) {
- msect->size = symaddr(s) - msect->addr;
-
- msect = newMachoSect(ms, "__nl_symbol_ptr");
- msect->addr = symaddr(s);
- msect->size = s->size;
- msect->off = datoff(msect->addr);
- msect->align = 2;
- msect->flag = 6; /* section with nonlazy symbol pointers */
- msect->res1 = lookup(".linkedit.plt", 0)->size / 4; /* offset into indirect symbol table */
- }
-
- msect = newMachoSect(ms, "__bss");
- msect->addr = va+v+segdata.filelen;
- msect->size = segdata.len - segdata.filelen;
- msect->flag = 1; /* flag - zero fill */
-
- switch(thechar) {
- default:
- diag("unknown macho architecture");
- errorexit();
- case '6':
- ml = newMachoLoad(5, 42+2); /* unix thread */
- ml->data[0] = 4; /* thread type */
- ml->data[1] = 42; /* word count */
- ml->data[2+32] = entryvalue(); /* start pc */
- ml->data[2+32+1] = entryvalue()>>16>>16; // hide >>32 for 8l
- break;
- case '8':
- ml = newMachoLoad(5, 16+2); /* unix thread */
- ml->data[0] = 1; /* thread type */
- ml->data[1] = 16; /* word count */
- ml->data[2+10] = entryvalue(); /* start pc */
- break;
- }
-
- if(!debug['d']) {
- Sym *s1, *s2, *s3, *s4;
-
- // must match domacholink below
- s1 = lookup(".dynsym", 0);
- s2 = lookup(".dynstr", 0);
- s3 = lookup(".linkedit.plt", 0);
- s4 = lookup(".linkedit.got", 0);
-
- ms = newMachoSeg("__LINKEDIT", 0);
- ms->vaddr = va+v+rnd(segdata.len, INITRND);
- ms->vsize = s1->size + s2->size + s3->size + s4->size;
- ms->fileoffset = linkoff;
- ms->filesize = ms->vsize;
- ms->prot1 = 7;
- ms->prot2 = 3;
-
- ml = newMachoLoad(2, 4); /* LC_SYMTAB */
- ml->data[0] = linkoff; /* symoff */
- ml->data[1] = s1->size / (macho64 ? 16 : 12); /* nsyms */
- ml->data[2] = linkoff + s1->size; /* stroff */
- ml->data[3] = s2->size; /* strsize */
-
- ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
- ml->data[0] = 0; /* ilocalsym */
- ml->data[1] = 0; /* nlocalsym */
- ml->data[2] = 0; /* iextdefsym */
- ml->data[3] = ndynexp; /* nextdefsym */
- ml->data[4] = ndynexp; /* iundefsym */
- ml->data[5] = (s1->size / (macho64 ? 16 : 12)) - ndynexp; /* nundefsym */
- ml->data[6] = 0; /* tocoffset */
- ml->data[7] = 0; /* ntoc */
- ml->data[8] = 0; /* modtaboff */
- ml->data[9] = 0; /* nmodtab */
- ml->data[10] = 0; /* extrefsymoff */
- ml->data[11] = 0; /* nextrefsyms */
- ml->data[12] = linkoff + s1->size + s2->size; /* indirectsymoff */
- ml->data[13] = (s3->size + s4->size) / 4; /* nindirectsyms */
- ml->data[14] = 0; /* extreloff */
- ml->data[15] = 0; /* nextrel */
- ml->data[16] = 0; /* locreloff */
- ml->data[17] = 0; /* nlocrel */
-
- ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */
- ml->data[0] = 12; /* offset to string */
- strcpy((char*)&ml->data[1], "/usr/lib/dyld");
-
- for(i=0; i<ndylib; i++) {
- ml = newMachoLoad(12, 4+(strlen(dylib[i])+1+7)/8*2); /* LC_LOAD_DYLIB */
- ml->data[0] = 24; /* offset of string from beginning of load */
- ml->data[1] = 0; /* time stamp */
- ml->data[2] = 0; /* version */
- ml->data[3] = 0; /* compatibility version */
- strcpy((char*)&ml->data[4], dylib[i]);
- }
- }
-
- if(!debug['s']) {
- Sym *s;
-
- md = newMachoDebug();
- s = lookup("symtab", 0);
- md->fileoffset = datoff(s->value);
- md->filesize = s->size;
-
- md = newMachoDebug();
- s = lookup("pclntab", 0);
- md->fileoffset = datoff(s->value);
- md->filesize = s->size;
-
- dwarfaddmachoheaders();
- }
-
- a = machowrite();
- if(a > HEADR)
- diag("HEADR too small: %d > %d", a, HEADR);
-}
-
-vlong
-domacholink(void)
-{
- int size;
- Sym *s1, *s2, *s3, *s4;
-
- // write data that will be linkedit section
- s1 = lookup(".dynsym", 0);
- relocsym(s1);
- s2 = lookup(".dynstr", 0);
- s3 = lookup(".linkedit.plt", 0);
- s4 = lookup(".linkedit.got", 0);
-
- while(s2->size%4)
- adduint8(s2, 0);
-
- size = s1->size + s2->size + s3->size + s4->size;
-
- if(size > 0) {
- linkoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND);
- seek(cout, linkoff, 0);
-
- ewrite(cout, s1->p, s1->size);
- ewrite(cout, s2->p, s2->size);
- ewrite(cout, s3->p, s3->size);
- ewrite(cout, s4->p, s4->size);
- }
-
- return rnd(size, INITRND);
-}
diff --git a/src/cmd/ld/macho.h b/src/cmd/ld/macho.h
deleted file mode 100644
index f55104150..000000000
--- a/src/cmd/ld/macho.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-typedef struct MachoHdr MachoHdr;
-struct MachoHdr {
- uint32 cpu;
- uint32 subcpu;
-};
-
-typedef struct MachoSect MachoSect;
-struct MachoSect {
- char* name;
- uint64 addr;
- uint64 size;
- uint32 off;
- uint32 align;
- uint32 reloc;
- uint32 nreloc;
- uint32 flag;
- uint32 res1;
- uint32 res2;
-};
-
-typedef struct MachoSeg MachoSeg;
-struct MachoSeg {
- char* name;
- uint64 vsize;
- uint64 vaddr;
- uint64 fileoffset;
- uint64 filesize;
- uint32 prot1;
- uint32 prot2;
- uint32 nsect;
- uint32 msect;
- MachoSect *sect;
- uint32 flag;
-};
-
-typedef struct MachoLoad MachoLoad;
-struct MachoLoad {
- uint32 type;
- uint32 ndata;
- uint32 *data;
-};
-
-typedef struct MachoDebug MachoDebug;
-struct MachoDebug {
- uint32 fileoffset;
- uint32 filesize;
-};
-
-MachoHdr* getMachoHdr();
-MachoSeg* newMachoSeg(char*, int);
-MachoSect* newMachoSect(MachoSeg*, char*);
-MachoLoad* newMachoLoad(uint32, uint32);
-MachoDebug* newMachoDebug(void);
-int machowrite(void);
-void machoinit(void);
-
-/*
- * Total amount of space to reserve at the start of the file
- * for Header, PHeaders, and SHeaders.
- * May waste some.
- */
-#define INITIAL_MACHO_HEADR 4*1024
-
-enum {
- MACHO_CPU_AMD64 = (1<<24)|7,
- MACHO_CPU_386 = 7,
- MACHO_SUBCPU_X86 = 3,
-
- MACHO32SYMSIZE = 12,
- MACHO64SYMSIZE = 16,
-
- MACHO_X86_64_RELOC_UNSIGNED = 0,
- MACHO_X86_64_RELOC_SIGNED = 1,
- MACHO_X86_64_RELOC_BRANCH = 2,
- MACHO_X86_64_RELOC_GOT_LOAD = 3,
- MACHO_X86_64_RELOC_GOT = 4,
- MACHO_X86_64_RELOC_SUBTRACTOR = 5,
- MACHO_X86_64_RELOC_SIGNED_1 = 6,
- MACHO_X86_64_RELOC_SIGNED_2 = 7,
- MACHO_X86_64_RELOC_SIGNED_4 = 8,
-
- MACHO_GENERIC_RELOC_VANILLA = 0,
-
- MACHO_FAKE_GOTPCREL = 100,
-};
-
-void domacho(void);
-vlong domacholink(void);
-void asmbmacho(void);
-void machoadddynlib(char*);
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
deleted file mode 100644
index 9ac0a50d8..000000000
--- a/src/cmd/ld/pe.c
+++ /dev/null
@@ -1,583 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// PE (Portable Executable) file writing
-// http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
-
-#include "l.h"
-#include "../ld/lib.h"
-#include "../ld/pe.h"
-#include "../ld/dwarf.h"
-
-// DOS stub that prints out
-// "This program cannot be run in DOS mode."
-static char dosstub[] =
-{
- 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
- 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,
- 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
- 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
- 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
- 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,
- 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
- 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static Sym *rsrcsym;
-
-static char symnames[256];
-static int nextsymoff;
-
-int32 PESECTHEADR;
-int32 PEFILEHEADR;
-
-static int pe64;
-static int nsect;
-static int nextsectoff;
-static int nextfileoff;
-
-static IMAGE_FILE_HEADER fh;
-static IMAGE_OPTIONAL_HEADER oh;
-static PE64_IMAGE_OPTIONAL_HEADER oh64;
-static IMAGE_SECTION_HEADER sh[16];
-static IMAGE_DATA_DIRECTORY* dd;
-
-#define set(n, v) (pe64 ? (oh64.n = v) : (oh.n = v))
-#define put(v) (pe64 ? vputl(v) : lputl(v))
-
-typedef struct Imp Imp;
-struct Imp {
- Sym* s;
- uvlong off;
- Imp* next;
-};
-
-typedef struct Dll Dll;
-struct Dll {
- char* name;
- uvlong nameoff;
- uvlong thunkoff;
- Imp* ms;
- Dll* next;
-};
-
-static Dll* dr;
-
-static Sym *dexport[1024];
-static int nexport;
-
-static IMAGE_SECTION_HEADER*
-addpesection(char *name, int sectsize, int filesize, Segment *s)
-{
- IMAGE_SECTION_HEADER *h;
-
- if(nsect == 16) {
- diag("too many sections");
- errorexit();
- }
- h = &sh[nsect++];
- strncpy((char*)h->Name, name, sizeof(h->Name));
- h->VirtualSize = sectsize;
- h->VirtualAddress = nextsectoff;
- nextsectoff = rnd(nextsectoff+sectsize, PESECTALIGN);
- h->PointerToRawData = nextfileoff;
- if(filesize > 0) {
- h->SizeOfRawData = rnd(filesize, PEFILEALIGN);
- nextfileoff += h->SizeOfRawData;
- }
- if(s) {
- if(s->vaddr-PEBASE != h->VirtualAddress) {
- diag("%s.VirtualAddress = %#llux, want %#llux", name, (vlong)h->VirtualAddress, (vlong)(s->vaddr-PEBASE));
- errorexit();
- }
- if(s->fileoff != h->PointerToRawData) {
- diag("%s.PointerToRawData = %#llux, want %#llux", name, (vlong)h->PointerToRawData, (vlong)(s->fileoff));
- errorexit();
- }
- }
- return h;
-}
-
-void
-peinit(void)
-{
- int32 l;
-
- switch(thechar) {
- // 64-bit architectures
- case '6':
- pe64 = 1;
- l = sizeof(oh64);
- dd = oh64.DataDirectory;
- break;
- // 32-bit architectures
- default:
- l = sizeof(oh);
- dd = oh.DataDirectory;
- break;
- }
-
- PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+l+sizeof(sh), PEFILEALIGN);
- PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN);
- nextsectoff = PESECTHEADR;
- nextfileoff = PEFILEHEADR;
-}
-
-static void
-pewrite(void)
-{
- seek(cout, 0, 0);
- ewrite(cout, dosstub, sizeof dosstub);
- strnput("PE", 4);
- cflush();
- // TODO: This code should not assume that the
- // memory representation is little-endian or
- // that the structs are packed identically to
- // their file representation.
- ewrite(cout, &fh, sizeof fh);
- if(pe64)
- ewrite(cout, &oh64, sizeof oh64);
- else
- ewrite(cout, &oh, sizeof oh);
- ewrite(cout, sh, nsect * sizeof sh[0]);
-}
-
-static void
-strput(char *s)
-{
- int n;
-
- for(n=0; *s; n++)
- cput(*s++);
- cput('\0');
- n++;
- // string must be padded to even size
- if(n%2)
- cput('\0');
-}
-
-static Dll*
-initdynimport(void)
-{
- Imp *m;
- Dll *d;
- Sym *s, *dynamic;
-
- dr = nil;
- m = nil;
- for(s = allsym; s != S; s = s->allsym) {
- if(!s->reachable || !s->dynimpname || s->dynexport)
- continue;
- for(d = dr; d != nil; d = d->next) {
- if(strcmp(d->name,s->dynimplib) == 0) {
- m = mal(sizeof *m);
- break;
- }
- }
- if(d == nil) {
- d = mal(sizeof *d);
- d->name = s->dynimplib;
- d->next = dr;
- dr = d;
- m = mal(sizeof *m);
- }
- m->s = s;
- m->next = d->ms;
- d->ms = m;
- }
-
- dynamic = lookup(".windynamic", 0);
- dynamic->reachable = 1;
- dynamic->type = SWINDOWS;
- for(d = dr; d != nil; d = d->next) {
- for(m = d->ms; m != nil; m = m->next) {
- m->s->type = SWINDOWS | SSUB;
- m->s->sub = dynamic->sub;
- dynamic->sub = m->s;
- m->s->value = dynamic->size;
- dynamic->size += PtrSize;
- }
- dynamic->size += PtrSize;
- }
-
- return dr;
-}
-
-static void
-addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
-{
- IMAGE_SECTION_HEADER *isect;
- uvlong n, oftbase, ftbase;
- Imp *m;
- Dll *d;
- Sym* dynamic;
-
- dynamic = lookup(".windynamic", 0);
-
- // skip import descriptor table (will write it later)
- n = 0;
- for(d = dr; d != nil; d = d->next)
- n++;
- seek(cout, fileoff + sizeof(IMAGE_IMPORT_DESCRIPTOR) * (n + 1), 0);
-
- // write dll names
- for(d = dr; d != nil; d = d->next) {
- d->nameoff = cpos() - fileoff;
- strput(d->name);
- }
-
- // write function names
- for(d = dr; d != nil; d = d->next) {
- for(m = d->ms; m != nil; m = m->next) {
- m->off = nextsectoff + cpos() - fileoff;
- wputl(0); // hint
- strput(m->s->dynimpname);
- }
- }
-
- // write OriginalFirstThunks
- oftbase = cpos() - fileoff;
- n = cpos();
- for(d = dr; d != nil; d = d->next) {
- d->thunkoff = cpos() - n;
- for(m = d->ms; m != nil; m = m->next)
- put(m->off);
- put(0);
- }
-
- // add pe section and pad it at the end
- n = cpos() - fileoff;
- isect = addpesection(".idata", n, n, 0);
- isect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
- IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
- strnput("", isect->SizeOfRawData - n);
- cflush();
-
- // write FirstThunks (allocated in .data section)
- ftbase = dynamic->value - datsect->VirtualAddress - PEBASE;
- seek(cout, datsect->PointerToRawData + ftbase, 0);
- for(d = dr; d != nil; d = d->next) {
- for(m = d->ms; m != nil; m = m->next)
- put(m->off);
- put(0);
- }
- cflush();
-
- // finally write import descriptor table
- seek(cout, fileoff, 0);
- for(d = dr; d != nil; d = d->next) {
- lputl(isect->VirtualAddress + oftbase + d->thunkoff);
- lputl(0);
- lputl(0);
- lputl(isect->VirtualAddress + d->nameoff);
- lputl(datsect->VirtualAddress + ftbase + d->thunkoff);
- }
- lputl(0); //end
- lputl(0);
- lputl(0);
- lputl(0);
- lputl(0);
- cflush();
-
- // update data directory
- dd[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress;
- dd[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize;
- dd[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE;
- dd[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size;
-
- seek(cout, 0, 2);
-}
-
-static int
-scmp(const void *p1, const void *p2)
-{
- Sym *s1, *s2;
-
- s1 = *(Sym**)p1;
- s2 = *(Sym**)p2;
- return strcmp(s1->dynimpname, s2->dynimpname);
-}
-
-static void
-initdynexport(void)
-{
- Sym *s;
-
- nexport = 0;
- for(s = allsym; s != S; s = s->allsym) {
- if(!s->reachable || !s->dynimpname || !s->dynexport)
- continue;
- if(nexport+1 > sizeof(dexport)/sizeof(dexport[0])) {
- diag("pe dynexport table is full");
- errorexit();
- }
-
- dexport[nexport] = s;
- nexport++;
- }
-
- qsort(dexport, nexport, sizeof dexport[0], scmp);
-}
-
-void
-addexports(vlong fileoff)
-{
- IMAGE_SECTION_HEADER *sect;
- IMAGE_EXPORT_DIRECTORY e;
- int size, i, va, va_name, va_addr, va_na, v;
-
- size = sizeof e + 10*nexport + strlen(outfile) + 1;
- for(i=0; i<nexport; i++)
- size += strlen(dexport[i]->dynimpname) + 1;
-
- if (nexport == 0)
- return;
-
- sect = addpesection(".edata", size, size, 0);
- sect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ;
- va = sect->VirtualAddress;
- dd[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = va;
- dd[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect->VirtualSize;
-
- seek(cout, fileoff, 0);
- va_name = va + sizeof e + nexport*4;
- va_addr = va + sizeof e;
- va_na = va + sizeof e + nexport*8;
-
- e.Characteristics = 0;
- e.MajorVersion = 0;
- e.MinorVersion = 0;
- e.NumberOfFunctions = nexport;
- e.NumberOfNames = nexport;
- e.Name = va + sizeof e + nexport*10; // Program names.
- e.Base = 1;
- e.AddressOfFunctions = va_addr;
- e.AddressOfNames = va_name;
- e.AddressOfNameOrdinals = va_na;
- // put IMAGE_EXPORT_DIRECTORY
- for (i=0; i<sizeof(e); i++)
- cput(((char*)&e)[i]);
- // put EXPORT Address Table
- for(i=0; i<nexport; i++)
- lputl(dexport[i]->value - PEBASE);
- // put EXPORT Name Pointer Table
- v = e.Name + strlen(outfile)+1;
- for(i=0; i<nexport; i++) {
- lputl(v);
- v += strlen(dexport[i]->dynimpname)+1;
- }
- // put EXPORT Ordinal Table
- for(i=0; i<nexport; i++)
- wputl(i);
- // put Names
- strnput(outfile, strlen(outfile)+1);
- for(i=0; i<nexport; i++)
- strnput(dexport[i]->dynimpname, strlen(dexport[i]->dynimpname)+1);
- strnput("", sect->SizeOfRawData - size);
- cflush();
-
- seek(cout, 0, 2);
-}
-
-void
-dope(void)
-{
- Sym *rel;
-
- /* relocation table */
- rel = lookup(".rel", 0);
- rel->reachable = 1;
- rel->type = SELFDATA;
-
- initdynimport();
- initdynexport();
-}
-
-/*
- * For more than 8 characters section names, name contains a slash (/) that is
- * followed by an ASCII representation of a decimal number that is an offset into
- * the string table.
- * reference: pecoff_v8.docx Page 24.
- * <http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx>
- */
-IMAGE_SECTION_HEADER*
-newPEDWARFSection(char *name, vlong size)
-{
- IMAGE_SECTION_HEADER *h;
- char s[8];
-
- if(size == 0)
- return nil;
-
- if(nextsymoff+strlen(name)+1 > sizeof(symnames)) {
- diag("pe string table is full");
- errorexit();
- }
-
- strcpy(&symnames[nextsymoff], name);
- sprint(s, "/%d\0", nextsymoff+4);
- nextsymoff += strlen(name);
- symnames[nextsymoff] = 0;
- nextsymoff ++;
- h = addpesection(s, size, size, 0);
- h->Characteristics = IMAGE_SCN_MEM_READ|
- IMAGE_SCN_MEM_DISCARDABLE;
-
- return h;
-}
-
-static void
-addsymtable(void)
-{
- IMAGE_SECTION_HEADER *h;
- int i, size;
-
- if(nextsymoff == 0)
- return;
-
- size = nextsymoff + 4;
- h = addpesection(".symtab", size, size, 0);
- h->Characteristics = IMAGE_SCN_MEM_READ|
- IMAGE_SCN_MEM_DISCARDABLE;
- fh.PointerToSymbolTable = cpos();
- fh.NumberOfSymbols = 0;
- // put symbol string table
- lputl(size);
- for (i=0; i<nextsymoff; i++)
- cput(symnames[i]);
- strnput("", h->SizeOfRawData - size);
- cflush();
-}
-
-void
-setpersrc(Sym *sym)
-{
- if(rsrcsym != nil)
- diag("too many .rsrc sections");
-
- rsrcsym = sym;
-}
-
-void
-addpersrc(void)
-{
- IMAGE_SECTION_HEADER *h;
- uchar *p;
- uint32 val;
- Reloc *r;
-
- if(rsrcsym == nil)
- return;
-
- h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size, 0);
- h->Characteristics = IMAGE_SCN_MEM_READ|
- IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA;
- // relocation
- for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) {
- p = rsrcsym->p + r->off;
- val = h->VirtualAddress + r->add;
- // 32-bit little-endian
- p[0] = val;
- p[1] = val>>8;
- p[2] = val>>16;
- p[3] = val>>24;
- }
- ewrite(cout, rsrcsym->p, rsrcsym->size);
- strnput("", h->SizeOfRawData - rsrcsym->size);
- cflush();
-
- // update data directory
- dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress;
- dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h->VirtualSize;
-}
-
-void
-asmbpe(void)
-{
- IMAGE_SECTION_HEADER *t, *d;
-
- switch(thechar) {
- default:
- diag("unknown PE architecture");
- errorexit();
- case '6':
- fh.Machine = IMAGE_FILE_MACHINE_AMD64;
- break;
- case '8':
- fh.Machine = IMAGE_FILE_MACHINE_I386;
- break;
- }
-
- t = addpesection(".text", segtext.len, segtext.len, &segtext);
- t->Characteristics = IMAGE_SCN_CNT_CODE|
- IMAGE_SCN_CNT_INITIALIZED_DATA|
- IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
-
- d = addpesection(".data", segdata.len, segdata.filelen, &segdata);
- d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
- IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
-
- if(!debug['s'])
- dwarfaddpeheaders();
-
- addimports(nextfileoff, d);
-
- addexports(nextfileoff);
-
- addsymtable();
-
- addpersrc();
-
- fh.NumberOfSections = nsect;
- fh.TimeDateStamp = time(0);
- fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED|
- IMAGE_FILE_EXECUTABLE_IMAGE|IMAGE_FILE_DEBUG_STRIPPED;
- if (pe64) {
- fh.SizeOfOptionalHeader = sizeof(oh64);
- fh.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
- set(Magic, 0x20b); // PE32+
- } else {
- fh.SizeOfOptionalHeader = sizeof(oh);
- fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE;
- set(Magic, 0x10b); // PE32
- oh.BaseOfData = d->VirtualAddress;
- }
- set(MajorLinkerVersion, 1);
- set(MinorLinkerVersion, 0);
- set(SizeOfCode, t->SizeOfRawData);
- set(SizeOfInitializedData, d->SizeOfRawData);
- set(SizeOfUninitializedData, 0);
- set(AddressOfEntryPoint, entryvalue()-PEBASE);
- set(BaseOfCode, t->VirtualAddress);
- set(ImageBase, PEBASE);
- set(SectionAlignment, PESECTALIGN);
- set(FileAlignment, PEFILEALIGN);
- set(MajorOperatingSystemVersion, 4);
- set(MinorOperatingSystemVersion, 0);
- set(MajorImageVersion, 1);
- set(MinorImageVersion, 0);
- set(MajorSubsystemVersion, 4);
- set(MinorSubsystemVersion, 0);
- set(SizeOfImage, nextsectoff);
- set(SizeOfHeaders, PEFILEHEADR);
- if(strcmp(headstring, "windowsgui") == 0)
- set(Subsystem, IMAGE_SUBSYSTEM_WINDOWS_GUI);
- else
- set(Subsystem, IMAGE_SUBSYSTEM_WINDOWS_CUI);
- set(SizeOfStackReserve, 0x0040000);
- set(SizeOfStackCommit, 0x00001000);
- set(SizeOfHeapReserve, 0x00100000);
- set(SizeOfHeapCommit, 0x00001000);
- set(NumberOfRvaAndSizes, 16);
-
- pewrite();
-}
diff --git a/src/cmd/ld/pe.h b/src/cmd/ld/pe.h
deleted file mode 100644
index 7aa938829..000000000
--- a/src/cmd/ld/pe.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-typedef struct {
- uint16 Machine;
- uint16 NumberOfSections;
- uint32 TimeDateStamp;
- uint32 PointerToSymbolTable;
- uint32 NumberOfSymbols;
- uint16 SizeOfOptionalHeader;
- uint16 Characteristics;
-} IMAGE_FILE_HEADER;
-
-typedef struct {
- uint32 VirtualAddress;
- uint32 Size;
-} IMAGE_DATA_DIRECTORY;
-
-typedef struct {
- uint16 Magic;
- uint8 MajorLinkerVersion;
- uint8 MinorLinkerVersion;
- uint32 SizeOfCode;
- uint32 SizeOfInitializedData;
- uint32 SizeOfUninitializedData;
- uint32 AddressOfEntryPoint;
- uint32 BaseOfCode;
- uint32 BaseOfData;
- uint32 ImageBase;
- uint32 SectionAlignment;
- uint32 FileAlignment;
- uint16 MajorOperatingSystemVersion;
- uint16 MinorOperatingSystemVersion;
- uint16 MajorImageVersion;
- uint16 MinorImageVersion;
- uint16 MajorSubsystemVersion;
- uint16 MinorSubsystemVersion;
- uint32 Win32VersionValue;
- uint32 SizeOfImage;
- uint32 SizeOfHeaders;
- uint32 CheckSum;
- uint16 Subsystem;
- uint16 DllCharacteristics;
- uint32 SizeOfStackReserve;
- uint32 SizeOfStackCommit;
- uint32 SizeOfHeapReserve;
- uint32 SizeOfHeapCommit;
- uint32 LoaderFlags;
- uint32 NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[16];
-} IMAGE_OPTIONAL_HEADER;
-
-typedef struct {
- uint8 Name[8];
- uint32 VirtualSize;
- uint32 VirtualAddress;
- uint32 SizeOfRawData;
- uint32 PointerToRawData;
- uint32 PointerToRelocations;
- uint32 PointerToLineNumbers;
- uint16 NumberOfRelocations;
- uint16 NumberOfLineNumbers;
- uint32 Characteristics;
-} IMAGE_SECTION_HEADER;
-
-typedef struct {
- uint32 OriginalFirstThunk;
- uint32 TimeDateStamp;
- uint32 ForwarderChain;
- uint32 Name;
- uint32 FirstThunk;
-} IMAGE_IMPORT_DESCRIPTOR;
-
-typedef struct _IMAGE_EXPORT_DIRECTORY {
- uint32 Characteristics;
- uint32 TimeDateStamp;
- uint16 MajorVersion;
- uint16 MinorVersion;
- uint32 Name;
- uint32 Base;
- uint32 NumberOfFunctions;
- uint32 NumberOfNames;
- uint32 AddressOfFunctions;
- uint32 AddressOfNames;
- uint32 AddressOfNameOrdinals;
-} IMAGE_EXPORT_DIRECTORY;
-
-#define PEBASE 0x00400000
-// SectionAlignment must be greater than or equal to FileAlignment.
-// The default is the page size for the architecture.
-#define PESECTALIGN 0x1000
-// FileAlignment should be a power of 2 between 512 and 64 K, inclusive.
-// The default is 512. If the SectionAlignment is less than
-// the architecture's page size, then FileAlignment must match SectionAlignment.
-#define PEFILEALIGN (2<<8)
-extern int32 PESECTHEADR;
-extern int32 PEFILEHEADR;
-
-enum {
- IMAGE_FILE_MACHINE_I386 = 0x14c,
- IMAGE_FILE_MACHINE_AMD64 = 0x8664,
-
- IMAGE_FILE_RELOCS_STRIPPED = 0x0001,
- IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002,
- IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020,
- IMAGE_FILE_32BIT_MACHINE = 0x0100,
- IMAGE_FILE_DEBUG_STRIPPED = 0x0200,
-
- IMAGE_SCN_CNT_CODE = 0x00000020,
- IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040,
- IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080,
- IMAGE_SCN_MEM_EXECUTE = 0x20000000,
- IMAGE_SCN_MEM_READ = 0x40000000,
- IMAGE_SCN_MEM_WRITE = 0x80000000,
- IMAGE_SCN_MEM_DISCARDABLE = 0x2000000,
-
- IMAGE_DIRECTORY_ENTRY_EXPORT = 0,
- IMAGE_DIRECTORY_ENTRY_IMPORT = 1,
- IMAGE_DIRECTORY_ENTRY_RESOURCE = 2,
- IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3,
- IMAGE_DIRECTORY_ENTRY_SECURITY = 4,
- IMAGE_DIRECTORY_ENTRY_BASERELOC = 5,
- IMAGE_DIRECTORY_ENTRY_DEBUG = 6,
- IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7,
- IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7,
- IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8,
- IMAGE_DIRECTORY_ENTRY_TLS = 9,
- IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10,
- IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11,
- IMAGE_DIRECTORY_ENTRY_IAT = 12,
- IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13,
- IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14,
-
- IMAGE_SUBSYSTEM_WINDOWS_GUI = 2,
- IMAGE_SUBSYSTEM_WINDOWS_CUI = 3,
-};
-
-void peinit(void);
-void asmbpe(void);
-void dope(void);
-
-IMAGE_SECTION_HEADER* newPEDWARFSection(char *name, vlong size);
-
-// X64
-typedef struct {
- uint16 Magic;
- uint8 MajorLinkerVersion;
- uint8 MinorLinkerVersion;
- uint32 SizeOfCode;
- uint32 SizeOfInitializedData;
- uint32 SizeOfUninitializedData;
- uint32 AddressOfEntryPoint;
- uint32 BaseOfCode;
- uint64 ImageBase;
- uint32 SectionAlignment;
- uint32 FileAlignment;
- uint16 MajorOperatingSystemVersion;
- uint16 MinorOperatingSystemVersion;
- uint16 MajorImageVersion;
- uint16 MinorImageVersion;
- uint16 MajorSubsystemVersion;
- uint16 MinorSubsystemVersion;
- uint32 Win32VersionValue;
- uint32 SizeOfImage;
- uint32 SizeOfHeaders;
- uint32 CheckSum;
- uint16 Subsystem;
- uint16 DllCharacteristics;
- uint64 SizeOfStackReserve;
- uint64 SizeOfStackCommit;
- uint64 SizeOfHeapReserve;
- uint64 SizeOfHeapCommit;
- uint32 LoaderFlags;
- uint32 NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[16];
-} PE64_IMAGE_OPTIONAL_HEADER;
-
-void setpersrc(Sym *sym);
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
deleted file mode 100644
index 60e146b35..000000000
--- a/src/cmd/ld/symtab.c
+++ /dev/null
@@ -1,378 +0,0 @@
-// Inferno utils/6l/span.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Symbol table.
-
-#include "l.h"
-#include "../ld/lib.h"
-#include "../ld/elf.h"
-
-char *elfstrdat;
-int elfstrsize;
-int maxelfstr;
-int elftextsh;
-
-int
-putelfstr(char *s)
-{
- int off, n;
-
- if(elfstrsize == 0 && s[0] != 0) {
- // first entry must be empty string
- putelfstr("");
- }
-
- n = strlen(s)+1;
- if(elfstrsize+n > maxelfstr) {
- maxelfstr = 2*(elfstrsize+n+(1<<20));
- elfstrdat = realloc(elfstrdat, maxelfstr);
- }
- off = elfstrsize;
- elfstrsize += n;
- memmove(elfstrdat+off, s, n);
- return off;
-}
-
-void
-putelfsyment(int off, vlong addr, vlong size, int info, int shndx)
-{
- switch(thechar) {
- case '6':
- LPUT(off);
- cput(info);
- cput(0);
- WPUT(shndx);
- VPUT(addr);
- VPUT(size);
- symsize += ELF64SYMSIZE;
- break;
- default:
- LPUT(off);
- LPUT(addr);
- LPUT(size);
- cput(info);
- cput(0);
- WPUT(shndx);
- symsize += ELF32SYMSIZE;
- break;
- }
-}
-
-void
-putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
-{
- int bind, type, shndx, off;
-
- USED(go);
- switch(t) {
- default:
- return;
- case 'T':
- type = STT_FUNC;
- shndx = elftextsh + 0;
- break;
- case 'D':
- type = STT_OBJECT;
- if((x->type&~SSUB) == SRODATA)
- shndx = elftextsh + 1;
- else
- shndx = elftextsh + 2;
- break;
- case 'B':
- type = STT_OBJECT;
- shndx = elftextsh + 3;
- break;
- }
- bind = ver ? STB_LOCAL : STB_GLOBAL;
- off = putelfstr(s);
- putelfsyment(off, addr, size, (bind<<4)|(type&0xf), shndx);
-}
-
-void
-asmelfsym(void)
-{
- // the first symbol entry is reserved
- putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0);
- genasmsym(putelfsym);
-}
-
-void
-putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
-{
- int i;
-
- USED(go);
- USED(ver);
- USED(size);
- USED(x);
- switch(t) {
- case 'T':
- case 'L':
- case 'D':
- case 'B':
- if(ver)
- t += 'a' - 'A';
- case 'a':
- case 'p':
- case 'f':
- case 'z':
- case 'Z':
- case 'm':
- lputb(addr);
- cput(t+0x80); /* 0x80 is variable length */
-
- if(t == 'z' || t == 'Z') {
- cput(s[0]);
- for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
- cput(s[i]);
- cput(s[i+1]);
- }
- cput(0);
- cput(0);
- i++;
- } else {
- /* skip the '<' in filenames */
- if(t == 'f')
- s++;
- for(i=0; s[i]; i++)
- cput(s[i]);
- cput(0);
- }
- symsize += 4 + 1 + i + 1;
- break;
- default:
- return;
- };
-}
-
-void
-asmplan9sym(void)
-{
- genasmsym(putplan9sym);
-}
-
-static Sym *symt;
-
-static void
-scput(int b)
-{
- uchar *p;
-
- symgrow(symt, symt->size+1);
- p = symt->p + symt->size;
- *p = b;
- symt->size++;
-}
-
-static void
-slputb(int32 v)
-{
- uchar *p;
-
- symgrow(symt, symt->size+4);
- p = symt->p + symt->size;
- *p++ = v>>24;
- *p++ = v>>16;
- *p++ = v>>8;
- *p = v;
- symt->size += 4;
-}
-
-void
-wputl(ushort w)
-{
- cput(w);
- cput(w>>8);
-}
-
-void
-wputb(ushort w)
-{
- cput(w>>8);
- cput(w);
-}
-
-void
-lputb(int32 l)
-{
- cput(l>>24);
- cput(l>>16);
- cput(l>>8);
- cput(l);
-}
-
-void
-lputl(int32 l)
-{
- cput(l);
- cput(l>>8);
- cput(l>>16);
- cput(l>>24);
-}
-
-void
-vputb(uint64 v)
-{
- lputb(v>>32);
- lputb(v);
-}
-
-void
-vputl(uint64 v)
-{
- lputl(v);
- lputl(v >> 32);
-}
-
-void
-putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
-{
- int i, f, l;
- Reloc *rel;
-
- USED(size);
- if(t == 'f')
- name++;
- l = 4;
-// if(!debug['8'])
-// l = 8;
- if(s != nil) {
- rel = addrel(symt);
- rel->siz = l + Rbig;
- rel->sym = s;
- rel->type = D_ADDR;
- rel->off = symt->size;
- v = 0;
- }
- if(l == 8)
- slputb(v>>32);
- slputb(v);
- if(ver)
- t += 'a' - 'A';
- scput(t+0x80); /* 0x80 is variable length */
-
- if(t == 'Z' || t == 'z') {
- scput(name[0]);
- for(i=1; name[i] != 0 || name[i+1] != 0; i += 2) {
- scput(name[i]);
- scput(name[i+1]);
- }
- scput(0);
- scput(0);
- }
- else {
- for(i=0; name[i]; i++)
- scput(name[i]);
- scput(0);
- }
- if(typ) {
- if(!typ->reachable)
- diag("unreachable type %s", typ->name);
- rel = addrel(symt);
- rel->siz = l;
- rel->sym = typ;
- rel->type = D_ADDR;
- rel->off = symt->size;
- }
- if(l == 8)
- slputb(0);
- slputb(0);
-
- if(debug['n']) {
- if(t == 'z' || t == 'Z') {
- Bprint(&bso, "%c %.8llux ", t, v);
- for(i=1; name[i] != 0 || name[i+1] != 0; i+=2) {
- f = ((name[i]&0xff) << 8) | (name[i+1]&0xff);
- Bprint(&bso, "/%x", f);
- }
- Bprint(&bso, "\n");
- return;
- }
- if(ver)
- Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, s->name, ver, typ ? typ->name : "");
- else
- Bprint(&bso, "%c %.8llux %s %s\n", t, v, s->name, typ ? typ->name : "");
- }
-}
-
-void
-symtab(void)
-{
- Sym *s;
-
- // Define these so that they'll get put into the symbol table.
- // data.c:/^address will provide the actual values.
- xdefine("text", STEXT, 0);
- xdefine("etext", STEXT, 0);
- xdefine("rodata", SRODATA, 0);
- xdefine("erodata", SRODATA, 0);
- xdefine("data", SBSS, 0);
- xdefine("edata", SBSS, 0);
- xdefine("end", SBSS, 0);
- xdefine("epclntab", SRODATA, 0);
- xdefine("esymtab", SRODATA, 0);
-
- // pseudo-symbols to mark locations of type, string, and go string data.
- s = lookup("type.*", 0);
- s->type = STYPE;
- s->size = 0;
- s->reachable = 1;
-
- s = lookup("go.string.*", 0);
- s->type = SGOSTRING;
- s->size = 0;
- s->reachable = 1;
-
- symt = lookup("symtab", 0);
- symt->type = SSYMTAB;
- symt->size = 0;
- symt->reachable = 1;
-
- // assign specific types so that they sort together.
- // within a type they sort by size, so the .* symbols
- // just defined above will be first.
- // hide the specific symbols.
- for(s = allsym; s != S; s = s->allsym) {
- if(!s->reachable || s->special || s->type != SRODATA)
- continue;
- if(strncmp(s->name, "type.", 5) == 0) {
- s->type = STYPE;
- s->hide = 1;
- }
- if(strncmp(s->name, "go.string.", 10) == 0) {
- s->type = SGOSTRING;
- s->hide = 1;
- }
- }
-
- if(debug['s'])
- return;
- genasmsym(putsymb);
-}