From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14365 invoked by alias); 4 Mar 2013 17:08:55 -0000 Received: (qmail 14305 invoked by uid 22791); 4 Mar 2013 17:08:53 -0000 X-SWARE-Spam-Status: No, hits=-8.0 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_SPAMHAUS_DROP,KHOP_THREADED,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,RP_MATCHES_RCVD,TW_EG X-Spam-Check-By: sourceware.org Received: from mga02.intel.com (HELO mga02.intel.com) (134.134.136.20) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 04 Mar 2013 17:08:13 +0000 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 04 Mar 2013 09:06:30 -0800 X-ExtLoop1: 1 Received: from swsutil001.isw.intel.com ([10.237.237.11]) by orsmga002.jf.intel.com with ESMTP; 04 Mar 2013 09:06:28 -0800 Received: from ulslx001.iul.intel.com (ulslx001.iul.intel.com [172.28.207.63]) by swsutil001.isw.intel.com (8.13.6/8.13.6/MailSET/Hub) with ESMTP id r24H6EhK004114; Mon, 4 Mar 2013 17:06:16 GMT Received: from ulslx001.iul.intel.com (localhost [127.0.0.1]) by ulslx001.iul.intel.com with ESMTP id r24H6Ebn020124; Mon, 4 Mar 2013 18:06:14 +0100 Received: (from mmetzger@localhost) by ulslx001.iul.intel.com with id r24H6EgE020120; Mon, 4 Mar 2013 18:06:14 +0100 From: Markus Metzger To: jan.kratochvil@redhat.com Cc: gdb-patches@sourceware.org, markus.t.metzger@gmail.com, Eli Zaretskii Subject: [patch v9 17/23] record: add "record instruction-history" command Date: Mon, 04 Mar 2013 17:09:00 -0000 Message-Id: <1362416770-19750-18-git-send-email-markus.t.metzger@intel.com> In-Reply-To: <1362416770-19750-1-git-send-email-markus.t.metzger@intel.com> References: <1362416770-19750-1-git-send-email-markus.t.metzger@intel.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2013-03/txt/msg00113.txt.bz2 Add a command to provide a disassembly of the execution trace log. The command iterates over the execution trace log similar to the "list" command. CC: Eli Zaretskii 2013-03-04 Markus Metzger * target.h (target_ops) : New fields. (target_insn_history): New. (target_insn_history_from): New. (target_insn_history_range): New. * target.c (target_insn_history): New. (target_insn_history_from): New. (target_insn_history_range): New. * record.c: Include cli/cli-utils.h, disasm.h, ctype.h. (record_insn_history_size): New. (get_insn_number): New. (get_context_size): New. (no_chunk): New. (get_insn_history_modifiers): New. (cmd_record_insn_history): New. (_initialize_record): Add "set/show record instruction-history-size" command. Add "record instruction-history" command. --- gdb/record.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/target.c | 51 +++++++++++++++ gdb/target.h | 20 ++++++ 3 files changed, 271 insertions(+), 0 deletions(-) diff --git a/gdb/record.c b/gdb/record.c index abd8216..4c5f3f0 100644 --- a/gdb/record.c +++ b/gdb/record.c @@ -24,10 +24,17 @@ #include "observer.h" #include "inferior.h" #include "common/common-utils.h" +#include "cli/cli-utils.h" +#include "disasm.h" + +#include /* This is the debug switch for process record. */ unsigned int record_debug = 0; +/* The number of instructions to print in "record instruction-history". */ +static unsigned int record_insn_history_size = 10; + struct cmd_list_element *record_cmdlist = NULL; struct cmd_list_element *set_record_cmdlist = NULL; struct cmd_list_element *show_record_cmdlist = NULL; @@ -289,6 +296,173 @@ cmd_record_goto (char *arg, int from_tty) } } +/* Read an instruction number from an argument string. */ + +static ULONGEST +get_insn_number (char **arg) +{ + ULONGEST number; + const char *begin, *end, *pos; + + begin = *arg; + pos = skip_spaces_const (begin); + + if (!isdigit (*pos)) + error (_("Expected positive number, got: %s."), pos); + + number = strtoulst (pos, &end, 10); + + *arg += (end - begin); + + return number; +} + +/* Read a context size from an argument string. */ + +static int +get_context_size (char **arg) +{ + char *pos; + int number; + + pos = skip_spaces (*arg); + + if (!isdigit (*pos)) + error (_("Expected positive number, got: %s."), pos); + + return strtol (pos, arg, 10); +} + +/* Complain about junk at the end of an argument string. */ + +static void +no_chunk (char *arg) +{ + if (*arg != 0) + error (_("Junk after argument: %s."), arg); +} + +/* Read instruction-history modifiers from an argument string. */ + +static int +get_insn_history_modifiers (char **arg) +{ + int modifiers; + char *args; + + modifiers = 0; + args = *arg; + + if (args == NULL) + return modifiers; + + while (*args == '/') + { + ++args; + + if (*args == '\0') + error (_("Missing modifier.")); + + for (; *args; ++args) + { + if (isspace (*args)) + break; + + if (*args == '/') + continue; + + switch (*args) + { + case 'm': + modifiers |= DISASSEMBLY_SOURCE; + modifiers |= DISASSEMBLY_FILENAME; + break; + case 'r': + modifiers |= DISASSEMBLY_RAW_INSN; + break; + case 'f': + modifiers |= DISASSEMBLY_OMIT_FNAME; + break; + default: + error (_("Invalid modifier: %c."), *args); + } + } + + args = skip_spaces (args); + } + + /* Update the argument string. */ + *arg = args; + + return modifiers; +} + +/* The "record instruction-history" command. */ + +static void +cmd_record_insn_history (char *arg, int from_tty) +{ + int flags, size; + + require_record_target (); + + flags = get_insn_history_modifiers (&arg); + size = (int) record_insn_history_size; + if (size < 0) + size = INT_MAX; + + if (arg == NULL || *arg == 0 || strcmp (arg, "+") == 0) + target_insn_history (size, flags); + else if (strcmp (arg, "-") == 0) + target_insn_history (- size, flags); + else + { + ULONGEST begin, end; + + begin = get_insn_number (&arg); + + if (*arg == ',') + { + arg = skip_spaces (++arg); + + if (*arg == '+') + { + arg += 1; + size = get_context_size (&arg); + + no_chunk (arg); + + target_insn_history_from (begin, size, flags); + } + else if (*arg == '-') + { + arg += 1; + size = get_context_size (&arg); + + no_chunk (arg); + + target_insn_history_from (begin, - size, flags); + } + else + { + end = get_insn_number (&arg); + + no_chunk (arg); + + target_insn_history_range (begin, end, flags); + } + } + else + { + no_chunk (arg); + + target_insn_history_from (begin, size, flags); + } + + dont_repeat (); + } +} + /* Provide a prototype to silence -Wmissing-prototypes. */ extern initialize_file_ftype _initialize_record; @@ -305,6 +479,13 @@ _initialize_record (void) NULL, show_record_debug, &setdebuglist, &showdebuglist); + add_setshow_uinteger_cmd ("instruction-history-size", no_class, + &record_insn_history_size, _("\ +Set number of instructions to print in \"record instruction-history\"."), _("\ +Show number of instructions to print in \"record instruction-history\"."), + NULL, NULL, NULL, &set_record_cmdlist, + &show_record_cmdlist); + c = add_prefix_cmd ("record", class_obscure, cmd_record_start, _("Start recording."), &record_cmdlist, "record ", 0, &cmdlist); @@ -346,4 +527,23 @@ Default filename is 'gdb_record.'."), Restore the program to its state at instruction number N.\n\ Argument is instruction number, as shown by 'info record'."), &record_cmdlist); + + add_cmd ("instruction-history", class_obscure, cmd_record_insn_history, _("\ +Print disassembled instructions stored in the execution log.\n\ +With a /m modifier, source lines are included (if available).\n\ +With a /r modifier, raw instructions in hex are included.\n\ +With a /f modifier, function names are omitted.\n\ +With no argument, disassembles ten more instructions after the previous \ +disassembly.\n\ +\"record instruction-history -\" disassembles ten instructions before a \ +previous disassembly.\n\ +One argument specifies an instruction number as shown by 'info record', and \ +ten instructions are disassembled after that instruction.\n\ +Two arguments with comma between specify starting and ending instruction \ +numbers to disassemble.\n\ +If the second argument is preceded by '+' or '-', it specifies the distance \ +from the first argument.\n\ +The number of instructions to disassemble can be defined with \"set record \ +instruction-history-size\"."), + &record_cmdlist); } diff --git a/gdb/target.c b/gdb/target.c index 8512ae5..e9d70b7 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -4360,6 +4360,57 @@ target_goto_record (ULONGEST insn) tcomplain (); } +/* See target.h. */ + +void +target_insn_history (int size, int flags) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + if (t->to_insn_history != NULL) + { + t->to_insn_history (size, flags); + return; + } + + tcomplain (); +} + +/* See target.h. */ + +void +target_insn_history_from (ULONGEST from, int size, int flags) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + if (t->to_insn_history_from != NULL) + { + t->to_insn_history_from (from, size, flags); + return; + } + + tcomplain (); +} + +/* See target.h. */ + +void +target_insn_history_range (ULONGEST begin, ULONGEST end, int flags) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + if (t->to_insn_history_range != NULL) + { + t->to_insn_history_range (begin, end, flags); + return; + } + + tcomplain (); +} + static void debug_to_prepare_to_store (struct regcache *regcache) { diff --git a/gdb/target.h b/gdb/target.h index d416193..4ecb6e2 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -897,6 +897,17 @@ struct target_ops /* Go to a specific location in the recorded execution trace. */ void (*to_goto_record) (ULONGEST insn); + /* Disassemble SIZE instructions in the recorded execution trace from + the current position. */ + void (*to_insn_history) (int size, int flags); + + /* Disassemble SIZE instructions in the recorded execution trace around + FROM. */ + void (*to_insn_history_from) (ULONGEST FROM, int size, int flags); + + /* Disassemble a section of the recorded execution trace. */ + void (*to_insn_history_range) (ULONGEST begin, ULONGEST end, int flags); + int to_magic; /* Need sub-structure for target machine related rather than comm related? */ @@ -1983,4 +1994,13 @@ extern void target_goto_record_end (void); /* See to_goto_record in struct target_ops. */ extern void target_goto_record (ULONGEST insn); +/* See to_insn_history. */ +extern void target_insn_history (int size, int flags); + +/* See to_insn_history_from. */ +extern void target_insn_history_from (ULONGEST from, int size, int flags); + +/* See to_insn_history_range. */ +extern void target_insn_history_range (ULONGEST begin, ULONGEST end, int flags); + #endif /* !defined (TARGET_H) */ -- 1.7.1