diff options
Diffstat (limited to 'src/cmd/ld/dwarf.c')
-rw-r--r-- | src/cmd/ld/dwarf.c | 156 |
1 files changed, 91 insertions, 65 deletions
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c index cc77b45cd..a3ba52325 100644 --- a/src/cmd/ld/dwarf.c +++ b/src/cmd/ld/dwarf.c @@ -19,7 +19,7 @@ #include "../ld/elf.h" #include "../ld/macho.h" #include "../ld/pe.h" -#include "../../pkg/runtime/typekind.h" +#include "../../runtime/typekind.h" /* * Offsets and sizes of the debug_* sections in the cout file. @@ -141,16 +141,22 @@ sleb128put(vlong v) * only a handful of them. The DWARF spec places no restriction on * the ordering of attributes 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. 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 { - uint8 attr; + uint16 attr; uint8 form; }; +// Go-specific type attributes. +enum { + DW_AT_go_kind = 0x2900, + DW_AT_go_key = 0x2901, + DW_AT_go_elem = 0x2902, + + DW_AT_internal_location = 253, // params and locals; not emitted +}; + // Index into the abbrevs table below. // Keep in sync with ispubname() and ispubtype() below. // ispubtype considers >= NULLTYPE public @@ -260,7 +266,7 @@ static struct DWAbbrev { DW_TAG_subrange_type, DW_CHILDREN_no, // No name! DW_AT_type, DW_FORM_ref_addr, - DW_AT_upper_bound, DW_FORM_data1, + DW_AT_count, DW_FORM_udata, 0, 0 }, @@ -277,6 +283,7 @@ static struct DWAbbrev { DW_AT_name, DW_FORM_string, DW_AT_encoding, DW_FORM_data1, DW_AT_byte_size, DW_FORM_data1, + DW_AT_go_kind, DW_FORM_data1, 0, 0 }, /* ARRAYTYPE */ @@ -286,6 +293,7 @@ static struct DWAbbrev { DW_AT_name, DW_FORM_string, DW_AT_type, DW_FORM_ref_addr, DW_AT_byte_size, DW_FORM_udata, + DW_AT_go_kind, DW_FORM_data1, 0, 0 }, @@ -294,6 +302,8 @@ static struct DWAbbrev { DW_TAG_typedef, DW_CHILDREN_no, DW_AT_name, DW_FORM_string, DW_AT_type, DW_FORM_ref_addr, + DW_AT_go_kind, DW_FORM_data1, + DW_AT_go_elem, DW_FORM_ref_addr, 0, 0 }, @@ -302,6 +312,7 @@ static struct DWAbbrev { DW_TAG_subroutine_type, DW_CHILDREN_yes, DW_AT_name, DW_FORM_string, // DW_AT_type, DW_FORM_ref_addr, + DW_AT_go_kind, DW_FORM_data1, 0, 0 }, @@ -310,6 +321,7 @@ static struct DWAbbrev { DW_TAG_typedef, DW_CHILDREN_yes, DW_AT_name, DW_FORM_string, DW_AT_type, DW_FORM_ref_addr, + DW_AT_go_kind, DW_FORM_data1, 0, 0 }, @@ -318,6 +330,9 @@ static struct DWAbbrev { DW_TAG_typedef, DW_CHILDREN_no, DW_AT_name, DW_FORM_string, DW_AT_type, DW_FORM_ref_addr, + DW_AT_go_kind, DW_FORM_data1, + DW_AT_go_key, DW_FORM_ref_addr, + DW_AT_go_elem, DW_FORM_ref_addr, 0, 0 }, @@ -326,6 +341,7 @@ static struct DWAbbrev { DW_TAG_pointer_type, DW_CHILDREN_no, DW_AT_name, DW_FORM_string, DW_AT_type, DW_FORM_ref_addr, + DW_AT_go_kind, DW_FORM_data1, 0, 0 }, /* BARE_PTRTYPE */ @@ -340,6 +356,8 @@ static struct DWAbbrev { DW_TAG_structure_type, DW_CHILDREN_yes, DW_AT_name, DW_FORM_string, DW_AT_byte_size, DW_FORM_udata, + DW_AT_go_kind, DW_FORM_data1, + DW_AT_go_elem, DW_FORM_ref_addr, 0, 0 }, @@ -348,6 +366,7 @@ static struct DWAbbrev { DW_TAG_structure_type, DW_CHILDREN_yes, DW_AT_name, DW_FORM_string, DW_AT_byte_size, DW_FORM_udata, + DW_AT_go_kind, DW_FORM_data1, 0, 0 }, @@ -356,6 +375,7 @@ static struct DWAbbrev { DW_TAG_structure_type, DW_CHILDREN_yes, DW_AT_name, DW_FORM_string, DW_AT_byte_size, DW_FORM_udata, + DW_AT_go_kind, DW_FORM_data1, 0, 0 }, @@ -371,7 +391,8 @@ static struct DWAbbrev { static void writeabbrev(void) { - int i, n; + int i, j; + DWAttrForm *f; abbrevo = cpos(); for (i = 1; i < DW_NABRV; i++) { @@ -379,11 +400,13 @@ writeabbrev(void) uleb128put(i); uleb128put(abbrevs[i].tag); cput(abbrevs[i].children); - // 0 is not a valid attr or form, and DWAbbrev.attr is - // 0-terminated, so we can treat it as a string - n = strlen((char*)abbrevs[i].attr) / 2; - strnput((char*)abbrevs[i].attr, - (n+1) * sizeof(DWAttrForm)); + for(j=0; j<nelem(abbrevs[i].attr); j++) { + f = &abbrevs[i].attr[j]; + uleb128put(f->attr); + uleb128put(f->form); + if(f->attr == 0) + break; + } } cput(0); abbrevsize = cpos() - abbrevo; @@ -417,7 +440,7 @@ hashstr(char* s) typedef struct DWAttr DWAttr; struct DWAttr { DWAttr *link; - uint8 atr; // DW_AT_ + uint16 atr; // DW_AT_ uint8 cls; // DW_CLS_ vlong value; char *data; @@ -445,7 +468,7 @@ static DWDie dwtypes; static DWDie dwglobals; static DWAttr* -newattr(DWDie *die, uint8 attr, int cls, vlong value, char *data) +newattr(DWDie *die, uint16 attr, int cls, vlong value, char *data) { DWAttr *a; @@ -463,7 +486,7 @@ newattr(DWDie *die, uint8 attr, int cls, vlong value, char *data) // name. getattr moves the desired one to the front so // frequently searched ones are found faster. static DWAttr* -getattr(DWDie *die, uint8 attr) +getattr(DWDie *die, uint16 attr) { DWAttr *a, *b; @@ -622,7 +645,7 @@ adddwarfrel(LSym* sec, LSym* sym, vlong offsetbase, int siz, vlong addend) } static DWAttr* -newrefattr(DWDie *die, uint8 attr, DWDie* ref) +newrefattr(DWDie *die, uint16 attr, DWDie* ref) { if (ref == nil) return nil; @@ -762,22 +785,22 @@ putattr(int abbrev, int form, int cls, vlong value, char *data) static void putattrs(int abbrev, DWAttr* attr) { - DWAttr *attrs[DW_AT_recursive + 1]; DWAttrForm* af; - - 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]) - putattr(abbrev, af->form, - attrs[af->attr]->cls, - attrs[af->attr]->value, - attrs[af->attr]->data); - else - putattr(abbrev, af->form, 0, 0, nil); + DWAttr *ap; + + for(af = abbrevs[abbrev].attr; af->attr; af++) { + for(ap=attr; ap; ap=ap->link) { + if(ap->atr == af->attr) { + putattr(abbrev, af->form, + ap->cls, + ap->value, + ap->data); + goto done; + } + } + putattr(abbrev, af->form, 0, 0, nil); + done:; + } } static void putdie(DWDie* die); @@ -835,11 +858,8 @@ newmemberoffsetattr(DWDie *die, int32 offs) int i; i = 0; - if (offs != 0) { - block[i++] = DW_OP_consts; - i += sleb128enc(offs, block+i); - block[i++] = DW_OP_plus; - } + block[i++] = DW_OP_plus_uconst; + i += uleb128enc(offs, block+i); newattr(die, DW_AT_data_member_location, DW_CLS_BLOCK, i, mal(i)); memmove(die->attr->data, block, i); } @@ -852,15 +872,6 @@ newabslocexprattr(DWDie *die, vlong addr, LSym *sym) newattr(die, DW_AT_location, DW_CLS_ADDRESS, addr, (char*)sym); } - -// 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 -}; - static DWDie* defptrto(DWDie *dwtype); // below // Lookup predefined types @@ -981,7 +992,8 @@ defgotype(LSym *gotype) 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); + // use actual length not upper bound; correct for 0-length arrays. + newattr(fld, DW_AT_count, DW_CLS_CONSTANT, decodetype_arraylen(gotype), 0); newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr")); break; @@ -989,7 +1001,7 @@ defgotype(LSym *gotype) die = newdie(&dwtypes, DW_ABRV_CHANTYPE, name); newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0); s = decodetype_chanelem(gotype); - newrefattr(die, DW_AT_internal_elem_type, defgotype(s)); + newrefattr(die, DW_AT_go_elem, defgotype(s)); break; case KindFunc: @@ -1027,9 +1039,9 @@ defgotype(LSym *gotype) case KindMap: die = newdie(&dwtypes, DW_ABRV_MAPTYPE, name); s = decodetype_mapkey(gotype); - newrefattr(die, DW_AT_internal_key_type, defgotype(s)); + newrefattr(die, DW_AT_go_key, defgotype(s)); s = decodetype_mapvalue(gotype); - newrefattr(die, DW_AT_internal_val_type, defgotype(s)); + newrefattr(die, DW_AT_go_elem, defgotype(s)); break; case KindPtr: @@ -1044,7 +1056,7 @@ defgotype(LSym *gotype) 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)); + newrefattr(die, DW_AT_go_elem, defgotype(s)); break; case KindString: @@ -1076,7 +1088,9 @@ defgotype(LSym *gotype) diag("dwarf: definition of unknown kind %d: %s", kind, gotype->name); die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name); newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "<unspecified>")); - } + } + + newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, kind, 0); return die; } @@ -1171,7 +1185,7 @@ synthesizeslicetypes(DWDie *die) if (die->abbrev != DW_ABRV_SLICETYPE) continue; copychildren(die, prototype); - elem = (DWDie*) getattr(die, DW_AT_internal_elem_type)->data; + elem = (DWDie*) getattr(die, DW_AT_go_elem)->data; substitutetype(die, "array", defptrto(elem)); } } @@ -1208,7 +1222,7 @@ synthesizemaptypes(DWDie *die) DWAttr *a; hash = walktypedef(defgotype(lookup_or_diag("type.runtime.hmap"))); - bucket = walktypedef(defgotype(lookup_or_diag("type.runtime.bucket"))); + bucket = walktypedef(defgotype(lookup_or_diag("type.runtime.bmap"))); if (hash == nil) return; @@ -1217,8 +1231,8 @@ synthesizemaptypes(DWDie *die) if (die->abbrev != DW_ABRV_MAPTYPE) continue; - keytype = walktypedef((DWDie*) getattr(die, DW_AT_internal_key_type)->data); - valtype = walktypedef((DWDie*) getattr(die, DW_AT_internal_val_type)->data); + keytype = walktypedef((DWDie*) getattr(die, DW_AT_go_key)->data); + valtype = walktypedef((DWDie*) getattr(die, DW_AT_go_elem)->data); // compute size info like hashmap.c does. a = getattr(keytype, DW_AT_byte_size); @@ -1243,7 +1257,7 @@ synthesizemaptypes(DWDie *die) newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize * keysize, 0); newrefattr(dwhk, DW_AT_type, indirect_key ? defptrto(keytype) : keytype); fld = newdie(dwhk, DW_ABRV_ARRAYRANGE, "size"); - newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, BucketSize, 0); + newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0); newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr")); // Construct type to represent an array of BucketSize values @@ -1253,7 +1267,7 @@ synthesizemaptypes(DWDie *die) newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize * valsize, 0); newrefattr(dwhv, DW_AT_type, indirect_val ? defptrto(valtype) : valtype); fld = newdie(dwhv, DW_ABRV_ARRAYRANGE, "size"); - newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, BucketSize, 0); + newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0); newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr")); // Construct bucket<K,V> @@ -1309,7 +1323,7 @@ synthesizechantypes(DWDie *die) for (; die != nil; die = die->link) { if (die->abbrev != DW_ABRV_CHANTYPE) continue; - elemtype = (DWDie*) getattr(die, DW_AT_internal_elem_type)->data; + elemtype = (DWDie*) getattr(die, DW_AT_go_elem)->data; a = getattr(elemtype, DW_AT_byte_size); elemsize = a ? a->value : PtrSize; @@ -1696,6 +1710,9 @@ enum static void putpccfadelta(vlong deltapc, vlong cfa) { + cput(DW_CFA_def_cfa_offset_sf); + sleb128put(cfa / DATAALIGNMENTFACTOR); + if (deltapc < 0x40) { cput(DW_CFA_advance_loc + deltapc); } else if (deltapc < 0x100) { @@ -1708,9 +1725,6 @@ putpccfadelta(vlong deltapc, vlong cfa) cput(DW_CFA_advance_loc4); LPUT(deltapc); } - - cput(DW_CFA_def_cfa_offset_sf); - sleb128put(cfa / DATAALIGNMENTFACTOR); } static void @@ -1719,6 +1733,7 @@ writeframes(void) LSym *s; vlong fdeo, fdesize, pad; Pciter pcsp; + uint32 nextpc; if(framesec == S) framesec = linklookup(ctxt, ".dwarfframe", 0); @@ -1761,8 +1776,17 @@ writeframes(void) addrput(0); // initial location addrput(0); // address range - for(pciterinit(ctxt, &pcsp, &s->pcln->pcsp); !pcsp.done; pciternext(&pcsp)) - putpccfadelta(pcsp.nextpc - pcsp.pc, PtrSize + pcsp.value); + for(pciterinit(ctxt, &pcsp, &s->pcln->pcsp); !pcsp.done; pciternext(&pcsp)) { + nextpc = pcsp.nextpc; + // pciterinit goes up to the end of the function, + // but DWARF expects us to stop just before the end. + if(nextpc == s->size) { + nextpc--; + if(nextpc < pcsp.pc) + continue; + } + putpccfadelta(nextpc - pcsp.pc, PtrSize + pcsp.value); + } fdesize = cpos() - fdeo - 4; // exclude the length field. pad = rnd(fdesize, PtrSize) - fdesize; @@ -2028,13 +2052,15 @@ dwarfemitdebugsections(void) newdie(&dwtypes, DW_ABRV_NULLTYPE, "<unspecified>"); newdie(&dwtypes, DW_ABRV_NULLTYPE, "void"); newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer"); + 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); + newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, KindUintptr, 0); // Needed by the prettyprinter code for interface inspection. - defgotype(lookup_or_diag("type.runtime.rtype")); - defgotype(lookup_or_diag("type.runtime.interfaceType")); + defgotype(lookup_or_diag("type.runtime._type")); + defgotype(lookup_or_diag("type.runtime.interfacetype")); defgotype(lookup_or_diag("type.runtime.itab")); genasmsym(defdwsymb); |