From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29506 invoked by alias); 2 Oct 2009 00:50:06 -0000 Received: (qmail 29491 invoked by uid 22791); 2 Oct 2009 00:50:05 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.45.13) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 02 Oct 2009 00:49:59 +0000 Received: from wpaz13.hot.corp.google.com (wpaz13.hot.corp.google.com [172.24.198.77]) by smtp-out.google.com with ESMTP id n920nwFc013392 for ; Thu, 1 Oct 2009 17:49:58 -0700 Received: from ppluzhnikov.mtv.corp.google.com (ppluzhnikov.mtv.corp.google.com [172.18.118.92]) by wpaz13.hot.corp.google.com with ESMTP id n920nsJV007201; Thu, 1 Oct 2009 17:49:55 -0700 Received: by ppluzhnikov.mtv.corp.google.com (Postfix, from userid 74925) id 8966C76B2B; Thu, 1 Oct 2009 17:49:54 -0700 (PDT) To: gdb-patches@sourceware.org Cc: ppluzhnikov@google.com Subject: [RFC][patch] Allow to disassemble line. Message-Id: <20091002004954.8966C76B2B@ppluzhnikov.mtv.corp.google.com> Date: Fri, 02 Oct 2009 00:50:00 -0000 From: ppluzhnikov@google.com (Paul Pluzhnikov) 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: 2009-10/txt/msg00044.txt.bz2 Greetings, When debugging optimized code, I often need to disassemble current line (with inlining, that could be quite a lot of assembly). Currently, I do this by using 'info line' followed by 'disas ', where start and end are cut/pasted. Needless to say, that is quite inconvenient. Attached patch makes it so 'disas/l' will disassemble current line, and 'disas/l foo.c:22' will disassemble line 22 of foo.c This is similar to 'set disassemble-next-line', but not exactly the same, see below. I'll appreciate comments. I realize this will need documentation update as well, which I'll do if this is considered reasonable. Thanks, P.S. With 'set disassemble-next-line on', current GDB appears to not work as described in the manual. In particular, the manual for it says: If ON, GDB will display disassembly of the next source line when execution of the program being debugged stops. But what GDB actually does is disassemble from *current instruction* to the end of line. If the reason for stopping is a breakpoint on the given line, then the end result is the same either way. If the reason for stopping is a crash, then you get disassembly only from crash point to end of line. I think it's reasonable for GDB to behave either way. If it should disassemble the *entire* current line, this code should be unified with my patch. If the current behavior is more desirable, the manual should be fixed instead. -- Paul Pluzhnikov 2009-10-01 Paul Pluzhnikov * cli/cli-cmds.c (disassemble_sal, disassemble_lines): New function. (disassemble_command): Handle /l modifier. (init_cli_cmds): Adjust help text. Index: cli/cli-cmds.c =================================================================== RCS file: /cvs/src/src/gdb/cli/cli-cmds.c,v retrieving revision 1.92 diff -u -p -u -r1.92 cli-cmds.c --- cli/cli-cmds.c 11 Jul 2009 14:04:23 -0000 1.92 +++ cli/cli-cmds.c 1 Oct 2009 22:26:49 -0000 @@ -964,6 +964,71 @@ disassemble_current_function (int flags) print_disassembly (gdbarch, name, low, high, flags); } +/* Disassemble line of code identified by SAL. */ + +static void +disassemble_sal (struct gdbarch *gdbarch, int flags, + const char *error_text, + const struct symtab_and_line *sal) +{ + char *name; + CORE_ADDR low, high; + + if (sal->line > 0 && find_line_pc_range (*sal, &low, &high) + && find_pc_partial_function (low, &name, NULL, NULL)) + { + if (low < high) + print_disassembly (gdbarch, name, low, high, flags); + else + printf_filtered (_("Line %s:%d contains no code.\n"), + sal->symtab->filename, sal->line); + } + else + error ("%s", error_text); +} + +/* Disassemble line LINE. If LINE is NULL, disassemle current line. */ + +static void +disassemble_lines (struct gdbarch *gdbarch, int flags, char *line) +{ + if (have_full_symbols () == 0 && have_partial_symbols () == 0) + error (_("No symbol table is loaded. Use the \"file\" command.")); + + if (line == NULL) + { + struct frame_info *frame; + struct symtab_and_line sal = { 0 }; + + frame = get_selected_frame (NULL); + find_frame_sal (frame, &sal); + disassemble_sal (gdbarch, flags, + _("No line information for current frame."), + &sal); + return; + } + else + { + struct cleanup *old_cleanups; + struct symtabs_and_lines sals; + + sals = decode_line_1 (&line, 0, 0, 0, 0, 0); + old_cleanups = make_cleanup (xfree, sals.sals); + if (sals.nelts > 1) + { + printf_filtered (_("Ambiguous line specification:\n")); + ambiguous_line_spec (&sals); + } + else if (sals.sals->line > 0) + disassemble_sal (gdbarch, flags, _("Unexpected error"), sals.sals); + else + error (_("Unable to decode line specification.")); + + do_cleanups (old_cleanups); + } + return; +} + /* Dump a specified section of assembly code. Usage: @@ -974,8 +1039,15 @@ disassemble_current_function (int flags) disassemble [/mr] low high - dump the assembly code in the range [LOW,HIGH) + disassemble /l[mr] + - dump the assembly code for current line + disassemble /l[mr] linespec + - dump the assembly code for linespec + A /m modifier will include source code with the assembly. - A /r modifier will include raw instructions in hex with the assembly. */ + A /r modifier will include raw instructions in hex with the assembly. + A /l modifier changes the meaning of argument to "line" instead of + "address". */ static void disassemble_command (char *arg, int from_tty) @@ -985,10 +1057,11 @@ disassemble_command (char *arg, int from char *name; CORE_ADDR pc, pc_masked; char *space_index; - int flags; + int flags, disassemble_line; name = NULL; flags = 0; + disassemble_line = 0; if (arg && *arg == '/') { @@ -1007,6 +1080,9 @@ disassemble_command (char *arg, int from case 'r': flags |= DISASSEMBLY_RAW_INSN; break; + case 'l': + disassemble_line = 1; + break; default: error (_("Invalid disassembly modifier.")); } @@ -1018,7 +1094,10 @@ disassemble_command (char *arg, int from if (! arg || ! *arg) { - disassemble_current_function (flags); + if (disassemble_line != 0) + disassemble_lines (gdbarch, flags, NULL); + else + disassemble_current_function (flags); return; } @@ -1028,6 +1107,12 @@ disassemble_command (char *arg, int from if (!(space_index = (char *) strchr (arg, ' '))) { /* One argument. */ + if (disassemble_line != 0) + { + /* We are given line coordinates rather than addresses. */ + disassemble_lines (gdbarch, flags, arg); + return; + } pc = parse_and_eval_address (arg); if (find_pc_partial_function (pc, &name, &low, &high) == 0) error (_("No function contains specified address.")); @@ -1044,6 +1129,13 @@ disassemble_command (char *arg, int from { /* Two arguments. */ *space_index = '\0'; + if (disassemble_line != 0) + { + /* We are given line coordinates rather than addresses. */ + warning (_("Second parameter ignored with /l modifier.\n")); + disassemble_lines (gdbarch, flags, arg); + return; + } low = parse_and_eval_address (arg); high = parse_and_eval_address (space_index + 1); } @@ -1457,10 +1549,12 @@ With two args if one is empty it stands c = add_com ("disassemble", class_vars, disassemble_command, _("\ Disassemble a specified section of memory.\n\ Default is the function surrounding the pc of the selected frame.\n\ +With a /l modifier, disassemble current line.\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 single argument, the function surrounding that address is dumped.\n\ -Two arguments are taken as a range of memory to dump.")); +Two arguments are taken as a range of memory to dump.\n\ +With a /l modifier, single argument is parsed as line specification.")); set_cmd_completer (c, location_completer); if (xdb_commands) add_com_alias ("va", "disassemble", class_xdb, 0);