summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dwarf_wrappers.cxx87
-rw-r--r--dwarf_wrappers.h15
-rw-r--r--dwflpp.cxx107
-rw-r--r--tapsets.cxx102
4 files changed, 159 insertions, 152 deletions
diff --git a/dwarf_wrappers.cxx b/dwarf_wrappers.cxx
index 0cb3cc0f..7b64aac5 100644
--- a/dwarf_wrappers.cxx
+++ b/dwarf_wrappers.cxx
@@ -10,11 +10,12 @@
#include "staptree.h"
#include <cstring>
+#include <sstream>
#include <string>
#include <elfutils/libdwfl.h>
#include <dwarf.h>
-using std::string;
+using namespace std;
void dwfl_assert(const string& desc, int rc)
{
@@ -89,4 +90,88 @@ dwarf_decl_line_integrate (Dwarf_Die *die, int *linep)
#endif // !_ELFUTILS_PREREQ(0, 143)
+static bool
+dwarf_type_name(Dwarf_Die *type_die, ostringstream& o)
+{
+ // if we've gotten down to a basic type, then we're done
+ bool done = true;
+ switch (dwarf_tag(type_die))
+ {
+ case DW_TAG_enumeration_type:
+ o << "enum ";
+ break;
+ case DW_TAG_structure_type:
+ o << "struct ";
+ break;
+ case DW_TAG_union_type:
+ o << "union ";
+ break;
+ case DW_TAG_typedef:
+ case DW_TAG_base_type:
+ break;
+ default:
+ done = false;
+ break;
+ }
+ if (done)
+ {
+ // this follows gdb precedent that anonymous structs/unions
+ // are displayed as "struct {...}" and "union {...}".
+ o << (dwarf_diename(type_die) ?: "{...}");
+ return true;
+ }
+
+ // otherwise, this die is a type modifier.
+
+ // recurse into the referent type
+ // if it can't be named, just call it "void"
+ Dwarf_Die subtype_die;
+ if (!dwarf_attr_die(type_die, DW_AT_type, &subtype_die)
+ || !dwarf_type_name(&subtype_die, o))
+ o.str("void"), o.seekp(4);
+
+ switch (dwarf_tag(type_die))
+ {
+ case DW_TAG_pointer_type:
+ o << "*";
+ break;
+ case DW_TAG_array_type:
+ o << "[]";
+ break;
+ case DW_TAG_const_type:
+ o << " const";
+ break;
+ case DW_TAG_volatile_type:
+ o << " volatile";
+ break;
+ default:
+ return false;
+ }
+
+ // XXX HACK! The va_list isn't usable as found in the debuginfo...
+ if (o.str() == "struct __va_list_tag*")
+ o.str("va_list"), o.seekp(7);
+
+ return true;
+}
+
+
+bool
+dwarf_type_name(Dwarf_Die *type_die, string& type_name)
+{
+ ostringstream o;
+ bool ret = dwarf_type_name(type_die, o);
+ type_name = o.str();
+ return ret;
+}
+
+
+string
+dwarf_type_name(Dwarf_Die *type_die)
+{
+ ostringstream o;
+ return dwarf_type_name(type_die, o) ? o.str() : "<unknown>";
+}
+
+
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/dwarf_wrappers.h b/dwarf_wrappers.h
index 54ab8fd4..766abb6d 100644
--- a/dwarf_wrappers.h
+++ b/dwarf_wrappers.h
@@ -103,6 +103,16 @@ public:
};
+// Look up the DIE for a reference-form attribute name
+inline Dwarf_Die *
+dwarf_attr_die (Dwarf_Die *die, unsigned int attr, Dwarf_Die *result)
+{
+ Dwarf_Attribute attr_mem;
+ return dwarf_formref_die (dwarf_attr_integrate (die, attr, &attr_mem),
+ result);
+}
+
+
#if !_ELFUTILS_PREREQ(0, 143)
// Elfutils prior to 0.143 didn't use attr_integrate when looking up the
// decl_file or decl_line, so the attributes would sometimes be missed. For
@@ -118,6 +128,11 @@ int dwarf_decl_line_integrate (Dwarf_Die *die, int *linep)
#endif // !_ELFUTILS_PREREQ(0, 143)
+// Resolve a full name for dwarf types
+bool dwarf_type_name(Dwarf_Die *type_die, std::string& type_name);
+std::string dwarf_type_name(Dwarf_Die *type_die);
+
+
#endif
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/dwflpp.cxx b/dwflpp.cxx
index b5663fff..6593e5a7 100644
--- a/dwflpp.cxx
+++ b/dwflpp.cxx
@@ -937,10 +937,8 @@ dwflpp::iterate_over_labels (Dwarf_Die *begin_die,
static string function_name = dwarf_diename (begin_die);
do
{
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr (&die, DW_AT_name, &attr_mem);
int tag = dwarf_tag(&die);
- const char *name = dwarf_formstring (attr);
+ const char *name = dwarf_diename (&die);
if (name == 0)
continue;
switch (tag)
@@ -1555,7 +1553,7 @@ dwflpp::print_members(Dwarf_Die *vardie, ostream &o)
if (typetag != DW_TAG_structure_type && typetag != DW_TAG_union_type)
{
o << " Error: "
- << (dwarf_diename (vardie) ?: "<anonymous>")
+ << dwarf_type_name(vardie)
<< " isn't a struct/union";
return;
}
@@ -1566,15 +1564,13 @@ dwflpp::print_members(Dwarf_Die *vardie, ostream &o)
switch (dwarf_child (vardie, die))
{
case 1: // No children.
- o << ((typetag == DW_TAG_union_type) ? " union " : " struct ")
- << (dwarf_diename (die) ?: "<anonymous>")
+ o << dwarf_type_name(vardie)
<< " is empty";
break;
case -1: // Error.
default: // Shouldn't happen.
- o << ((typetag == DW_TAG_union_type) ? " union " : " struct ")
- << (dwarf_diename (die) ?: "<anonymous>")
+ o << dwarf_type_name(vardie)
<< ": " << dwarf_errmsg (-1);
break;
@@ -1591,20 +1587,14 @@ dwflpp::print_members(Dwarf_Die *vardie, ostream &o)
o << " " << member;
else
{
- Dwarf_Die temp_die = *die;
- Dwarf_Attribute temp_attr ;
-
- if (!dwarf_attr_integrate (&temp_die, DW_AT_type, &temp_attr))
- {
- clog << "\n Error in obtaining type attribute for "
- << (dwarf_diename(&temp_die)?:"<anonymous>");
- return;
- }
-
- if (!dwarf_formref_die (&temp_attr, &temp_die))
+ Dwarf_Die temp_die;
+ if (!dwarf_attr_die (die, DW_AT_type, &temp_die))
{
- clog << "\n Error in decoding type attribute for "
- << (dwarf_diename(&temp_die)?:"<anonymous>");
+ string source = dwarf_decl_file(die) ?: "<unknown source>";
+ int line = -1;
+ dwarf_decl_line(die, &line);
+ clog << "\n Error in obtaining type attribute for anonymous member at "
+ << source << ":" << line;
return;
}
@@ -1634,8 +1624,7 @@ dwflpp::find_struct_member(const target_symbol::component& c,
return false;
case -1: /* Error. */
default: /* Shouldn't happen */
- throw semantic_error (string (dwarf_tag(parentdie) == DW_TAG_union_type ? "union" : "struct")
- + string (dwarf_diename (parentdie) ?: "<anonymous>")
+ throw semantic_error (dwarf_type_name(parentdie) + ": "
+ string (dwarf_errmsg (-1)),
c.tok);
}
@@ -1650,12 +1639,8 @@ dwflpp::find_struct_member(const target_symbol::component& c,
{
// need to recurse for anonymous structs/unions
Dwarf_Die subdie;
-
- if (!dwarf_attr_integrate (&die, DW_AT_type, &attr) ||
- !dwarf_formref_die (&attr, &subdie))
- continue;
-
- if (find_struct_member(c, &subdie, memberdie, locs))
+ if (dwarf_attr_die (&die, DW_AT_type, &subdie) &&
+ find_struct_member(c, &subdie, memberdie, locs))
goto success;
}
else if (name == c.member)
@@ -1728,6 +1713,12 @@ dwflpp::translate_components(struct obstack *pool,
break;
case DW_TAG_pointer_type:
+ /* A pointer with no type is a void* -- can't dereference it. */
+ if (!dwarf_hasattr_integrate (die, DW_AT_type))
+ throw semantic_error ("invalid access '" + lex_cast<string>(c)
+ + "' vs. " + dwarf_type_name(die),
+ c.tok);
+
c_translate_pointer (pool, 1, 0 /* PR9768*/, die, tail);
if (c.type != target_symbol::comp_literal_array_index &&
c.type != target_symbol::comp_expression_array_index)
@@ -1760,15 +1751,14 @@ dwflpp::translate_components(struct obstack *pool,
if (c.type != target_symbol::comp_struct_member)
throw semantic_error ("invalid access '"
+ lex_cast<string>(c)
- + "' for struct/union type",
+ + "' for " + dwarf_type_name(die),
c.tok);
if (dwarf_hasattr(die, DW_AT_declaration))
{
Dwarf_Die *tmpdie = dwflpp::declaration_resolve(dwarf_diename(die));
if (tmpdie == NULL)
- throw semantic_error ("unresolved struct "
- + string (dwarf_diename (die) ?: "<anonymous>"),
+ throw semantic_error ("unresolved " + dwarf_type_name(die),
c.tok);
*die_mem = *tmpdie;
}
@@ -1778,15 +1768,26 @@ dwflpp::translate_components(struct obstack *pool,
vector<Dwarf_Attribute> locs;
if (!find_struct_member(c, &parentdie, die, locs))
{
+ /* Add a file:line hint for anonymous types */
+ string source;
+ if (!dwarf_hasattr_integrate(&parentdie, DW_AT_name))
+ {
+ int line;
+ const char *file = dwarf_decl_file(&parentdie);
+ if (file && dwarf_decl_line(&parentdie, &line) == 0)
+ source = " (" + string(file) + ":"
+ + lex_cast<string>(line) + ")";
+ }
+
string alternatives;
stringstream members;
print_members(&parentdie, members);
if (members.str().size() != 0)
- alternatives = " (alternatives:" + members.str();
+ alternatives = " (alternatives:" + members.str() + ")";
throw semantic_error("unable to find member '" +
- c.member + "' for struct "
- + string(dwarf_diename(&parentdie) ?: "<unknown>")
- + alternatives,
+ c.member + "' for "
+ + dwarf_type_name(&parentdie)
+ + source + alternatives,
c.tok);
}
@@ -1798,27 +1799,20 @@ dwflpp::translate_components(struct obstack *pool,
break;
case DW_TAG_enumeration_type:
- throw semantic_error ("invalid access '"
- + lex_cast<string>(c)
- + "' vs. enum type "
- + string(dwarf_diename (die) ?: "<anonymous type>"),
- c.tok);
- break;
case DW_TAG_base_type:
throw semantic_error ("invalid access '"
+ lex_cast<string>(c)
- + "' vs. base type "
- + string(dwarf_diename (die) ?: "<anonymous type>"),
+ + "' vs. " + dwarf_type_name(die),
c.tok);
break;
+
case -1:
throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1)),
c.tok);
break;
default:
- throw semantic_error (string(dwarf_diename (die) ?: "<anonymous type>")
- + ": unexpected type tag "
+ throw semantic_error (dwarf_type_name(die) + ": unexpected type tag "
+ lex_cast<string>(dwarf_tag (die)),
c.tok);
break;
@@ -1881,8 +1875,6 @@ dwflpp::translate_final_fetch_or_store (struct obstack *pool,
Dwarf_Die typedie_mem;
Dwarf_Die *typedie;
int typetag;
- char const *dname;
- string diestr;
typedie = resolve_unqualified_inner_typedie (&typedie_mem, attr_mem, e);
typetag = dwarf_tag (typedie);
@@ -1908,19 +1900,15 @@ dwflpp::translate_final_fetch_or_store (struct obstack *pool,
switch (typetag)
{
default:
- dname = dwarf_diename(die);
- diestr = (dname != NULL) ? dname : "<unknown>";
throw semantic_error ("unsupported type tag "
+ lex_cast<string>(typetag)
- + " for " + diestr, e->tok);
+ + " for " + dwarf_type_name(die), e->tok);
break;
case DW_TAG_structure_type:
case DW_TAG_union_type:
- dname = dwarf_diename(die);
- diestr = (dname != NULL) ? dname : "<unknown>";
- throw semantic_error ("struct/union '" + diestr
- + "' is being accessed instead of a member of the struct/union", e->tok);
+ throw semantic_error ("'" + dwarf_type_name(die)
+ + "' is being accessed instead of a member", e->tok);
break;
case DW_TAG_enumeration_type:
@@ -1928,9 +1916,6 @@ dwflpp::translate_final_fetch_or_store (struct obstack *pool,
// Reject types we can't handle in systemtap
{
- dname = dwarf_diename(die);
- diestr = (dname != NULL) ? dname : "<unknown>";
-
Dwarf_Attribute encoding_attr;
Dwarf_Word encoding = (Dwarf_Word) -1;
dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, &encoding_attr),
@@ -1939,7 +1924,7 @@ dwflpp::translate_final_fetch_or_store (struct obstack *pool,
{
// clog << "bad type1 " << encoding << " diestr" << endl;
throw semantic_error ("unsupported type (mystery encoding " + lex_cast<string>(encoding) + ")" +
- " for " + diestr, e->tok);
+ " for " + dwarf_type_name(die), e->tok);
}
if (encoding == DW_ATE_float
@@ -1948,7 +1933,7 @@ dwflpp::translate_final_fetch_or_store (struct obstack *pool,
{
// clog << "bad type " << encoding << " diestr" << endl;
throw semantic_error ("unsupported type (encoding " + lex_cast<string>(encoding) + ")" +
- " for " + diestr, e->tok);
+ " for " + dwarf_type_name(die), e->tok);
}
}
@@ -2201,7 +2186,7 @@ dwflpp::literal_stmt_for_pointer (Dwarf_Die *type_die,
{
if (sess.verbose>2)
clog << "literal_stmt_for_pointer: finding value for "
- << (dwarf_diename(type_die) ?: "<unknown>")
+ << dwarf_type_name(type_die)
<< "("
<< (dwarf_diename(cu) ?: "<unknown>")
<< ")\n";
diff --git a/tapsets.cxx b/tapsets.cxx
index 3d38a3ce..04d03503 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -2770,8 +2770,6 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
}
-static bool dwarf_type_name(Dwarf_Die& type_die, string& c_type);
-
void
dwarf_derived_probe::saveargs(Dwarf_Die* scope_die)
{
@@ -2782,13 +2780,11 @@ dwarf_derived_probe::saveargs(Dwarf_Die* scope_die)
stringstream argstream;
string type_name;
- Dwarf_Attribute type_attr;
Dwarf_Die type_die;
if (has_return &&
- dwarf_attr_integrate (scope_die, DW_AT_type, &type_attr) &&
- dwarf_formref_die (&type_attr, &type_die) &&
- dwarf_type_name(type_die, type_name))
+ dwarf_attr_die (scope_die, DW_AT_type, &type_die) &&
+ dwarf_type_name(&type_die, type_name))
argstream << " $return:" << type_name;
Dwarf_Die arg;
@@ -2810,9 +2806,8 @@ dwarf_derived_probe::saveargs(Dwarf_Die* scope_die)
continue;
type_name.clear();
- if (!dwarf_attr_integrate (&arg, DW_AT_type, &type_attr) ||
- !dwarf_formref_die (&type_attr, &type_die) ||
- !dwarf_type_name(type_die, type_name))
+ if (!dwarf_attr_die (&arg, DW_AT_type, &type_die) ||
+ !dwarf_type_name(&type_die, type_name))
continue;
argstream << " $" << arg_name << ":" << type_name;
@@ -4288,13 +4283,11 @@ uprobe_derived_probe::saveargs(Dwarf_Die* scope_die)
stringstream argstream;
string type_name;
- Dwarf_Attribute type_attr;
Dwarf_Die type_die;
if (return_p &&
- dwarf_attr_integrate (scope_die, DW_AT_type, &type_attr) &&
- dwarf_formref_die (&type_attr, &type_die) &&
- dwarf_type_name(type_die, type_name))
+ dwarf_attr_die (scope_die, DW_AT_type, &type_die) &&
+ dwarf_type_name(&type_die, type_name))
argstream << " $return:" << type_name;
Dwarf_Die arg;
@@ -4316,9 +4309,8 @@ uprobe_derived_probe::saveargs(Dwarf_Die* scope_die)
continue;
type_name.clear();
- if (!dwarf_attr_integrate (&arg, DW_AT_type, &type_attr) ||
- !dwarf_formref_die (&type_attr, &type_die) ||
- !dwarf_type_name(type_die, type_name))
+ if (!dwarf_attr_die (&arg, DW_AT_type, &type_die) ||
+ !dwarf_type_name(&type_die, type_name))
continue;
argstream << " $" << arg_name << ":" << type_name;
@@ -5583,82 +5575,15 @@ tracepoint_derived_probe::tracepoint_derived_probe (systemtap_session& s,
static bool
-dwarf_type_name(Dwarf_Die& type_die, string& c_type)
-{
- // if we've gotten down to a basic type, then we're done
- bool done = true;
- switch (dwarf_tag(&type_die))
- {
- case DW_TAG_structure_type:
- c_type.append("struct ");
- break;
- case DW_TAG_union_type:
- c_type.append("union ");
- break;
- case DW_TAG_typedef:
- case DW_TAG_base_type:
- break;
- default:
- done = false;
- break;
- }
- if (done)
- {
- c_type.append(dwarf_diename(&type_die));
- return true;
- }
-
- // otherwise, this die is a type modifier.
-
- // recurse into the referent type
- // if it can't be named, just call it "void"
- Dwarf_Attribute subtype_attr;
- Dwarf_Die subtype_die;
- if (!dwarf_attr_integrate(&type_die, DW_AT_type, &subtype_attr)
- || !dwarf_formref_die(&subtype_attr, &subtype_die)
- || !dwarf_type_name(subtype_die, c_type))
- c_type = "void";
-
- const char *suffix = NULL;
- switch (dwarf_tag(&type_die))
- {
- case DW_TAG_pointer_type:
- suffix = "*";
- break;
- case DW_TAG_array_type:
- suffix = "[]";
- break;
- case DW_TAG_const_type:
- suffix = " const";
- break;
- case DW_TAG_volatile_type:
- suffix = " volatile";
- break;
- default:
- return false;
- }
- c_type.append(suffix);
-
- // XXX HACK! The va_list isn't usable as found in the debuginfo...
- if (c_type == "struct __va_list_tag*")
- c_type = "va_list";
-
- return true;
-}
-
-
-static bool
resolve_tracepoint_arg_type(tracepoint_arg& arg)
{
- Dwarf_Attribute type_attr;
switch (dwarf_tag(&arg.type_die))
{
case DW_TAG_typedef:
case DW_TAG_const_type:
case DW_TAG_volatile_type:
// iterate on the referent type
- return (dwarf_attr_integrate(&arg.type_die, DW_AT_type, &type_attr)
- && dwarf_formref_die(&type_attr, &arg.type_die)
+ return (dwarf_attr_die(&arg.type_die, DW_AT_type, &arg.type_die)
&& resolve_tracepoint_arg_type(arg));
case DW_TAG_base_type:
// base types will simply be treated as script longs
@@ -5667,8 +5592,7 @@ resolve_tracepoint_arg_type(tracepoint_arg& arg)
case DW_TAG_pointer_type:
// pointers can be treated as script longs,
// and if we know their type, they can also be dereferenced
- if (dwarf_attr_integrate(&arg.type_die, DW_AT_type, &type_attr)
- && dwarf_formref_die(&type_attr, &arg.type_die))
+ if (dwarf_attr_die(&arg.type_die, DW_AT_type, &arg.type_die))
arg.isptr = true;
arg.typecast = "(intptr_t)";
return true;
@@ -5699,10 +5623,8 @@ tracepoint_derived_probe::build_args(dwflpp& dw, Dwarf_Die& func_die)
tparg.name = dwarf_diename(&arg);
// read the type of this parameter
- Dwarf_Attribute type_attr;
- if (!dwarf_attr_integrate (&arg, DW_AT_type, &type_attr)
- || !dwarf_formref_die (&type_attr, &tparg.type_die)
- || !dwarf_type_name(tparg.type_die, tparg.c_type))
+ if (!dwarf_attr_die (&arg, DW_AT_type, &tparg.type_die)
+ || !dwarf_type_name(&tparg.type_die, tparg.c_type))
throw semantic_error ("cannot get type of tracepoint '"
+ tracepoint_name + "' parameter '"
+ tparg.name + "'");