diff options
-rw-r--r-- | dwarf_wrappers.cxx | 87 | ||||
-rw-r--r-- | dwarf_wrappers.h | 15 | ||||
-rw-r--r-- | dwflpp.cxx | 107 | ||||
-rw-r--r-- | tapsets.cxx | 102 |
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 : */ @@ -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 + "'"); |