xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/cli/cli-dump.c (revision 8ecbf5f02b752fcb7debe1a8fab1dc82602bc760)
1 /* Dump-to-file commands, for GDB, the GNU debugger.
2 
3    Copyright (C) 2002-2017 Free Software Foundation, Inc.
4 
5    Contributed by Red Hat.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 #include "defs.h"
23 #include "cli/cli-decode.h"
24 #include "cli/cli-cmds.h"
25 #include "value.h"
26 #include "completer.h"
27 #include <ctype.h>
28 #include "target.h"
29 #include "readline/readline.h"
30 #include "gdbcore.h"
31 #include "cli/cli-utils.h"
32 #include "gdb_bfd.h"
33 #include "filestuff.h"
34 
35 
36 static const char *
37 scan_expression_with_cleanup (const char **cmd, const char *def)
38 {
39   if ((*cmd) == NULL || (**cmd) == '\0')
40     {
41       char *exp = xstrdup (def);
42 
43       make_cleanup (xfree, exp);
44       return exp;
45     }
46   else
47     {
48       char *exp;
49       const char *end;
50 
51       end = (*cmd) + strcspn (*cmd, " \t");
52       exp = savestring ((*cmd), end - (*cmd));
53       make_cleanup (xfree, exp);
54       (*cmd) = skip_spaces_const (end);
55       return exp;
56     }
57 }
58 
59 
60 static char *
61 scan_filename_with_cleanup (const char **cmd, const char *defname)
62 {
63   char *filename;
64   char *fullname;
65 
66   /* FIXME: Need to get the ``/a(ppend)'' flag from somewhere.  */
67 
68   /* File.  */
69   if ((*cmd) == NULL)
70     {
71       if (defname == NULL)
72 	error (_("Missing filename."));
73       filename = xstrdup (defname);
74       make_cleanup (xfree, filename);
75     }
76   else
77     {
78       /* FIXME: should parse a possibly quoted string.  */
79       const char *end;
80 
81       (*cmd) = skip_spaces_const (*cmd);
82       end = *cmd + strcspn (*cmd, " \t");
83       filename = savestring ((*cmd), end - (*cmd));
84       make_cleanup (xfree, filename);
85       (*cmd) = skip_spaces_const (end);
86     }
87   gdb_assert (filename != NULL);
88 
89   fullname = tilde_expand (filename);
90   make_cleanup (xfree, fullname);
91 
92   return fullname;
93 }
94 
95 static FILE *
96 fopen_with_cleanup (const char *filename, const char *mode)
97 {
98   FILE *file = gdb_fopen_cloexec (filename, mode);
99 
100   if (file == NULL)
101     perror_with_name (filename);
102   make_cleanup_fclose (file);
103   return file;
104 }
105 
106 static gdb_bfd_ref_ptr
107 bfd_openr_or_error (const char *filename, const char *target)
108 {
109   gdb_bfd_ref_ptr ibfd (gdb_bfd_openr (filename, target));
110   if (ibfd == NULL)
111     error (_("Failed to open %s: %s."), filename,
112 	   bfd_errmsg (bfd_get_error ()));
113 
114   if (!bfd_check_format (ibfd.get (), bfd_object))
115     error (_("'%s' is not a recognized file format."), filename);
116 
117   return ibfd;
118 }
119 
120 static gdb_bfd_ref_ptr
121 bfd_openw_or_error (const char *filename, const char *target, const char *mode)
122 {
123   gdb_bfd_ref_ptr obfd;
124 
125   if (*mode == 'w')	/* Write: create new file */
126     {
127       obfd = gdb_bfd_openw (filename, target);
128       if (obfd == NULL)
129 	error (_("Failed to open %s: %s."), filename,
130 	       bfd_errmsg (bfd_get_error ()));
131       if (!bfd_set_format (obfd.get (), bfd_object))
132 	error (_("bfd_openw_or_error: %s."), bfd_errmsg (bfd_get_error ()));
133     }
134   else if (*mode == 'a')	/* Append to existing file.  */
135     {	/* FIXME -- doesn't work...  */
136       error (_("bfd_openw does not work with append."));
137     }
138   else
139     error (_("bfd_openw_or_error: unknown mode %s."), mode);
140 
141   return obfd;
142 }
143 
144 static struct cmd_list_element *dump_cmdlist;
145 static struct cmd_list_element *append_cmdlist;
146 static struct cmd_list_element *srec_cmdlist;
147 static struct cmd_list_element *ihex_cmdlist;
148 static struct cmd_list_element *verilog_cmdlist;
149 static struct cmd_list_element *tekhex_cmdlist;
150 static struct cmd_list_element *binary_dump_cmdlist;
151 static struct cmd_list_element *binary_append_cmdlist;
152 
153 static void
154 dump_command (char *cmd, int from_tty)
155 {
156   printf_unfiltered (_("\"dump\" must be followed by a subcommand.\n\n"));
157   help_list (dump_cmdlist, "dump ", all_commands, gdb_stdout);
158 }
159 
160 static void
161 append_command (char *cmd, int from_tty)
162 {
163   printf_unfiltered (_("\"append\" must be followed by a subcommand.\n\n"));
164   help_list (dump_cmdlist, "append ", all_commands, gdb_stdout);
165 }
166 
167 static void
168 dump_binary_file (const char *filename, const char *mode,
169 		  const bfd_byte *buf, ULONGEST len)
170 {
171   FILE *file;
172   int status;
173 
174   file = fopen_with_cleanup (filename, mode);
175   status = fwrite (buf, len, 1, file);
176   if (status != 1)
177     perror_with_name (filename);
178 }
179 
180 static void
181 dump_bfd_file (const char *filename, const char *mode,
182 	       const char *target, CORE_ADDR vaddr,
183 	       const bfd_byte *buf, ULONGEST len)
184 {
185   asection *osection;
186 
187   gdb_bfd_ref_ptr obfd (bfd_openw_or_error (filename, target, mode));
188   osection = bfd_make_section_anyway (obfd.get (), ".newsec");
189   bfd_set_section_size (obfd.get (), osection, len);
190   bfd_set_section_vma (obfd.get (), osection, vaddr);
191   bfd_set_section_alignment (obfd.get (), osection, 0);
192   bfd_set_section_flags (obfd.get (), osection, (SEC_HAS_CONTENTS
193 						 | SEC_ALLOC
194 						 | SEC_LOAD));
195   osection->entsize = 0;
196   if (!bfd_set_section_contents (obfd.get (), osection, buf, 0, len))
197     warning (_("writing dump file '%s' (%s)"), filename,
198 	     bfd_errmsg (bfd_get_error ()));
199 }
200 
201 static void
202 dump_memory_to_file (const char *cmd, const char *mode, const char *file_format)
203 {
204   struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
205   CORE_ADDR lo;
206   CORE_ADDR hi;
207   ULONGEST count;
208   const char *filename;
209   const char *lo_exp;
210   const char *hi_exp;
211 
212   /* Open the file.  */
213   filename = scan_filename_with_cleanup (&cmd, NULL);
214 
215   /* Find the low address.  */
216   if (cmd == NULL || *cmd == '\0')
217     error (_("Missing start address."));
218   lo_exp = scan_expression_with_cleanup (&cmd, NULL);
219 
220   /* Find the second address - rest of line.  */
221   if (cmd == NULL || *cmd == '\0')
222     error (_("Missing stop address."));
223   hi_exp = cmd;
224 
225   lo = parse_and_eval_address (lo_exp);
226   hi = parse_and_eval_address (hi_exp);
227   if (hi <= lo)
228     error (_("Invalid memory address range (start >= end)."));
229   count = hi - lo;
230 
231   /* FIXME: Should use read_memory_partial() and a magic blocking
232      value.  */
233   std::unique_ptr<gdb_byte[]> buf (new gdb_byte[count]);
234   read_memory (lo, buf.get (), count);
235 
236   /* Have everything.  Open/write the data.  */
237   if (file_format == NULL || strcmp (file_format, "binary") == 0)
238     {
239       dump_binary_file (filename, mode, buf.get (), count);
240     }
241   else
242     {
243       dump_bfd_file (filename, mode, file_format, lo, buf.get (), count);
244     }
245 
246   do_cleanups (old_cleanups);
247 }
248 
249 static void
250 dump_memory_command (char *cmd, const char *mode)
251 {
252   dump_memory_to_file (cmd, mode, "binary");
253 }
254 
255 static void
256 dump_value_to_file (const char *cmd, const char *mode, const char *file_format)
257 {
258   struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
259   struct value *val;
260   const char *filename;
261 
262   /* Open the file.  */
263   filename = scan_filename_with_cleanup (&cmd, NULL);
264 
265   /* Find the value.  */
266   if (cmd == NULL || *cmd == '\0')
267     error (_("No value to %s."), *mode == 'a' ? "append" : "dump");
268   val = parse_and_eval (cmd);
269   if (val == NULL)
270     error (_("Invalid expression."));
271 
272   /* Have everything.  Open/write the data.  */
273   if (file_format == NULL || strcmp (file_format, "binary") == 0)
274     {
275       dump_binary_file (filename, mode, value_contents (val),
276 			TYPE_LENGTH (value_type (val)));
277     }
278   else
279     {
280       CORE_ADDR vaddr;
281 
282       if (VALUE_LVAL (val))
283 	{
284 	  vaddr = value_address (val);
285 	}
286       else
287 	{
288 	  vaddr = 0;
289 	  warning (_("value is not an lval: address assumed to be zero"));
290 	}
291 
292       dump_bfd_file (filename, mode, file_format, vaddr,
293 		     value_contents (val),
294 		     TYPE_LENGTH (value_type (val)));
295     }
296 
297   do_cleanups (old_cleanups);
298 }
299 
300 static void
301 dump_value_command (char *cmd, const char *mode)
302 {
303   dump_value_to_file (cmd, mode, "binary");
304 }
305 
306 static void
307 dump_srec_memory (char *args, int from_tty)
308 {
309   dump_memory_to_file (args, FOPEN_WB, "srec");
310 }
311 
312 static void
313 dump_srec_value (char *args, int from_tty)
314 {
315   dump_value_to_file (args, FOPEN_WB, "srec");
316 }
317 
318 static void
319 dump_ihex_memory (char *args, int from_tty)
320 {
321   dump_memory_to_file (args, FOPEN_WB, "ihex");
322 }
323 
324 static void
325 dump_ihex_value (char *args, int from_tty)
326 {
327   dump_value_to_file (args, FOPEN_WB, "ihex");
328 }
329 
330 static void
331 dump_verilog_memory (char *args, int from_tty)
332 {
333   dump_memory_to_file (args, FOPEN_WB, "verilog");
334 }
335 
336 static void
337 dump_verilog_value (char *args, int from_tty)
338 {
339   dump_value_to_file (args, FOPEN_WB, "verilog");
340 }
341 
342 static void
343 dump_tekhex_memory (char *args, int from_tty)
344 {
345   dump_memory_to_file (args, FOPEN_WB, "tekhex");
346 }
347 
348 static void
349 dump_tekhex_value (char *args, int from_tty)
350 {
351   dump_value_to_file (args, FOPEN_WB, "tekhex");
352 }
353 
354 static void
355 dump_binary_memory (char *args, int from_tty)
356 {
357   dump_memory_to_file (args, FOPEN_WB, "binary");
358 }
359 
360 static void
361 dump_binary_value (char *args, int from_tty)
362 {
363   dump_value_to_file (args, FOPEN_WB, "binary");
364 }
365 
366 static void
367 append_binary_memory (char *args, int from_tty)
368 {
369   dump_memory_to_file (args, FOPEN_AB, "binary");
370 }
371 
372 static void
373 append_binary_value (char *args, int from_tty)
374 {
375   dump_value_to_file (args, FOPEN_AB, "binary");
376 }
377 
378 struct dump_context
379 {
380   void (*func) (char *cmd, const char *mode);
381   const char *mode;
382 };
383 
384 static void
385 call_dump_func (struct cmd_list_element *c, char *args, int from_tty)
386 {
387   struct dump_context *d = (struct dump_context *) get_cmd_context (c);
388 
389   d->func (args, d->mode);
390 }
391 
392 static void
393 add_dump_command (const char *name,
394 		  void (*func) (char *args, const char *mode),
395 		  const char *descr)
396 
397 {
398   struct cmd_list_element *c;
399   struct dump_context *d;
400 
401   c = add_cmd (name, all_commands, NULL, descr, &dump_cmdlist);
402   c->completer =  filename_completer;
403   d = XNEW (struct dump_context);
404   d->func = func;
405   d->mode = FOPEN_WB;
406   set_cmd_context (c, d);
407   c->func = call_dump_func;
408 
409   c = add_cmd (name, all_commands, NULL, descr, &append_cmdlist);
410   c->completer =  filename_completer;
411   d = XNEW (struct dump_context);
412   d->func = func;
413   d->mode = FOPEN_AB;
414   set_cmd_context (c, d);
415   c->func = call_dump_func;
416 
417   /* Replace "Dump " at start of docstring with "Append " (borrowed
418      from [deleted] deprecated_add_show_from_set).  */
419   if (   c->doc[0] == 'W'
420       && c->doc[1] == 'r'
421       && c->doc[2] == 'i'
422       && c->doc[3] == 't'
423       && c->doc[4] == 'e'
424       && c->doc[5] == ' ')
425     c->doc = concat ("Append ", c->doc + 6, (char *)NULL);
426 }
427 
428 /* Opaque data for restore_section_callback.  */
429 struct callback_data {
430   CORE_ADDR load_offset;
431   CORE_ADDR load_start;
432   CORE_ADDR load_end;
433 };
434 
435 /* Function: restore_section_callback.
436 
437    Callback function for bfd_map_over_sections.
438    Selectively loads the sections into memory.  */
439 
440 static void
441 restore_section_callback (bfd *ibfd, asection *isec, void *args)
442 {
443   struct callback_data *data = (struct callback_data *) args;
444   bfd_vma sec_start  = bfd_section_vma (ibfd, isec);
445   bfd_size_type size = bfd_section_size (ibfd, isec);
446   bfd_vma sec_end    = sec_start + size;
447   bfd_size_type sec_offset = 0;
448   bfd_size_type sec_load_count = size;
449   struct cleanup *old_chain;
450   gdb_byte *buf;
451   int ret;
452 
453   /* Ignore non-loadable sections, eg. from elf files.  */
454   if (!(bfd_get_section_flags (ibfd, isec) & SEC_LOAD))
455     return;
456 
457   /* Does the section overlap with the desired restore range? */
458   if (sec_end <= data->load_start
459       || (data->load_end > 0 && sec_start >= data->load_end))
460     {
461       /* No, no useable data in this section.  */
462       printf_filtered (_("skipping section %s...\n"),
463 		       bfd_section_name (ibfd, isec));
464       return;
465     }
466 
467   /* Compare section address range with user-requested
468      address range (if any).  Compute where the actual
469      transfer should start and end.  */
470   if (sec_start < data->load_start)
471     sec_offset = data->load_start - sec_start;
472   /* Size of a partial transfer.  */
473   sec_load_count -= sec_offset;
474   if (data->load_end > 0 && sec_end > data->load_end)
475     sec_load_count -= sec_end - data->load_end;
476 
477   /* Get the data.  */
478   buf = (gdb_byte *) xmalloc (size);
479   old_chain = make_cleanup (xfree, buf);
480   if (!bfd_get_section_contents (ibfd, isec, buf, 0, size))
481     error (_("Failed to read bfd file %s: '%s'."), bfd_get_filename (ibfd),
482 	   bfd_errmsg (bfd_get_error ()));
483 
484   printf_filtered ("Restoring section %s (0x%lx to 0x%lx)",
485 		   bfd_section_name (ibfd, isec),
486 		   (unsigned long) sec_start,
487 		   (unsigned long) sec_end);
488 
489   if (data->load_offset != 0 || data->load_start != 0 || data->load_end != 0)
490     printf_filtered (" into memory (%s to %s)\n",
491 		     paddress (target_gdbarch (),
492 			       (unsigned long) sec_start
493 			       + sec_offset + data->load_offset),
494 		     paddress (target_gdbarch (),
495 			       (unsigned long) sec_start + sec_offset
496 				+ data->load_offset + sec_load_count));
497   else
498     puts_filtered ("\n");
499 
500   /* Write the data.  */
501   ret = target_write_memory (sec_start + sec_offset + data->load_offset,
502 			     buf + sec_offset, sec_load_count);
503   if (ret != 0)
504     warning (_("restore: memory write failed (%s)."), safe_strerror (ret));
505   do_cleanups (old_chain);
506   return;
507 }
508 
509 static void
510 restore_binary_file (const char *filename, struct callback_data *data)
511 {
512   struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
513   FILE *file = fopen_with_cleanup (filename, FOPEN_RB);
514   long len;
515 
516   /* Get the file size for reading.  */
517   if (fseek (file, 0, SEEK_END) == 0)
518     {
519       len = ftell (file);
520       if (len < 0)
521 	perror_with_name (filename);
522     }
523   else
524     perror_with_name (filename);
525 
526   if (len <= data->load_start)
527     error (_("Start address is greater than length of binary file %s."),
528 	   filename);
529 
530   /* Chop off "len" if it exceeds the requested load_end addr.  */
531   if (data->load_end != 0 && data->load_end < len)
532     len = data->load_end;
533   /* Chop off "len" if the requested load_start addr skips some bytes.  */
534   if (data->load_start > 0)
535     len -= data->load_start;
536 
537   printf_filtered
538     ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n",
539      filename,
540      (unsigned long) (data->load_start + data->load_offset),
541      (unsigned long) (data->load_start + data->load_offset + len));
542 
543   /* Now set the file pos to the requested load start pos.  */
544   if (fseek (file, data->load_start, SEEK_SET) != 0)
545     perror_with_name (filename);
546 
547   /* Now allocate a buffer and read the file contents.  */
548   std::unique_ptr<gdb_byte[]> buf (new gdb_byte[len]);
549   if (fread (buf.get (), 1, len, file) != len)
550     perror_with_name (filename);
551 
552   /* Now write the buffer into target memory.  */
553   len = target_write_memory (data->load_start + data->load_offset,
554 			     buf.get (), len);
555   if (len != 0)
556     warning (_("restore: memory write failed (%s)."), safe_strerror (len));
557   do_cleanups (cleanup);
558 }
559 
560 static void
561 restore_command (char *args_in, int from_tty)
562 {
563   char *filename;
564   struct callback_data data;
565   bfd *ibfd;
566   int binary_flag = 0;
567   const char *args = args_in;
568 
569   if (!target_has_execution)
570     noprocess ();
571 
572   data.load_offset = 0;
573   data.load_start  = 0;
574   data.load_end    = 0;
575 
576   /* Parse the input arguments.  First is filename (required).  */
577   filename = scan_filename_with_cleanup (&args, NULL);
578   if (args != NULL && *args != '\0')
579     {
580       static const char binary_string[] = "binary";
581 
582       /* Look for optional "binary" flag.  */
583       if (startswith (args, binary_string))
584 	{
585 	  binary_flag = 1;
586 	  args += strlen (binary_string);
587 	  args = skip_spaces_const (args);
588 	}
589       /* Parse offset (optional).  */
590       if (args != NULL && *args != '\0')
591 	data.load_offset = binary_flag ?
592 	  parse_and_eval_address (scan_expression_with_cleanup (&args, NULL)) :
593 	  parse_and_eval_long (scan_expression_with_cleanup (&args, NULL));
594       if (args != NULL && *args != '\0')
595 	{
596 	  /* Parse start address (optional).  */
597 	  data.load_start =
598 	    parse_and_eval_long (scan_expression_with_cleanup (&args, NULL));
599 	  if (args != NULL && *args != '\0')
600 	    {
601 	      /* Parse end address (optional).  */
602 	      data.load_end = parse_and_eval_long (args);
603 	      if (data.load_end <= data.load_start)
604 		error (_("Start must be less than end."));
605 	    }
606 	}
607     }
608 
609   if (info_verbose)
610     printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n",
611 		     filename, (unsigned long) data.load_offset,
612 		     (unsigned long) data.load_start,
613 		     (unsigned long) data.load_end);
614 
615   if (binary_flag)
616     {
617       restore_binary_file (filename, &data);
618     }
619   else
620     {
621       /* Open the file for loading.  */
622       gdb_bfd_ref_ptr ibfd (bfd_openr_or_error (filename, NULL));
623 
624       /* Process the sections.  */
625       bfd_map_over_sections (ibfd.get (), restore_section_callback, &data);
626     }
627 }
628 
629 static void
630 srec_dump_command (char *cmd, int from_tty)
631 {
632   printf_unfiltered (_("\"dump srec\" must be followed by a subcommand.\n"));
633   help_list (srec_cmdlist, "dump srec ", all_commands, gdb_stdout);
634 }
635 
636 static void
637 ihex_dump_command (char *cmd, int from_tty)
638 {
639   printf_unfiltered (_("\"dump ihex\" must be followed by a subcommand.\n"));
640   help_list (ihex_cmdlist, "dump ihex ", all_commands, gdb_stdout);
641 }
642 
643 static void
644 verilog_dump_command (char *cmd, int from_tty)
645 {
646   printf_unfiltered (_("\"dump verilog\" must be followed by a subcommand.\n"));
647   help_list (verilog_cmdlist, "dump verilog ", all_commands, gdb_stdout);
648 }
649 
650 static void
651 tekhex_dump_command (char *cmd, int from_tty)
652 {
653   printf_unfiltered (_("\"dump tekhex\" must be followed by a subcommand.\n"));
654   help_list (tekhex_cmdlist, "dump tekhex ", all_commands, gdb_stdout);
655 }
656 
657 static void
658 binary_dump_command (char *cmd, int from_tty)
659 {
660   printf_unfiltered (_("\"dump binary\" must be followed by a subcommand.\n"));
661   help_list (binary_dump_cmdlist, "dump binary ", all_commands, gdb_stdout);
662 }
663 
664 static void
665 binary_append_command (char *cmd, int from_tty)
666 {
667   printf_unfiltered (_("\"append binary\" must be followed by a subcommand.\n"));
668   help_list (binary_append_cmdlist, "append binary ", all_commands,
669 	     gdb_stdout);
670 }
671 
672 extern initialize_file_ftype _initialize_cli_dump; /* -Wmissing-prototypes */
673 
674 void
675 _initialize_cli_dump (void)
676 {
677   struct cmd_list_element *c;
678 
679   add_prefix_cmd ("dump", class_vars, dump_command,
680 		  _("Dump target code/data to a local file."),
681 		  &dump_cmdlist, "dump ",
682 		  0/*allow-unknown*/,
683 		  &cmdlist);
684   add_prefix_cmd ("append", class_vars, append_command,
685 		  _("Append target code/data to a local file."),
686 		  &append_cmdlist, "append ",
687 		  0/*allow-unknown*/,
688 		  &cmdlist);
689 
690   add_dump_command ("memory", dump_memory_command, "\
691 Write contents of memory to a raw binary file.\n\
692 Arguments are FILE START STOP.  Writes the contents of memory within the\n\
693 range [START .. STOP) to the specified FILE in raw target ordered bytes.");
694 
695   add_dump_command ("value", dump_value_command, "\
696 Write the value of an expression to a raw binary file.\n\
697 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION to\n\
698 the specified FILE in raw target ordered bytes.");
699 
700   add_prefix_cmd ("srec", all_commands, srec_dump_command,
701 		  _("Write target code/data to an srec file."),
702 		  &srec_cmdlist, "dump srec ",
703 		  0 /*allow-unknown*/,
704 		  &dump_cmdlist);
705 
706   add_prefix_cmd ("ihex", all_commands, ihex_dump_command,
707 		  _("Write target code/data to an intel hex file."),
708 		  &ihex_cmdlist, "dump ihex ",
709 		  0 /*allow-unknown*/,
710 		  &dump_cmdlist);
711 
712   add_prefix_cmd ("verilog", all_commands, verilog_dump_command,
713 		  _("Write target code/data to a verilog hex file."),
714 		  &verilog_cmdlist, "dump verilog ",
715 		  0 /*allow-unknown*/,
716 		  &dump_cmdlist);
717 
718   add_prefix_cmd ("tekhex", all_commands, tekhex_dump_command,
719 		  _("Write target code/data to a tekhex file."),
720 		  &tekhex_cmdlist, "dump tekhex ",
721 		  0 /*allow-unknown*/,
722 		  &dump_cmdlist);
723 
724   add_prefix_cmd ("binary", all_commands, binary_dump_command,
725 		  _("Write target code/data to a raw binary file."),
726 		  &binary_dump_cmdlist, "dump binary ",
727 		  0 /*allow-unknown*/,
728 		  &dump_cmdlist);
729 
730   add_prefix_cmd ("binary", all_commands, binary_append_command,
731 		  _("Append target code/data to a raw binary file."),
732 		  &binary_append_cmdlist, "append binary ",
733 		  0 /*allow-unknown*/,
734 		  &append_cmdlist);
735 
736   add_cmd ("memory", all_commands, dump_srec_memory, _("\
737 Write contents of memory to an srec file.\n\
738 Arguments are FILE START STOP.  Writes the contents of memory\n\
739 within the range [START .. STOP) to the specified FILE in srec format."),
740 	   &srec_cmdlist);
741 
742   add_cmd ("value", all_commands, dump_srec_value, _("\
743 Write the value of an expression to an srec file.\n\
744 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
745 to the specified FILE in srec format."),
746 	   &srec_cmdlist);
747 
748   add_cmd ("memory", all_commands, dump_ihex_memory, _("\
749 Write contents of memory to an ihex file.\n\
750 Arguments are FILE START STOP.  Writes the contents of memory within\n\
751 the range [START .. STOP) to the specified FILE in intel hex format."),
752 	   &ihex_cmdlist);
753 
754   add_cmd ("value", all_commands, dump_ihex_value, _("\
755 Write the value of an expression to an ihex file.\n\
756 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
757 to the specified FILE in intel hex format."),
758 	   &ihex_cmdlist);
759 
760   add_cmd ("memory", all_commands, dump_verilog_memory, _("\
761 Write contents of memory to a verilog hex file.\n\
762 Arguments are FILE START STOP.  Writes the contents of memory within\n\
763 the range [START .. STOP) to the specified FILE in verilog hex format."),
764 	   &verilog_cmdlist);
765 
766   add_cmd ("value", all_commands, dump_verilog_value, _("\
767 Write the value of an expression to a verilog hex file.\n\
768 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
769 to the specified FILE in verilog hex format."),
770 	   &verilog_cmdlist);
771 
772   add_cmd ("memory", all_commands, dump_tekhex_memory, _("\
773 Write contents of memory to a tekhex file.\n\
774 Arguments are FILE START STOP.  Writes the contents of memory\n\
775 within the range [START .. STOP) to the specified FILE in tekhex format."),
776 	   &tekhex_cmdlist);
777 
778   add_cmd ("value", all_commands, dump_tekhex_value, _("\
779 Write the value of an expression to a tekhex file.\n\
780 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
781 to the specified FILE in tekhex format."),
782 	   &tekhex_cmdlist);
783 
784   add_cmd ("memory", all_commands, dump_binary_memory, _("\
785 Write contents of memory to a raw binary file.\n\
786 Arguments are FILE START STOP.  Writes the contents of memory\n\
787 within the range [START .. STOP) to the specified FILE in binary format."),
788 	   &binary_dump_cmdlist);
789 
790   add_cmd ("value", all_commands, dump_binary_value, _("\
791 Write the value of an expression to a raw binary file.\n\
792 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
793 to the specified FILE in raw target ordered bytes."),
794 	   &binary_dump_cmdlist);
795 
796   add_cmd ("memory", all_commands, append_binary_memory, _("\
797 Append contents of memory to a raw binary file.\n\
798 Arguments are FILE START STOP.  Writes the contents of memory within the\n\
799 range [START .. STOP) to the specified FILE in raw target ordered bytes."),
800 	   &binary_append_cmdlist);
801 
802   add_cmd ("value", all_commands, append_binary_value, _("\
803 Append the value of an expression to a raw binary file.\n\
804 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
805 to the specified FILE in raw target ordered bytes."),
806 	   &binary_append_cmdlist);
807 
808   c = add_com ("restore", class_vars, restore_command, _("\
809 Restore the contents of FILE to target memory.\n\
810 Arguments are FILE OFFSET START END where all except FILE are optional.\n\
811 OFFSET will be added to the base address of the file (default zero).\n\
812 If START and END are given, only the file contents within that range\n\
813 (file relative) will be restored to target memory."));
814   c->completer = filename_completer;
815   /* FIXME: completers for other commands.  */
816 }
817