PR gdb/7912:
[platform/upstream/binutils.git] / gdb / cli / cli-dump.c
1 /* Dump-to-file commands, for GDB, the GNU debugger.
2
3    Copyright (C) 2002-2013 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 #include "cli/cli-utils.h"
35 #include "gdb_bfd.h"
36 #include "filestuff.h"
37
38 #define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
39
40
41 char *
42 scan_expression_with_cleanup (char **cmd, const char *def)
43 {
44   if ((*cmd) == NULL || (**cmd) == '\0')
45     {
46       char *exp = xstrdup (def);
47
48       make_cleanup (xfree, exp);
49       return exp;
50     }
51   else
52     {
53       char *exp;
54       char *end;
55
56       end = (*cmd) + strcspn (*cmd, " \t");
57       exp = savestring ((*cmd), end - (*cmd));
58       make_cleanup (xfree, exp);
59       (*cmd) = skip_spaces (end);
60       return exp;
61     }
62 }
63
64
65 char *
66 scan_filename_with_cleanup (char **cmd, const char *defname)
67 {
68   char *filename;
69   char *fullname;
70
71   /* FIXME: Need to get the ``/a(ppend)'' flag from somewhere.  */
72
73   /* File.  */
74   if ((*cmd) == NULL)
75     {
76       if (defname == NULL)
77         error (_("Missing filename."));
78       filename = xstrdup (defname);
79       make_cleanup (xfree, filename);
80     }
81   else
82     {
83       /* FIXME: should parse a possibly quoted string.  */
84       char *end;
85
86       (*cmd) = skip_spaces (*cmd);
87       end = *cmd + strcspn (*cmd, " \t");
88       filename = savestring ((*cmd), end - (*cmd));
89       make_cleanup (xfree, filename);
90       (*cmd) = skip_spaces (end);
91     }
92   gdb_assert (filename != NULL);
93
94   fullname = tilde_expand (filename);
95   make_cleanup (xfree, fullname);
96   
97   return fullname;
98 }
99
100 FILE *
101 fopen_with_cleanup (const char *filename, const char *mode)
102 {
103   FILE *file = gdb_fopen_cloexec (filename, mode);
104
105   if (file == NULL)
106     perror_with_name (filename);
107   make_cleanup_fclose (file);
108   return file;
109 }
110
111 static bfd *
112 bfd_openr_with_cleanup (const char *filename, const char *target)
113 {
114   bfd *ibfd;
115
116   ibfd = gdb_bfd_openr (filename, target);
117   if (ibfd == NULL)
118     error (_("Failed to open %s: %s."), filename, 
119            bfd_errmsg (bfd_get_error ()));
120
121   make_cleanup_bfd_unref (ibfd);
122   if (!bfd_check_format (ibfd, bfd_object))
123     error (_("'%s' is not a recognized file format."), filename);
124
125   return ibfd;
126 }
127
128 static bfd *
129 bfd_openw_with_cleanup (const char *filename, const char *target,
130                         const char *mode)
131 {
132   bfd *obfd;
133
134   if (*mode == 'w')     /* Write: create new file */
135     {
136       obfd = gdb_bfd_openw (filename, target);
137       if (obfd == NULL)
138         error (_("Failed to open %s: %s."), filename, 
139                bfd_errmsg (bfd_get_error ()));
140       make_cleanup_bfd_unref (obfd);
141       if (!bfd_set_format (obfd, bfd_object))
142         error (_("bfd_openw_with_cleanup: %s."), bfd_errmsg (bfd_get_error ()));
143     }
144   else if (*mode == 'a')        /* Append to existing file.  */
145     {   /* FIXME -- doesn't work...  */
146       error (_("bfd_openw does not work with append."));
147     }
148   else
149     error (_("bfd_openw_with_cleanup: unknown mode %s."), mode);
150
151   return obfd;
152 }
153
154 static struct cmd_list_element *dump_cmdlist;
155 static struct cmd_list_element *append_cmdlist;
156 static struct cmd_list_element *srec_cmdlist;
157 static struct cmd_list_element *ihex_cmdlist;
158 static struct cmd_list_element *tekhex_cmdlist;
159 static struct cmd_list_element *binary_dump_cmdlist;
160 static struct cmd_list_element *binary_append_cmdlist;
161
162 static void
163 dump_command (char *cmd, int from_tty)
164 {
165   printf_unfiltered (_("\"dump\" must be followed by a subcommand.\n\n"));
166   help_list (dump_cmdlist, "dump ", -1, gdb_stdout);
167 }
168
169 static void
170 append_command (char *cmd, int from_tty)
171 {
172   printf_unfiltered (_("\"append\" must be followed by a subcommand.\n\n"));
173   help_list (dump_cmdlist, "append ", -1, gdb_stdout);
174 }
175
176 static void
177 dump_binary_file (const char *filename, const char *mode, 
178                   const bfd_byte *buf, ULONGEST len)
179 {
180   FILE *file;
181   int status;
182
183   file = fopen_with_cleanup (filename, mode);
184   status = fwrite (buf, len, 1, file);
185   if (status != 1)
186     perror_with_name (filename);
187 }
188
189 static void
190 dump_bfd_file (const char *filename, const char *mode, 
191                const char *target, CORE_ADDR vaddr, 
192                const bfd_byte *buf, ULONGEST len)
193 {
194   bfd *obfd;
195   asection *osection;
196
197   obfd = bfd_openw_with_cleanup (filename, target, mode);
198   osection = bfd_make_section_anyway (obfd, ".newsec");
199   bfd_set_section_size (obfd, osection, len);
200   bfd_set_section_vma (obfd, osection, vaddr);
201   bfd_set_section_alignment (obfd, osection, 0);
202   bfd_set_section_flags (obfd, osection, (SEC_HAS_CONTENTS
203                                           | SEC_ALLOC
204                                           | SEC_LOAD));
205   osection->entsize = 0;
206   if (!bfd_set_section_contents (obfd, osection, buf, 0, len))
207     warning (_("writing dump file '%s' (%s)"), filename, 
208              bfd_errmsg (bfd_get_error ()));
209 }
210
211 static void
212 dump_memory_to_file (char *cmd, char *mode, char *file_format)
213 {
214   struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
215   CORE_ADDR lo;
216   CORE_ADDR hi;
217   ULONGEST count;
218   char *filename;
219   void *buf;
220   char *lo_exp;
221   char *hi_exp;
222
223   /* Open the file.  */
224   filename = scan_filename_with_cleanup (&cmd, NULL);
225
226   /* Find the low address.  */
227   if (cmd == NULL || *cmd == '\0')
228     error (_("Missing start address."));
229   lo_exp = scan_expression_with_cleanup (&cmd, NULL);
230
231   /* Find the second address - rest of line.  */
232   if (cmd == NULL || *cmd == '\0')
233     error (_("Missing stop address."));
234   hi_exp = cmd;
235
236   lo = parse_and_eval_address (lo_exp);
237   hi = parse_and_eval_address (hi_exp);
238   if (hi <= lo)
239     error (_("Invalid memory address range (start >= end)."));
240   count = hi - lo;
241
242   /* FIXME: Should use read_memory_partial() and a magic blocking
243      value.  */
244   buf = xmalloc (count);
245   make_cleanup (xfree, buf);
246   read_memory (lo, buf, count);
247   
248   /* Have everything.  Open/write the data.  */
249   if (file_format == NULL || strcmp (file_format, "binary") == 0)
250     {
251       dump_binary_file (filename, mode, buf, count);
252     }
253   else
254     {
255       dump_bfd_file (filename, mode, file_format, lo, buf, count);
256     }
257
258   do_cleanups (old_cleanups);
259 }
260
261 static void
262 dump_memory_command (char *cmd, char *mode)
263 {
264   dump_memory_to_file (cmd, mode, "binary");
265 }
266
267 static void
268 dump_value_to_file (char *cmd, char *mode, char *file_format)
269 {
270   struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
271   struct value *val;
272   char *filename;
273
274   /* Open the file.  */
275   filename = scan_filename_with_cleanup (&cmd, NULL);
276
277   /* Find the value.  */
278   if (cmd == NULL || *cmd == '\0')
279     error (_("No value to %s."), *mode == 'a' ? "append" : "dump");
280   val = parse_and_eval (cmd);
281   if (val == NULL)
282     error (_("Invalid expression."));
283
284   /* Have everything.  Open/write the data.  */
285   if (file_format == NULL || strcmp (file_format, "binary") == 0)
286     {
287       dump_binary_file (filename, mode, value_contents (val), 
288                         TYPE_LENGTH (value_type (val)));
289     }
290   else
291     {
292       CORE_ADDR vaddr;
293
294       if (VALUE_LVAL (val))
295         {
296           vaddr = value_address (val);
297         }
298       else
299         {
300           vaddr = 0;
301           warning (_("value is not an lval: address assumed to be zero"));
302         }
303
304       dump_bfd_file (filename, mode, file_format, vaddr, 
305                      value_contents (val), 
306                      TYPE_LENGTH (value_type (val)));
307     }
308
309   do_cleanups (old_cleanups);
310 }
311
312 static void
313 dump_value_command (char *cmd, char *mode)
314 {
315   dump_value_to_file (cmd, mode, "binary");
316 }
317
318 static void
319 dump_srec_memory (char *args, int from_tty)
320 {
321   dump_memory_to_file (args, FOPEN_WB, "srec");
322 }
323
324 static void
325 dump_srec_value (char *args, int from_tty)
326 {
327   dump_value_to_file (args, FOPEN_WB, "srec");
328 }
329
330 static void
331 dump_ihex_memory (char *args, int from_tty)
332 {
333   dump_memory_to_file (args, FOPEN_WB, "ihex");
334 }
335
336 static void
337 dump_ihex_value (char *args, int from_tty)
338 {
339   dump_value_to_file (args, FOPEN_WB, "ihex");
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, char *mode);
381   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 = get_cmd_context (c);
388
389   d->func (args, d->mode);
390 }
391
392 void
393 add_dump_command (char *name, void (*func) (char *args, char *mode),
394                   char *descr)
395
396 {
397   struct cmd_list_element *c;
398   struct dump_context *d;
399
400   c = add_cmd (name, all_commands, NULL, descr, &dump_cmdlist);
401   c->completer =  filename_completer;
402   d = XMALLOC (struct dump_context);
403   d->func = func;
404   d->mode = FOPEN_WB;
405   set_cmd_context (c, d);
406   c->func = call_dump_func;
407
408   c = add_cmd (name, all_commands, NULL, descr, &append_cmdlist);
409   c->completer =  filename_completer;
410   d = XMALLOC (struct dump_context);
411   d->func = func;
412   d->mode = FOPEN_AB;
413   set_cmd_context (c, d);
414   c->func = call_dump_func;
415
416   /* Replace "Dump " at start of docstring with "Append " (borrowed
417      from [deleted] deprecated_add_show_from_set).  */
418   if (   c->doc[0] == 'W' 
419       && c->doc[1] == 'r' 
420       && c->doc[2] == 'i'
421       && c->doc[3] == 't' 
422       && c->doc[4] == 'e'
423       && c->doc[5] == ' ')
424     c->doc = concat ("Append ", c->doc + 6, (char *)NULL);
425 }
426
427 /* Opaque data for restore_section_callback.  */
428 struct callback_data {
429   CORE_ADDR load_offset;
430   CORE_ADDR load_start;
431   CORE_ADDR load_end;
432 };
433
434 /* Function: restore_section_callback.
435
436    Callback function for bfd_map_over_sections.
437    Selectively loads the sections into memory.  */
438
439 static void
440 restore_section_callback (bfd *ibfd, asection *isec, void *args)
441 {
442   struct callback_data *data = args;
443   bfd_vma sec_start  = bfd_section_vma (ibfd, isec);
444   bfd_size_type size = bfd_section_size (ibfd, isec);
445   bfd_vma sec_end    = sec_start + size;
446   bfd_size_type sec_offset = 0;
447   bfd_size_type sec_load_count = size;
448   struct cleanup *old_chain;
449   gdb_byte *buf;
450   int ret;
451
452   /* Ignore non-loadable sections, eg. from elf files.  */
453   if (!(bfd_get_section_flags (ibfd, isec) & SEC_LOAD))
454     return;
455
456   /* Does the section overlap with the desired restore range? */
457   if (sec_end <= data->load_start 
458       || (data->load_end > 0 && sec_start >= data->load_end))
459     {
460       /* No, no useable data in this section.  */
461       printf_filtered (_("skipping section %s...\n"), 
462                        bfd_section_name (ibfd, isec));
463       return;
464     }
465
466   /* Compare section address range with user-requested
467      address range (if any).  Compute where the actual
468      transfer should start and end.  */
469   if (sec_start < data->load_start)
470     sec_offset = data->load_start - sec_start;
471   /* Size of a partial transfer.  */
472   sec_load_count -= sec_offset;
473   if (data->load_end > 0 && sec_end > data->load_end)
474     sec_load_count -= sec_end - data->load_end;
475
476   /* Get the data.  */
477   buf = xmalloc (size);
478   old_chain = make_cleanup (xfree, buf);
479   if (!bfd_get_section_contents (ibfd, isec, buf, 0, size))
480     error (_("Failed to read bfd file %s: '%s'."), bfd_get_filename (ibfd), 
481            bfd_errmsg (bfd_get_error ()));
482
483   printf_filtered ("Restoring section %s (0x%lx to 0x%lx)",
484                    bfd_section_name (ibfd, isec), 
485                    (unsigned long) sec_start, 
486                    (unsigned long) sec_end);
487
488   if (data->load_offset != 0 || data->load_start != 0 || data->load_end != 0)
489     printf_filtered (" into memory (%s to %s)\n",
490                      paddress (target_gdbarch (),
491                                (unsigned long) sec_start
492                                + sec_offset + data->load_offset), 
493                      paddress (target_gdbarch (),
494                                (unsigned long) sec_start + sec_offset
495                                 + data->load_offset + sec_load_count));
496   else
497     puts_filtered ("\n");
498
499   /* Write the data.  */
500   ret = target_write_memory (sec_start + sec_offset + data->load_offset, 
501                              buf + sec_offset, sec_load_count);
502   if (ret != 0)
503     warning (_("restore: memory write failed (%s)."), safe_strerror (ret));
504   do_cleanups (old_chain);
505   return;
506 }
507
508 static void
509 restore_binary_file (char *filename, struct callback_data *data)
510 {
511   FILE *file = fopen_with_cleanup (filename, FOPEN_RB);
512   gdb_byte *buf;
513   long len;
514
515   /* Get the file size for reading.  */
516   if (fseek (file, 0, SEEK_END) == 0)
517     {
518       len = ftell (file);
519       if (len < 0)
520         perror_with_name (filename);
521     }
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
669   add_prefix_cmd ("dump", class_vars, dump_command,
670                   _("Dump target code/data to a local file."),
671                   &dump_cmdlist, "dump ",
672                   0/*allow-unknown*/,
673                   &cmdlist);
674   add_prefix_cmd ("append", class_vars, append_command,
675                   _("Append target code/data to a local file."),
676                   &append_cmdlist, "append ",
677                   0/*allow-unknown*/,
678                   &cmdlist);
679
680   add_dump_command ("memory", dump_memory_command, "\
681 Write contents of memory to a raw binary file.\n\
682 Arguments are FILE START STOP.  Writes the contents of memory within the\n\
683 range [START .. STOP) to the specified FILE in raw target ordered bytes.");
684
685   add_dump_command ("value", dump_value_command, "\
686 Write the value of an expression to a raw binary file.\n\
687 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION to\n\
688 the specified FILE in raw target ordered bytes.");
689
690   add_prefix_cmd ("srec", all_commands, srec_dump_command,
691                   _("Write target code/data to an srec file."),
692                   &srec_cmdlist, "dump srec ", 
693                   0 /*allow-unknown*/, 
694                   &dump_cmdlist);
695
696   add_prefix_cmd ("ihex", all_commands, ihex_dump_command,
697                   _("Write target code/data to an intel hex file."),
698                   &ihex_cmdlist, "dump ihex ", 
699                   0 /*allow-unknown*/, 
700                   &dump_cmdlist);
701
702   add_prefix_cmd ("tekhex", all_commands, tekhex_dump_command,
703                   _("Write target code/data to a tekhex file."),
704                   &tekhex_cmdlist, "dump tekhex ", 
705                   0 /*allow-unknown*/, 
706                   &dump_cmdlist);
707
708   add_prefix_cmd ("binary", all_commands, binary_dump_command,
709                   _("Write target code/data to a raw binary file."),
710                   &binary_dump_cmdlist, "dump binary ", 
711                   0 /*allow-unknown*/, 
712                   &dump_cmdlist);
713
714   add_prefix_cmd ("binary", all_commands, binary_append_command,
715                   _("Append target code/data to a raw binary file."),
716                   &binary_append_cmdlist, "append binary ", 
717                   0 /*allow-unknown*/, 
718                   &append_cmdlist);
719
720   add_cmd ("memory", all_commands, dump_srec_memory, _("\
721 Write contents of memory to an srec file.\n\
722 Arguments are FILE START STOP.  Writes the contents of memory\n\
723 within the range [START .. STOP) to the specified FILE in srec format."),
724            &srec_cmdlist);
725
726   add_cmd ("value", all_commands, dump_srec_value, _("\
727 Write the value of an expression to an srec file.\n\
728 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
729 to the specified FILE in srec format."),
730            &srec_cmdlist);
731
732   add_cmd ("memory", all_commands, dump_ihex_memory, _("\
733 Write contents of memory to an ihex file.\n\
734 Arguments are FILE START STOP.  Writes the contents of memory within\n\
735 the range [START .. STOP) to the specified FILE in intel hex format."),
736            &ihex_cmdlist);
737
738   add_cmd ("value", all_commands, dump_ihex_value, _("\
739 Write the value of an expression to an ihex file.\n\
740 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
741 to the specified FILE in intel hex format."),
742            &ihex_cmdlist);
743
744   add_cmd ("memory", all_commands, dump_tekhex_memory, _("\
745 Write contents of memory to a tekhex file.\n\
746 Arguments are FILE START STOP.  Writes the contents of memory\n\
747 within the range [START .. STOP) to the specified FILE in tekhex format."),
748            &tekhex_cmdlist);
749
750   add_cmd ("value", all_commands, dump_tekhex_value, _("\
751 Write the value of an expression to a tekhex file.\n\
752 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
753 to the specified FILE in tekhex format."),
754            &tekhex_cmdlist);
755
756   add_cmd ("memory", all_commands, dump_binary_memory, _("\
757 Write contents of memory to a raw binary file.\n\
758 Arguments are FILE START STOP.  Writes the contents of memory\n\
759 within the range [START .. STOP) to the specified FILE in binary format."),
760            &binary_dump_cmdlist);
761
762   add_cmd ("value", all_commands, dump_binary_value, _("\
763 Write the value of an expression to a raw binary file.\n\
764 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
765 to the specified FILE in raw target ordered bytes."),
766            &binary_dump_cmdlist);
767
768   add_cmd ("memory", all_commands, append_binary_memory, _("\
769 Append contents of memory to a raw binary file.\n\
770 Arguments are FILE START STOP.  Writes the contents of memory within the\n\
771 range [START .. STOP) to the specified FILE in raw target ordered bytes."),
772            &binary_append_cmdlist);
773
774   add_cmd ("value", all_commands, append_binary_value, _("\
775 Append the value of an expression to a raw binary file.\n\
776 Arguments are FILE EXPRESSION.  Writes the value of EXPRESSION\n\
777 to the specified FILE in raw target ordered bytes."),
778            &binary_append_cmdlist);
779
780   c = add_com ("restore", class_vars, restore_command, _("\
781 Restore the contents of FILE to target memory.\n\
782 Arguments are FILE OFFSET START END where all except FILE are optional.\n\
783 OFFSET will be added to the base address of the file (default zero).\n\
784 If START and END are given, only the file contents within that range\n\
785 (file relative) will be restored to target memory."));
786   c->completer = filename_completer;
787   /* FIXME: completers for other commands.  */
788 }