diff options
author | Mark Wielaard <mjw@redhat.com> | 2009-08-20 16:31:55 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2009-08-20 16:31:55 +0200 |
commit | 30868aad20865f5a949c22ad0a20d1ebe2fd669a (patch) | |
tree | bcf328c8a25f40d7991da4015428847ae2be834f | |
parent | b313f94ed30b4342eb02def7d8e895f5d2af8008 (diff) | |
download | systemtap-steved-30868aad20865f5a949c22ad0a20d1ebe2fd669a.tar.gz systemtap-steved-30868aad20865f5a949c22ad0a20d1ebe2fd669a.tar.xz systemtap-steved-30868aad20865f5a949c22ad0a20d1ebe2fd669a.zip |
PR10537 process().function().label() should select multiple inlined instances.
This is less useful than one would hope. gcc will often emit a label with
a DW_AT_low_pc that is not really in the neighbourhood of where one would
expect it when the label is inlined and gcc can proof the label isn't really
used in the optimized code. dwflpp::iterate_over_labels will now really
iterate recursively through the die, even for dies without a name (like
lexical blocks). This means we should now always find the concrete inlined
label instances that have a real DW_AT_low_pc and so we don't need the trick
to use the line table to get at the actual address.
* dwflpp.cxx (iterate_over_labels): Accept dies without a name. Don't handle
labels without a name or without a lowpc attribute.
* testsuite/systemtap.base/inlinedvars.c (m): Trick gcc into thinking label
is always used.
(call, call2): Activate.
(main): Call call and call2.
* testsuite/systemtap.base/inlinedvars.exp: New result_string.
Test both unoptimized and optimized (inlined) builds.
-rw-r--r-- | dwflpp.cxx | 29 | ||||
-rw-r--r-- | testsuite/systemtap.base/inlinedvars.c | 13 | ||||
-rw-r--r-- | testsuite/systemtap.base/inlinedvars.exp | 40 |
3 files changed, 38 insertions, 44 deletions
@@ -939,17 +939,22 @@ dwflpp::iterate_over_labels (Dwarf_Die *begin_die, { int tag = dwarf_tag(&die); const char *name = dwarf_diename (&die); - if (name == 0) - continue; switch (tag) { case DW_TAG_label: + if (name) + break; + else + continue; // Cannot handle unnamed label. break; case DW_TAG_subprogram: - if (!dwarf_hasattr(&die, DW_AT_declaration)) + if (!dwarf_hasattr(&die, DW_AT_declaration) && name) function_name = name; else continue; + case DW_TAG_inlined_subroutine: + if (name) + function_name = name; default: if (dwarf_haschildren (&die)) iterate_over_labels (&die, sym, symfunction, q, callback); @@ -975,23 +980,7 @@ dwflpp::iterate_over_labels (Dwarf_Die *begin_die, Dwarf_Addr stmt_addr; if (dwarf_lowpc (&die, &stmt_addr) != 0) - { - // There is no lowpc so figure out the address - // Get the real die for this cu - Dwarf_Die cudie; - dwarf_diecu (cu, &cudie, NULL, NULL); - size_t nlines = 0; - // Get the line for this label - Dwarf_Line **aline; - dwarf_getsrc_file (module_dwarf, file, dline, 0, &aline, &nlines); - // Get the address - for (size_t i = 0; i < nlines; i++) - { - dwarf_lineaddr (*aline, &stmt_addr); - if ((dwarf_haspc (&die, stmt_addr))) - break; - } - } + continue; // Don't try to be smart. Just drop no addr labels. Dwarf_Die *scopes; int nscopes = 0; diff --git a/testsuite/systemtap.base/inlinedvars.c b/testsuite/systemtap.base/inlinedvars.c index 2756323e..ab1d9fb2 100644 --- a/testsuite/systemtap.base/inlinedvars.c +++ b/testsuite/systemtap.base/inlinedvars.c @@ -4,16 +4,20 @@ m(char *name, int i, long j) // Random syntactical block to be inlined. // Mimics what STAP_PROBE macro does a bit. do { + // Dummy (volatile) counter to trick gcc into thinking we are actually + // using the label. If not it will partially optimize the label away, + // but still emits a somewhat bogus DW_AT_low_pc for it... + volatile int c = 0; volatile __typeof__(name) p_name = name; volatile __typeof__(i) p_i = i; volatile __typeof__(j) p_j = j; // empty asm to force locals into regs. - inlined_label: asm volatile ("" :: "g"(p_name), "g"(p_i), "g"(p_j)); + inlined_label: asm volatile ("nop" : "=g"(c) : "g"(p_name), "g"(p_i), "g"(p_j)); + if (c != 0) goto inlined_label; } while (0); return i + 32; } -/* XXX PR10537 label() doesn't select multiple instances. static inline int call(int pi, long pj) { @@ -29,15 +33,14 @@ call2(int pi2, long pj2) volatile jc2 = pj2 - 64; return m("call2", ic2, jc2); } -*/ int main (int argc, char **argv) { volatile int i = 64; volatile long j = 42; - i = 54;// XXX PR10537 call(i, j); - j = 150; // XXX PR10537 call2(i, j); + call(i, j); + call2(i, j); m("main", i, j); return 0; } diff --git a/testsuite/systemtap.base/inlinedvars.exp b/testsuite/systemtap.base/inlinedvars.exp index 95950110..00a6d417 100644 --- a/testsuite/systemtap.base/inlinedvars.exp +++ b/testsuite/systemtap.base/inlinedvars.exp @@ -1,26 +1,28 @@ set test "inlinedvars" -# XXX PR10537 - so only one result for now. -#set ::result_string {call (22,84) -#call2 (118,-22) -#main (54,150)} -set ::result_string {main (54,150)} +set ::result_string {call (22,84) +call2 (128,-22) +main (64,42)} -set test_flags "additional_flags=-g" -set test_flags "$test_flags additional_flags=-O2" +# Try both inlined and non-inlined compiles. +set opt_flags {{-O0} {-O1} {-O2} {-O3}} +foreach opt $opt_flags { + set test_flags "additional_flags=-g" + set test_flags "$test_flags additional_flags=$opt" -set res [target_compile $srcdir/$subdir/$test.c $test.exe executable "$test_flags"] -if { $res != "" } { + set res [target_compile $srcdir/$subdir/$test.c $test.exe executable "$test_flags"] + if { $res != "" } { verbose "target_compile failed: $res" 2 - fail "compiling $test.c" - untested "$test.c compile" + fail "compiling $test.c $opt" + untested "$test.c compile $opt" continue -} else { - pass "$test.c compile" -} + } else { + pass "$test.c compile $opt" + } -if {[installtest_p] && [uprobes_p]} { - stap_run3 "$test" $srcdir/$subdir/$test.stp $test.exe -c ./$test.exe -} else { - untested "$test" + if {[installtest_p] && [uprobes_p]} { + stap_run3 "$test-$opt" $srcdir/$subdir/$test.stp $test.exe -c ./$test.exe + } else { + untested "$test-$opt" + } + catch {exec rm -f $test.exe} } -#catch {exec rm -f $test.exe} |