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