summaryrefslogtreecommitdiff
path: root/usr/src/tools/ctf
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2018-10-12 15:28:11 +0300
committerDan McDonald <danmcd@joyent.com>2019-01-17 21:17:01 -0500
commit2dc5cbd37af38054ac6aab88a3ecee22a13ed2eb (patch)
tree26dd5b41fa385e7ac7b9f517d07e741a6ca80f28 /usr/src/tools/ctf
parent50971960b7b1866cdd785b20a4df98c90c231638 (diff)
downloadillumos-gate-2dc5cbd37af38054ac6aab88a3ecee22a13ed2eb.tar.gz
9312 ctf: be less clever about skipping 'extern' variables declarations
9864 DWARF->CTF enum conversion needs to be careful of sign Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: Andy Fiddaman <af@citrus-it.net> Reviewed by: Igor Kozhukhov <igor@dilos.org> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/tools/ctf')
-rw-r--r--usr/src/tools/ctf/cvt/dwarf.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/usr/src/tools/ctf/cvt/dwarf.c b/usr/src/tools/ctf/cvt/dwarf.c
index 5fdcd35e33..afca423005 100644
--- a/usr/src/tools/ctf/cvt/dwarf.c
+++ b/usr/src/tools/ctf/cvt/dwarf.c
@@ -863,11 +863,19 @@ die_enum_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
el = xcalloc(sizeof (elist_t));
el->el_name = die_name(dw, mem);
- if (die_signed(dw, mem, DW_AT_const_value, &sval, 0)) {
- el->el_number = sval;
- } else if (die_unsigned(dw, mem, DW_AT_const_value,
+ /*
+ * We have to be careful here: newer GCCs generate DWARF
+ * where an unsigned value will happily pass
+ * die_signed(). Since negative values will fail
+ * die_unsigned(), we try that first to make sure we get
+ * the right value.
+ */
+ if (die_unsigned(dw, mem, DW_AT_const_value,
&uval, 0)) {
el->el_number = uval;
+ } else if (die_signed(dw, mem, DW_AT_const_value,
+ &sval, 0)) {
+ el->el_number = sval;
} else {
terminate("die %llu: enum %llu: member without "
"value\n", off, die_off(dw, mem));
@@ -1643,8 +1651,34 @@ die_variable_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
debug(3, "die %llu: creating object definition\n", off);
- if (die_isdecl(dw, die) || (name = die_name(dw, die)) == NULL)
- return; /* skip prototypes and nameless objects */
+ /* Skip "Non-Defining Declarations" */
+ if (die_isdecl(dw, die))
+ return;
+
+ /*
+ * If we find a DIE of "Declarations Completing Non-Defining
+ * Declarations", we will use the referenced type's DIE. This isn't
+ * quite correct, e.g. DW_AT_decl_line will be the forward declaration
+ * not this site. It's sufficient for what we need, however: in
+ * particular, we should find DW_AT_external as needed there.
+ */
+ if (die_attr(dw, die, DW_AT_specification, 0) != NULL) {
+ Dwarf_Die sdie;
+ Dwarf_Off soff;
+
+ soff = die_attr_ref(dw, die, DW_AT_specification);
+
+ if (dwarf_offdie(dw->dw_dw, soff,
+ &sdie, &dw->dw_err) != DW_DLV_OK) {
+ terminate("dwarf_offdie(%llu) failed: %s\n",
+ soff, dwarf_errmsg(dw->dw_err));
+ }
+
+ die = sdie;
+ }
+
+ if ((name = die_name(dw, die)) == NULL)
+ return;
ii = xcalloc(sizeof (iidesc_t));
ii->ii_type = die_isglobal(dw, die) ? II_GVAR : II_SVAR;