mirror of
https://github.com/golang/go
synced 2024-11-21 13:24:40 -07:00
ld: add .gcdata and .gcbss sections
R=rsc CC=golang-dev https://golang.org/cl/6281048
This commit is contained in:
parent
9a82324fb7
commit
032e5bfb30
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 <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
|
||||
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);
|
||||
|
215
src/cmd/ld/decodesym.c
Normal file
215
src/cmd/ld/decodesym.c
Normal 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);
|
||||
}
|
@ -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 {
|
||||
|
@ -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*);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user