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