From 032e5bfb302714c4f9330540ca3d4087062bdc1a Mon Sep 17 00:00:00 2001 From: Jan Ziak <0xe2.0x9a.0x9b@gmail.com> Date: Thu, 13 Sep 2012 15:59:34 -0400 Subject: [PATCH] ld: add .gcdata and .gcbss sections R=rsc CC=golang-dev https://golang.org/cl/6281048 --- src/cmd/5l/asm.c | 6 +- src/cmd/6l/asm.c | 6 +- src/cmd/8l/asm.c | 6 +- src/cmd/gc/subr.c | 1 - src/cmd/ld/data.c | 340 ++++++++++++++++++++++++++++------------- src/cmd/ld/decodesym.c | 215 ++++++++++++++++++++++++++ src/cmd/ld/dwarf.c | 236 +--------------------------- src/cmd/ld/lib.h | 30 +++- src/cmd/ld/symtab.c | 4 + 9 files changed, 498 insertions(+), 346 deletions(-) create mode 100644 src/cmd/ld/decodesym.c diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index 3c5a9a77011..10872297901 100644 --- a/src/cmd/5l/asm.c +++ b/src/cmd/5l/asm.c @@ -505,6 +505,8 @@ doelf(void) if(HEADTYPE == Hnetbsd) elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident"); addstring(shstrtab, ".rodata"); + addstring(shstrtab, ".gcdata"); + addstring(shstrtab, ".gcbss"); addstring(shstrtab, ".gosymtab"); addstring(shstrtab, ".gopclntab"); if(!debug['s']) { @@ -661,7 +663,7 @@ asmb(void) cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); codeblk(sect->vaddr, sect->len); - /* output read-only data in text segment (rodata, gosymtab and pclntab) */ + /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */ for(sect = sect->next; sect != nil; sect = sect->next) { cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); @@ -2274,6 +2276,8 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)) case SNOPTRDATA: case SSYMTAB: case SPCLNTAB: + case SGCDATA: + case SGCBSS: if(!s->reachable) continue; put(s, s->name, 'D', s->value, s->size, s->version, s->gotype); diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index a9901c73748..3b7feeca431 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -579,6 +579,8 @@ doelf(void) elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident"); addstring(shstrtab, ".elfdata"); addstring(shstrtab, ".rodata"); + addstring(shstrtab, ".gcdata"); + addstring(shstrtab, ".gcbss"); addstring(shstrtab, ".gosymtab"); addstring(shstrtab, ".gopclntab"); if(!debug['s']) { @@ -732,7 +734,7 @@ asmb(void) cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); codeblk(sect->vaddr, sect->len); - /* output read-only data in text segment (rodata, gosymtab and pclntab) */ + /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */ for(sect = sect->next; sect != nil; sect = sect->next) { cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); @@ -1200,6 +1202,8 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)) case SSTRING: case SGOSTRING: case SWINDOWS: + case SGCDATA: + case SGCBSS: if(!s->reachable) continue; put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype); diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index 99c9b238b12..87888d2bb24 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -536,6 +536,8 @@ doelf(void) elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident"); addstring(shstrtab, ".elfdata"); addstring(shstrtab, ".rodata"); + addstring(shstrtab, ".gcdata"); + addstring(shstrtab, ".gcbss"); addstring(shstrtab, ".gosymtab"); addstring(shstrtab, ".gopclntab"); if(!debug['s']) { @@ -684,7 +686,7 @@ asmb(void) cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); codeblk(sect->vaddr, sect->len); - /* output read-only data in text segment (rodata, gosymtab and pclntab) */ + /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */ for(sect = sect->next; sect != nil; sect = sect->next) { cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); @@ -1266,6 +1268,8 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)) case SNOPTRDATA: case SSYMTAB: case SPCLNTAB: + case SGCDATA: + case SGCBSS: if(!s->reachable) continue; put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype); diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index c04c1edc710..383340f3231 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -3515,7 +3515,6 @@ ngotype(Node *n) { if(n->sym != S && n->realtype != T) if(strncmp(n->sym->name, "autotmp_", 8) != 0) - if(strncmp(n->sym->name, "statictmp_", 8) != 0) return typename(n->realtype)->left->sym; return S; diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index 865f282114e..e1d380b317f 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -34,6 +34,7 @@ #include "../ld/lib.h" #include "../ld/elf.h" #include "../ld/pe.h" +#include "../../pkg/runtime/mgc0.h" void dynreloc(void); static vlong addaddrplus4(Sym *s, Sym *t, int32 add); @@ -628,41 +629,51 @@ addstring(Sym *s, char *str) } vlong -adduintxx(Sym *s, uint64 v, int wid) +setuintxx(Sym *s, vlong off, uint64 v, int wid) { - int32 i, r, fl; + int32 i, 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); + if(s->size < off+wid) { + s->size = off+wid; + symgrow(s, s->size); + } fl = v; cast = (uchar*)&fl; switch(wid) { case 1: - s->p[r] = cast[inuxi1[0]]; + s->p[off] = cast[inuxi1[0]]; break; case 2: for(i=0; i<2; i++) - s->p[r+i] = cast[inuxi2[i]]; + s->p[off+i] = cast[inuxi2[i]]; break; case 4: for(i=0; i<4; i++) - s->p[r+i] = cast[inuxi4[i]]; + s->p[off+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]]; + s->p[off+i] = cast[inuxi8[i]]; break; } - return r; + return off; +} + +vlong +adduintxx(Sym *s, uint64 v, int wid) +{ + int32 off; + + off = s->size; + setuintxx(s, off, v, wid); + return off; } vlong @@ -689,6 +700,30 @@ adduint64(Sym *s, uint64 v) return adduintxx(s, v, 8); } +void +setuint8(Sym *s, vlong r, uint8 v) +{ + setuintxx(s, r, v, 1); +} + +void +setuint16(Sym *s, vlong r, uint16 v) +{ + setuintxx(s, r, v, 2); +} + +void +setuint32(Sym *s, vlong r, uint32 v) +{ + setuintxx(s, r, v, 4); +} + +void +setuint64(Sym *s, vlong r, uint64 v) +{ + setuintxx(s, r, v, 8); +} + vlong addaddrplus(Sym *s, Sym *t, int32 add) { @@ -793,17 +828,87 @@ dosymtype(void) } } +static int32 +alignsymsize(int32 s) +{ + if(s >= PtrSize) + s = rnd(s, PtrSize); + else if(s > 2) + s = rnd(s, 4); + return s; +} + +static int32 +aligndatsize(int32 datsize, Sym *s) +{ + int32 t; + + if(s->align != 0) { + datsize = rnd(datsize, s->align); + } else { + t = alignsymsize(s->size); + if(t & 1) { + ; + } else if(t & 2) + datsize = rnd(datsize, 2); + else if(t & 4) + datsize = rnd(datsize, 4); + else + datsize = rnd(datsize, 8); + } + return datsize; +} + +static void +gcaddsym(Sym *gc, Sym *s, int32 off) +{ + int32 a; + Sym *gotype; + + if(s->size < PtrSize) + return; + if(strcmp(s->name, ".string") == 0) + return; + + gotype = s->gotype; + if(gotype != nil) { + //print("gcaddsym: %s %d %s\n", s->name, s->size, gotype->name); + adduintxx(gc, GC_CALL, PtrSize); + adduintxx(gc, off, PtrSize); + addaddrplus(gc, decodetype_gc(gotype), 1*PtrSize); + } else { + //print("gcaddsym: %s %d \n", s->name, s->size); + for(a = -off&(PtrSize-1); a+PtrSize<=s->size; a+=PtrSize) { + adduintxx(gc, GC_APTR, PtrSize); + adduintxx(gc, off+a, PtrSize); + } + } +} + void dodata(void) { int32 t, datsize; - Section *sect, *noptr; + Section *sect; Sym *s, *last, **l; + Sym *gcdata1, *gcbss1; if(debug['v']) Bprint(&bso, "%5.2f dodata\n", cputime()); Bflush(&bso); + // define garbage collection symbols + gcdata1 = lookup("gcdata1", 0); + gcdata1->type = SGCDATA; + gcdata1->reachable = 1; + gcbss1 = lookup("gcbss1", 0); + gcbss1->type = SGCBSS; + gcbss1->reachable = 1; + + // size of .data and .bss section. the zero value is later replaced by the actual size of the section. + adduintxx(gcdata1, 0, PtrSize); + adduintxx(gcbss1, 0, PtrSize); + last = nil; datap = nil; @@ -847,16 +952,102 @@ dodata(void) datap = datsort(datap); /* - * allocate data sections. list is sorted by type, + * allocate sections. list is sorted by type, * so we can just walk it for each piece we want to emit. + * segdata is processed before segtext, because we need + * to see all symbols in the .data and .bss sections in order + * to generate garbage collection information. */ + /* begin segdata */ + + /* skip symbols belonging to segtext */ + s = datap; + for(; s != nil && s->type < SELFSECT; s = s->next); + + /* writable ELF sections */ + datsize = 0; + for(; s != nil && s->type < SNOPTRDATA; s = s->next) { + sect = addsection(&segdata, s->name, 06); + if(s->align != 0) + datsize = rnd(datsize, s->align); + sect->vaddr = datsize; + s->type = SDATA; + s->value = datsize; + datsize += rnd(s->size, PtrSize); + sect->len = datsize - sect->vaddr; + } + + /* pointer-free data */ + sect = addsection(&segdata, ".noptrdata", 06); + sect->vaddr = datsize; + for(; s != nil && s->type < SDATA; s = s->next) { + s->type = SDATA; + t = alignsymsize(s->size); + datsize = aligndatsize(datsize, s); + s->value = datsize; + datsize += t; + } + sect->len = datsize - sect->vaddr; + datsize = rnd(datsize, PtrSize); + + /* data */ + sect = addsection(&segdata, ".data", 06); + sect->vaddr = datsize; + for(; s != nil && s->type < SBSS; s = s->next) { + s->type = SDATA; + t = alignsymsize(s->size); + datsize = aligndatsize(datsize, s); + s->value = datsize; + gcaddsym(gcdata1, s, datsize - sect->vaddr); // gc + datsize += t; + } + sect->len = datsize - sect->vaddr; + datsize = rnd(datsize, PtrSize); + + adduintxx(gcdata1, GC_END, PtrSize); + setuintxx(gcdata1, 0, sect->len, PtrSize); + + /* bss */ + sect = addsection(&segdata, ".bss", 06); + sect->vaddr = datsize; + for(; s != nil && s->type < SNOPTRBSS; s = s->next) { + t = alignsymsize(s->size); + datsize = aligndatsize(datsize, s); + s->value = datsize; + gcaddsym(gcbss1, s, datsize - sect->vaddr); // gc + datsize += t; + } + sect->len = datsize - sect->vaddr; + datsize = rnd(datsize, PtrSize); + + adduintxx(gcbss1, GC_END, PtrSize); + setuintxx(gcbss1, 0, sect->len, PtrSize); + + /* pointer-free bss */ + sect = addsection(&segdata, ".noptrbss", 06); + sect->vaddr = datsize; + for(; s != nil; s = s->next) { + if(s->type > SNOPTRBSS) { + cursym = s; + diag("unexpected symbol type %d", s->type); + } + t = alignsymsize(s->size); + datsize = aligndatsize(datsize, s); + s->value = datsize; + datsize += t; + } + sect->len = datsize - sect->vaddr; + datsize = rnd(datsize, PtrSize); + + /* we finished segdata, begin segtext */ + /* read-only data */ sect = addsection(&segtext, ".rodata", 04); sect->vaddr = 0; datsize = 0; s = datap; - for(; s != nil && s->type < SSYMTAB; s = s->next) { + for(; s != nil && s->type < SGCDATA; s = s->next) { if(s->align != 0) datsize = rnd(datsize, s->align); s->type = SRODATA; @@ -865,6 +1056,28 @@ dodata(void) } sect->len = datsize - sect->vaddr; + /* gcdata */ + sect = addsection(&segtext, ".gcdata", 04); + sect->vaddr = datsize; + for(; s != nil && s->type == SGCDATA; s = s->next) { + s->type = SRODATA; + s->value = datsize; + datsize += s->size; + } + sect->len = datsize - sect->vaddr; + datsize = rnd(datsize, PtrSize); + + /* gcbss */ + sect = addsection(&segtext, ".gcbss", 04); + sect->vaddr = datsize; + for(; s != nil && s->type == SGCBSS; s = s->next) { + s->type = SRODATA; + s->value = datsize; + datsize += s->size; + } + sect->len = datsize - sect->vaddr; + datsize = rnd(datsize, PtrSize); + /* gosymtab */ sect = addsection(&segtext, ".gosymtab", 04); sect->vaddr = datsize; @@ -898,96 +1111,6 @@ dodata(void) datsize += rnd(s->size, PtrSize); sect->len = datsize - sect->vaddr; } - - /* writable ELF sections */ - datsize = 0; - for(; s != nil && s->type < SNOPTRDATA; s = s->next) { - sect = addsection(&segdata, s->name, 06); - if(s->align != 0) - datsize = rnd(datsize, s->align); - sect->vaddr = datsize; - s->type = SDATA; - s->value = datsize; - datsize += rnd(s->size, PtrSize); - sect->len = datsize - sect->vaddr; - } - - /* pointer-free data, then data */ - sect = addsection(&segdata, ".noptrdata", 06); - sect->vaddr = datsize; - noptr = sect; - for(; ; s = s->next) { - if((s == nil || s->type >= SDATA) && sect == noptr) { - // finish noptrdata, start data - datsize = rnd(datsize, 8); - sect->len = datsize - sect->vaddr; - sect = addsection(&segdata, ".data", 06); - sect->vaddr = datsize; - } - if(s == nil || s->type >= SBSS) { - // finish data - sect->len = datsize - sect->vaddr; - break; - } - s->type = SDATA; - t = s->size; - if(t >= PtrSize) - t = rnd(t, PtrSize); - else if(t > 2) - t = rnd(t, 4); - if(s->align != 0) - datsize = rnd(datsize, s->align); - else 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; - } - - /* bss, then pointer-free bss */ - noptr = nil; - sect = addsection(&segdata, ".bss", 06); - sect->vaddr = datsize; - for(; ; s = s->next) { - if((s == nil || s->type >= SNOPTRBSS) && noptr == nil) { - // finish bss, start noptrbss - datsize = rnd(datsize, 8); - sect->len = datsize - sect->vaddr; - sect = addsection(&segdata, ".noptrbss", 06); - sect->vaddr = datsize; - noptr = sect; - } - if(s == nil) { - sect->len = datsize - sect->vaddr; - break; - } - if(s->type > SNOPTRBSS) { - 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(s->align != 0) - datsize = rnd(datsize, s->align); - else 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; - } } // assign addresses to text @@ -1038,6 +1161,7 @@ void address(void) { Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss; + Section *gcdata, *gcbss; Sym *sym, *sub; uvlong va; @@ -1084,7 +1208,9 @@ address(void) text = segtext.sect; rodata = text->next; - symtab = rodata->next; + gcdata = rodata->next; + gcbss = gcdata->next; + symtab = gcbss->next; pclntab = symtab->next; for(sym = datap; sym != nil; sym = sym->next) { @@ -1101,6 +1227,10 @@ address(void) xdefine("etext", STEXT, text->vaddr + text->len); xdefine("rodata", SRODATA, rodata->vaddr); xdefine("erodata", SRODATA, rodata->vaddr + rodata->len); + xdefine("gcdata", SGCDATA, gcdata->vaddr); + xdefine("egcdata", SGCDATA, gcdata->vaddr + gcdata->len); + xdefine("gcbss", SGCBSS, gcbss->vaddr); + xdefine("egcbss", SGCBSS, gcbss->vaddr + gcbss->len); xdefine("symtab", SRODATA, symtab->vaddr); xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len); xdefine("pclntab", SRODATA, pclntab->vaddr); diff --git a/src/cmd/ld/decodesym.c b/src/cmd/ld/decodesym.c new file mode 100644 index 00000000000..f3f91c34d88 --- /dev/null +++ b/src/cmd/ld/decodesym.c @@ -0,0 +1,215 @@ +// Copyright 2012 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 "../../pkg/runtime/typekind.h" + +// 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. + +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 +uint8 +decodetype_kind(Sym *s) +{ + return s->p[3*PtrSize + 7] & ~KindNoPointers; // 0x13 / 0x1f +} + +// Type.commonType.size +vlong +decodetype_size(Sym *s) +{ + return decode_inuxi(s->p + 2*PtrSize, PtrSize); // 0x8 / 0x10 +} + +// Type.commonType.gc +Sym* +decodetype_gc(Sym *s) +{ + return decode_reloc_sym(s, 3*PtrSize + 8 + 1*PtrSize); +} + +// Type.ArrayType.elem and Type.SliceType.Elem +Sym* +decodetype_arrayelem(Sym *s) +{ + return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30 +} + +vlong +decodetype_arraylen(Sym *s) +{ + return decode_inuxi(s->p + CommonSize+PtrSize, PtrSize); +} + +// Type.PtrType.elem +Sym* +decodetype_ptrelem(Sym *s) +{ + return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30 +} + +// Type.MapType.key, elem +Sym* +decodetype_mapkey(Sym *s) +{ + return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30 +} +Sym* +decodetype_mapvalue(Sym *s) +{ + return decode_reloc_sym(s, CommonSize+PtrSize); // 0x20 / 0x38 +} + +// Type.ChanType.elem +Sym* +decodetype_chanelem(Sym *s) +{ + return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30 +} + +// Type.FuncType.dotdotdot +int +decodetype_funcdotdotdot(Sym *s) +{ + return s->p[CommonSize]; +} + +// Type.FuncType.in.len +int +decodetype_funcincount(Sym *s) +{ + return decode_inuxi(s->p + CommonSize+2*PtrSize, 4); +} + +int +decodetype_funcoutcount(Sym *s) +{ + return decode_inuxi(s->p + CommonSize+3*PtrSize + 2*4, 4); +} + +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); +} + +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 +int +decodetype_structfieldcount(Sym *s) +{ + return decode_inuxi(s->p + CommonSize + PtrSize, 4); +} + +enum { + StructFieldSize = 5*PtrSize +}; +// Type.StructType.fields[]-> name, typ and offset. +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 +} + +Sym* +decodetype_structfieldtype(Sym *s, int i) +{ + return decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize + 2*PtrSize); +} + +vlong +decodetype_structfieldoffs(Sym *s, int i) +{ + return decode_inuxi(s->p + CommonSize + PtrSize + 2*4 + i*StructFieldSize + 4*PtrSize, 4); +} + +// InterfaceTYpe.methods.len +vlong +decodetype_ifacemethodcount(Sym *s) +{ + return decode_inuxi(s->p + CommonSize + PtrSize, 4); +} diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c index 9a78d9610d7..2cf450eda92 100644 --- a/src/cmd/ld/dwarf.c +++ b/src/cmd/ld/dwarf.c @@ -19,6 +19,7 @@ #include "../ld/elf.h" #include "../ld/macho.h" #include "../ld/pe.h" +#include "../../pkg/runtime/typekind.h" /* * Offsets and sizes of the debug_* sections in the cout file. @@ -740,241 +741,6 @@ newabslocexprattr(DWDie *die, vlong addr) 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+ 6*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 { diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index 25c0b3709d7..d322df5c6b4 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -39,6 +39,8 @@ enum SSTRING, SGOSTRING, SRODATA, + SGCDATA, + SGCBSS, SSYMTAB, SPCLNTAB, SELFROSECT, @@ -186,14 +188,18 @@ void savedata(Sym*, Prog*, char*); void symgrow(Sym*, int32); void addstrdata(char*, char*); vlong addstring(Sym*, char*); +vlong adduint8(Sym*, uint8); +vlong adduint16(Sym*, uint16); 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 setuint8(Sym*, vlong, uint8); +void setuint16(Sym*, vlong, uint16); +void setuint32(Sym*, vlong, uint32); +void setuint64(Sym*, vlong, uint64); void asmsym(void); void asmelfsym(void); void asmplan9sym(void); @@ -315,3 +321,23 @@ void cseek(vlong); void cwrite(void*, int); void importcycles(void); int Zconv(Fmt*); + +uint8 decodetype_kind(Sym*); +vlong decodetype_size(Sym*); +Sym* decodetype_gc(Sym*); +Sym* decodetype_arrayelem(Sym*); +vlong decodetype_arraylen(Sym*); +Sym* decodetype_ptrelem(Sym*); +Sym* decodetype_mapkey(Sym*); +Sym* decodetype_mapvalue(Sym*); +Sym* decodetype_chanelem(Sym*); +int decodetype_funcdotdotdot(Sym*); +int decodetype_funcincount(Sym*); +int decodetype_funcoutcount(Sym*); +Sym* decodetype_funcintype(Sym*, int); +Sym* decodetype_funcouttype(Sym*, int); +int decodetype_structfieldcount(Sym*); +char* decodetype_structfieldname(Sym*, int); +Sym* decodetype_structfieldtype(Sym*, int); +vlong decodetype_structfieldoffs(Sym*, int); +vlong decodetype_ifacemethodcount(Sym*); diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c index c43051a3921..7513ff570df 100644 --- a/src/cmd/ld/symtab.c +++ b/src/cmd/ld/symtab.c @@ -339,6 +339,10 @@ symtab(void) xdefine("etext", STEXT, 0); xdefine("rodata", SRODATA, 0); xdefine("erodata", SRODATA, 0); + xdefine("gcdata", SGCDATA, 0); + xdefine("egcdata", SGCDATA, 0); + xdefine("gcbss", SGCBSS, 0); + xdefine("egcbss", SGCBSS, 0); xdefine("noptrdata", SNOPTRDATA, 0); xdefine("enoptrdata", SNOPTRDATA, 0); xdefine("data", SDATA, 0);