include/
[external/binutils.git] / gdb / cli / cli-dump.c
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 }