Add a new modifier /c to "disassemble" command to make it output binary code

Michael Snyder msnyder@vmware.com
Thu Jul 9 22:00:00 GMT 2009


How about test suites?
At a minimum, gdb.base/help.exp probably needs an update.

Hui Zhu wrote:
> Hi,
> 
> The objdump will output the binary code when it works but gdb not.
> I make a patch to add a new modifier /c to "disassemble" command to
> make it output binary code.
> Please help me review it.
> 
> Thanks,
> Hui
> 
> 2009-07-09  Hui Zhu  <teawater@gmail.com>
> 
> 	* cli/cli-cmds.c (disassemble_command): Add a new modifier /c
> 	to "disassemble" command to make it output binary code.
> 	(init_cli_cmds): Ditto.
> 	(print_disassembly): Add a new argument "code" to make sure
> 	output binary code or not.
> 	(disassemble_current_function): Ditto.
> 	* mi/mi-cmd-disas.c (mi_cmd_disassemble): Ditto.
> 	* stack.c (gdb_disassembly_stub): Ditto.
> 	* disasm.h (gdb_disassembly): Ditto.
> 	* disasm.c (do_mixed_source_and_assembly): Ditto.
> 	(do_mixed_source_and_assembly): Ditto.
> 	(do_assembly_only): Ditto.
> 	(gdb_disassembly): Ditto.
> 	(dump_insns): Output the binary code if "code" is true.
> 
> ---
>  cli/cli-cmds.c    |   27 +++++++++++++++++----------
>  disasm.c          |   35 ++++++++++++++++++++++++++---------
>  disasm.h          |    3 ++-
>  mi/mi-cmd-disas.c |    2 +-
>  stack.c           |    2 +-
>  5 files changed, 47 insertions(+), 22 deletions(-)
> 
> --- a/cli/cli-cmds.c
> +++ b/cli/cli-cmds.c
> @@ -908,7 +908,7 @@ list_command (char *arg, int from_tty)
> 
>  static void
>  print_disassembly (struct gdbarch *gdbarch, const char *name,
> -		   CORE_ADDR low, CORE_ADDR high, int mixed)
> +		   CORE_ADDR low, CORE_ADDR high, int mixed, int code)
>  {
>  #if defined(TUI)
>    if (!tui_is_window_visible (DISASSEM_WIN))
> @@ -922,7 +922,7 @@ print_disassembly (struct gdbarch *gdbar
>  			 paddress (gdbarch, low), paddress (gdbarch, high));
> 
>        /* Dump the specified range.  */
> -      gdb_disassembly (gdbarch, uiout, 0, mixed, -1, low, high);
> +      gdb_disassembly (gdbarch, uiout, 0, mixed, -1, code, low, high);
> 
>        printf_filtered ("End of assembler dump.\n");
>        gdb_flush (gdb_stdout);
> @@ -940,7 +940,7 @@ print_disassembly (struct gdbarch *gdbar
>     MIXED is non-zero to print source with the assembler.  */
> 
>  static void
> -disassemble_current_function (int mixed)
> +disassemble_current_function (int mixed, int code)
>  {
>    struct frame_info *frame;
>    struct gdbarch *gdbarch;
> @@ -961,20 +961,21 @@ disassemble_current_function (int mixed)
>  #endif
>    low += gdbarch_deprecated_function_start_offset (gdbarch);
> 
> -  print_disassembly (gdbarch, name, low, high, mixed);
> +  print_disassembly (gdbarch, name, low, high, mixed, code);
>  }
> 
>  /* Dump a specified section of assembly code.
> 
>     Usage:
> -     disassemble [/m]
> +     disassemble [/mc]
>         - dump the assembly code for the function of the current pc
> -     disassemble [/m] addr
> +     disassemble [/mc] addr
>         - dump the assembly code for the function at ADDR
> -     disassemble [/m] low high
> +     disassemble [/mc] low high
>         - dump the assembly code in the range [LOW,HIGH)
> 
> -   A /m modifier will include source code with the assembly.  */
> +   A /m modifier will include source code with the assembly.
> +   A /c modifier will include binary code with the assembly.  */
> 
>  static void
>  disassemble_command (char *arg, int from_tty)
> @@ -985,9 +986,11 @@ disassemble_command (char *arg, int from
>    CORE_ADDR pc, pc_masked;
>    char *space_index;
>    int mixed_source_and_assembly;
> +  int code;
> 
>    name = NULL;
>    mixed_source_and_assembly = 0;
> +  code = 0;
> 
>    if (arg && *arg == '/')
>      {
> @@ -1003,6 +1006,9 @@ disassemble_command (char *arg, int from
>  	    case 'm':
>  	      mixed_source_and_assembly = 1;
>  	      break;
> +	    case 'c':
> +	      code = 1;
> +	      break;
>  	    default:
>  	      error (_("Invalid disassembly modifier."));
>  	    }
> @@ -1014,7 +1020,7 @@ disassemble_command (char *arg, int from
> 
>    if (! arg || ! *arg)
>      {
> -      disassemble_current_function (mixed_source_and_assembly);
> +      disassemble_current_function (mixed_source_and_assembly, code);
>        return;
>      }
> 
> @@ -1044,7 +1050,7 @@ disassemble_command (char *arg, int from
>        high = parse_and_eval_address (space_index + 1);
>      }
> 
> -  print_disassembly (gdbarch, name, low, high, mixed_source_and_assembly);
> +  print_disassembly (gdbarch, name, low, high,
> mixed_source_and_assembly, code);
>  }
> 
>  static void
> @@ -1453,6 +1459,7 @@ With two args if one is empty it stands
>  Disassemble a specified section of memory.\n\
>  Default is the function surrounding the pc of the selected frame.\n\
>  With a /m modifier, source lines are included (if available).\n\
> +With a /c modifier, binary code 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."));
>    set_cmd_completer (c, location_completer);
> --- a/disasm.c
> +++ b/disasm.c
> @@ -88,7 +88,7 @@ static int
>  dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
>  	    struct disassemble_info * di,
>  	    CORE_ADDR low, CORE_ADDR high,
> -	    int how_many, struct ui_stream *stb)
> +	    int how_many, int code, struct ui_stream *stb)
>  {
>    int num_displayed = 0;
>    CORE_ADDR pc;
> @@ -135,7 +135,23 @@ dump_insns (struct gdbarch *gdbarch, str
>  	xfree (name);
> 
>        ui_file_rewind (stb->stream);
> -      pc += gdbarch_print_insn (gdbarch, pc, di);
> +      if (code)
> +        {
> +          CORE_ADDR old_pc = pc;
> +          bfd_byte data;
> +          int status;
> +          pc += gdbarch_print_insn (gdbarch, pc, di);
> +          for (;old_pc < pc; old_pc++)
> +            {
> +              status = (*di->read_memory_func) (old_pc, &data, 1, di);
> +              if (status != 0)
> +                (*di->memory_error_func) (status, old_pc, di);
> +              ui_out_message (uiout, 0, " %02x", (unsigned)data);
> +            }
> +          ui_out_text (uiout, "\t");
> +        }
> +      else
> +        pc += gdbarch_print_insn (gdbarch, pc, di);
>        ui_out_field_stream (uiout, "inst", stb);
>        ui_file_rewind (stb->stream);
>        do_cleanups (ui_out_chain);
> @@ -154,7 +170,7 @@ do_mixed_source_and_assembly (struct gdb
>  			      struct linetable_entry *le,
>  			      CORE_ADDR low, CORE_ADDR high,
>  			      struct symtab *symtab,
> -			      int how_many, struct ui_stream *stb)
> +			      int how_many, int code, struct ui_stream *stb)
>  {
>    int newlines = 0;
>    struct dis_line_entry *mle;
> @@ -278,7 +294,7 @@ do_mixed_source_and_assembly (struct gdb
> 
>        num_displayed += dump_insns (gdbarch, uiout, di,
>  				   mle[i].start_pc, mle[i].end_pc,
> -				   how_many, stb);
> +				   how_many, code, stb);
> 
>        /* When we've reached the end of the mle array, or we've seen the last
>           assembly range for this source line, close out the list/tuple.  */
> @@ -301,14 +317,15 @@ static void
>  do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
>  		  struct disassemble_info * di,
>  		  CORE_ADDR low, CORE_ADDR high,
> -		  int how_many, struct ui_stream *stb)
> +		  int how_many, int code, struct ui_stream *stb)
>  {
>    int num_displayed = 0;
>    struct cleanup *ui_out_chain;
> 
>    ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
> 
> -  num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many, stb);
> +  num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many,
> +                              code, stb);
> 
>    do_cleanups (ui_out_chain);
>  }
> @@ -357,7 +374,7 @@ void
>  gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
>  		char *file_string,
>  		int mixed_source_and_assembly,
> -		int how_many, CORE_ADDR low, CORE_ADDR high)
> +		int how_many, int code, CORE_ADDR low, CORE_ADDR high)
>  {
>    struct ui_stream *stb = ui_out_stream_new (uiout);
>    struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb);
> @@ -379,11 +396,11 @@ gdb_disassembly (struct gdbarch *gdbarch
> 
>    if (!mixed_source_and_assembly || nlines <= 0
>        || symtab == NULL || symtab->linetable == NULL)
> -    do_assembly_only (gdbarch, uiout, &di, low, high, how_many, stb);
> +    do_assembly_only (gdbarch, uiout, &di, low, high, how_many, code, stb);
> 
>    else if (mixed_source_and_assembly)
>      do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low,
> -				  high, symtab, how_many, stb);
> +				  high, symtab, how_many, code, stb);
> 
>    do_cleanups (cleanups);
>    gdb_flush (gdb_stdout);
> --- a/disasm.h
> +++ b/disasm.h
> @@ -25,7 +25,8 @@ struct ui_file;
>  extern void gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
>  			     char *file_string,
>  			     int mixed_source_and_assembly,
> -			     int how_many, CORE_ADDR low, CORE_ADDR high);
> +			     int how_many, int code, CORE_ADDR low,
> +	                     CORE_ADDR high);
> 
>  /* Print the instruction at address MEMADDR in debugged memory,
>     on STREAM.  Returns the length of the instruction, in bytes,
> --- a/mi/mi-cmd-disas.c
> +++ b/mi/mi-cmd-disas.c
> @@ -156,6 +156,6 @@ mi_cmd_disassemble (char *command, char
> 
>    gdb_disassembly (gdbarch, uiout,
>    		   file_string,
> -		   mixed_source_and_assembly, how_many, low, high);
> +		   mixed_source_and_assembly, 0, how_many, low, high);
> 
>  }
> --- a/stack.c
> +++ b/stack.c
> @@ -481,7 +481,7 @@ static void
>  gdb_disassembly_stub (void *args)
>  {
>    struct gdb_disassembly_stub_args *p = args;
> -  gdb_disassembly (p->gdbarch, uiout, 0, 0, p->how_many, p->low, p->high);
> +  gdb_disassembly (p->gdbarch, uiout, 0, 0, 1, p->how_many, p->low, p->high);
>  }
> 
>  /* Use TRY_CATCH to catch the exception from the gdb_disassembly
> 
> 
> 2009-07-09  Hui Zhu  <teawater@gmail.com>
> 
> 	* gdb.texinfo (disassemble): Add a new modifier /c
> 	to "disassemble" command to make it output binary code.
> 
> ---
>  doc/gdb.texinfo |    5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> --- a/doc/gdb.texinfo
> +++ b/doc/gdb.texinfo
> @@ -6177,10 +6177,11 @@ Variables}).
>  @cindex machine instructions
>  @cindex listing machine instructions
>  @item disassemble
> -@itemx disassemble /m
> +@itemx disassemble /mc
>  This specialized command dumps a range of memory as machine
>  instructions.  It can also print mixed source+disassembly by specifying
> -the @code{/m} modifier.
> +the @code{/m} modifier and print binary code by specifying
> +the @code{/c}.
>  The default memory range is the function surrounding the
>  program counter of the selected frame.  A single argument to this
>  command is a program counter value; @value{GDBN} dumps the function
> 
> 
> ------------------------------------------------------------------------
> 
> ---
>  cli/cli-cmds.c    |   27 +++++++++++++++++----------
>  disasm.c          |   35 ++++++++++++++++++++++++++---------
>  disasm.h          |    3 ++-
>  mi/mi-cmd-disas.c |    2 +-
>  stack.c           |    2 +-
>  5 files changed, 47 insertions(+), 22 deletions(-)
> 
> --- a/cli/cli-cmds.c
> +++ b/cli/cli-cmds.c
> @@ -908,7 +908,7 @@ list_command (char *arg, int from_tty)
>  
>  static void
>  print_disassembly (struct gdbarch *gdbarch, const char *name,
> -		   CORE_ADDR low, CORE_ADDR high, int mixed)
> +		   CORE_ADDR low, CORE_ADDR high, int mixed, int code)
>  {
>  #if defined(TUI)
>    if (!tui_is_window_visible (DISASSEM_WIN))
> @@ -922,7 +922,7 @@ print_disassembly (struct gdbarch *gdbar
>  			 paddress (gdbarch, low), paddress (gdbarch, high));
>  
>        /* Dump the specified range.  */
> -      gdb_disassembly (gdbarch, uiout, 0, mixed, -1, low, high);
> +      gdb_disassembly (gdbarch, uiout, 0, mixed, -1, code, low, high);
>  
>        printf_filtered ("End of assembler dump.\n");
>        gdb_flush (gdb_stdout);
> @@ -940,7 +940,7 @@ print_disassembly (struct gdbarch *gdbar
>     MIXED is non-zero to print source with the assembler.  */
>  
>  static void
> -disassemble_current_function (int mixed)
> +disassemble_current_function (int mixed, int code)
>  {
>    struct frame_info *frame;
>    struct gdbarch *gdbarch;
> @@ -961,20 +961,21 @@ disassemble_current_function (int mixed)
>  #endif
>    low += gdbarch_deprecated_function_start_offset (gdbarch);
>  
> -  print_disassembly (gdbarch, name, low, high, mixed);
> +  print_disassembly (gdbarch, name, low, high, mixed, code);
>  }
>  
>  /* Dump a specified section of assembly code.
>  
>     Usage:
> -     disassemble [/m]
> +     disassemble [/mc]
>         - dump the assembly code for the function of the current pc
> -     disassemble [/m] addr
> +     disassemble [/mc] addr
>         - dump the assembly code for the function at ADDR
> -     disassemble [/m] low high
> +     disassemble [/mc] low high
>         - dump the assembly code in the range [LOW,HIGH)
>  
> -   A /m modifier will include source code with the assembly.  */
> +   A /m modifier will include source code with the assembly.
> +   A /c modifier will include binary code with the assembly.  */
>  
>  static void
>  disassemble_command (char *arg, int from_tty)
> @@ -985,9 +986,11 @@ disassemble_command (char *arg, int from
>    CORE_ADDR pc, pc_masked;
>    char *space_index;
>    int mixed_source_and_assembly;
> +  int code;
>  
>    name = NULL;
>    mixed_source_and_assembly = 0;
> +  code = 0;
>  
>    if (arg && *arg == '/')
>      {
> @@ -1003,6 +1006,9 @@ disassemble_command (char *arg, int from
>  	    case 'm':
>  	      mixed_source_and_assembly = 1;
>  	      break;
> +	    case 'c':
> +	      code = 1;
> +	      break;
>  	    default:
>  	      error (_("Invalid disassembly modifier."));
>  	    }
> @@ -1014,7 +1020,7 @@ disassemble_command (char *arg, int from
>  
>    if (! arg || ! *arg)
>      {
> -      disassemble_current_function (mixed_source_and_assembly);
> +      disassemble_current_function (mixed_source_and_assembly, code);
>        return;
>      }
>  
> @@ -1044,7 +1050,7 @@ disassemble_command (char *arg, int from
>        high = parse_and_eval_address (space_index + 1);
>      }
>  
> -  print_disassembly (gdbarch, name, low, high, mixed_source_and_assembly);
> +  print_disassembly (gdbarch, name, low, high, mixed_source_and_assembly, code);
>  }
>  
>  static void
> @@ -1453,6 +1459,7 @@ With two args if one is empty it stands 
>  Disassemble a specified section of memory.\n\
>  Default is the function surrounding the pc of the selected frame.\n\
>  With a /m modifier, source lines are included (if available).\n\
> +With a /c modifier, binary code 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."));
>    set_cmd_completer (c, location_completer);
> --- a/disasm.c
> +++ b/disasm.c
> @@ -88,7 +88,7 @@ static int
>  dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
>  	    struct disassemble_info * di,
>  	    CORE_ADDR low, CORE_ADDR high,
> -	    int how_many, struct ui_stream *stb)
> +	    int how_many, int code, struct ui_stream *stb)
>  {
>    int num_displayed = 0;
>    CORE_ADDR pc;
> @@ -135,7 +135,23 @@ dump_insns (struct gdbarch *gdbarch, str
>  	xfree (name);
>  
>        ui_file_rewind (stb->stream);
> -      pc += gdbarch_print_insn (gdbarch, pc, di);
> +      if (code)
> +        {
> +          CORE_ADDR old_pc = pc;
> +          bfd_byte data;
> +          int status;
> +          pc += gdbarch_print_insn (gdbarch, pc, di);
> +          for (;old_pc < pc; old_pc++)
> +            {
> +              status = (*di->read_memory_func) (old_pc, &data, 1, di);
> +              if (status != 0)
> +                (*di->memory_error_func) (status, old_pc, di);
> +              ui_out_message (uiout, 0, " %02x", (unsigned)data);
> +            }
> +          ui_out_text (uiout, "\t");
> +        }
> +      else
> +        pc += gdbarch_print_insn (gdbarch, pc, di);
>        ui_out_field_stream (uiout, "inst", stb);
>        ui_file_rewind (stb->stream);
>        do_cleanups (ui_out_chain);
> @@ -154,7 +170,7 @@ do_mixed_source_and_assembly (struct gdb
>  			      struct linetable_entry *le,
>  			      CORE_ADDR low, CORE_ADDR high,
>  			      struct symtab *symtab,
> -			      int how_many, struct ui_stream *stb)
> +			      int how_many, int code, struct ui_stream *stb)
>  {
>    int newlines = 0;
>    struct dis_line_entry *mle;
> @@ -278,7 +294,7 @@ do_mixed_source_and_assembly (struct gdb
>  
>        num_displayed += dump_insns (gdbarch, uiout, di,
>  				   mle[i].start_pc, mle[i].end_pc,
> -				   how_many, stb);
> +				   how_many, code, stb);
>  
>        /* When we've reached the end of the mle array, or we've seen the last
>           assembly range for this source line, close out the list/tuple.  */
> @@ -301,14 +317,15 @@ static void
>  do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
>  		  struct disassemble_info * di,
>  		  CORE_ADDR low, CORE_ADDR high,
> -		  int how_many, struct ui_stream *stb)
> +		  int how_many, int code, struct ui_stream *stb)
>  {
>    int num_displayed = 0;
>    struct cleanup *ui_out_chain;
>  
>    ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
>  
> -  num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many, stb);
> +  num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many,
> +                              code, stb);
>  
>    do_cleanups (ui_out_chain);
>  }
> @@ -357,7 +374,7 @@ void
>  gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
>  		char *file_string,
>  		int mixed_source_and_assembly,
> -		int how_many, CORE_ADDR low, CORE_ADDR high)
> +		int how_many, int code, CORE_ADDR low, CORE_ADDR high)
>  {
>    struct ui_stream *stb = ui_out_stream_new (uiout);
>    struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb);
> @@ -379,11 +396,11 @@ gdb_disassembly (struct gdbarch *gdbarch
>  
>    if (!mixed_source_and_assembly || nlines <= 0
>        || symtab == NULL || symtab->linetable == NULL)
> -    do_assembly_only (gdbarch, uiout, &di, low, high, how_many, stb);
> +    do_assembly_only (gdbarch, uiout, &di, low, high, how_many, code, stb);
>  
>    else if (mixed_source_and_assembly)
>      do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low,
> -				  high, symtab, how_many, stb);
> +				  high, symtab, how_many, code, stb);
>  
>    do_cleanups (cleanups);
>    gdb_flush (gdb_stdout);
> --- a/disasm.h
> +++ b/disasm.h
> @@ -25,7 +25,8 @@ struct ui_file;
>  extern void gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
>  			     char *file_string,
>  			     int mixed_source_and_assembly,
> -			     int how_many, CORE_ADDR low, CORE_ADDR high);
> +			     int how_many, int code, CORE_ADDR low,
> +	                     CORE_ADDR high);
>  
>  /* Print the instruction at address MEMADDR in debugged memory,
>     on STREAM.  Returns the length of the instruction, in bytes,
> --- a/mi/mi-cmd-disas.c
> +++ b/mi/mi-cmd-disas.c
> @@ -156,6 +156,6 @@ mi_cmd_disassemble (char *command, char 
>  
>    gdb_disassembly (gdbarch, uiout,
>    		   file_string,
> -		   mixed_source_and_assembly, how_many, low, high);
> +		   mixed_source_and_assembly, 0, how_many, low, high);
>  
>  }
> --- a/stack.c
> +++ b/stack.c
> @@ -481,7 +481,7 @@ static void
>  gdb_disassembly_stub (void *args)
>  {
>    struct gdb_disassembly_stub_args *p = args;
> -  gdb_disassembly (p->gdbarch, uiout, 0, 0, p->how_many, p->low, p->high);
> +  gdb_disassembly (p->gdbarch, uiout, 0, 0, 1, p->how_many, p->low, p->high);
>  }
>  
>  /* Use TRY_CATCH to catch the exception from the gdb_disassembly
> 
> 
> ------------------------------------------------------------------------
> 
> ---
>  doc/gdb.texinfo |    5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> --- a/doc/gdb.texinfo
> +++ b/doc/gdb.texinfo
> @@ -6177,10 +6177,11 @@ Variables}).
>  @cindex machine instructions
>  @cindex listing machine instructions
>  @item disassemble
> -@itemx disassemble /m
> +@itemx disassemble /mc
>  This specialized command dumps a range of memory as machine
>  instructions.  It can also print mixed source+disassembly by specifying
> -the @code{/m} modifier.
> +the @code{/m} modifier and print binary code by specifying
> +the @code{/c}.
>  The default memory range is the function surrounding the
>  program counter of the selected frame.  A single argument to this
>  command is a program counter value; @value{GDBN} dumps the function



More information about the Gdb-patches mailing list