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