summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfche <fche>2007-04-23 19:36:36 +0000
committerfche <fche>2007-04-23 19:36:36 +0000
commit5bc4ac10aaa5e85a081f2975972be1241286a07b (patch)
treef6ab59438dbd4c79d5b10d2d0827a9c5a3cd47fa
parent0e0739046f8dbdcf278d9e7ba5fb7c5b4780d1f2 (diff)
downloadsystemtap-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--ChangeLog5
-rw-r--r--tapsets.cxx54
2 files changed, 53 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index b2b9e4b5..0fd1b4a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)