1
0
mirror of https://github.com/golang/go synced 2024-11-23 05:40:04 -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 arangessize;
static vlong gdbscripto; static vlong gdbscripto;
static vlong gdbscriptsize; static vlong gdbscriptsize;
static vlong inforeloco;
static vlong inforelocsize;
static char gdbscript[1024]; static char gdbscript[1024];
static Sym *dsym;
/* /*
* Basic I/O * Basic I/O
*/ */
@ -485,26 +489,43 @@ mkindex(DWDie *die)
die->hash = mal(HASHSIZE * sizeof(DWDie*)); 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 // Find child by AT_name using hashtable if available or linear scan
// if not. // if not.
static DWDie* static DWDie*
find(DWDie *die, char* name) find(DWDie *die, char* name)
{ {
DWDie *a, *b; DWDie *a, *b, *die2;
int h; int h;
top:
if (die->hash == nil) { if (die->hash == nil) {
for (a = die->child; a != nil; a = a->link) for (a = die->child; a != nil; a = a->link)
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0) if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
return a; return a;
return nil; goto notfound;
} }
h = hashstr(name); h = hashstr(name);
a = die->hash[h]; a = die->hash[h];
if (a == nil) if (a == nil)
return nil; goto notfound;
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0) if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
@ -522,6 +543,14 @@ find(DWDie *die, char* name)
a = b; a = b;
b = b->hlink; b = b->hlink;
} }
notfound:
die2 = walktypedef(die);
if(die2 != die) {
die = die2;
goto top;
}
return nil; return nil;
} }
@ -531,7 +560,7 @@ find_or_diag(DWDie *die, char* name)
DWDie *r; DWDie *r;
r = find(die, name); r = find(die, name);
if (r == nil) { 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(); errorexit();
} }
return r; return r;
@ -548,14 +577,33 @@ newrefattr(DWDie *die, uint8 attr, DWDie* ref)
static int fwdcount; static int fwdcount;
static void 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) { switch(form) {
case DW_FORM_addr: // address case DW_FORM_addr: // address
addrput(value); addrput(value);
break; break;
case DW_FORM_block1: // block 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; value &= 0xff;
cput(value); cput(value);
while(value--) while(value--)
@ -615,13 +663,23 @@ putattr(int form, int cls, vlong value, char *data)
break; break;
case DW_FORM_ref_addr: // reference to a DIE in the .info section 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) { if (data == nil) {
diag("dwarf: null reference"); diag("dwarf: null reference in %d", abbrev);
LPUT(0); // invalid dwarf, gdb will complain. if(PtrSize == 8)
VPUT(0); // invalid dwarf, gdb will complain.
else
LPUT(0); // invalid dwarf, gdb will complain.
} else { } else {
if (((DWDie*)data)->offs == 0) if (((DWDie*)data)->offs == 0)
fwdcount++; fwdcount++;
LPUT(((DWDie*)data)->offs); if(PtrSize == 8)
VPUT(((DWDie*)data)->offs);
else
LPUT(((DWDie*)data)->offs);
} }
break; break;
@ -654,12 +712,12 @@ putattrs(int abbrev, DWAttr* attr)
for(af = abbrevs[abbrev].attr; af->attr; af++) for(af = abbrevs[abbrev].attr; af->attr; af++)
if (attrs[af->attr]) if (attrs[af->attr])
putattr(af->form, putattr(abbrev, af->form,
attrs[af->attr]->cls, attrs[af->attr]->cls,
attrs[af->attr]->value, attrs[af->attr]->value,
attrs[af->attr]->data); attrs[af->attr]->data);
else else
putattr(af->form, 0, 0, 0); putattr(abbrev, af->form, 0, 0, 0);
} }
static void putdie(DWDie* die); 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 // GDB doesn't like DW_FORM_addr for DW_AT_location, so emit a
// location expression that evals to a const. // location expression that evals to a const.
static void static void
newabslocexprattr(DWDie *die, vlong addr) newabslocexprattr(DWDie *die, vlong addr, Sym *sym)
{ {
char block[10]; newattr(die, DW_AT_location, DW_CLS_ADDRESS, addr, (char*)sym);
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);
} }
@ -766,6 +817,31 @@ lookup_or_diag(char *n)
return s; 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. // Define gotype, for composite ones recurse into constituents.
static DWDie* static DWDie*
defgotype(Sym *gotype) defgotype(Sym *gotype)
@ -840,6 +916,7 @@ defgotype(Sym *gotype)
case KindArray: case KindArray:
die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name); die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0); newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype); s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s)); newrefattr(die, DW_AT_type, defgotype(s));
@ -857,6 +934,7 @@ defgotype(Sym *gotype)
case KindFunc: case KindFunc:
die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name); die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name);
dotypedef(&dwtypes, name, die);
newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "void")); newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "void"));
nfields = decodetype_funcincount(gotype); nfields = decodetype_funcincount(gotype);
for (i = 0; i < nfields; i++) { for (i = 0; i < nfields; i++) {
@ -876,6 +954,7 @@ defgotype(Sym *gotype)
case KindInterface: case KindInterface:
die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name); die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0); newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
nfields = decodetype_ifacemethodcount(gotype); nfields = decodetype_ifacemethodcount(gotype);
if (nfields == 0) if (nfields == 0)
@ -895,12 +974,14 @@ defgotype(Sym *gotype)
case KindPtr: case KindPtr:
die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name); die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name);
dotypedef(&dwtypes, name, die);
s = decodetype_ptrelem(gotype); s = decodetype_ptrelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s)); newrefattr(die, DW_AT_type, defgotype(s));
break; break;
case KindSlice: case KindSlice:
die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name); die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0); newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype); s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_internal_elem_type, defgotype(s)); newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
@ -913,6 +994,7 @@ defgotype(Sym *gotype)
case KindStruct: case KindStruct:
die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name); die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0); newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
nfields = decodetype_structfieldcount(gotype); nfields = decodetype_structfieldcount(gotype);
for (i = 0; i < nfields; i++) { for (i = 0; i < nfields; i++) {
@ -998,7 +1080,7 @@ synthesizestringtypes(DWDie* die)
{ {
DWDie *prototype; DWDie *prototype;
prototype = defgotype(lookup_or_diag("type.runtime._string")); prototype = walktypedef(defgotype(lookup_or_diag("type.runtime._string")));
if (prototype == nil) if (prototype == nil)
return; return;
@ -1014,7 +1096,7 @@ synthesizeslicetypes(DWDie *die)
{ {
DWDie *prototype, *elem; DWDie *prototype, *elem;
prototype = defgotype(lookup_or_diag("type.runtime.slice")); prototype = walktypedef(defgotype(lookup_or_diag("type.runtime.slice")));
if (prototype == nil) if (prototype == nil)
return; return;
@ -1082,9 +1164,9 @@ synthesizechantypes(DWDie *die)
DWAttr *a; DWAttr *a;
int elemsize, sudogsize; int elemsize, sudogsize;
sudog = defgotype(lookup_or_diag("type.runtime.sudog")); sudog = walktypedef(defgotype(lookup_or_diag("type.runtime.sudog")));
waitq = defgotype(lookup_or_diag("type.runtime.waitq")); waitq = walktypedef(defgotype(lookup_or_diag("type.runtime.waitq")));
hchan = defgotype(lookup_or_diag("type.runtime.hchan")); hchan = walktypedef(defgotype(lookup_or_diag("type.runtime.hchan")));
if (sudog == nil || waitq == nil || hchan == nil) if (sudog == nil || waitq == nil || hchan == nil)
return; return;
@ -1153,7 +1235,7 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype)
case 'D': case 'D':
case 'B': case 'B':
dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s); dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s);
newabslocexprattr(dv, v); newabslocexprattr(dv, v, sym);
if (ver == 0) if (ver == 0)
newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0); newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0);
// fallthrough // fallthrough
@ -1514,12 +1596,12 @@ mkvarname(char* name, int da)
// flush previous compilation unit. // flush previous compilation unit.
static void 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; vlong here;
if (dwinfo != nil && pc != 0) { 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) { if (unitstart >= 0) {
@ -1530,7 +1612,7 @@ flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
here = cpos(); here = cpos();
cseek(unitstart); cseek(unitstart);
LPUT(here - unitstart - sizeof(int32)); // unit_length LPUT(here - unitstart - sizeof(int32)); // unit_length
WPUT(3); // dwarf version WPUT(2); // dwarf version
LPUT(header_length); // header length starting here LPUT(header_length); // header length starting here
cseek(here); cseek(here);
} }
@ -1540,7 +1622,7 @@ static void
writelines(void) writelines(void)
{ {
Prog *q; Prog *q;
Sym *s; Sym *s, *epcs;
Auto *a; Auto *a;
vlong unitstart, headerend, offs; vlong unitstart, headerend, offs;
vlong pc, epc, lc, llc, lline; vlong pc, epc, lc, llc, lline;
@ -1555,6 +1637,7 @@ writelines(void)
headerend = -1; headerend = -1;
pc = 0; pc = 0;
epc = 0; epc = 0;
epcs = S;
lc = 1; lc = 1;
llc = 1; llc = 1;
currfile = -1; currfile = -1;
@ -1570,7 +1653,7 @@ writelines(void)
// we're entering a new compilation unit // we're entering a new compilation unit
if (inithist(s->autom)) { if (inithist(s->autom)) {
flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10); flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
unitstart = cpos(); unitstart = cpos();
if(debug['v'] > 1) { if(debug['v'] > 1) {
@ -1587,12 +1670,12 @@ writelines(void)
dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, estrdup(histfile[1])); dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, estrdup(histfile[1]));
newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT,lang, 0); 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_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) // Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf // Fields marked with (*) must be changed for 64-bit dwarf
LPUT(0); // unit_length (*), will be filled in by flushunit. 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. LPUT(0); // header_length (*), filled in by flushunit.
// cpos == unitstart + 4 + 2 + 4 // cpos == unitstart + 4 + 2 + 4
cput(1); // minimum_instruction_length cput(1); // minimum_instruction_length
@ -1616,6 +1699,7 @@ writelines(void)
pc = s->text->pc; pc = s->text->pc;
epc = pc; epc = pc;
epcs = s;
currfile = 1; currfile = 1;
lc = 1; lc = 1;
llc = 1; llc = 1;
@ -1634,9 +1718,9 @@ writelines(void)
} }
dwfunc = newdie(dwinfo, DW_ABRV_FUNCTION, s->name); 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; 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) if (s->version == 0)
newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0); newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0);
@ -1718,7 +1802,7 @@ writelines(void)
dwfunc->hash = nil; dwfunc->hash = nil;
} }
flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10); flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
linesize = cpos() - lineo; linesize = cpos() - lineo;
} }
@ -1842,6 +1926,9 @@ writeinfo(void)
vlong unitstart, here; vlong unitstart, here;
fwdcount = 0; fwdcount = 0;
if (dsym == S)
dsym = lookup(".dwarfinfo", 0);
dsym->nr = 0;
for (compunit = dwroot.child; compunit; compunit = compunit->link) { for (compunit = dwroot.child; compunit; compunit = compunit->link) {
unitstart = cpos(); unitstart = cpos();
@ -1850,7 +1937,7 @@ writeinfo(void)
// Fields marked with (*) must be changed for 64-bit dwarf // Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above. // This must match COMPUNITHEADERSIZE above.
LPUT(0); // unit_length (*), will be filled in later. 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 (*) LPUT(0); // debug_abbrev_offset (*)
cput(PtrSize); // address_size cput(PtrSize); // address_size
@ -1990,6 +2077,27 @@ align(vlong size)
strnput("", rnd(size, PEFILEALIGN) - 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 * This is the main entry point for generating dwarf. After emitting
* the mandatory debug_abbrev section, it calls writelines() to set up * the mandatory debug_abbrev section, it calls writelines() to set up
@ -2090,6 +2198,10 @@ dwarfemitdebugsections(void)
gdbscripto = writegdbscript(); gdbscripto = writegdbscript();
gdbscriptsize = cpos() - gdbscripto; gdbscriptsize = cpos() - gdbscripto;
align(gdbscriptsize); align(gdbscriptsize);
inforeloco = writeinforeloc();
inforelocsize = cpos() - inforeloco;
align(inforelocsize);
} }
/* /*
@ -2249,6 +2361,8 @@ dwarfaddmachoheaders(void)
msect = newMachoSect(ms, "__debug_info", "__DWARF"); msect = newMachoSect(ms, "__debug_info", "__DWARF");
msect->off = infoo; msect->off = infoo;
msect->size = infosize; msect->size = infosize;
msect->reloc = inforeloco;
msect->nreloc = inforelocsize / 8;
ms->filesize += msect->size; ms->filesize += msect->size;
if (pubnamessize > 0) { if (pubnamessize > 0) {