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