summaryrefslogtreecommitdiff
path: root/src/cmd/ld/dwarf.c
diff options
context:
space:
mode:
authorTianon Gravi <admwiggin@gmail.com>2015-01-15 12:50:40 -0700
committerTianon Gravi <admwiggin@gmail.com>2015-01-15 12:50:40 -0700
commit2a0db60599fdd75b1bc3e297180fbe1282763759 (patch)
tree68d43c3e30d9ab961ddf6b7365201ca6b675b253 /src/cmd/ld/dwarf.c
parentef33cba3c8de6c431df56503df51fcd3a473c89e (diff)
parentf154da9e12608589e8d5f0508f908a0c3e88a1bb (diff)
downloadgolang-2a0db60599fdd75b1bc3e297180fbe1282763759.tar.gz
Merge tag 'upstream/1.4' into debian-experimental
* tag 'upstream/1.4': Imported Upstream version 1.4
Diffstat (limited to 'src/cmd/ld/dwarf.c')
-rw-r--r--src/cmd/ld/dwarf.c156
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);