diff options
author | fche <fche> | 2007-04-23 19:36:36 +0000 |
---|---|---|
committer | fche <fche> | 2007-04-23 19:36:36 +0000 |
commit | 5bc4ac10aaa5e85a081f2975972be1241286a07b (patch) | |
tree | f6ab59438dbd4c79d5b10d2d0827a9c5a3cd47fa | |
parent | 0e0739046f8dbdcf278d9e7ba5fb7c5b4780d1f2 (diff) | |
download | systemtap-steved-5bc4ac10aaa5e85a081f2975972be1241286a07b.tar.gz systemtap-steved-5bc4ac10aaa5e85a081f2975972be1241286a07b.tar.xz systemtap-steved-5bc4ac10aaa5e85a081f2975972be1241286a07b.zip |
2007-04-23 Frank Ch. Eigler <fche@redhat.com>
* tapsets.cxx (die_entrypc): Expand search algorithm to
check for "aranges", as sometimes occurs for inlined functions.
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | tapsets.cxx | 54 |
2 files changed, 53 insertions, 6 deletions
@@ -1,3 +1,8 @@ +2007-04-23 Frank Ch. Eigler <fche@redhat.com> + + * tapsets.cxx (die_entrypc): Expand search algorithm to + check for "aranges", as sometimes occurs for inlined functions. + 2007-04-20 Roland McGrath <roland@redhat.com> * systemtap.spec.in (elfutils_version): Bump to 0.127. diff --git a/tapsets.cxx b/tapsets.cxx index bbbcffb3..dc306c8a 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1155,13 +1155,55 @@ struct dwflpp bool die_entrypc (Dwarf_Die * die, Dwarf_Addr * addr) { - Dwarf_Attribute attr_mem; - Dwarf_Attribute *attr = dwarf_attr (die, DW_AT_entry_pc, &attr_mem); - if (attr != NULL) - return (dwarf_formaddr (attr, addr) == 0); + int rc = 0; + string lookup_method; + + * addr = 0; + + lookup_method = "dwarf_entrypc"; + rc = dwarf_entrypc (die, addr); + + if (rc) + { + lookup_method = "dwarf_lowpc"; + rc = dwarf_lowpc (die, addr); + } - return (dwarf_lowpc (die, addr) == 0); - // XXX: see also _entrypc ? + if (rc) + { + lookup_method = "dwarf_ranges"; + + Dwarf_Addr base; + Dwarf_Addr begin; + Dwarf_Addr end; + ptrdiff_t offset = dwarf_ranges (die, 0, &base, &begin, &end); + if (offset < 0) rc = -1; + else if (offset > 0) + { + * addr = begin; + rc = 0; + + // Now we need to check that there are no more ranges + // associated with this function, which could conceivably + // happen if a function is inlined, then pieces of it are + // split amongst different conditional branches. It's not + // obvious which of them to favour. As a heuristic, we + // pick the beginning of the first range, and ignore the + // others (but with a warning). + + unsigned extra = 0; + while ((offset = dwarf_ranges (die, offset, &base, &begin, &end)) > 0) + extra ++; + if (extra) + lookup_method += ", ignored " + lex_cast<string>(extra) + " more"; + } + } + + if (sess.verbose > 2) + clog << "entry-pc lookup (" << lookup_method << ") = 0x" << hex << *addr << dec + << " (rc " << rc << ")" + << endl; + return (rc == 0); } void function_die (Dwarf_Die *d) |