From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1726) id C34AA38983A2; Mon, 10 Oct 2022 11:19:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C34AA38983A2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1665400770; bh=Ct2yVtfeiUd0l5tIEdegVAa+KrTT723t76xVoFqI9a0=; h=From:To:Subject:Date:From; b=IDa9LD4nDGmsfGph10iTtFjd8ExmVOcwhPgrWt8jHC5h6hbmAt02Vcx5MqUKEGvq8 qkZk1wBlB3d8fyoV25eMLXzAZ4L2+qDB8O+NDbDY7lprB+ClAaXZZ0Jnzktv5qvFpq Oi8hwryiogskai6RnDeTX5r+krs86B/XC7Ki38OU= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Andrew Burgess To: gdb-cvs@sourceware.org Subject: [binutils-gdb] gdb: add infcall specific debugging X-Act-Checkin: binutils-gdb X-Git-Author: Andrew Burgess X-Git-Refname: refs/heads/master X-Git-Oldrev: 58fd1204aa0f66dd2df30f673c9441e0265b8515 X-Git-Newrev: e4014689b9a1b9aa0dde8f8a358401774566fe8b Message-Id: <20221010111930.C34AA38983A2@sourceware.org> Date: Mon, 10 Oct 2022 11:19:30 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3De4014689b9a1= b9aa0dde8f8a358401774566fe8b commit e4014689b9a1b9aa0dde8f8a358401774566fe8b Author: Andrew Burgess Date: Tue May 10 15:16:46 2022 +0100 gdb: add infcall specific debugging =20 Add two new commands: =20 set debug infcall on|off show debug infcall =20 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. Diff: --- gdb/NEWS | 4 ++++ gdb/doc/gdb.texinfo | 7 ++++++ gdb/infcall.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 79 insertions(+) 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. =20 +set debug infcall on|off +show debug infcall + Print additional debug messages about inferior function calls. + * Changed commands =20 document user-defined diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 44d87e95748..3de511a4844 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -27587,6 +27587,13 @@ for implementing operations such as single-steppin= g the inferior. @item show debug infrun Displays the current state of @value{GDBN} inferior debugging. =20 +@item set debug infcall +@cindex inferior function call debugging info +Turns on or off display of debugging info related to inferior function +calls made by @value{GDBN}. +@item show debug infcall +Displays the current state of @value{GDBN} inferior function call debuggin= g. + @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 16e6b9e9355..e2de045d7b7 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -44,6 +44,34 @@ #include "gdbsupport/scope-exit.h" #include =20 +/* True if we are debugging inferior calls. */ + +static bool debug_infcall =3D 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 =3D=3D STOP_STACK_DUMMY) { /* Done. */ @@ -577,10 +607,17 @@ static struct gdb_exception run_inferior_call (std::unique_ptr 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 =3D call_thread->ptid; int was_running =3D call_thread->state =3D=3D THREAD_RUNNING; =20 + infcall_debug_printf ("call function at %s in thread %s, was_running =3D= %d", + core_addr_to_string (real_pc), + call_thread_ptid.to_string ().c_str (), + was_running); + current_ui->unregister_file_handler (); =20 scoped_restore restore_in_infcall @@ -610,15 +647,25 @@ run_inferior_call (std::unique_ptr s= m, =20 proceed (real_pc, GDB_SIGNAL_0); =20 + infrun_debug_show_threads ("non-exited threads after proceed for inf= erior-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 =3D std::move (e); } =20 + 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 =3D 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.")); =20 + 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 =3D run_inferior_call (std::move (sm_up), call_thread.get (), real= _pc); } =20 + 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); =20 if (call_thread->state !=3D THREAD_EXITED) @@ -1287,6 +1345,8 @@ call_function_by_hand_dummy (struct value *function, { struct value *retval; =20 + 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, =20 return retval; } + else + infcall_debug_printf ("call did not complete"); =20 /* 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); =20 + 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); }