diff options
author | CoprDistGit <infra@openeuler.org> | 2024-08-05 02:06:24 +0000 |
---|---|---|
committer | CoprDistGit <infra@openeuler.org> | 2024-08-05 02:06:24 +0000 |
commit | fb9e94c608e22ae34d776deffbfd225a2be15a53 (patch) | |
tree | 4fa0b980b9deb3a41ba7b8a17845888d77150f31 /gdb-rhel-13298-inferior-funcall-bp-condition-4-of-5.patch | |
parent | ba9480ce1210dc551f343b938be2fa00759e1616 (diff) |
automatic import of gdbopeneuler24.03_LTS
Diffstat (limited to 'gdb-rhel-13298-inferior-funcall-bp-condition-4-of-5.patch')
-rw-r--r-- | gdb-rhel-13298-inferior-funcall-bp-condition-4-of-5.patch | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/gdb-rhel-13298-inferior-funcall-bp-condition-4-of-5.patch b/gdb-rhel-13298-inferior-funcall-bp-condition-4-of-5.patch new file mode 100644 index 0000000..579e2f5 --- /dev/null +++ b/gdb-rhel-13298-inferior-funcall-bp-condition-4-of-5.patch @@ -0,0 +1,413 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Andrew Burgess <aburgess@redhat.com> +Date: Wed, 18 Jan 2023 10:17:57 +0000 +Subject: gdb-rhel-13298-inferior-funcall-bp-condition-4-of-5.patch + +;;gdb: introduce unwind-on-timeout setting +;;(Andrew Burgess, RHEL-13298) + +Now that inferior function calls can timeout (see the recent +introduction of direct-call-timeout and indirect-call-timeout), this +commit adds a new setting unwind-on-timeout. + +This new setting is just like the existing unwindonsignal and +unwind-on-terminating-exception, but the new setting will cause GDB to +unwind the stack if an inferior function call times out. + +The existing inferior function call timeout tests have been updated to +cover the new setting. + +Reviewed-By: Eli Zaretskii <eliz@gnu.org> +Tested-By: Luis Machado <luis.machado@arm.com> +Tested-By: Keith Seitz <keiths@redhat.com> + +diff --git a/gdb/NEWS b/gdb/NEWS +--- a/gdb/NEWS ++++ b/gdb/NEWS +@@ -72,6 +72,15 @@ show indirect-call-timeout + ignored, GDB will wait indefinitely for an inferior function to + complete, unless interrupted by the user using Ctrl-C. + ++set unwind-on-timeout on|off ++show unwind-on-timeout ++ These commands control whether GDB should unwind the stack when a ++ timeout occurs during an inferior function call. The default is ++ off, in which case the inferior will remain in the frame where the ++ timeout occurred. When on, GDB will unwind the stack removing the ++ dummy frame that was added for the inferior call, and restoring the ++ inferior state to how it was before the inferior call started. ++ + * New features in the GDB remote stub, GDBserver + + ** The --remote-debug and --event-loop-debug command line options +diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo +--- a/gdb/doc/gdb.texinfo ++++ b/gdb/doc/gdb.texinfo +@@ -20932,6 +20932,22 @@ the default C@t{++} exception handler and the inferior terminated. + Show the current setting of stack unwinding in the functions called by + @value{GDBN}. + ++@anchor{set unwind-on-timeout} ++@item set unwind-on-timeout ++@kindex set unwind-on-timeout ++@cindex unwind stack in called functions when timing out ++@cindex call dummy stack unwinding on timeout. ++Set unwinding of the stack if a function called from @value{GDBN} ++times out. If set to @code{off} (the default), @value{GDBN} stops in ++the frame where the timeout occurred. If set to @code{on}, ++@value{GDBN} unwinds the stack it created for the call and restores ++the context to what it was before the call. ++ ++@item show unwind-on-timeout ++@kindex show unwind-on-timeout ++Show whether @value{GDBN} will unwind the stack if a function called ++from @value{GDBN} times out. ++ + @item set may-call-functions + @kindex set may-call-functions + @cindex disabling calling functions in the program +@@ -20963,11 +20979,11 @@ call by typing the interrupt character (often @kbd{Ctrl-c}). + + If a called function is interrupted for any reason, including hitting + a breakpoint, or triggering a watchpoint, and the stack is not unwound +-due to @code{set unwind-on-terminating-exception on} or @code{set +-unwindonsignal on} (@pxref{stack unwind settings}), +-then the dummy-frame, created by @value{GDBN} to facilitate the call +-to the program function, will be visible in the backtrace, for example +-frame @code{#3} in the following backtrace: ++due to @code{set unwind-on-terminating-exception on}, @code{set ++unwind-on-timeout on}, or @code{set unwindonsignal on} (@pxref{stack ++unwind settings}), then the dummy-frame, created by @value{GDBN} to ++facilitate the call to the program function, will be visible in the ++backtrace, for example frame @code{#3} in the following backtrace: + + @smallexample + (@value{GDBP}) backtrace +@@ -20992,6 +21008,11 @@ Execution}) @value{GDBN} can place a timeout on any functions called + from @value{GDBN}. If the timeout expires and the function call is + still ongoing, then @value{GDBN} will interrupt the program. + ++If a function called from @value{GDBN} is interrupted by a timeout, ++then by default the inferior is left in the frame where the timeout ++occurred, this behaviour can be adjusted with @samp{set ++unwind-on-timeout} (@pxref{set unwind-on-timeout}). ++ + For targets that don't support asynchronous execution + (@pxref{Background Execution}) then timeouts for functions called from + @value{GDBN} are not supported, the timeout settings described below +diff --git a/gdb/infcall.c b/gdb/infcall.c +--- a/gdb/infcall.c ++++ b/gdb/infcall.c +@@ -218,6 +218,27 @@ show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty, + value); + } + ++/* This boolean tells GDB what to do if an inferior function, called from ++ GDB, times out. If true, GDB unwinds the stack and restores the context ++ to what it was before the call. When false, GDB leaves the thread as it ++ is at the point of the timeout. ++ ++ The default is to stop in the frame where the timeout occurred. */ ++ ++static bool unwind_on_timeout_p = false; ++ ++/* Implement 'show unwind-on-timeout'. */ ++ ++static void ++show_unwind_on_timeout_p (struct ui_file *file, int from_tty, ++ struct cmd_list_element *c, const char *value) ++{ ++ gdb_printf (file, ++ _("Unwinding of stack if a timeout occurs " ++ "while in a call dummy is %s.\n"), ++ value); ++} ++ + /* Perform the standard coercions that are specified + for arguments to be passed to C, Ada or Fortran functions. + +@@ -574,6 +595,16 @@ struct call_thread_fsm : public thread_fsm + bool should_stop (struct thread_info *thread) override; + + bool should_notify_stop () override; ++ ++ /* Record that this thread timed out while performing an infcall. */ ++ void timed_out () ++ { ++ m_timed_out = true; ++ } ++ ++private: ++ /* Set true if the thread timed out while performing an infcall. */ ++ bool m_timed_out = false; + }; + + /* Allocate a new call_thread_fsm object. */ +@@ -649,7 +680,8 @@ call_thread_fsm::should_notify_stop () + + infcall_debug_printf ("inferior call didn't complete fully"); + +- if (stopped_by_random_signal && unwind_on_signal_p) ++ if ((stopped_by_random_signal && unwind_on_signal_p) ++ || (m_timed_out && unwind_on_timeout_p)) + { + infcall_debug_printf ("unwind-on-signal is on, don't notify"); + return false; +@@ -742,6 +774,9 @@ struct infcall_timer_controller + + infcall_debug_printf ("Stopping thread %s", + m_thread->ptid.to_string ().c_str ()); ++ call_thread_fsm *fsm ++ = gdb::checked_static_cast<call_thread_fsm *> (m_thread->thread_fsm ()); ++ fsm->timed_out (); + target_stop (m_thread->ptid); + } + }; +@@ -1744,14 +1779,27 @@ When the function is done executing, GDB will silently stop."), + /* A timeout results in a signal being sent to the inferior. */ + gdb_assert (stopped_by_random_signal); + +- /* Indentation is weird here. A later patch is going to move the +- following block into an if/else, so I'm leaving the indentation +- here to minimise the later patch. ++ if (unwind_on_timeout_p) ++ { ++ /* The user wants the context restored. */ ++ ++ /* We must get back to the frame we were before the ++ dummy call. */ ++ dummy_frame_pop (dummy_id, call_thread.get ()); + +- Also, the error message used below refers to 'set +- unwind-on-timeout' which doesn't exist yet. This will be added +- in a later commit, I'm leaving this in for now to minimise the +- churn caused by the commit that adds unwind-on-timeout. */ ++ /* We also need to restore inferior status to that before the ++ dummy call. */ ++ restore_infcall_control_state (inf_status.release ()); ++ ++ error (_("\ ++The program being debugged timed out while in a function called from GDB.\n\ ++GDB has restored the context to what it was before the call.\n\ ++To change this behavior use \"set unwind-on-timeout off\".\n\ ++Evaluation of the expression containing the function\n\ ++(%s) will be abandoned."), ++ name.c_str ()); ++ } ++ else + { + /* The user wants to stay in the frame where we stopped + (default). Discard inferior status, we're not at the same +@@ -1877,6 +1925,20 @@ The default is to unwind the frame."), + show_unwind_on_terminating_exception_p, + &setlist, &showlist); + ++ add_setshow_boolean_cmd ("unwind-on-timeout", no_class, ++ &unwind_on_timeout_p, _("\ ++Set unwinding of stack if a timeout occurs while in a call dummy."), _("\ ++Show unwinding of stack if a timeout occurs while in a call dummy."), ++ _("\ ++The unwind on timeout flag lets the user determine what gdb should do if\n\ ++gdb times out while in a function called from gdb. If set, gdb unwinds\n\ ++the stack and restores the context to what it was before the call. If\n\ ++unset, gdb leaves the inferior in the frame where the timeout occurred.\n\ ++The default is to stop in the frame where the timeout occurred."), ++ NULL, ++ show_unwind_on_timeout_p, ++ &setlist, &showlist); ++ + add_setshow_uinteger_cmd ("direct-call-timeout", no_class, + &direct_call_timeout, _("\ + Set the timeout, for direct calls to inferior function calls."), _("\ +diff --git a/gdb/testsuite/gdb.base/infcall-timeout.exp b/gdb/testsuite/gdb.base/infcall-timeout.exp +--- a/gdb/testsuite/gdb.base/infcall-timeout.exp ++++ b/gdb/testsuite/gdb.base/infcall-timeout.exp +@@ -28,7 +28,11 @@ if { [build_executable "failed to prepare" ${binfile} "${srcfile}" \ + # then adjust the direct-call-timeout, and make an inferior function + # call that will never return. GDB should eventually timeout and stop + # the inferior. +-proc run_test { target_async target_non_stop non_stop } { ++# ++# When UNWIND is "off" the inferior wil be left in the frame where the ++# timeout occurs, otherwise, when UNWIND is "on", GDB should unwind ++# back to the frame where the inferior call was made. ++proc run_test { target_async target_non_stop non_stop unwind } { + save_vars { ::GDBFLAGS } { + append ::GDBFLAGS \ + " -ex \"maint set target-non-stop $target_non_stop\"" +@@ -45,28 +49,43 @@ proc run_test { target_async target_non_stop non_stop } { + } + + gdb_test_no_output "set direct-call-timeout 5" ++ gdb_test_no_output "set unwind-on-timeout $unwind" ++ ++ if { $unwind } { ++ gdb_test "print function_that_never_returns ()" \ ++ [multi_line \ ++ "The program being debugged timed out while in a function called from GDB\\." \ ++ "GDB has restored the context to what it was before the call\\." \ ++ "To change this behavior use \"set unwind-on-timeout off\"\\." \ ++ "Evaluation of the expression containing the function" \ ++ "\\(function_that_never_returns\\) will be abandoned\\."] + +- # When non-stop mode is off we get slightly different output from GDB. +- if { ([target_info gdb_protocol] == "remote" +- || [target_info gdb_protocol] == "extended-remote") +- && !$target_non_stop } { +- set stopped_line_pattern "Program received signal SIGINT, Interrupt\\." ++ gdb_test "bt" \ ++ "#0\\s+main \\(\\).*" + } else { +- set stopped_line_pattern "Program stopped\\." +- } ++ # When non-stop mode is off we get slightly different output from GDB. ++ if { ([target_info gdb_protocol] == "remote" ++ || [target_info gdb_protocol] == "extended-remote") ++ && !$target_non_stop } { ++ set stopped_line_pattern "Program received signal SIGINT, Interrupt\\." ++ } else { ++ set stopped_line_pattern "Program stopped\\." ++ } + +- gdb_test "print function_that_never_returns ()" \ +- [multi_line \ +- $stopped_line_pattern \ +- ".*" \ +- "The program being debugged timed out while in a function called from GDB\\." \ +- "GDB remains in the frame where the timeout occurred\\." \ +- "To change this behavior use \"set unwind-on-timeout on\"\\." \ +- "Evaluation of the expression containing the function" \ +- "\\(function_that_never_returns\\) will be abandoned\\." \ +- "When the function is done executing, GDB will silently stop\\."] +- +- gdb_test "bt" ".* function_that_never_returns .*<function called from gdb>.*" ++ gdb_test "print function_that_never_returns ()" \ ++ [multi_line \ ++ $stopped_line_pattern \ ++ ".*" \ ++ "The program being debugged timed out while in a function called from GDB\\." \ ++ "GDB remains in the frame where the timeout occurred\\." \ ++ "To change this behavior use \"set unwind-on-timeout on\"\\." \ ++ "Evaluation of the expression containing the function" \ ++ "\\(function_that_never_returns\\) will be abandoned\\." \ ++ "When the function is done executing, GDB will silently stop\\."] ++ ++ gdb_test "bt" \ ++ ".* function_that_never_returns .*<function called from gdb>.*" ++ } + } + + foreach_with_prefix target_async { "on" "off" } { +@@ -88,7 +107,9 @@ foreach_with_prefix target_async { "on" "off" } { + continue + } + +- run_test $target_async $target_non_stop $non_stop ++ foreach_with_prefix unwind { "on" "off" } { ++ run_test $target_async $target_non_stop $non_stop $unwind ++ } + } + } + } +diff --git a/gdb/testsuite/gdb.threads/infcall-from-bp-cond-timeout.exp b/gdb/testsuite/gdb.threads/infcall-from-bp-cond-timeout.exp +--- a/gdb/testsuite/gdb.threads/infcall-from-bp-cond-timeout.exp ++++ b/gdb/testsuite/gdb.threads/infcall-from-bp-cond-timeout.exp +@@ -41,7 +41,12 @@ set segfault_line [gdb_get_line_number "Segfault here"] + # thread, on which the inferior call relies, either hits a breakpoint + # (when OTHER_THREAD_BP is true), or crashes (when OTHER_THREAD_BP is + # false). +-proc run_test { target_async target_non_stop non_stop other_thread_bp } { ++# ++# When UNWIND is "on" GDB will unwind the thread which performed the ++# inferior function call back to the state where the inferior call was ++# made (when the inferior call times out). Otherwise, when UNWIND is ++# "off", the inferior is left in the frame where the timeout occurred. ++proc run_test { target_async target_non_stop non_stop other_thread_bp unwind } { + save_vars { ::GDBFLAGS } { + append ::GDBFLAGS " -ex \"maint set target-non-stop $target_non_stop\"" + append ::GDBFLAGS " -ex \"maint non-stop $non_stop\"" +@@ -72,6 +77,7 @@ proc run_test { target_async target_non_stop non_stop other_thread_bp } { + # for this timeout. For now though, we just hope 5 seconds is + # enough. + gdb_test_no_output "set indirect-call-timeout 5" ++ gdb_test_no_output "set unwind-on-timeout $unwind" + + gdb_breakpoint \ + "${::srcfile}:${::cond_bp_line} if (condition_func ())" +@@ -92,27 +98,43 @@ proc run_test { target_async target_non_stop non_stop other_thread_bp } { + "get number for segfault breakpoint"] + } + +- # When non-stop mode is off we get slightly different output from GDB. +- if { ([target_info gdb_protocol] == "remote" +- || [target_info gdb_protocol] == "extended-remote") +- && !$target_non_stop} { +- set stopped_line_pattern "Thread ${::decimal} \"\[^\r\n\"\]+\" received signal SIGINT, Interrupt\\." ++ if { $unwind } { ++ gdb_test "continue" \ ++ [multi_line \ ++ "Error in testing condition for breakpoint ${bp_num}:" \ ++ "The program being debugged timed out while in a function called from GDB\\." \ ++ "GDB has restored the context to what it was before the call\\." \ ++ "To change this behavior use \"set unwind-on-timeout off\"\\." \ ++ "Evaluation of the expression containing the function" \ ++ "\\(condition_func\\) will be abandoned\\.(\r\n\\\[New Thread \[^\r\n\]+\\\])*" \ ++ "" \ ++ "Thread ${::decimal}\[^\r\n\]*hit Breakpoint ${bp_num}, \[^\r\n\]+" \ ++ "\[^\r\n\]+ Conditional breakpoint here\\. \[^\r\n\]+"] \ ++ "expected timeout waiting for inferior call to complete" + } else { +- set stopped_line_pattern "Thread ${::decimal} \"\[^\r\n\"\]+\" stopped\\." +- } ++ # When non-stop mode is off we get slightly different output from GDB. ++ if { ([target_info gdb_protocol] == "remote" ++ || [target_info gdb_protocol] == "extended-remote") ++ && !$target_non_stop} { ++ set stopped_line_pattern \ ++ "Thread ${::decimal} \"\[^\r\n\"\]+\" received signal SIGINT, Interrupt\\." ++ } else { ++ set stopped_line_pattern "Thread ${::decimal} \"\[^\r\n\"\]+\" stopped\\." ++ } + +- gdb_test "continue" \ +- [multi_line \ +- $stopped_line_pattern \ +- ".*" \ +- "Error in testing condition for breakpoint ${bp_num}:" \ +- "The program being debugged timed out while in a function called from GDB\\." \ +- "GDB remains in the frame where the timeout occurred\\." \ +- "To change this behavior use \"set unwind-on-timeout on\"\\." \ +- "Evaluation of the expression containing the function" \ +- "\\(condition_func\\) will be abandoned\\." \ +- "When the function is done executing, GDB will silently stop\\."] \ +- "expected timeout waiting for inferior call to complete" ++ gdb_test "continue" \ ++ [multi_line \ ++ "$stopped_line_pattern" \ ++ ".*" \ ++ "Error in testing condition for breakpoint ${bp_num}:" \ ++ "The program being debugged timed out while in a function called from GDB\\." \ ++ "GDB remains in the frame where the timeout occurred\\." \ ++ "To change this behavior use \"set unwind-on-timeout on\"\\." \ ++ "Evaluation of the expression containing the function" \ ++ "\\(condition_func\\) will be abandoned\\." \ ++ "When the function is done executing, GDB will silently stop\\."] \ ++ "expected timeout waiting for inferior call to complete" ++ } + + # Remember that other thread that either crashed (with a segfault) + # or hit a breakpoint? Now that the inferior call has timed out, +@@ -158,8 +180,11 @@ foreach_with_prefix target_async {"on" "off" } { + # disabled. + continue + } +- foreach_with_prefix other_thread_bp { true false } { +- run_test $target_async $target_non_stop $non_stop $other_thread_bp ++ foreach_with_prefix unwind {"off" "on"} { ++ foreach_with_prefix other_thread_bp { true false } { ++ run_test $target_async $target_non_stop $non_stop \ ++ $other_thread_bp $unwind ++ } + } + } + } |