[3/3] gdb: add infcall specific debugging

Message ID 9871275a989ff2c262ea9c94e3172c7eabfe7957.1665076921.git.aburgess@redhat.com
State New
Headers
Series Another set of debug output patches |

Commit Message

Andrew Burgess Oct. 6, 2022, 5:23 p.m. UTC
  Add two new commands:

  set debug infcall on|off
  show debug infcall

These enable some new debugging related to when GDB makes inferior
function calls.  I've added some basic debugging for what I think are
the major steps in the inferior function call process, but I'm sure we
might want to add more later.
---
 gdb/NEWS            |  4 +++
 gdb/doc/gdb.texinfo |  7 +++++
 gdb/infcall.c       | 68 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+)
  

Comments

Eli Zaretskii Oct. 6, 2022, 5:32 p.m. UTC | #1
> Date: Thu,  6 Oct 2022 18:23:45 +0100
> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 796a4ef8072..8b519a648f7 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -111,6 +111,10 @@ maintenance print frame-id [ LEVEL ]
>    Print GDB's internal frame-id for the frame at LEVEL.  If LEVEL is
>    not given, then print the frame-id for the currently selected frame.
>  
> +set debug infcall on|off
> +show debug infcall
> +  Print additional debug messages about inferior function calls.
> +

This part is OK.

> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -27587,6 +27587,13 @@
>  @item show debug infrun
>  Displays the current state of @value{GDBN} inferior debugging.
>  
> +@item set debug infcall
> +@cindex inferior function call debugging info
> +Turns on or off display of debugging info related to when @value{GDBN}
> +makes inferior function calls.

Is the "related to when" part accurate?  It seems to imply that we
only display indications of such calls, whereas the code seems to do
much more: it shows detailed information about the call and its
results.  So maybe reword as follows:

  Turns on or off display of debugging info related to inferior
  function calls made by @value{GDBN}.

Thanks.
  
Andrew Burgess Oct. 10, 2022, 12:05 p.m. UTC | #2
Eli Zaretskii <eliz@gnu.org> writes:

>> Date: Thu,  6 Oct 2022 18:23:45 +0100
>> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
>> 
>> diff --git a/gdb/NEWS b/gdb/NEWS
>> index 796a4ef8072..8b519a648f7 100644
>> --- a/gdb/NEWS
>> +++ b/gdb/NEWS
>> @@ -111,6 +111,10 @@ maintenance print frame-id [ LEVEL ]
>>    Print GDB's internal frame-id for the frame at LEVEL.  If LEVEL is
>>    not given, then print the frame-id for the currently selected frame.
>>  
>> +set debug infcall on|off
>> +show debug infcall
>> +  Print additional debug messages about inferior function calls.
>> +
>
> This part is OK.
>
>> --- a/gdb/doc/gdb.texinfo
>> +++ b/gdb/doc/gdb.texinfo
>> @@ -27587,6 +27587,13 @@
>>  @item show debug infrun
>>  Displays the current state of @value{GDBN} inferior debugging.
>>  
>> +@item set debug infcall
>> +@cindex inferior function call debugging info
>> +Turns on or off display of debugging info related to when @value{GDBN}
>> +makes inferior function calls.
>
> Is the "related to when" part accurate?  It seems to imply that we
> only display indications of such calls, whereas the code seems to do
> much more: it shows detailed information about the call and its
> results.  So maybe reword as follows:
>
>   Turns on or off display of debugging info related to inferior
>   function calls made by @value{GDBN}.

Thanks for the feedback.  I pushed this series with the fix you
suggested.

Thanks,
Andrew
  

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index 796a4ef8072..8b519a648f7 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -111,6 +111,10 @@  maintenance print frame-id [ LEVEL ]
   Print GDB's internal frame-id for the frame at LEVEL.  If LEVEL is
   not given, then print the frame-id for the currently selected frame.
 
+set debug infcall on|off
+show debug infcall
+  Print additional debug messages about inferior function calls.
+
 * Changed commands
 
 document user-defined
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 44d87e95748..e04c053c7bc 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -27587,6 +27587,13 @@ 
 @item show debug infrun
 Displays the current state of @value{GDBN} inferior debugging.
 
+@item set debug infcall
+@cindex inferior function call debugging info
+Turns on or off display of debugging info related to when @value{GDBN}
+makes inferior function calls.
+@item show debug infcall
+Displays the current state of @value{GDBN} inferior function call debugging.
+
 @item set debug jit
 @cindex just-in-time compilation, debugging messages
 Turn on or off debugging messages from JIT debug support.
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 34852191043..8e12a119c15 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -44,6 +44,34 @@ 
 #include "gdbsupport/scope-exit.h"
 #include <list>
 
+/* True if we are debugging inferior calls.  */
+
+static bool debug_infcall = false;
+
+/* Print an "infcall" debug statement.  */
+
+#define infcall_debug_printf(fmt, ...) \
+  debug_prefixed_printf_cond (debug_infcall, "infcall", fmt, ##__VA_ARGS__)
+
+/* Print "infcall" enter/exit debug statements.  */
+
+#define INFCALL_SCOPED_DEBUG_ENTER_EXIT \
+  scoped_debug_enter_exit (debug_infcall, "infcall")
+
+/* Print "infcall" start/end debug statements.  */
+
+#define INFCALL_SCOPED_DEBUG_START_END(fmt, ...) \
+  scoped_debug_start_end (debug_infrun, "infcall", fmt, ##__VA_ARGS__)
+
+/* Implement 'show debug infcall'.  */
+
+static void
+show_debug_infcall (struct ui_file *file, int from_tty,
+		   struct cmd_list_element *c, const char *value)
+{
+  gdb_printf (file, _("Inferior call debugging is %s.\n"), value);
+}
+
 /* If we can't find a function's name from its address,
    we print this instead.  */
 #define RAW_FUNCTION_ADDRESS_FORMAT "at 0x%s"
@@ -529,6 +557,8 @@  call_thread_fsm::call_thread_fsm (struct ui *waiting_ui,
 bool
 call_thread_fsm::should_stop (struct thread_info *thread)
 {
+  INFCALL_SCOPED_DEBUG_ENTER_EXIT;
+
   if (stop_stack_dummy == STOP_STACK_DUMMY)
     {
       /* Done.  */
@@ -577,10 +607,17 @@  static struct gdb_exception
 run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
 		   struct thread_info *call_thread, CORE_ADDR real_pc)
 {
+  INFCALL_SCOPED_DEBUG_ENTER_EXIT;
+
   struct gdb_exception caught_error;
   ptid_t call_thread_ptid = call_thread->ptid;
   int was_running = call_thread->state == THREAD_RUNNING;
 
+  infcall_debug_printf ("call function at %s in thread %s, was_running = %d",
+			core_addr_to_string (real_pc),
+			call_thread_ptid.to_string ().c_str (),
+			was_running);
+
   current_ui->unregister_file_handler ();
 
   scoped_restore restore_in_infcall
@@ -610,15 +647,25 @@  run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
 
       proceed (real_pc, GDB_SIGNAL_0);
 
+      infrun_debug_show_threads ("non-exited threads after proceed for inferior-call",
+				 all_non_exited_threads ());
+
       /* Inferior function calls are always synchronous, even if the
 	 target supports asynchronous execution.  */
       wait_sync_command_done ();
+
+      infcall_debug_printf ("inferior call completed successfully");
     }
   catch (gdb_exception &e)
     {
+      infcall_debug_printf ("exception while making inferior call (%d): %s",
+			    e.reason, e.what ());
       caught_error = std::move (e);
     }
 
+  infcall_debug_printf ("thread is now: %s",
+			inferior_ptid.to_string ().c_str ());
+
   /* If GDB has the prompt blocked before, then ensure that it remains
      so.  normal_stop calls async_enable_stdin, so reset the prompt
      state again here.  In other cases, stdin will be re-enabled by
@@ -764,6 +811,8 @@  call_function_by_hand_dummy (struct value *function,
 			     dummy_frame_dtor_ftype *dummy_dtor,
 			     void *dummy_dtor_data)
 {
+  INFCALL_SCOPED_DEBUG_ENTER_EXIT;
+
   CORE_ADDR sp;
   struct type *target_values_type;
   function_call_return_method return_method = return_method_normal;
@@ -830,6 +879,9 @@  call_function_by_hand_dummy (struct value *function,
   if (args.size () < ftype->num_fields ())
     error (_("Too few arguments in function call."));
 
+  infcall_debug_printf ("calling %s", get_function_name (funaddr, name_buf,
+							 sizeof (name_buf)));
+
   /* A holder for the inferior status.
      This is only needed while we're preparing the inferior function call.  */
   infcall_control_state_up inf_status (save_infcall_control_state ());
@@ -1276,6 +1328,12 @@  call_function_by_hand_dummy (struct value *function,
       e = run_inferior_call (std::move (sm_up), call_thread.get (), real_pc);
     }
 
+    if (e.reason < 0)
+      infcall_debug_printf ("after inferior call, exception (%d): %s",
+			    e.reason, e.what ());
+    infcall_debug_printf ("after inferior call, thread state is: %s",
+			  thread_state_string (call_thread->state));
+
     gdb::observers::inferior_call_post.notify (call_thread_ptid, funaddr);
 
     if (call_thread->state != THREAD_EXITED)
@@ -1287,6 +1345,8 @@  call_function_by_hand_dummy (struct value *function,
 	  {
 	    struct value *retval;
 
+	    infcall_debug_printf ("call completed");
+
 	    /* The inferior call is successful.  Pop the dummy frame,
 	       which runs its destructors and restores the inferior's
 	       suspend state, and restore the inferior control
@@ -1317,6 +1377,8 @@  call_function_by_hand_dummy (struct value *function,
 
 	    return retval;
 	  }
+	else
+	  infcall_debug_printf ("call did not complete");
 
 	/* Didn't complete.  Clean up / destroy the call FSM, and restore the
 	   previous state machine, and handle the error.  */
@@ -1572,4 +1634,10 @@  The default is to unwind the frame."),
 			   show_unwind_on_terminating_exception_p,
 			   &setlist, &showlist);
 
+  add_setshow_boolean_cmd
+    ("infcall", class_maintenance, &debug_infcall,
+     _("Set inferior call debugging."),
+     _("Show inferior call debugging."),
+     _("When on, inferior function call specific debugging is enabled."),
+     NULL, show_debug_infcall, &setdebuglist, &showdebuglist);
 }