diff mbox

[v3] Add command to erase all flash memory regions

Message ID 1484659856-22290-1-git-send-email-lgustavo@codesourcery.com
State New
Headers show

Commit Message

Luis Machado Jan. 17, 2017, 1:30 p.m. UTC
Changes in v3:

- Addressed comments by Pedro.
- Output of memory region size now in hex format.
- Misc formatting fixups.
- Addressed Simon's comments on formatting.
- Adjusted command text in the manual entry.
- Fixed up ChangeLog.
- Renamed flash_erase_all_command to flash_erase_command.

Changes in v2:

- Added NEWS entry.
- Fixed long lines.
- Address printing with paddress.

Years ago we contributed flash programming patches upstream.  The following
patch is a leftover one that complements that functionality by adding a new
command to erase all reported flash memory blocks.

The command is most useful when we're dealing with flash-enabled targets
(mostly bare-metal) and we need to reset the board for some reason.

The wiping out of flash memory regions should help the target come up with a
known clean state from which the user can load a new image and resume
debugging. It is convenient enough to do this from the debugger, and there is
also an MI command to expose this functionality to the IDE's.

Regression tested on Ubuntu 16.04 x86-64. No regressions.

Thoughts?

gdb/doc/ChangeLog:

2017-01-17  Mike Wrighton  <mike_wrighton@codesourcery.com>
	    Luis Machado  <lgustavo@codesourcery.com>

	* gdb.texinfo (-target-flash-erase): New MI command description.
	(flash-erase): New CLI command description.

gdb/ChangeLog:

2017-01-17  Mike Wrighton  <mike_wrighton@codesourcery.com>
	    Luis Machado  <lgustavo@codesourcery.com>

	* NEWS (New commands): Mention flash-erase.
	(New MI commands): Mention target-flash-erase.
	* mi/mi-cmds.c (mi_cmd_target_flash_erase): Added target-flash-erase MI
	command.
	* mi/mi-cmds.h (mi_cmd_target_flash_erase): New declaration.
	* mi/mi-main.c (mi_cmd_target_flash_erase): New function.
	* target.c (flash_erase_command): New function.
	(initialize_targets): Add new flash-erase command.
	* target.h (flash_erase_command): New declaration.
---
 gdb/NEWS            | 11 +++++++++++
 gdb/doc/gdb.texinfo | 32 ++++++++++++++++++++++++++++++++
 gdb/mi/mi-cmds.c    |  1 +
 gdb/mi/mi-cmds.h    |  1 +
 gdb/mi/mi-main.c    |  6 ++++++
 gdb/target.c        | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/target.h        |  3 +++
 7 files changed, 103 insertions(+)

Comments

Pedro Alves Jan. 19, 2017, 3:28 p.m. UTC | #1
> 2017-01-17  Mike Wrighton  <mike_wrighton@codesourcery.com>
> 	    Luis Machado  <lgustavo@codesourcery.com>
> 
> 	* NEWS (New commands): Mention flash-erase.
> 	(New MI commands): Mention target-flash-erase.
> 	* mi/mi-cmds.c (mi_cmd_target_flash_erase): Added target-flash-erase MI
> 	command.

"Add".

> 	* mi/mi-cmds.h (mi_cmd_target_flash_erase): New declaration.
> 	* mi/mi-main.c (mi_cmd_target_flash_erase): New function.
> 	* target.c (flash_erase_command): New function.
> 	(initialize_targets): Add new flash-erase command.
> 	* target.h (flash_erase_command): New declaration.



> +@smallexample
> +(gdb)
> +-target-flash-erase
> +^done,erased-regions=@{address="0x0",size="0x40000"@}
> +(gdb)


> +          current_uiout->message (", size = ");
> +          current_uiout->field_fmt ("size", "0x%s", phex (m->hi - m->lo, 0));

phex always prints 64-bit hex numbers with leading "00000000".  So 
I think that instead of:

  +^done,erased-regions=@{address="0x0",size="0x40000"@}

you're getting something like:

  +^done,erased-regions=@{address="0x0",size="0x0000000000040000"@}

You can avoid that by using phex_nz instead.  Or better, use
hex_string, and remove the "0x" from the string, since hex_string
already handles that.

OK with that change.

Thanks,
Pedro Alves
Luis Machado Jan. 20, 2017, 2:14 p.m. UTC | #2
On 01/19/2017 09:28 AM, Pedro Alves wrote:
>> 2017-01-17  Mike Wrighton  <mike_wrighton@codesourcery.com>
>> 	    Luis Machado  <lgustavo@codesourcery.com>
>>
>> 	* NEWS (New commands): Mention flash-erase.
>> 	(New MI commands): Mention target-flash-erase.
>> 	* mi/mi-cmds.c (mi_cmd_target_flash_erase): Added target-flash-erase MI
>> 	command.
>
> "Add".
>

Fixed.

>> 	* mi/mi-cmds.h (mi_cmd_target_flash_erase): New declaration.
>> 	* mi/mi-main.c (mi_cmd_target_flash_erase): New function.
>> 	* target.c (flash_erase_command): New function.
>> 	(initialize_targets): Add new flash-erase command.
>> 	* target.h (flash_erase_command): New declaration.
>
>
>
>> +@smallexample
>> +(gdb)
>> +-target-flash-erase
>> +^done,erased-regions=@{address="0x0",size="0x40000"@}
>> +(gdb)
>
>
>> +          current_uiout->message (", size = ");
>> +          current_uiout->field_fmt ("size", "0x%s", phex (m->hi - m->lo, 0));
>
> phex always prints 64-bit hex numbers with leading "00000000".  So
> I think that instead of:
>
>   +^done,erased-regions=@{address="0x0",size="0x40000"@}
>
> you're getting something like:
>
>   +^done,erased-regions=@{address="0x0",size="0x0000000000040000"@}
>
> You can avoid that by using phex_nz instead.  Or better, use
> hex_string, and remove the "0x" from the string, since hex_string
> already handles that.

That looks better.

>
> OK with that change.

Addressed the above and pushed to master as
78cbbba8e0bc8b0288f5ce4360b4689ab893aa13.

Thanks,
Luis
diff mbox

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index b976815..21e8cd3 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -57,6 +57,17 @@  FreeBSD/mips			mips*-*-freebsd
 Synopsys ARC			arc*-*-elf32
 FreeBSD/mips			mips*-*-freebsd
 
+* New commands
+
+flash-erase
+  Erases all the flash memory regions reported by the target.
+
+* New MI commands
+
+-target-flash-erase
+  Erases all the flash memory regions reported by the target.  This is
+  equivalent to the CLI command flash-erase.
+
 *** Changes in GDB 7.12
 
 * GDB and GDBserver now build with a C++ compiler by default.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 14628fa..6d0b281 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19626,6 +19626,16 @@  load programs into flash memory.
 @code{load} does not repeat if you press @key{RET} again after using it.
 @end table
 
+@table @code
+
+@kindex flash-erase
+@item flash-erase
+@anchor{flash-erase}
+
+Erases all known flash memory regions on the target.
+
+@end table
+
 @node Byte Order
 @section Choosing Target Byte Order
 
@@ -31863,6 +31873,28 @@  No equivalent.
 @subsubheading Example
 N.A.
 
+@subheading The @code{-target-flash-erase} Command
+@findex -target-flash-erase
+
+@subsubheading Synopsis
+
+@smallexample
+ -target-flash-erase
+@end smallexample
+
+Erases all known flash memory regions on the target.
+
+The corresponding @value{GDBN} command is @samp{flash-erase}.
+
+The output is a list of flash regions that have been erased, with starting
+addresses and memory region sizes.
+
+@smallexample
+(gdb)
+-target-flash-erase
+^done,erased-regions=@{address="0x0",size="0x40000"@}
+(gdb)
+@end smallexample
 
 @subheading The @code{-target-select} Command
 @findex -target-select
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index cdea008..abb70bd 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -147,6 +147,7 @@  static struct mi_cmd mi_cmds[] =
   DEF_MI_CMD_MI ("target-file-delete", mi_cmd_target_file_delete),
   DEF_MI_CMD_MI ("target-file-get", mi_cmd_target_file_get),
   DEF_MI_CMD_MI ("target-file-put", mi_cmd_target_file_put),
+  DEF_MI_CMD_MI ("target-flash-erase", mi_cmd_target_flash_erase),
   DEF_MI_CMD_CLI ("target-select", "target", 1),
   DEF_MI_CMD_MI ("thread-info", mi_cmd_thread_info),
   DEF_MI_CMD_MI ("thread-list-ids", mi_cmd_thread_list_ids),
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index 8bd947b..d0906e6 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -93,6 +93,7 @@  extern mi_cmd_argv_ftype mi_cmd_target_detach;
 extern mi_cmd_argv_ftype mi_cmd_target_file_get;
 extern mi_cmd_argv_ftype mi_cmd_target_file_put;
 extern mi_cmd_argv_ftype mi_cmd_target_file_delete;
+extern mi_cmd_argv_ftype mi_cmd_target_flash_erase;
 extern mi_cmd_argv_ftype mi_cmd_thread_info;
 extern mi_cmd_argv_ftype mi_cmd_thread_list_ids;
 extern mi_cmd_argv_ftype mi_cmd_thread_select;
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 22803cb..57c23eb 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -553,6 +553,12 @@  mi_cmd_target_detach (char *command, char **argv, int argc)
 }
 
 void
+mi_cmd_target_flash_erase (char *command, char **argv, int argc)
+{
+  flash_erase_command (NULL, 0);
+}
+
+void
 mi_cmd_thread_select (char *command, char **argv, int argc)
 {
   enum gdb_rc rc;
diff --git a/gdb/target.c b/gdb/target.c
index be7367c..988602a 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3943,6 +3943,52 @@  do_monitor_command (char *cmd,
   target_rcmd (cmd, gdb_stdtarg);
 }
 
+/* Erases all the memory regions marked as flash.  CMD and FROM_TTY are
+   ignored.  */
+
+void
+flash_erase_command (char *cmd, int from_tty)
+{
+  /* Used to communicate termination of flash operations to the target.  */
+  bool found_flash_region = false;
+  struct mem_region *m;
+  struct gdbarch *gdbarch = target_gdbarch ();
+
+  VEC(mem_region_s) *mem_regions = target_memory_map ();
+
+  /* Iterate over all memory regions.  */
+  for (int i = 0; VEC_iterate (mem_region_s, mem_regions, i, m); i++)
+    {
+      /* Fetch the memory attribute.  */
+      struct mem_attrib *attrib = &m->attrib;
+
+      /* Is this a flash memory region?  */
+      if (attrib->mode == MEM_FLASH)
+        {
+          found_flash_region = true;
+          target_flash_erase (m->lo, m->hi - m->lo);
+
+	  struct cleanup *cleanup_tuple
+	      = make_cleanup_ui_out_tuple_begin_end (current_uiout,
+						     "erased-regions");
+
+          current_uiout->message (_("Erasing flash memory region at address "));
+          current_uiout->field_fmt ("address", "%s", paddress (gdbarch,
+								 m->lo));
+          current_uiout->message (", size = ");
+          current_uiout->field_fmt ("size", "0x%s", phex (m->hi - m->lo, 0));
+          current_uiout->message ("\n");
+          do_cleanups (cleanup_tuple);
+        }
+    }
+
+  /* Did we do any flash operations?  If so, we need to finalize them.  */
+  if (found_flash_region)
+    target_flash_done ();
+  else
+    current_uiout->message (_("No flash memory regions found.\n"));
+}
+
 /* Print the name of each layers of our target stack.  */
 
 static void
@@ -4233,6 +4279,9 @@  Otherwise, any attempt to interrupt or stop will be ignored."),
 			   set_target_permissions, NULL,
 			   &setlist, &showlist);
 
+  add_com ("flash-erase", no_class, flash_erase_command,
+           _("Erase all flash memory regions."));
+
   add_setshow_boolean_cmd ("auto-connect-native-target", class_support,
 			   &auto_connect_native_target, _("\
 Set whether GDB may automatically connect to the native target."), _("\
diff --git a/gdb/target.h b/gdb/target.h
index f2b9181..8df117e 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1451,6 +1451,9 @@  extern int target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr,
    is returned.  */
 VEC(mem_region_s) *target_memory_map (void);
 
+/* Erases all flash memory regions on the target.  */
+void flash_erase_command (char *cmd, int from_tty);
+
 /* Erase the specified flash region.  */
 void target_flash_erase (ULONGEST address, LONGEST length);