1 /* Dump-to-file commands, for GDB, the GNU debugger.
3 Copyright (C) 2002-2017 Free Software Foundation, Inc.
5 Contributed by Red Hat.
7 This file is part of GDB.
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.
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.
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/>. */
23 #include "cli/cli-decode.h"
24 #include "cli/cli-cmds.h"
26 #include "completer.h"
29 #include "readline/readline.h"
31 #include "cli/cli-utils.h"
33 #include "filestuff.h"
34 #include "common/byte-vector.h"
37 scan_expression_with_cleanup (const char **cmd
, const char *def
)
39 if ((*cmd
) == NULL
|| (**cmd
) == '\0')
41 char *exp
= xstrdup (def
);
43 make_cleanup (xfree
, exp
);
51 end
= (*cmd
) + strcspn (*cmd
, " \t");
52 exp
= savestring ((*cmd
), end
- (*cmd
));
53 make_cleanup (xfree
, exp
);
54 (*cmd
) = skip_spaces_const (end
);
61 scan_filename_with_cleanup (const char **cmd
, const char *defname
)
66 /* FIXME: Need to get the ``/a(ppend)'' flag from somewhere. */
72 error (_("Missing filename."));
73 filename
= xstrdup (defname
);
74 make_cleanup (xfree
, filename
);
78 /* FIXME: should parse a possibly quoted string. */
81 (*cmd
) = skip_spaces_const (*cmd
);
82 end
= *cmd
+ strcspn (*cmd
, " \t");
83 filename
= savestring ((*cmd
), end
- (*cmd
));
84 make_cleanup (xfree
, filename
);
85 (*cmd
) = skip_spaces_const (end
);
87 gdb_assert (filename
!= NULL
);
89 fullname
= tilde_expand (filename
);
90 make_cleanup (xfree
, fullname
);
95 static gdb_bfd_ref_ptr
96 bfd_openr_or_error (const char *filename
, const char *target
)
98 gdb_bfd_ref_ptr
ibfd (gdb_bfd_openr (filename
, target
));
100 error (_("Failed to open %s: %s."), filename
,
101 bfd_errmsg (bfd_get_error ()));
103 if (!bfd_check_format (ibfd
.get (), bfd_object
))
104 error (_("'%s' is not a recognized file format."), filename
);
109 static gdb_bfd_ref_ptr
110 bfd_openw_or_error (const char *filename
, const char *target
, const char *mode
)
112 gdb_bfd_ref_ptr obfd
;
114 if (*mode
== 'w') /* Write: create new file */
116 obfd
= gdb_bfd_openw (filename
, target
);
118 error (_("Failed to open %s: %s."), filename
,
119 bfd_errmsg (bfd_get_error ()));
120 if (!bfd_set_format (obfd
.get (), bfd_object
))
121 error (_("bfd_openw_or_error: %s."), bfd_errmsg (bfd_get_error ()));
123 else if (*mode
== 'a') /* Append to existing file. */
124 { /* FIXME -- doesn't work... */
125 error (_("bfd_openw does not work with append."));
128 error (_("bfd_openw_or_error: unknown mode %s."), mode
);
133 static struct cmd_list_element
*dump_cmdlist
;
134 static struct cmd_list_element
*append_cmdlist
;
135 static struct cmd_list_element
*srec_cmdlist
;
136 static struct cmd_list_element
*ihex_cmdlist
;
137 static struct cmd_list_element
*verilog_cmdlist
;
138 static struct cmd_list_element
*tekhex_cmdlist
;
139 static struct cmd_list_element
*binary_dump_cmdlist
;
140 static struct cmd_list_element
*binary_append_cmdlist
;
143 dump_command (char *cmd
, int from_tty
)
145 printf_unfiltered (_("\"dump\" must be followed by a subcommand.\n\n"));
146 help_list (dump_cmdlist
, "dump ", all_commands
, gdb_stdout
);
150 append_command (char *cmd
, int from_tty
)
152 printf_unfiltered (_("\"append\" must be followed by a subcommand.\n\n"));
153 help_list (dump_cmdlist
, "append ", all_commands
, gdb_stdout
);
157 dump_binary_file (const char *filename
, const char *mode
,
158 const bfd_byte
*buf
, ULONGEST len
)
162 gdb_file_up file
= gdb_fopen_cloexec (filename
, mode
);
163 status
= fwrite (buf
, len
, 1, file
.get ());
165 perror_with_name (filename
);
169 dump_bfd_file (const char *filename
, const char *mode
,
170 const char *target
, CORE_ADDR vaddr
,
171 const bfd_byte
*buf
, ULONGEST len
)
175 gdb_bfd_ref_ptr
obfd (bfd_openw_or_error (filename
, target
, mode
));
176 osection
= bfd_make_section_anyway (obfd
.get (), ".newsec");
177 bfd_set_section_size (obfd
.get (), osection
, len
);
178 bfd_set_section_vma (obfd
.get (), osection
, vaddr
);
179 bfd_set_section_alignment (obfd
.get (), osection
, 0);
180 bfd_set_section_flags (obfd
.get (), osection
, (SEC_HAS_CONTENTS
183 osection
->entsize
= 0;
184 if (!bfd_set_section_contents (obfd
.get (), osection
, buf
, 0, len
))
185 warning (_("writing dump file '%s' (%s)"), filename
,
186 bfd_errmsg (bfd_get_error ()));
190 dump_memory_to_file (const char *cmd
, const char *mode
, const char *file_format
)
192 struct cleanup
*old_cleanups
= make_cleanup (null_cleanup
, NULL
);
196 const char *filename
;
201 filename
= scan_filename_with_cleanup (&cmd
, NULL
);
203 /* Find the low address. */
204 if (cmd
== NULL
|| *cmd
== '\0')
205 error (_("Missing start address."));
206 lo_exp
= scan_expression_with_cleanup (&cmd
, NULL
);
208 /* Find the second address - rest of line. */
209 if (cmd
== NULL
|| *cmd
== '\0')
210 error (_("Missing stop address."));
213 lo
= parse_and_eval_address (lo_exp
);
214 hi
= parse_and_eval_address (hi_exp
);
216 error (_("Invalid memory address range (start >= end)."));
219 /* FIXME: Should use read_memory_partial() and a magic blocking
221 gdb::byte_vector
buf (count
);
222 read_memory (lo
, buf
.data (), count
);
224 /* Have everything. Open/write the data. */
225 if (file_format
== NULL
|| strcmp (file_format
, "binary") == 0)
227 dump_binary_file (filename
, mode
, buf
.data (), count
);
231 dump_bfd_file (filename
, mode
, file_format
, lo
, buf
.data (), count
);
234 do_cleanups (old_cleanups
);
238 dump_memory_command (char *cmd
, const char *mode
)
240 dump_memory_to_file (cmd
, mode
, "binary");
244 dump_value_to_file (const char *cmd
, const char *mode
, const char *file_format
)
246 struct cleanup
*old_cleanups
= make_cleanup (null_cleanup
, NULL
);
248 const char *filename
;
251 filename
= scan_filename_with_cleanup (&cmd
, NULL
);
253 /* Find the value. */
254 if (cmd
== NULL
|| *cmd
== '\0')
255 error (_("No value to %s."), *mode
== 'a' ? "append" : "dump");
256 val
= parse_and_eval (cmd
);
258 error (_("Invalid expression."));
260 /* Have everything. Open/write the data. */
261 if (file_format
== NULL
|| strcmp (file_format
, "binary") == 0)
263 dump_binary_file (filename
, mode
, value_contents (val
),
264 TYPE_LENGTH (value_type (val
)));
270 if (VALUE_LVAL (val
))
272 vaddr
= value_address (val
);
277 warning (_("value is not an lval: address assumed to be zero"));
280 dump_bfd_file (filename
, mode
, file_format
, vaddr
,
281 value_contents (val
),
282 TYPE_LENGTH (value_type (val
)));
285 do_cleanups (old_cleanups
);
289 dump_value_command (char *cmd
, const char *mode
)
291 dump_value_to_file (cmd
, mode
, "binary");
295 dump_srec_memory (char *args
, int from_tty
)
297 dump_memory_to_file (args
, FOPEN_WB
, "srec");
301 dump_srec_value (char *args
, int from_tty
)
303 dump_value_to_file (args
, FOPEN_WB
, "srec");
307 dump_ihex_memory (char *args
, int from_tty
)
309 dump_memory_to_file (args
, FOPEN_WB
, "ihex");
313 dump_ihex_value (char *args
, int from_tty
)
315 dump_value_to_file (args
, FOPEN_WB
, "ihex");
319 dump_verilog_memory (char *args
, int from_tty
)
321 dump_memory_to_file (args
, FOPEN_WB
, "verilog");
325 dump_verilog_value (char *args
, int from_tty
)
327 dump_value_to_file (args
, FOPEN_WB
, "verilog");
331 dump_tekhex_memory (char *args
, int from_tty
)
333 dump_memory_to_file (args
, FOPEN_WB
, "tekhex");
337 dump_tekhex_value (char *args
, int from_tty
)
339 dump_value_to_file (args
, FOPEN_WB
, "tekhex");
343 dump_binary_memory (char *args
, int from_tty
)
345 dump_memory_to_file (args
, FOPEN_WB
, "binary");
349 dump_binary_value (char *args
, int from_tty
)
351 dump_value_to_file (args
, FOPEN_WB
, "binary");
355 append_binary_memory (char *args
, int from_tty
)
357 dump_memory_to_file (args
, FOPEN_AB
, "binary");
361 append_binary_value (char *args
, int from_tty
)
363 dump_value_to_file (args
, FOPEN_AB
, "binary");
368 void (*func
) (char *cmd
, const char *mode
);
373 call_dump_func (struct cmd_list_element
*c
, char *args
, int from_tty
)
375 struct dump_context
*d
= (struct dump_context
*) get_cmd_context (c
);
377 d
->func (args
, d
->mode
);
381 add_dump_command (const char *name
,
382 void (*func
) (char *args
, const char *mode
),
386 struct cmd_list_element
*c
;
387 struct dump_context
*d
;
389 c
= add_cmd (name
, all_commands
, NULL
, descr
, &dump_cmdlist
);
390 c
->completer
= filename_completer
;
391 d
= XNEW (struct dump_context
);
394 set_cmd_context (c
, d
);
395 c
->func
= call_dump_func
;
397 c
= add_cmd (name
, all_commands
, NULL
, descr
, &append_cmdlist
);
398 c
->completer
= filename_completer
;
399 d
= XNEW (struct dump_context
);
402 set_cmd_context (c
, d
);
403 c
->func
= call_dump_func
;
405 /* Replace "Dump " at start of docstring with "Append " (borrowed
406 from [deleted] deprecated_add_show_from_set). */
407 if ( c
->doc
[0] == 'W'
413 c
->doc
= concat ("Append ", c
->doc
+ 6, (char *)NULL
);
416 /* Opaque data for restore_section_callback. */
417 struct callback_data
{
418 CORE_ADDR load_offset
;
419 CORE_ADDR load_start
;
423 /* Function: restore_section_callback.
425 Callback function for bfd_map_over_sections.
426 Selectively loads the sections into memory. */
429 restore_section_callback (bfd
*ibfd
, asection
*isec
, void *args
)
431 struct callback_data
*data
= (struct callback_data
*) args
;
432 bfd_vma sec_start
= bfd_section_vma (ibfd
, isec
);
433 bfd_size_type size
= bfd_section_size (ibfd
, isec
);
434 bfd_vma sec_end
= sec_start
+ size
;
435 bfd_size_type sec_offset
= 0;
436 bfd_size_type sec_load_count
= size
;
437 struct cleanup
*old_chain
;
441 /* Ignore non-loadable sections, eg. from elf files. */
442 if (!(bfd_get_section_flags (ibfd
, isec
) & SEC_LOAD
))
445 /* Does the section overlap with the desired restore range? */
446 if (sec_end
<= data
->load_start
447 || (data
->load_end
> 0 && sec_start
>= data
->load_end
))
449 /* No, no useable data in this section. */
450 printf_filtered (_("skipping section %s...\n"),
451 bfd_section_name (ibfd
, isec
));
455 /* Compare section address range with user-requested
456 address range (if any). Compute where the actual
457 transfer should start and end. */
458 if (sec_start
< data
->load_start
)
459 sec_offset
= data
->load_start
- sec_start
;
460 /* Size of a partial transfer. */
461 sec_load_count
-= sec_offset
;
462 if (data
->load_end
> 0 && sec_end
> data
->load_end
)
463 sec_load_count
-= sec_end
- data
->load_end
;
466 buf
= (gdb_byte
*) xmalloc (size
);
467 old_chain
= make_cleanup (xfree
, buf
);
468 if (!bfd_get_section_contents (ibfd
, isec
, buf
, 0, size
))
469 error (_("Failed to read bfd file %s: '%s'."), bfd_get_filename (ibfd
),
470 bfd_errmsg (bfd_get_error ()));
472 printf_filtered ("Restoring section %s (0x%lx to 0x%lx)",
473 bfd_section_name (ibfd
, isec
),
474 (unsigned long) sec_start
,
475 (unsigned long) sec_end
);
477 if (data
->load_offset
!= 0 || data
->load_start
!= 0 || data
->load_end
!= 0)
478 printf_filtered (" into memory (%s to %s)\n",
479 paddress (target_gdbarch (),
480 (unsigned long) sec_start
481 + sec_offset
+ data
->load_offset
),
482 paddress (target_gdbarch (),
483 (unsigned long) sec_start
+ sec_offset
484 + data
->load_offset
+ sec_load_count
));
486 puts_filtered ("\n");
488 /* Write the data. */
489 ret
= target_write_memory (sec_start
+ sec_offset
+ data
->load_offset
,
490 buf
+ sec_offset
, sec_load_count
);
492 warning (_("restore: memory write failed (%s)."), safe_strerror (ret
));
493 do_cleanups (old_chain
);
498 restore_binary_file (const char *filename
, struct callback_data
*data
)
500 gdb_file_up file
= gdb_fopen_cloexec (filename
, FOPEN_RB
);
503 /* Get the file size for reading. */
504 if (fseek (file
.get (), 0, SEEK_END
) == 0)
506 len
= ftell (file
.get ());
508 perror_with_name (filename
);
511 perror_with_name (filename
);
513 if (len
<= data
->load_start
)
514 error (_("Start address is greater than length of binary file %s."),
517 /* Chop off "len" if it exceeds the requested load_end addr. */
518 if (data
->load_end
!= 0 && data
->load_end
< len
)
519 len
= data
->load_end
;
520 /* Chop off "len" if the requested load_start addr skips some bytes. */
521 if (data
->load_start
> 0)
522 len
-= data
->load_start
;
525 ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n",
527 (unsigned long) (data
->load_start
+ data
->load_offset
),
528 (unsigned long) (data
->load_start
+ data
->load_offset
+ len
));
530 /* Now set the file pos to the requested load start pos. */
531 if (fseek (file
.get (), data
->load_start
, SEEK_SET
) != 0)
532 perror_with_name (filename
);
534 /* Now allocate a buffer and read the file contents. */
535 gdb::byte_vector
buf (len
);
536 if (fread (buf
.data (), 1, len
, file
.get ()) != len
)
537 perror_with_name (filename
);
539 /* Now write the buffer into target memory. */
540 len
= target_write_memory (data
->load_start
+ data
->load_offset
,
543 warning (_("restore: memory write failed (%s)."), safe_strerror (len
));
547 restore_command (char *args_in
, int from_tty
)
550 struct callback_data data
;
553 const char *args
= args_in
;
555 if (!target_has_execution
)
558 data
.load_offset
= 0;
562 /* Parse the input arguments. First is filename (required). */
563 filename
= scan_filename_with_cleanup (&args
, NULL
);
564 if (args
!= NULL
&& *args
!= '\0')
566 static const char binary_string
[] = "binary";
568 /* Look for optional "binary" flag. */
569 if (startswith (args
, binary_string
))
572 args
+= strlen (binary_string
);
573 args
= skip_spaces_const (args
);
575 /* Parse offset (optional). */
576 if (args
!= NULL
&& *args
!= '\0')
577 data
.load_offset
= binary_flag
?
578 parse_and_eval_address (scan_expression_with_cleanup (&args
, NULL
)) :
579 parse_and_eval_long (scan_expression_with_cleanup (&args
, NULL
));
580 if (args
!= NULL
&& *args
!= '\0')
582 /* Parse start address (optional). */
584 parse_and_eval_long (scan_expression_with_cleanup (&args
, NULL
));
585 if (args
!= NULL
&& *args
!= '\0')
587 /* Parse end address (optional). */
588 data
.load_end
= parse_and_eval_long (args
);
589 if (data
.load_end
<= data
.load_start
)
590 error (_("Start must be less than end."));
596 printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n",
597 filename
, (unsigned long) data
.load_offset
,
598 (unsigned long) data
.load_start
,
599 (unsigned long) data
.load_end
);
603 restore_binary_file (filename
, &data
);
607 /* Open the file for loading. */
608 gdb_bfd_ref_ptr
ibfd (bfd_openr_or_error (filename
, NULL
));
610 /* Process the sections. */
611 bfd_map_over_sections (ibfd
.get (), restore_section_callback
, &data
);
616 srec_dump_command (char *cmd
, int from_tty
)
618 printf_unfiltered (_("\"dump srec\" must be followed by a subcommand.\n"));
619 help_list (srec_cmdlist
, "dump srec ", all_commands
, gdb_stdout
);
623 ihex_dump_command (char *cmd
, int from_tty
)
625 printf_unfiltered (_("\"dump ihex\" must be followed by a subcommand.\n"));
626 help_list (ihex_cmdlist
, "dump ihex ", all_commands
, gdb_stdout
);
630 verilog_dump_command (char *cmd
, int from_tty
)
632 printf_unfiltered (_("\"dump verilog\" must be followed by a subcommand.\n"));
633 help_list (verilog_cmdlist
, "dump verilog ", all_commands
, gdb_stdout
);
637 tekhex_dump_command (char *cmd
, int from_tty
)
639 printf_unfiltered (_("\"dump tekhex\" must be followed by a subcommand.\n"));
640 help_list (tekhex_cmdlist
, "dump tekhex ", all_commands
, gdb_stdout
);
644 binary_dump_command (char *cmd
, int from_tty
)
646 printf_unfiltered (_("\"dump binary\" must be followed by a subcommand.\n"));
647 help_list (binary_dump_cmdlist
, "dump binary ", all_commands
, gdb_stdout
);
651 binary_append_command (char *cmd
, int from_tty
)
653 printf_unfiltered (_("\"append binary\" must be followed by a subcommand.\n"));
654 help_list (binary_append_cmdlist
, "append binary ", all_commands
,
658 extern initialize_file_ftype _initialize_cli_dump
; /* -Wmissing-prototypes */
661 _initialize_cli_dump (void)
663 struct cmd_list_element
*c
;
665 add_prefix_cmd ("dump", class_vars
, dump_command
,
666 _("Dump target code/data to a local file."),
667 &dump_cmdlist
, "dump ",
670 add_prefix_cmd ("append", class_vars
, append_command
,
671 _("Append target code/data to a local file."),
672 &append_cmdlist
, "append ",
676 add_dump_command ("memory", dump_memory_command
, "\
677 Write contents of memory to a raw binary file.\n\
678 Arguments are FILE START STOP. Writes the contents of memory within the\n\
679 range [START .. STOP) to the specified FILE in raw target ordered bytes.");
681 add_dump_command ("value", dump_value_command
, "\
682 Write the value of an expression to a raw binary file.\n\
683 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\
684 the specified FILE in raw target ordered bytes.");
686 add_prefix_cmd ("srec", all_commands
, srec_dump_command
,
687 _("Write target code/data to an srec file."),
688 &srec_cmdlist
, "dump srec ",
692 add_prefix_cmd ("ihex", all_commands
, ihex_dump_command
,
693 _("Write target code/data to an intel hex file."),
694 &ihex_cmdlist
, "dump ihex ",
698 add_prefix_cmd ("verilog", all_commands
, verilog_dump_command
,
699 _("Write target code/data to a verilog hex file."),
700 &verilog_cmdlist
, "dump verilog ",
704 add_prefix_cmd ("tekhex", all_commands
, tekhex_dump_command
,
705 _("Write target code/data to a tekhex file."),
706 &tekhex_cmdlist
, "dump tekhex ",
710 add_prefix_cmd ("binary", all_commands
, binary_dump_command
,
711 _("Write target code/data to a raw binary file."),
712 &binary_dump_cmdlist
, "dump binary ",
716 add_prefix_cmd ("binary", all_commands
, binary_append_command
,
717 _("Append target code/data to a raw binary file."),
718 &binary_append_cmdlist
, "append binary ",
722 add_cmd ("memory", all_commands
, dump_srec_memory
, _("\
723 Write contents of memory to an srec file.\n\
724 Arguments are FILE START STOP. Writes the contents of memory\n\
725 within the range [START .. STOP) to the specified FILE in srec format."),
728 add_cmd ("value", all_commands
, dump_srec_value
, _("\
729 Write the value of an expression to an srec file.\n\
730 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
731 to the specified FILE in srec format."),
734 add_cmd ("memory", all_commands
, dump_ihex_memory
, _("\
735 Write contents of memory to an ihex file.\n\
736 Arguments are FILE START STOP. Writes the contents of memory within\n\
737 the range [START .. STOP) to the specified FILE in intel hex format."),
740 add_cmd ("value", all_commands
, dump_ihex_value
, _("\
741 Write the value of an expression to an ihex file.\n\
742 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
743 to the specified FILE in intel hex format."),
746 add_cmd ("memory", all_commands
, dump_verilog_memory
, _("\
747 Write contents of memory to a verilog hex file.\n\
748 Arguments are FILE START STOP. Writes the contents of memory within\n\
749 the range [START .. STOP) to the specified FILE in verilog hex format."),
752 add_cmd ("value", all_commands
, dump_verilog_value
, _("\
753 Write the value of an expression to a verilog hex file.\n\
754 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
755 to the specified FILE in verilog hex format."),
758 add_cmd ("memory", all_commands
, dump_tekhex_memory
, _("\
759 Write contents of memory to a tekhex file.\n\
760 Arguments are FILE START STOP. Writes the contents of memory\n\
761 within the range [START .. STOP) to the specified FILE in tekhex format."),
764 add_cmd ("value", all_commands
, dump_tekhex_value
, _("\
765 Write the value of an expression to a tekhex file.\n\
766 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
767 to the specified FILE in tekhex format."),
770 add_cmd ("memory", all_commands
, dump_binary_memory
, _("\
771 Write contents of memory to a raw binary file.\n\
772 Arguments are FILE START STOP. Writes the contents of memory\n\
773 within the range [START .. STOP) to the specified FILE in binary format."),
774 &binary_dump_cmdlist
);
776 add_cmd ("value", all_commands
, dump_binary_value
, _("\
777 Write the value of an expression to a raw binary file.\n\
778 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
779 to the specified FILE in raw target ordered bytes."),
780 &binary_dump_cmdlist
);
782 add_cmd ("memory", all_commands
, append_binary_memory
, _("\
783 Append contents of memory to a raw binary file.\n\
784 Arguments are FILE START STOP. Writes the contents of memory within the\n\
785 range [START .. STOP) to the specified FILE in raw target ordered bytes."),
786 &binary_append_cmdlist
);
788 add_cmd ("value", all_commands
, append_binary_value
, _("\
789 Append the value of an expression to a raw binary file.\n\
790 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
791 to the specified FILE in raw target ordered bytes."),
792 &binary_append_cmdlist
);
794 c
= add_com ("restore", class_vars
, restore_command
, _("\
795 Restore the contents of FILE to target memory.\n\
796 Arguments are FILE OFFSET START END where all except FILE are optional.\n\
797 OFFSET will be added to the base address of the file (default zero).\n\
798 If START and END are given, only the file contents within that range\n\
799 (file relative) will be restored to target memory."));
800 c
->completer
= filename_completer
;
801 /* FIXME: completers for other commands. */