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