This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC][patch] Allow to disassemble line.


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 <start> <end>',
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  <ppluzhnikov@google.com>

	* 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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]