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]

Disassemble branch delay slot instructions automatically


Hello,

 This is a change that implements automatic disassembly of instructions in 
a branch delay slot if a branch is the last instruction to be output.  It 
is especially useful with the "display /i" command when single-stepping, 
where you may want to see a single instruction normally not to get 
distracted, but with a branch an intruction that follows would be executed 
without having been printed.

 Here is an example for MIPS machine code -- this is with our current 
implementation:

(gdb) x /i 0x801018a4
0x801018a4 <pthread_create+52>: beqz    v0,0x80101a10 <pthread_create+416>

and here -- the same command with the patch applied:

(gdb) x /i 0x801018a4
0x801018a4 <pthread_create+52>: beqz    v0,0x80101a10 <pthread_create+416>
0x801018a8 <pthread_create+56>: li      v1,11

This change has been tested natively for mips-unknown-linux-gnu and
remotely for mipsisa32-sde-elf, using mips-sim-sde32/-EB and
mips-sim-sde32/-EL as the targets, with no regressions.

2007-05-15  Nigel Stephens  <nigel@mips.com>
            Maciej W. Rozycki  <macro@mips.com>

	* disasm.c (gdb_set_disassemble_info): New public function to
	set up a disassemble_info structure, ready for a call to
	TARGET_PRINT_INSN.
	* disasm.h (gdb_set_disassemble_info): Add prototype.
	* printcmd.c (branch_delay_insns): New variable to record number
	of delay slots after disassembling a branch.
	(print_formatted): When disassembling don't call gdb_print_insn,
	but call TARGET_PRINT_INSN directly.  Then pick up the resulting
	branch_delay_insns from the disassemble_info structure and store
	in local variable of same name.
	(do_examine): When disassembling, if the last instruction
	disassembled has any branch delay slots, then bump the count so
	that they get disassembled too.

 OK to apply?

  Maciej

12235.diff
Index: binutils-quilt/src/gdb/printcmd.c
===================================================================
--- binutils-quilt.orig/src/gdb/printcmd.c	2007-05-15 18:59:05.000000000 +0100
+++ binutils-quilt/src/gdb/printcmd.c	2007-05-15 18:59:46.000000000 +0100
@@ -43,6 +43,7 @@
 #include "gdb_assert.h"
 #include "block.h"
 #include "disasm.h"
+#include "dis-asm.h"
 
 #ifdef TUI
 #include "tui/tui.h"		/* For tui_active et.al.   */
@@ -70,6 +71,10 @@
 
 static CORE_ADDR next_address;
 
+/* Number of delay instructions following current disassembled insn.  */
+
+static int branch_delay_insns;
+
 /* Last address examined.  */
 
 static CORE_ADDR last_examine_address;
@@ -277,8 +282,17 @@
 
       /* We often wrap here if there are long symbolic names.  */
       wrap_here ("    ");
-      next_address = VALUE_ADDRESS (val)
-	+ gdb_print_insn (VALUE_ADDRESS (val), stream);
+      {
+	static struct disassemble_info di;
+
+	gdb_set_disassemble_info (current_gdbarch, stream, &di);
+	next_address = (VALUE_ADDRESS (val)
+			+ TARGET_PRINT_INSN (VALUE_ADDRESS (val), &di));
+	if (di.insn_info_valid)
+	  branch_delay_insns = di.branch_delay_insns;
+	else
+	  branch_delay_insns = 0;
+      }
       break;
 
     default:
@@ -800,6 +814,10 @@
 	    release_value (last_examine_value);
 
 	  print_formatted (last_examine_value, format, size, gdb_stdout);
+
+	  /* Display any branch delay slots following the final insn.  */
+	  if (format == 'i' && count == 1)
+	    count += branch_delay_insns;
 	}
       printf_filtered ("\n");
       gdb_flush (gdb_stdout);
Index: binutils-quilt/src/gdb/disasm.c
===================================================================
--- binutils-quilt.orig/src/gdb/disasm.c	2007-05-15 18:59:05.000000000 +0100
+++ binutils-quilt/src/gdb/disasm.c	2007-05-15 18:59:46.000000000 +0100
@@ -349,6 +349,15 @@
   return di;
 }
 
+/* Publicly callable version of gdb_disassemble_info which doesn't
+   return a structure, but stores the result via a pointer.  */
+void
+gdb_set_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file,
+			  struct disassemble_info *di)
+{
+  *di = gdb_disassemble_info (gdbarch, file);
+}
+
 void
 gdb_disassembly (struct ui_out *uiout,
 		char *file_string,
Index: binutils-quilt/src/gdb/disasm.h
===================================================================
--- binutils-quilt.orig/src/gdb/disasm.h	2007-05-15 18:59:05.000000000 +0100
+++ binutils-quilt/src/gdb/disasm.h	2007-05-15 18:59:46.000000000 +0100
@@ -35,4 +35,13 @@
 
 extern int gdb_print_insn (CORE_ADDR memaddr, struct ui_file *stream);
 
+/* Fill in a disassemble_info structure, ready for a call to
+   TARGET_PRINT_INSN.  */
+
+struct disassemble_info;
+
+extern void gdb_set_disassemble_info (struct gdbarch *,
+				      struct ui_file *,
+				      struct disassemble_info *);
+
 #endif


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