mirror of
https://github.com/golang/go
synced 2024-11-22 03:34:40 -07:00
[68]l: correct dwarf location for globals and ranges for arrays.
R=rsc CC=golang-dev https://golang.org/cl/3306042
This commit is contained in:
parent
93f97ca235
commit
f08baa38f8
@ -112,7 +112,8 @@ sleb128put(vlong v)
|
||||
* the ordering of atributes in the Abbrevs and DIEs, and we will
|
||||
* always write them out in the order of declaration in the abbrev.
|
||||
* 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;
|
||||
struct DWAttrForm {
|
||||
@ -122,6 +123,7 @@ struct DWAttrForm {
|
||||
|
||||
// Index into the abbrevs table below.
|
||||
// Keep in sync with ispubname() and ispubtype() below.
|
||||
// ispubtype considers >= NULLTYPE public
|
||||
enum
|
||||
{
|
||||
DW_ABRV_NULL,
|
||||
@ -131,6 +133,7 @@ enum
|
||||
DW_ABRV_AUTO,
|
||||
DW_ABRV_PARAM,
|
||||
DW_ABRV_STRUCTFIELD,
|
||||
DW_ABRV_ARRAYRANGE,
|
||||
DW_ABRV_NULLTYPE,
|
||||
DW_ABRV_BASETYPE,
|
||||
DW_ABRV_ARRAYTYPE,
|
||||
@ -177,7 +180,7 @@ static struct DWAbbrev {
|
||||
{
|
||||
DW_TAG_variable, DW_CHILDREN_no,
|
||||
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_external, DW_FORM_flag,
|
||||
0, 0
|
||||
@ -206,7 +209,16 @@ static struct DWAbbrev {
|
||||
DW_AT_type, DW_FORM_ref_addr,
|
||||
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 */
|
||||
{
|
||||
DW_TAG_unspecified_type, DW_CHILDREN_no,
|
||||
@ -222,8 +234,9 @@ static struct DWAbbrev {
|
||||
0, 0
|
||||
},
|
||||
/* 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_type, DW_FORM_ref_addr,
|
||||
DW_AT_byte_size, DW_FORM_udata,
|
||||
@ -449,6 +462,8 @@ mkindex(DWDie *die)
|
||||
die->hash = mal(HASHSIZE * sizeof(DWDie*));
|
||||
}
|
||||
|
||||
// Find child by AT_name using hashtable if available or linear scan
|
||||
// if not.
|
||||
static DWDie*
|
||||
find(DWDie *die, char* name)
|
||||
{
|
||||
@ -456,8 +471,10 @@ find(DWDie *die, char* name)
|
||||
int h;
|
||||
|
||||
if (die->hash == nil) {
|
||||
diag("lookup of %s in non-indexed DIE", name);
|
||||
errorexit();
|
||||
for (a = die->child; a != nil; a = a->link)
|
||||
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
|
||||
return a;
|
||||
return nil;
|
||||
}
|
||||
|
||||
h = hashstr(name);
|
||||
@ -466,7 +483,6 @@ find(DWDie *die, char* name)
|
||||
if (a == nil)
|
||||
return nil;
|
||||
|
||||
// AT_name always exists.
|
||||
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
|
||||
return a;
|
||||
|
||||
@ -485,6 +501,17 @@ find(DWDie *die, char* name)
|
||||
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*
|
||||
newrefattr(DWDie *die, uint8 attr, DWDie* ref)
|
||||
{
|
||||
@ -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
|
||||
putattrs(int abbrev, DWAttr* attr)
|
||||
{
|
||||
@ -595,6 +624,7 @@ putattrs(int abbrev, DWAttr* attr)
|
||||
|
||||
memset(attrs, 0, sizeof attrs);
|
||||
for( ; attr; attr = attr->link)
|
||||
if (attr->atr < nelem(attrs))
|
||||
attrs[attr->atr] = attr;
|
||||
for(af = abbrevs[abbrev].attr; af->attr; af++)
|
||||
if (attrs[af->attr])
|
||||
@ -670,6 +700,19 @@ newmemberoffsetattr(DWDie *die, int32 offs)
|
||||
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
|
||||
// ../../pkg/runtime/type.go, or more specificaly, with what
|
||||
// ../gc/reflect.c stuffs in these.
|
||||
@ -768,6 +811,12 @@ decodetype_arrayelem(Sym *s)
|
||||
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
|
||||
static Sym*
|
||||
decodetype_ptrelem(Sym *s)
|
||||
@ -808,6 +857,14 @@ decodetype_structfieldoffs(Sym *s, int i)
|
||||
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.
|
||||
static DWDie*
|
||||
defgotype(Sym *gotype)
|
||||
@ -820,11 +877,11 @@ defgotype(Sym *gotype)
|
||||
int i, nfields;
|
||||
|
||||
if (gotype == nil)
|
||||
return find(&dwtypes, "<unspecified>"); // must be defined before
|
||||
return find_or_diag(&dwtypes, "<unspecified>");
|
||||
|
||||
if (strncmp("type.", gotype->name, 5) != 0) {
|
||||
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
|
||||
|
||||
@ -901,6 +958,10 @@ defgotype(Sym *gotype)
|
||||
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
|
||||
s = decodetype_arrayelem(gotype);
|
||||
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;
|
||||
|
||||
case KindChan:
|
||||
@ -1014,7 +1075,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);
|
||||
newattr(dv, DW_AT_location, DW_CLS_ADDRESS, v, 0);
|
||||
newabslocexprattr(dv, v);
|
||||
if (ver == 0)
|
||||
newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0);
|
||||
// fallthrough
|
||||
@ -1379,7 +1440,7 @@ writelines(void)
|
||||
int currfile;
|
||||
int i, lang, da, dt;
|
||||
Linehist *lh;
|
||||
DWDie *dwinfo, *dwfunc, *dwvar;
|
||||
DWDie *dwinfo, *dwfunc, *dwvar, **dws;
|
||||
DWDie *varhash[HASHSIZE];
|
||||
char *n;
|
||||
|
||||
@ -1521,6 +1582,16 @@ writelines(void)
|
||||
dwvar = newdie(dwfunc, dt, n);
|
||||
newcfaoffsetattr(dwvar, a->aoffset);
|
||||
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++;
|
||||
}
|
||||
|
||||
@ -1806,6 +1877,9 @@ dwarfemitdebugsections(void)
|
||||
newdie(&dwtypes, DW_ABRV_NULLTYPE, "void");
|
||||
die = newdie(&dwtypes, DW_ABRV_PTRTYPE, "unsafe.Pointer");
|
||||
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>");
|
||||
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_signed, 0);
|
||||
@ -1833,7 +1907,7 @@ dwarfemitdebugsections(void)
|
||||
|
||||
infoo = cpos();
|
||||
writeinfo();
|
||||
infoe = cpos();
|
||||
arangeso = pubtypeso = pubnameso = infoe = cpos();
|
||||
|
||||
if (fwdcount > 0) {
|
||||
if (debug['v'])
|
||||
@ -1961,12 +2035,18 @@ dwarfaddmachoheaders(void)
|
||||
MachoSeg *ms;
|
||||
|
||||
vlong fakestart;
|
||||
int nsect;
|
||||
|
||||
// Zero vsize segments won't be loaded in memory, even so they
|
||||
// have to be page aligned in the file.
|
||||
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->filesize = abbrevo-fakestart;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user