Commit f08baa38 authored by Luuk van Dijk's avatar Luuk van Dijk

[68]l: correct dwarf location for globals and ranges for arrays.

R=rsc
CC=golang-dev
https://golang.org/cl/3306042
parent 93f97ca2
...@@ -112,7 +112,8 @@ sleb128put(vlong v) ...@@ -112,7 +112,8 @@ sleb128put(vlong v)
* the ordering of atributes in the Abbrevs and DIEs, and we will * the ordering of atributes in the Abbrevs and DIEs, and we will
* always write them out in the order of declaration in the abbrev. * always write them out in the order of declaration in the abbrev.
* This implementation relies on tag, attr < 127, so they serialize as * This implementation relies on tag, attr < 127, so they serialize as
* a char, hence we do not support user-defined tags or attributes. * a char. Higher numbered user-defined tags or attributes can be used
* for storing internal data but won't be serialized.
*/ */
typedef struct DWAttrForm DWAttrForm; typedef struct DWAttrForm DWAttrForm;
struct DWAttrForm { struct DWAttrForm {
...@@ -122,6 +123,7 @@ struct DWAttrForm { ...@@ -122,6 +123,7 @@ struct DWAttrForm {
// Index into the abbrevs table below. // Index into the abbrevs table below.
// Keep in sync with ispubname() and ispubtype() below. // Keep in sync with ispubname() and ispubtype() below.
// ispubtype considers >= NULLTYPE public
enum enum
{ {
DW_ABRV_NULL, DW_ABRV_NULL,
...@@ -131,6 +133,7 @@ enum ...@@ -131,6 +133,7 @@ enum
DW_ABRV_AUTO, DW_ABRV_AUTO,
DW_ABRV_PARAM, DW_ABRV_PARAM,
DW_ABRV_STRUCTFIELD, DW_ABRV_STRUCTFIELD,
DW_ABRV_ARRAYRANGE,
DW_ABRV_NULLTYPE, DW_ABRV_NULLTYPE,
DW_ABRV_BASETYPE, DW_ABRV_BASETYPE,
DW_ABRV_ARRAYTYPE, DW_ABRV_ARRAYTYPE,
...@@ -177,7 +180,7 @@ static struct DWAbbrev { ...@@ -177,7 +180,7 @@ static struct DWAbbrev {
{ {
DW_TAG_variable, DW_CHILDREN_no, DW_TAG_variable, DW_CHILDREN_no,
DW_AT_name, DW_FORM_string, DW_AT_name, DW_FORM_string,
DW_AT_location, DW_FORM_addr, DW_AT_location, DW_FORM_block1,
DW_AT_type, DW_FORM_ref_addr, DW_AT_type, DW_FORM_ref_addr,
DW_AT_external, DW_FORM_flag, DW_AT_external, DW_FORM_flag,
0, 0 0, 0
...@@ -206,7 +209,16 @@ static struct DWAbbrev { ...@@ -206,7 +209,16 @@ static struct DWAbbrev {
DW_AT_type, DW_FORM_ref_addr, DW_AT_type, DW_FORM_ref_addr,
0, 0 0, 0
}, },
/* ARRAYRANGE */
{
DW_TAG_subrange_type, DW_CHILDREN_no,
// No name!
DW_AT_type, DW_FORM_ref_addr,
DW_AT_upper_bound, DW_FORM_data1,
0, 0
},
// Below here are the types considered public by ispubtype
/* NULLTYPE */ /* NULLTYPE */
{ {
DW_TAG_unspecified_type, DW_CHILDREN_no, DW_TAG_unspecified_type, DW_CHILDREN_no,
...@@ -222,8 +234,9 @@ static struct DWAbbrev { ...@@ -222,8 +234,9 @@ static struct DWAbbrev {
0, 0 0, 0
}, },
/* ARRAYTYPE */ /* ARRAYTYPE */
// child is subrange with upper bound
{ {
DW_TAG_array_type, DW_CHILDREN_no, DW_TAG_array_type, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string, DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr, DW_AT_type, DW_FORM_ref_addr,
DW_AT_byte_size, DW_FORM_udata, DW_AT_byte_size, DW_FORM_udata,
...@@ -449,6 +462,8 @@ mkindex(DWDie *die) ...@@ -449,6 +462,8 @@ mkindex(DWDie *die)
die->hash = mal(HASHSIZE * sizeof(DWDie*)); die->hash = mal(HASHSIZE * sizeof(DWDie*));
} }
// Find child by AT_name using hashtable if available or linear scan
// if not.
static DWDie* static DWDie*
find(DWDie *die, char* name) find(DWDie *die, char* name)
{ {
...@@ -456,8 +471,10 @@ find(DWDie *die, char* name) ...@@ -456,8 +471,10 @@ find(DWDie *die, char* name)
int h; int h;
if (die->hash == nil) { if (die->hash == nil) {
diag("lookup of %s in non-indexed DIE", name); for (a = die->child; a != nil; a = a->link)
errorexit(); if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
return a;
return nil;
} }
h = hashstr(name); h = hashstr(name);
...@@ -466,7 +483,6 @@ find(DWDie *die, char* name) ...@@ -466,7 +483,6 @@ find(DWDie *die, char* name)
if (a == nil) if (a == nil)
return nil; return nil;
// AT_name always exists.
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0) if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
return a; return a;
...@@ -485,6 +501,17 @@ find(DWDie *die, char* name) ...@@ -485,6 +501,17 @@ find(DWDie *die, char* name)
return nil; return nil;
} }
static DWDie*
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);
return r;
}
static DWAttr* static DWAttr*
newrefattr(DWDie *die, uint8 attr, DWDie* ref) newrefattr(DWDie *die, uint8 attr, DWDie* ref)
{ {
...@@ -587,6 +614,8 @@ putattr(int form, int cls, vlong value, char *data) ...@@ -587,6 +614,8 @@ putattr(int form, int cls, vlong value, char *data)
} }
} }
// Note that we can (and do) add arbitrary attributes to a DIE, but
// only the ones actually listed in the Abbrev will be written out.
static void static void
putattrs(int abbrev, DWAttr* attr) putattrs(int abbrev, DWAttr* attr)
{ {
...@@ -595,6 +624,7 @@ putattrs(int abbrev, DWAttr* attr) ...@@ -595,6 +624,7 @@ putattrs(int abbrev, DWAttr* attr)
memset(attrs, 0, sizeof attrs); memset(attrs, 0, sizeof attrs);
for( ; attr; attr = attr->link) for( ; attr; attr = attr->link)
if (attr->atr < nelem(attrs))
attrs[attr->atr] = attr; attrs[attr->atr] = 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])
...@@ -630,7 +660,7 @@ putdie(DWDie* die) ...@@ -630,7 +660,7 @@ putdie(DWDie* die)
static void static void
reverselist(DWDie** list) reverselist(DWDie** list)
{ {
DWDie *curr, * prev; DWDie *curr, *prev;
curr = *list; curr = *list;
prev = nil; prev = nil;
...@@ -670,6 +700,19 @@ newmemberoffsetattr(DWDie *die, int32 offs) ...@@ -670,6 +700,19 @@ newmemberoffsetattr(DWDie *die, int32 offs)
memmove(die->attr->data, block, i); memmove(die->attr->data, block, i);
} }
static void
newabslocexprattr(DWDie *die, vlong addr)
{
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);
}
// Decoding the type.* symbols. This has to be in sync with // Decoding the type.* symbols. This has to be in sync with
// ../../pkg/runtime/type.go, or more specificaly, with what // ../../pkg/runtime/type.go, or more specificaly, with what
// ../gc/reflect.c stuffs in these. // ../gc/reflect.c stuffs in these.
...@@ -768,6 +811,12 @@ decodetype_arrayelem(Sym *s) ...@@ -768,6 +811,12 @@ decodetype_arrayelem(Sym *s)
return decode_reloc(s, 5*PtrSize + 8); // 0x1c / 0x30 return decode_reloc(s, 5*PtrSize + 8); // 0x1c / 0x30
} }
static vlong
decodetype_arraylen(Sym *s)
{
return decode_inuxi(s->p + 6*PtrSize + 8, PtrSize);
}
// Type.PtrType.elem // Type.PtrType.elem
static Sym* static Sym*
decodetype_ptrelem(Sym *s) decodetype_ptrelem(Sym *s)
...@@ -808,6 +857,14 @@ decodetype_structfieldoffs(Sym *s, int i) ...@@ -808,6 +857,14 @@ decodetype_structfieldoffs(Sym *s, int i)
return decode_inuxi(s->p + 10*PtrSize + 0x10 + i*5*PtrSize, 4); // 0x38 / 0x60 return decode_inuxi(s->p + 10*PtrSize + 0x10 + i*5*PtrSize, 4); // 0x38 / 0x60
} }
// Fake attributes for slices, maps and channel
enum {
DW_AT_internal_elem_type = 250, // channels and slices
DW_AT_internal_key_type = 251, // maps
DW_AT_internal_val_type = 252, // maps
DW_AT_internal_location = 253, // params and locals
};
// 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)
...@@ -820,11 +877,11 @@ defgotype(Sym *gotype) ...@@ -820,11 +877,11 @@ defgotype(Sym *gotype)
int i, nfields; int i, nfields;
if (gotype == nil) if (gotype == nil)
return find(&dwtypes, "<unspecified>"); // must be defined before return find_or_diag(&dwtypes, "<unspecified>");
if (strncmp("type.", gotype->name, 5) != 0) { if (strncmp("type.", gotype->name, 5) != 0) {
diag("Type name doesn't start with \".type\": %s", gotype->name); diag("Type name doesn't start with \".type\": %s", gotype->name);
return find(&dwtypes, "<unspecified>"); return find_or_diag(&dwtypes, "<unspecified>");
} }
name = gotype->name + 5; // Altenatively decode from Type.string name = gotype->name + 5; // Altenatively decode from Type.string
...@@ -901,6 +958,10 @@ defgotype(Sym *gotype) ...@@ -901,6 +958,10 @@ defgotype(Sym *gotype)
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));
fld = newdie(die, DW_ABRV_ARRAYRANGE, "range");
newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, decodetype_arraylen(gotype), 0);
newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
break; break;
case KindChan: case KindChan:
...@@ -1014,7 +1075,7 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype) ...@@ -1014,7 +1075,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);
newattr(dv, DW_AT_location, DW_CLS_ADDRESS, v, 0); newabslocexprattr(dv, v);
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
...@@ -1379,7 +1440,7 @@ writelines(void) ...@@ -1379,7 +1440,7 @@ writelines(void)
int currfile; int currfile;
int i, lang, da, dt; int i, lang, da, dt;
Linehist *lh; Linehist *lh;
DWDie *dwinfo, *dwfunc, *dwvar; DWDie *dwinfo, *dwfunc, *dwvar, **dws;
DWDie *varhash[HASHSIZE]; DWDie *varhash[HASHSIZE];
char *n; char *n;
...@@ -1521,6 +1582,16 @@ writelines(void) ...@@ -1521,6 +1582,16 @@ writelines(void)
dwvar = newdie(dwfunc, dt, n); dwvar = newdie(dwfunc, dt, n);
newcfaoffsetattr(dwvar, a->aoffset); newcfaoffsetattr(dwvar, a->aoffset);
newrefattr(dwvar, DW_AT_type, defgotype(a->gotype)); newrefattr(dwvar, DW_AT_type, defgotype(a->gotype));
// push dwvar down dwfunc->child to keep order
newattr(dwvar, DW_AT_internal_location, DW_CLS_CONSTANT, a->aoffset, NULL);
dwfunc->child = dwvar->link; // take dwvar out from the top of the list
for (dws = &dwfunc->child; *dws != nil; dws = &(*dws)->link)
if (a->aoffset > getattr(*dws, DW_AT_internal_location)->value)
break;
dwvar->link = *dws;
*dws = dwvar;
da++; da++;
} }
...@@ -1795,7 +1866,7 @@ void ...@@ -1795,7 +1866,7 @@ void
dwarfemitdebugsections(void) dwarfemitdebugsections(void)
{ {
vlong infoe; vlong infoe;
DWDie* die; DWDie *die;
mkindex(&dwroot); mkindex(&dwroot);
mkindex(&dwtypes); mkindex(&dwtypes);
...@@ -1806,6 +1877,9 @@ dwarfemitdebugsections(void) ...@@ -1806,6 +1877,9 @@ dwarfemitdebugsections(void)
newdie(&dwtypes, DW_ABRV_NULLTYPE, "void"); newdie(&dwtypes, DW_ABRV_NULLTYPE, "void");
die = newdie(&dwtypes, DW_ABRV_PTRTYPE, "unsafe.Pointer"); die = newdie(&dwtypes, DW_ABRV_PTRTYPE, "unsafe.Pointer");
newrefattr(die, DW_AT_type, find(&dwtypes, "void")); newrefattr(die, DW_AT_type, find(&dwtypes, "void"));
die = newdie(&dwtypes, DW_ABRV_BASETYPE, "uintptr"); // needed for array size
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, PtrSize, 0);
die = newdie(&dwtypes, DW_ABRV_BASETYPE, "<int32>"); die = newdie(&dwtypes, DW_ABRV_BASETYPE, "<int32>");
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_signed, 0); newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_signed, 0);
...@@ -1833,7 +1907,7 @@ dwarfemitdebugsections(void) ...@@ -1833,7 +1907,7 @@ dwarfemitdebugsections(void)
infoo = cpos(); infoo = cpos();
writeinfo(); writeinfo();
infoe = cpos(); arangeso = pubtypeso = pubnameso = infoe = cpos();
if (fwdcount > 0) { if (fwdcount > 0) {
if (debug['v']) if (debug['v'])
...@@ -1961,12 +2035,18 @@ dwarfaddmachoheaders(void) ...@@ -1961,12 +2035,18 @@ dwarfaddmachoheaders(void)
MachoSeg *ms; MachoSeg *ms;
vlong fakestart; vlong fakestart;
int nsect;
// Zero vsize segments won't be loaded in memory, even so they // Zero vsize segments won't be loaded in memory, even so they
// have to be page aligned in the file. // have to be page aligned in the file.
fakestart = abbrevo & ~0xfff; fakestart = abbrevo & ~0xfff;
ms = newMachoSeg("__DWARF", 7); nsect = 4;
if (pubnamessize > 0) nsect++;
if (pubtypessize > 0) nsect++;
if (arangessize > 0) nsect++;
ms = newMachoSeg("__DWARF", nsect);
ms->fileoffset = fakestart; ms->fileoffset = fakestart;
ms->filesize = abbrevo-fakestart; ms->filesize = abbrevo-fakestart;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment