1
0
mirror of https://github.com/golang/go synced 2024-11-21 19:04:44 -07:00

ld: add .gcdata and .gcbss sections

R=rsc
CC=golang-dev
https://golang.org/cl/6281048
This commit is contained in:
Jan Ziak 2012-09-13 15:59:34 -04:00 committed by Russ Cox
parent 9a82324fb7
commit 032e5bfb30
9 changed files with 498 additions and 346 deletions

View File

@ -505,6 +505,8 @@ doelf(void)
if(HEADTYPE == Hnetbsd) if(HEADTYPE == Hnetbsd)
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident"); elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
addstring(shstrtab, ".rodata"); addstring(shstrtab, ".rodata");
addstring(shstrtab, ".gcdata");
addstring(shstrtab, ".gcbss");
addstring(shstrtab, ".gosymtab"); addstring(shstrtab, ".gosymtab");
addstring(shstrtab, ".gopclntab"); addstring(shstrtab, ".gopclntab");
if(!debug['s']) { if(!debug['s']) {
@ -661,7 +663,7 @@ asmb(void)
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
codeblk(sect->vaddr, sect->len); 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) { for(sect = sect->next; sect != nil; sect = sect->next) {
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
datblk(sect->vaddr, sect->len); datblk(sect->vaddr, sect->len);
@ -2274,6 +2276,8 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
case SNOPTRDATA: case SNOPTRDATA:
case SSYMTAB: case SSYMTAB:
case SPCLNTAB: case SPCLNTAB:
case SGCDATA:
case SGCBSS:
if(!s->reachable) if(!s->reachable)
continue; continue;
put(s, s->name, 'D', s->value, s->size, s->version, s->gotype); put(s, s->name, 'D', s->value, s->size, s->version, s->gotype);

View File

@ -579,6 +579,8 @@ doelf(void)
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident"); elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
addstring(shstrtab, ".elfdata"); addstring(shstrtab, ".elfdata");
addstring(shstrtab, ".rodata"); addstring(shstrtab, ".rodata");
addstring(shstrtab, ".gcdata");
addstring(shstrtab, ".gcbss");
addstring(shstrtab, ".gosymtab"); addstring(shstrtab, ".gosymtab");
addstring(shstrtab, ".gopclntab"); addstring(shstrtab, ".gopclntab");
if(!debug['s']) { if(!debug['s']) {
@ -732,7 +734,7 @@ asmb(void)
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
codeblk(sect->vaddr, sect->len); 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) { for(sect = sect->next; sect != nil; sect = sect->next) {
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
datblk(sect->vaddr, sect->len); datblk(sect->vaddr, sect->len);
@ -1200,6 +1202,8 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
case SSTRING: case SSTRING:
case SGOSTRING: case SGOSTRING:
case SWINDOWS: case SWINDOWS:
case SGCDATA:
case SGCBSS:
if(!s->reachable) if(!s->reachable)
continue; continue;
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype); put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);

View File

@ -536,6 +536,8 @@ doelf(void)
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident"); elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
addstring(shstrtab, ".elfdata"); addstring(shstrtab, ".elfdata");
addstring(shstrtab, ".rodata"); addstring(shstrtab, ".rodata");
addstring(shstrtab, ".gcdata");
addstring(shstrtab, ".gcbss");
addstring(shstrtab, ".gosymtab"); addstring(shstrtab, ".gosymtab");
addstring(shstrtab, ".gopclntab"); addstring(shstrtab, ".gopclntab");
if(!debug['s']) { if(!debug['s']) {
@ -684,7 +686,7 @@ asmb(void)
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
codeblk(sect->vaddr, sect->len); 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) { for(sect = sect->next; sect != nil; sect = sect->next) {
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
datblk(sect->vaddr, sect->len); datblk(sect->vaddr, sect->len);
@ -1266,6 +1268,8 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
case SNOPTRDATA: case SNOPTRDATA:
case SSYMTAB: case SSYMTAB:
case SPCLNTAB: case SPCLNTAB:
case SGCDATA:
case SGCBSS:
if(!s->reachable) if(!s->reachable)
continue; continue;
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype); put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);

View File

@ -3515,7 +3515,6 @@ ngotype(Node *n)
{ {
if(n->sym != S && n->realtype != T) if(n->sym != S && n->realtype != T)
if(strncmp(n->sym->name, "autotmp_", 8) != 0) if(strncmp(n->sym->name, "autotmp_", 8) != 0)
if(strncmp(n->sym->name, "statictmp_", 8) != 0)
return typename(n->realtype)->left->sym; return typename(n->realtype)->left->sym;
return S; return S;

View File

@ -34,6 +34,7 @@
#include "../ld/lib.h" #include "../ld/lib.h"
#include "../ld/elf.h" #include "../ld/elf.h"
#include "../ld/pe.h" #include "../ld/pe.h"
#include "../../pkg/runtime/mgc0.h"
void dynreloc(void); void dynreloc(void);
static vlong addaddrplus4(Sym *s, Sym *t, int32 add); static vlong addaddrplus4(Sym *s, Sym *t, int32 add);
@ -628,41 +629,51 @@ addstring(Sym *s, char *str)
} }
vlong 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; vlong o;
uchar *cast; uchar *cast;
if(s->type == 0) if(s->type == 0)
s->type = SDATA; s->type = SDATA;
s->reachable = 1; s->reachable = 1;
r = s->size; if(s->size < off+wid) {
s->size += wid; s->size = off+wid;
symgrow(s, s->size); symgrow(s, s->size);
assert(r+wid <= s->size); }
fl = v; fl = v;
cast = (uchar*)&fl; cast = (uchar*)&fl;
switch(wid) { switch(wid) {
case 1: case 1:
s->p[r] = cast[inuxi1[0]]; s->p[off] = cast[inuxi1[0]];
break; break;
case 2: case 2:
for(i=0; i<2; i++) for(i=0; i<2; i++)
s->p[r+i] = cast[inuxi2[i]]; s->p[off+i] = cast[inuxi2[i]];
break; break;
case 4: case 4:
for(i=0; i<4; i++) for(i=0; i<4; i++)
s->p[r+i] = cast[inuxi4[i]]; s->p[off+i] = cast[inuxi4[i]];
break; break;
case 8: case 8:
o = v; o = v;
cast = (uchar*)&o; cast = (uchar*)&o;
for(i=0; i<8; i++) for(i=0; i<8; i++)
s->p[r+i] = cast[inuxi8[i]]; s->p[off+i] = cast[inuxi8[i]];
break; 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 vlong
@ -689,6 +700,30 @@ adduint64(Sym *s, uint64 v)
return adduintxx(s, v, 8); 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 vlong
addaddrplus(Sym *s, Sym *t, int32 add) 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 <unknown type>\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 void
dodata(void) dodata(void)
{ {
int32 t, datsize; int32 t, datsize;
Section *sect, *noptr; Section *sect;
Sym *s, *last, **l; Sym *s, *last, **l;
Sym *gcdata1, *gcbss1;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime()); Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso); 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; last = nil;
datap = nil; datap = nil;
@ -847,16 +952,102 @@ dodata(void)
datap = datsort(datap); 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. * 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 */ /* read-only data */
sect = addsection(&segtext, ".rodata", 04); sect = addsection(&segtext, ".rodata", 04);
sect->vaddr = 0; sect->vaddr = 0;
datsize = 0; datsize = 0;
s = datap; s = datap;
for(; s != nil && s->type < SSYMTAB; s = s->next) { for(; s != nil && s->type < SGCDATA; s = s->next) {
if(s->align != 0) if(s->align != 0)
datsize = rnd(datsize, s->align); datsize = rnd(datsize, s->align);
s->type = SRODATA; s->type = SRODATA;
@ -865,6 +1056,28 @@ dodata(void)
} }
sect->len = datsize - sect->vaddr; 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 */ /* gosymtab */
sect = addsection(&segtext, ".gosymtab", 04); sect = addsection(&segtext, ".gosymtab", 04);
sect->vaddr = datsize; sect->vaddr = datsize;
@ -898,96 +1111,6 @@ dodata(void)
datsize += rnd(s->size, PtrSize); datsize += rnd(s->size, PtrSize);
sect->len = datsize - sect->vaddr; 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 // assign addresses to text
@ -1038,6 +1161,7 @@ void
address(void) address(void)
{ {
Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss; Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
Section *gcdata, *gcbss;
Sym *sym, *sub; Sym *sym, *sub;
uvlong va; uvlong va;
@ -1084,7 +1208,9 @@ address(void)
text = segtext.sect; text = segtext.sect;
rodata = text->next; rodata = text->next;
symtab = rodata->next; gcdata = rodata->next;
gcbss = gcdata->next;
symtab = gcbss->next;
pclntab = symtab->next; pclntab = symtab->next;
for(sym = datap; sym != nil; sym = sym->next) { for(sym = datap; sym != nil; sym = sym->next) {
@ -1101,6 +1227,10 @@ address(void)
xdefine("etext", STEXT, text->vaddr + text->len); xdefine("etext", STEXT, text->vaddr + text->len);
xdefine("rodata", SRODATA, rodata->vaddr); xdefine("rodata", SRODATA, rodata->vaddr);
xdefine("erodata", SRODATA, rodata->vaddr + rodata->len); 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("symtab", SRODATA, symtab->vaddr);
xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len); xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
xdefine("pclntab", SRODATA, pclntab->vaddr); xdefine("pclntab", SRODATA, pclntab->vaddr);

215
src/cmd/ld/decodesym.c Normal file
View File

@ -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);
}

View File

@ -19,6 +19,7 @@
#include "../ld/elf.h" #include "../ld/elf.h"
#include "../ld/macho.h" #include "../ld/macho.h"
#include "../ld/pe.h" #include "../ld/pe.h"
#include "../../pkg/runtime/typekind.h"
/* /*
* Offsets and sizes of the debug_* sections in the cout file. * 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); 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 // Fake attributes for slices, maps and channel
enum { enum {

View File

@ -39,6 +39,8 @@ enum
SSTRING, SSTRING,
SGOSTRING, SGOSTRING,
SRODATA, SRODATA,
SGCDATA,
SGCBSS,
SSYMTAB, SSYMTAB,
SPCLNTAB, SPCLNTAB,
SELFROSECT, SELFROSECT,
@ -186,14 +188,18 @@ void savedata(Sym*, Prog*, char*);
void symgrow(Sym*, int32); void symgrow(Sym*, int32);
void addstrdata(char*, char*); void addstrdata(char*, char*);
vlong addstring(Sym*, char*); vlong addstring(Sym*, char*);
vlong adduint8(Sym*, uint8);
vlong adduint16(Sym*, uint16);
vlong adduint32(Sym*, uint32); vlong adduint32(Sym*, uint32);
vlong adduint64(Sym*, uint64); vlong adduint64(Sym*, uint64);
vlong addaddr(Sym*, Sym*); vlong addaddr(Sym*, Sym*);
vlong addaddrplus(Sym*, Sym*, int32); vlong addaddrplus(Sym*, Sym*, int32);
vlong addpcrelplus(Sym*, Sym*, int32); vlong addpcrelplus(Sym*, Sym*, int32);
vlong addsize(Sym*, Sym*); vlong addsize(Sym*, Sym*);
vlong adduint8(Sym*, uint8); void setuint8(Sym*, vlong, uint8);
vlong adduint16(Sym*, uint16); void setuint16(Sym*, vlong, uint16);
void setuint32(Sym*, vlong, uint32);
void setuint64(Sym*, vlong, uint64);
void asmsym(void); void asmsym(void);
void asmelfsym(void); void asmelfsym(void);
void asmplan9sym(void); void asmplan9sym(void);
@ -315,3 +321,23 @@ void cseek(vlong);
void cwrite(void*, int); void cwrite(void*, int);
void importcycles(void); void importcycles(void);
int Zconv(Fmt*); 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*);

View File

@ -339,6 +339,10 @@ symtab(void)
xdefine("etext", STEXT, 0); xdefine("etext", STEXT, 0);
xdefine("rodata", SRODATA, 0); xdefine("rodata", SRODATA, 0);
xdefine("erodata", 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("noptrdata", SNOPTRDATA, 0);
xdefine("enoptrdata", SNOPTRDATA, 0); xdefine("enoptrdata", SNOPTRDATA, 0);
xdefine("data", SDATA, 0); xdefine("data", SDATA, 0);