From patchwork Sat May 5 19:28:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philippe Waroquiers X-Patchwork-Id: 27127 Received: (qmail 15556 invoked by alias); 5 May 2018 19:28:30 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 15410 invoked by uid 89); 5 May 2018 19:28:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-27.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=letters, silently, Usage, Commands X-HELO: mailsec109.isp.belgacom.be Received: from mailsec109.isp.belgacom.be (HELO mailsec109.isp.belgacom.be) (195.238.20.105) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 05 May 2018 19:28:26 +0000 IronPort-PHdr: =?us-ascii?q?9a23=3ArgLNUxLOtgic/0GLQdmcpTZWNBhigK39O0sv0rFi?= =?us-ascii?q?tYgeLvTxwZ3uMQTl6Ol3ixeRBMOHs6kC07KempujcFRI2YyGvnEGfc4EfD4+ou?= =?us-ascii?q?JSoTYdBtWYA1bwNv/gYn9yNs1DUFh44yPzahANS47xaFLIv3K98yMZFAnhOgpp?= =?us-ascii?q?POT1HZPZg9iq2+yo9JDffwtFiCChbb9uMR67sRjfus4KjIV4N60/0AHJonxGe+?= =?us-ascii?q?RXwWNnO1eelAvi68mz4ZBu7T1et+ou+MBcX6r6eb84TaFDAzQ9L281/szrugLd?= =?us-ascii?q?QgaJ+3ART38ZkhtMAwjC8RH6QpL8uTb0u+ZhxCWXO9D9QLYpUjqg8qhrUgflhi?= =?us-ascii?q?cZOTAk/m/Zict+g6BVoB+6uxBz35TZbJ2POfZiYq/Qe84RS2pbXsZWUixMGpmy?= =?us-ascii?q?b4sOD+oFPOZYt5H9qEUTphS+HwasHuTvyiZVhn/3w6I6yf8hGhzB0Qw4H9IOsX?= =?us-ascii?q?DUrNTtNKcKT++51qfJwi/Zb/NRwDf99YnIfQ47ofGXRr9wasnRyEkpFwzbklWc?= =?us-ascii?q?s5fqMC2M2+kLrmOV7PJgWPqyh2I7rwx9uCWjy8kwhoXTm44Z1FHJ+T9nzIs7O9?= =?us-ascii?q?G1TlNwb8S+H5tKrS6aMpN7QsYlQ251pik30qYGuZunfCgSz5Qn2gLfZ+SHc4eW?= =?us-ascii?q?5hLjU/6cITJli35/eLK/gBOy/la4xu39UMm7zkpKozJYntXQsn0BzQHf58abRv?= =?us-ascii?q?dn40utxzeC2xrN5uxKP0w4ja/bJIQgwr40mJoTq0PDHirulUXujK+Wd0Ek+umw?= =?us-ascii?q?6+T/fLrqvJGdOJVuigH5K6Quh82/DvoiMggVRGWb4ue81b3l/ULnXLVGlOY5nb?= =?us-ascii?q?fBvJDAOcsbvrK5AxNS0os75BawEiyp3M0AnXYdMFJKZBKHgJbyO1zVO/D4Cuq/?= =?us-ascii?q?g06wnzh1yfHJJKfhDYvXInjEirfhcq5361RAxwor0dBf+5VUB6kZIPLzW0/xsN?= =?us-ascii?q?3YDgchMwOq2ermBs9y1pkZWWKWH6+ZMb3dsUWT5u80OOmMZ48UuDDjJPg5/fLh?= =?us-ascii?q?lmE2yhchevym0ZFScHmkFfRrOG2CZmf2idoeGH0H+A0kQ7/EklqHBAZTZnKzR7?= =?us-ascii?q?oxrg4yEoW/EIbOXJvl1KSB3SO6BoVbIH9PEFeVDHblbZ6sQPQdbi+OZMVsxG9X?= =?us-ascii?q?HYO9QpMsgEn9/DTxzKBqe7LZ?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A2CnCAAkBe5a/+h+gm1cHAEBAQQBAQoBA?= =?us-ascii?q?YNEgVuMdowVAYIpAUMakySBeAsrAYRAAoI3IjYWAQIBAQEBAQECAWsogjUiglI?= =?us-ascii?q?GViMQPxI5HoU+qhuEWINpgjiJeT+BD4JWinwChxKGH4pzCIFljF0LgTWDYIdNk?= =?us-ascii?q?EmBJSMNJIFSbYMXgh8Xjhk9gSgBGgGPIwEB?= X-IPAS-Result: =?us-ascii?q?A2CnCAAkBe5a/+h+gm1cHAEBAQQBAQoBAYNEgVuMdowVAYI?= =?us-ascii?q?pAUMakySBeAsrAYRAAoI3IjYWAQIBAQEBAQECAWsogjUiglIGViMQPxI5HoU+q?= =?us-ascii?q?huEWINpgjiJeT+BD4JWinwChxKGH4pzCIFljF0LgTWDYIdNkEmBJSMNJIFSbYM?= =?us-ascii?q?Xgh8Xjhk9gSgBGgGPIwEB?= Received: from 232.126-130-109.adsl-dyn.isp.belgacom.be (HELO md.home) ([109.130.126.232]) by relay.skynet.be with ESMTP/TLS/DHE-RSA-AES128-GCM-SHA256; 05 May 2018 21:28:17 +0200 From: Philippe Waroquiers To: gdb-patches@sourceware.org Cc: Philippe Waroquiers Subject: [RFC 2/5] Implement frame apply [all | COUNT | -COUNT] [-FLAGS...] COMMAND Date: Sat, 5 May 2018 21:28:01 +0200 Message-Id: <20180505192804.12731-3-philippe.waroquiers@skynet.be> In-Reply-To: <20180505192804.12731-1-philippe.waroquiers@skynet.be> References: <20180505192804.12731-1-philippe.waroquiers@skynet.be> X-IsSubscribed: yes Also implement the command 'faas COMMAND', a shortcut for 'frame apply all -s COMMAND' --- gdb/stack.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 214 insertions(+), 25 deletions(-) diff --git a/gdb/stack.c b/gdb/stack.c index ecf1ee8379..61e86ab18b 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -777,7 +777,7 @@ do_gdb_disassembly (struct gdbarch *gdbarch, SRC_LINE: Print only source line. LOCATION: Print only location. - LOC_AND_SRC: Print location and source line. + SRC_AND_LOC: Print location and source line. Used in "where" output, and to emit breakpoint or step messages. */ @@ -1687,6 +1687,39 @@ info_frame_command (const char *addr_exp, int from_tty) } } +/* COUNT specifies the nr of outermost frames we are interested in. + trailing_outermost_frame returns the starting frame + needed to handle COUNT outermost frames. */ + +static struct frame_info* +trailing_outermost_frame (int count) +{ + struct frame_info *current; + struct frame_info *trailing; + + trailing = get_current_frame (); + + gdb_assert (count > 0); + + current = trailing; + while (current && count--) + { + QUIT; + current = get_prev_frame (current); + } + + /* Will stop when CURRENT reaches the top of the stack. + TRAILING will be COUNT below it. */ + while (current) + { + QUIT; + trailing = get_prev_frame (trailing); + current = get_prev_frame (current); + } + + return trailing; +} + /* Print briefly all stack frames or just the innermost COUNT_EXP frames. */ @@ -1696,7 +1729,6 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags, { struct frame_info *fi; int count; - int i; int py_start = 0, py_end = 0; enum ext_lang_bt_status result = EXT_LANG_BT_ERROR; @@ -1756,30 +1788,13 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags, if (count_exp != NULL && count < 0) { - struct frame_info *current; - - count = -count; - - current = trailing; - while (current && count--) - { - QUIT; - current = get_prev_frame (current); - } - - /* Will stop when CURRENT reaches the top of the stack. - TRAILING will be COUNT below it. */ - while (current) - { - QUIT; - trailing = get_prev_frame (trailing); - current = get_prev_frame (current); - } - + trailing = trailing_outermost_frame (-count); count = -1; } + else + trailing = get_current_frame (); - for (i = 0, fi = trailing; fi && count--; i++, fi = get_prev_frame (fi)) + for (fi = trailing; fi && count--; fi = get_prev_frame (fi)) { QUIT; @@ -2506,9 +2521,148 @@ func_command (const char *arg, int from_tty) select_and_print_frame (frame); } +/* Apply a GDB command to a all stack frames, or innermost COUNT frames. + With a negative COUNT, apply command on outermost -COUNT frames. + + frame apply 3 info frame Apply 'info frame' to frames 0, 1, 2 + frame apply -3 info frame Apply 'info frame' to outermost 3 frames. + frame apply all x/i $pc Apply 'x/i $pc' cmd to all frames. + frame apply all -s p local_var_no_idea_in_which_frame + If a frame has a local variable called + local_var_no_idea_in_which_frame, print frame + and value of local_var_no_idea_in_which_frame. + frame apply all -sqq p local_var_no_idea_in_which_frame + Same as before, but only print the variable value. */ + +/* Apply a GDB command to COUNT stack frames, starting at trailing. + COUNT -1 means all frames starting at trailing. WHICH_COMMAND is used + for error messages. */ +static void +frame_apply_command_count (const char* which_command, + const char *cmd, int from_tty, + struct frame_info *trailing, int count) +{ + int print_what_v = 2; /* Corresponding to LOCATION. */ + enum print_what print_what[5] = + { + LOC_AND_ADDRESS, /* Should never be used, this is verbosity 0. */ + SRC_LINE, + LOCATION, + LOC_AND_ADDRESS, + SRC_AND_LOC + }; + bool cont; + bool silent; + struct frame_info *fi; + + if (cmd != NULL) + check_for_flags_vqcs (which_command, &cmd, + &print_what_v, 4, + &cont, &silent); + + if (cmd == NULL || *cmd == '\000') + error (_("Please specify a command to apply on the selected frames")); + + for (fi = trailing; fi && count--; fi = get_prev_frame (fi)) + { + struct frame_id frame_id = get_frame_id (fi); + + QUIT; + + select_frame (fi); + TRY + { + std::string cmd_result = execute_command_to_string (cmd, from_tty); + if (!silent || cmd_result.length() > 0) + { + if (print_what_v > 0) + print_stack_frame (fi, 1, print_what[print_what_v], 0); + printf_filtered ("%s", cmd_result.c_str ()); + } + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (!silent) + { + if (print_what_v > 0) + print_stack_frame (fi, 1, print_what [print_what_v], 0); + if (cont) + printf_filtered ("%s\n", ex.message); + else + throw_exception (ex); + } + } + END_CATCH; + + /* execute_command_to_string might invalidate FI. */ + fi = frame_find_by_id (frame_id); + if (fi == NULL) + { + trailing = NULL; + warning (_("Unable to restore previously selected frame.")); + break; + } + } +} + +static void +frame_apply_all_command (const char *cmd, int from_tty) +{ + struct frame_info *fi; + struct frame_info *trailing = NULL; + int count; + int i; + + if (!target_has_stack) + error (_("No stack.")); + + frame_apply_command_count ("frame apply all", cmd, from_tty, + get_current_frame(), INT_MAX); +} + +/* Implementation of the "frame apply" command. */ + +static void +frame_apply_command (const char* cmd, int from_tty) +{ + int count; + struct frame_info *trailing; + + if (!target_has_stack) + error (_("No stack.")); + + count = get_number_trailer (&cmd, 0); + + if (count < 0) + { + trailing = trailing_outermost_frame (-count); + count = -1; + } + else + trailing = get_current_frame (); + + frame_apply_command_count ("frame apply", cmd, from_tty, + trailing, count); +} + +/* Implementation of the "faas" command. */ + +static void +faas_command (const char *cmd, int from_tty) +{ + std::string expanded = std::string ("frame apply all -s ") + std::string (cmd); + execute_command (expanded.c_str (), from_tty); +} + + +/* Commands with a prefix of `frame'. */ +struct cmd_list_element *frame_cmd_list = NULL; + void _initialize_stack (void) { + static struct cmd_list_element *frame_apply_list = NULL; + add_com ("return", class_stack, return_command, _("\ Make selected stack frame return to its caller.\n\ Control remains in the debugger, but when you continue\n\ @@ -2531,14 +2685,49 @@ An argument says how many frames down to go.")); Same as the `down' command, but does not print anything.\n\ This is useful in command scripts.")); - add_com ("frame", class_stack, frame_command, _("\ + add_prefix_cmd ("frame", class_stack, frame_command, _("\ Select and print a stack frame.\nWith no argument, \ print the selected stack frame. (See also \"info frame\").\n\ An argument specifies the frame to select.\n\ -It can be a stack frame number or the address of the frame.")); +It can be a stack frame number or the address of the frame."), + &frame_cmd_list, "frame ", 1, &cmdlist); add_com_alias ("f", "frame", class_stack, 1); +#define FRAME_APPLY_FLAGS_HELP "\ +FLAGS letters are v(increase verbosity), q(decrease verbosity)\n\ + c(continue), s(silent).\n\ +Verbosity (default 2) controls what to print for a frame:\n\ + 0 : no frame info is printed\n\ + 1 : source line\n\ + 2 : location\n\ + 3 : location and address\n\ + 4 : source line and location\n\ +By default, if a COMMAND raises an error, frame apply is aborted.\n\ +Flag c indicates to print the error and continue.\n\ +Flag s indicates to silently ignore a COMMAND that raises an error\n\ +or produces no output." + + add_prefix_cmd ("apply", class_stack, frame_apply_command, + _("Apply a command to a number of frames.\n\ +Usage: frame apply COUNT [-FLAGS...] COMMAND\n\ +With a negative COUNT argument, applies the command on outermost -COUNT frames.\n" +FRAME_APPLY_FLAGS_HELP), + &frame_apply_list, "frame apply ", 1, &frame_cmd_list); + + add_cmd ("all", class_stack, frame_apply_all_command, + _("\ +Apply a command to all frames.\n\ +\n\ +Usage: frame apply all [-FLAGS...] COMMAND\n" +FRAME_APPLY_FLAGS_HELP), + &frame_apply_list); + + add_com ("faas", class_stack, faas_command, _("\ +Apply a command to all frames (ignoring errors and empty output)\n\ +Usage: faas COMMAND\n\ +shortcut for 'frame apply all -s COMMAND'")); + add_com_suppress_notification ("select-frame", class_stack, select_frame_command, _("\ Select a stack frame without printing anything.\n\ An argument specifies the frame to select.\n\