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