From: Julian Seward Date: Fri, 18 Oct 2013 13:21:26 +0000 (+0000) Subject: arm-linux only: make unwinding by stack scanning (a nasty hack) X-Git-Tag: svn/VALGRIND_3_9_0~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=682b7211e6d64720299b928ee788736f37524d00;p=thirdparty%2Fvalgrind.git arm-linux only: make unwinding by stack scanning (a nasty hack) be controllable from the command line. Fixes (kind of) #289578. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13657 --- diff --git a/coregrind/m_main.c b/coregrind/m_main.c index c2a918c552..610d782519 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -212,6 +212,11 @@ static void usage_NORETURN ( Bool debug_help ) " in the main exe: --soname-synonyms=somalloc=NONE\n" " in libxyzzy.so: --soname-synonyms=somalloc=libxyzzy.so\n" " --sigill-diagnostics=yes|no warn about illegal instructions? [yes]\n" +" --unw-stack-scan-thresh= Enable stack-scan unwind if fewer\n" +" than good frames found [0, meaning \"disabled\"]\n" +" NOTE: stack scanning is only available on arm-linux.\n" +" --unw-stack-scan-frames= Max number of frames that can be\n" +" recovered by stack scanning [5]\n" "\n"; const HChar usage2[] = @@ -798,6 +803,11 @@ void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd, else if VG_XACT_CLO(arg, "--gen-suppressions=all", VG_(clo_gen_suppressions), 2) {} + else if VG_BINT_CLO(arg, "--unw-stack-scan-thresh", + VG_(clo_unw_stack_scan_thresh), 0, 100) {} + else if VG_BINT_CLO(arg, "--unw-stack-scan-frames", + VG_(clo_unw_stack_scan_frames), 0, 32) {} + else if ( ! VG_(needs).command_line_options || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) { VG_(fmsg_bad_option)(arg, ""); diff --git a/coregrind/m_options.c b/coregrind/m_options.c index b8e3cac583..81225768da 100644 --- a/coregrind/m_options.c +++ b/coregrind/m_options.c @@ -125,6 +125,9 @@ VgSmc VG_(clo_smc_check) = Vg_SmcStack; const HChar* VG_(clo_kernel_variant) = NULL; Bool VG_(clo_dsymutil) = False; Bool VG_(clo_sigill_diag) = True; +UInt VG_(clo_unw_stack_scan_thresh) = 0; /* disabled by default */ +UInt VG_(clo_unw_stack_scan_frames) = 5; + /*====================================================================*/ /*=== File expansion ===*/ diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index 3a1fdff02b..c0523500ff 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -957,6 +957,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, /* Loop unwinding the stack. */ Bool do_stack_scan = False; + /* First try the Official Way, using Dwarf CFI. */ while (True) { if (debug) { VG_(printf)("i: %d, r15: 0x%lx, r13: 0x%lx\n", @@ -977,12 +978,17 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, if (UNLIKELY(cmrf > 0)) {RECURSIVE_MERGE(cmrf,ips,i);}; continue; } + /* No luck. We have to give up. */ do_stack_scan = True; break; } - if (0/*DISABLED BY DEFAULT*/ && do_stack_scan && i < max_n_ips && i <= 2) { + /* Now try Plan B (maybe) -- stack scanning. This often gives + pretty bad results, so this has to be enabled explicitly by the + user. */ + if (do_stack_scan + && i < max_n_ips && i < (Int)VG_(clo_unw_stack_scan_thresh)) { Int nByStackScan = 0; Addr lr = uregs.r14; Addr sp = uregs.r13 & ~3; @@ -1015,7 +1021,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, if (fps) fps[i] = 0; ips[i++] = cand; if (UNLIKELY(cmrf > 0)) {RECURSIVE_MERGE(cmrf,ips,i);}; - if (++nByStackScan >= 5) break; + if (++nByStackScan >= VG_(clo_unw_stack_scan_frames)) break; } } sp += 4; diff --git a/coregrind/pub_core_options.h b/coregrind/pub_core_options.h index 0202ab9e27..7554722085 100644 --- a/coregrind/pub_core_options.h +++ b/coregrind/pub_core_options.h @@ -318,6 +318,19 @@ extern Bool VG_(should_we_trace_this_child) ( HChar* child_exe_name, depends on verbosity (False if -q). */ extern Bool VG_(clo_sigill_diag); +/* Unwind using stack scanning (a nasty hack at the best of times) + when the normal CFI/FP-chain scan fails. If the number of + "normally" recovered frames is below this number, stack scanning + will be used (on platforms on which it is supported, currently only + arm-linux). The default value of zero has the effect of disabling + stack scanning. Default: zero*/ +extern UInt VG_(clo_unw_stack_scan_thresh); + +/* If stack scanning is used, this is how many frames it may recover. + Since it tends to pick up a lot of junk, this value is set pretty + low by default. Default: 5 */ +extern UInt VG_(clo_unw_stack_scan_frames); + #endif // __PUB_CORE_OPTIONS_H /*--------------------------------------------------------------------*/ diff --git a/none/tests/cmdline1.stdout.exp b/none/tests/cmdline1.stdout.exp index 12d7cce91d..26f1e21c81 100644 --- a/none/tests/cmdline1.stdout.exp +++ b/none/tests/cmdline1.stdout.exp @@ -100,6 +100,11 @@ usage: valgrind [options] prog-and-args in the main exe: --soname-synonyms=somalloc=NONE in libxyzzy.so: --soname-synonyms=somalloc=libxyzzy.so --sigill-diagnostics=yes|no warn about illegal instructions? [yes] + --unw-stack-scan-thresh= Enable stack-scan unwind if fewer + than good frames found [0, meaning "disabled"] + NOTE: stack scanning is only available on arm-linux. + --unw-stack-scan-frames= Max number of frames that can be + recovered by stack scanning [5] user options for Nulgrind: (none) diff --git a/none/tests/cmdline2.stdout.exp b/none/tests/cmdline2.stdout.exp index c3e3d3c972..f76a25ba08 100644 --- a/none/tests/cmdline2.stdout.exp +++ b/none/tests/cmdline2.stdout.exp @@ -100,6 +100,11 @@ usage: valgrind [options] prog-and-args in the main exe: --soname-synonyms=somalloc=NONE in libxyzzy.so: --soname-synonyms=somalloc=libxyzzy.so --sigill-diagnostics=yes|no warn about illegal instructions? [yes] + --unw-stack-scan-thresh= Enable stack-scan unwind if fewer + than good frames found [0, meaning "disabled"] + NOTE: stack scanning is only available on arm-linux. + --unw-stack-scan-frames= Max number of frames that can be + recovered by stack scanning [5] user options for Nulgrind: (none)