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