1
0
mirror of https://github.com/golang/go synced 2024-11-23 05:30:07 -07:00

cmd/ld: fix bad merge

CL 7504044 accidentally reverted part of CL 7891044 and 7552045, this CL
bring those part back.

R=golang-dev
TBR=rsc
CC=golang-dev
https://golang.org/cl/7950045
This commit is contained in:
Shenghou Ma 2013-03-22 03:54:14 +08:00
parent ec8caf696a
commit f74b4d3de3

View File

@ -41,9 +41,13 @@ static vlong arangeso;
static vlong arangessize;
static vlong gdbscripto;
static vlong gdbscriptsize;
static vlong inforeloco;
static vlong inforelocsize;
static char gdbscript[1024];
static Sym *dsym;
/*
* Basic I/O
*/
@ -485,26 +489,43 @@ mkindex(DWDie *die)
die->hash = mal(HASHSIZE * sizeof(DWDie*));
}
static DWDie*
walktypedef(DWDie *die)
{
DWAttr *attr;
// Resolve typedef if present.
if (die->abbrev == DW_ABRV_TYPEDECL) {
for (attr = die->attr; attr; attr = attr->link) {
if (attr->atr == DW_AT_type && attr->cls == DW_CLS_REFERENCE && attr->data != nil) {
return (DWDie*)attr->data;
}
}
}
return die;
}
// Find child by AT_name using hashtable if available or linear scan
// if not.
static DWDie*
find(DWDie *die, char* name)
{
DWDie *a, *b;
DWDie *a, *b, *die2;
int h;
top:
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;
goto notfound;
}
h = hashstr(name);
a = die->hash[h];
if (a == nil)
return nil;
goto notfound;
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
@ -522,6 +543,14 @@ find(DWDie *die, char* name)
a = b;
b = b->hlink;
}
notfound:
die2 = walktypedef(die);
if(die2 != die) {
die = die2;
goto top;
}
return nil;
}
@ -531,7 +560,7 @@ 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);
diag("dwarf find: %s %p has no %s", getattr(die, DW_AT_name)->data, die, name);
errorexit();
}
return r;
@ -548,14 +577,33 @@ newrefattr(DWDie *die, uint8 attr, DWDie* ref)
static int fwdcount;
static void
putattr(int form, int cls, vlong value, char *data)
putattr(int abbrev, int form, int cls, vlong value, char *data)
{
Reloc *r;
switch(form) {
case DW_FORM_addr: // address
addrput(value);
break;
case DW_FORM_block1: // block
if(cls == DW_CLS_ADDRESS) {
cput(1+PtrSize);
cput(DW_OP_addr);
if(linkmode == LinkExternal) {
r = addrel(dsym);
r->sym = (Sym*)data;
r->xsym = r->sym;
r->off = cpos() - infoo;
r->siz = PtrSize;
r->type = D_ADDR;
r->add = value - r->sym->value;
r->xadd = r->add;
value = r->add;
}
addrput(value);
break;
}
value &= 0xff;
cput(value);
while(value--)
@ -615,13 +663,23 @@ putattr(int form, int cls, vlong value, char *data)
break;
case DW_FORM_ref_addr: // reference to a DIE in the .info section
// In DWARF 2 (which is what we claim to generate),
// the ref_addr is the same size as a normal address.
// In DWARF 3 it is always 32 bits, unless emitting a large
// (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
if (data == nil) {
diag("dwarf: null reference");
LPUT(0); // invalid dwarf, gdb will complain.
diag("dwarf: null reference in %d", abbrev);
if(PtrSize == 8)
VPUT(0); // invalid dwarf, gdb will complain.
else
LPUT(0); // invalid dwarf, gdb will complain.
} else {
if (((DWDie*)data)->offs == 0)
fwdcount++;
LPUT(((DWDie*)data)->offs);
if(PtrSize == 8)
VPUT(((DWDie*)data)->offs);
else
LPUT(((DWDie*)data)->offs);
}
break;
@ -654,12 +712,12 @@ putattrs(int abbrev, DWAttr* attr)
for(af = abbrevs[abbrev].attr; af->attr; af++)
if (attrs[af->attr])
putattr(af->form,
putattr(abbrev, af->form,
attrs[af->attr]->cls,
attrs[af->attr]->value,
attrs[af->attr]->data);
else
putattr(af->form, 0, 0, 0);
putattr(abbrev, af->form, 0, 0, 0);
}
static void putdie(DWDie* die);
@ -729,16 +787,9 @@ newmemberoffsetattr(DWDie *die, int32 offs)
// 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)
newabslocexprattr(DWDie *die, vlong addr, Sym *sym)
{
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);
newattr(die, DW_AT_location, DW_CLS_ADDRESS, addr, (char*)sym);
}
@ -766,6 +817,31 @@ lookup_or_diag(char *n)
return s;
}
static void
dotypedef(DWDie *parent, char *name, DWDie *def)
{
DWDie *die;
// Only emit typedefs for real names.
if(strncmp(name, "map[", 4) == 0)
return;
if(strncmp(name, "struct {", 8) == 0)
return;
if(strncmp(name, "chan ", 5) == 0)
return;
if(*name == '[' || *name == '*')
return;
if(def == nil)
diag("dwarf: bad def in dotypedef");
// The typedef entry must be created after the def,
// so that future lookups will find the typedef instead
// of the real definition. This hooks the typedef into any
// circular definition loops, so that gdb can understand them.
die = newdie(parent, DW_ABRV_TYPEDECL, name);
newrefattr(die, DW_AT_type, def);
}
// Define gotype, for composite ones recurse into constituents.
static DWDie*
defgotype(Sym *gotype)
@ -840,6 +916,7 @@ defgotype(Sym *gotype)
case KindArray:
die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s));
@ -857,6 +934,7 @@ defgotype(Sym *gotype)
case KindFunc:
die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name);
dotypedef(&dwtypes, name, die);
newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "void"));
nfields = decodetype_funcincount(gotype);
for (i = 0; i < nfields; i++) {
@ -876,6 +954,7 @@ defgotype(Sym *gotype)
case KindInterface:
die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
nfields = decodetype_ifacemethodcount(gotype);
if (nfields == 0)
@ -895,12 +974,14 @@ defgotype(Sym *gotype)
case KindPtr:
die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name);
dotypedef(&dwtypes, name, die);
s = decodetype_ptrelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s));
break;
case KindSlice:
die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
@ -913,6 +994,7 @@ defgotype(Sym *gotype)
case KindStruct:
die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
nfields = decodetype_structfieldcount(gotype);
for (i = 0; i < nfields; i++) {
@ -998,7 +1080,7 @@ synthesizestringtypes(DWDie* die)
{
DWDie *prototype;
prototype = defgotype(lookup_or_diag("type.runtime._string"));
prototype = walktypedef(defgotype(lookup_or_diag("type.runtime._string")));
if (prototype == nil)
return;
@ -1014,7 +1096,7 @@ synthesizeslicetypes(DWDie *die)
{
DWDie *prototype, *elem;
prototype = defgotype(lookup_or_diag("type.runtime.slice"));
prototype = walktypedef(defgotype(lookup_or_diag("type.runtime.slice")));
if (prototype == nil)
return;
@ -1082,9 +1164,9 @@ synthesizechantypes(DWDie *die)
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"));
sudog = walktypedef(defgotype(lookup_or_diag("type.runtime.sudog")));
waitq = walktypedef(defgotype(lookup_or_diag("type.runtime.waitq")));
hchan = walktypedef(defgotype(lookup_or_diag("type.runtime.hchan")));
if (sudog == nil || waitq == nil || hchan == nil)
return;
@ -1153,7 +1235,7 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype)
case 'D':
case 'B':
dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s);
newabslocexprattr(dv, v);
newabslocexprattr(dv, v, sym);
if (ver == 0)
newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0);
// fallthrough
@ -1514,12 +1596,12 @@ mkvarname(char* name, int da)
// flush previous compilation unit.
static void
flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
flushunit(DWDie *dwinfo, vlong pc, Sym *pcsym, vlong unitstart, int32 header_length)
{
vlong here;
if (dwinfo != nil && pc != 0) {
newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, 0);
newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, (char*)pcsym);
}
if (unitstart >= 0) {
@ -1530,7 +1612,7 @@ flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
here = cpos();
cseek(unitstart);
LPUT(here - unitstart - sizeof(int32)); // unit_length
WPUT(3); // dwarf version
WPUT(2); // dwarf version
LPUT(header_length); // header length starting here
cseek(here);
}
@ -1540,7 +1622,7 @@ static void
writelines(void)
{
Prog *q;
Sym *s;
Sym *s, *epcs;
Auto *a;
vlong unitstart, headerend, offs;
vlong pc, epc, lc, llc, lline;
@ -1555,6 +1637,7 @@ writelines(void)
headerend = -1;
pc = 0;
epc = 0;
epcs = S;
lc = 1;
llc = 1;
currfile = -1;
@ -1570,7 +1653,7 @@ writelines(void)
// we're entering a new compilation unit
if (inithist(s->autom)) {
flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
unitstart = cpos();
if(debug['v'] > 1) {
@ -1587,12 +1670,12 @@ writelines(void)
dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, estrdup(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);
newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, (char*)s);
// 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)
WPUT(2); // dwarf version (appendix F)
LPUT(0); // header_length (*), filled in by flushunit.
// cpos == unitstart + 4 + 2 + 4
cput(1); // minimum_instruction_length
@ -1616,6 +1699,7 @@ writelines(void)
pc = s->text->pc;
epc = pc;
epcs = s;
currfile = 1;
lc = 1;
llc = 1;
@ -1634,9 +1718,9 @@ writelines(void)
}
dwfunc = newdie(dwinfo, DW_ABRV_FUNCTION, s->name);
newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, 0);
newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, (char*)s);
epc = s->value + s->size;
newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, 0);
newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, (char*)s);
if (s->version == 0)
newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0);
@ -1718,7 +1802,7 @@ writelines(void)
dwfunc->hash = nil;
}
flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
linesize = cpos() - lineo;
}
@ -1842,6 +1926,9 @@ writeinfo(void)
vlong unitstart, here;
fwdcount = 0;
if (dsym == S)
dsym = lookup(".dwarfinfo", 0);
dsym->nr = 0;
for (compunit = dwroot.child; compunit; compunit = compunit->link) {
unitstart = cpos();
@ -1850,7 +1937,7 @@ writeinfo(void)
// 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)
WPUT(2); // dwarf version (appendix F)
LPUT(0); // debug_abbrev_offset (*)
cput(PtrSize); // address_size
@ -1990,6 +2077,27 @@ align(vlong size)
strnput("", rnd(size, PEFILEALIGN) - size);
}
static vlong
writeinforeloc(void)
{
int i;
vlong start;
Reloc *r;
start = cpos();
for(r = dsym->r; r < dsym->r+dsym->nr; r++) {
if(iself)
i = elfreloc1(r, r->off);
else if(HEADTYPE == Hdarwin)
i = machoreloc1(r, r->off);
else
i = -1;
if(i < 0)
diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
}
return start;
}
/*
* This is the main entry point for generating dwarf. After emitting
* the mandatory debug_abbrev section, it calls writelines() to set up
@ -2090,6 +2198,10 @@ dwarfemitdebugsections(void)
gdbscripto = writegdbscript();
gdbscriptsize = cpos() - gdbscripto;
align(gdbscriptsize);
inforeloco = writeinforeloc();
inforelocsize = cpos() - inforeloco;
align(inforelocsize);
}
/*
@ -2249,6 +2361,8 @@ dwarfaddmachoheaders(void)
msect = newMachoSect(ms, "__debug_info", "__DWARF");
msect->off = infoo;
msect->size = infosize;
msect->reloc = inforeloco;
msect->nreloc = inforelocsize / 8;
ms->filesize += msect->size;
if (pubnamessize > 0) {