1 /* Dump-to-file commands, for GDB, the GNU debugger.
3 Copyright 2002 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 2 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, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
25 #include "gdb_string.h"
26 #include "cli/cli-decode.h"
27 #include "cli/cli-cmds.h"
29 #include "completer.h"
30 #include "cli/cli-dump.h"
31 #include "gdb_assert.h"
34 #include <readline/readline.h>
36 #define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
40 skip_spaces (char *chp
)
44 while (isspace (*chp
))
50 scan_expression_with_cleanup (char **cmd
, const char *def
)
52 if ((*cmd
) == NULL
|| (**cmd
) == '\0')
54 char *exp
= xstrdup (def
);
55 make_cleanup (xfree
, exp
);
63 end
= (*cmd
) + strcspn (*cmd
, " \t");
64 exp
= savestring ((*cmd
), end
- (*cmd
));
65 make_cleanup (xfree
, exp
);
66 (*cmd
) = skip_spaces (end
);
73 do_fclose_cleanup (void *arg
)
79 static struct cleanup
*
80 make_cleanup_fclose (FILE *file
)
82 return make_cleanup (do_fclose_cleanup
, file
);
86 scan_filename_with_cleanup (char **cmd
, const char *defname
)
91 /* FIXME: Need to get the ``/a(ppend)'' flag from somewhere. */
97 error ("Missing filename.");
98 filename
= xstrdup (defname
);
99 make_cleanup (xfree
, filename
);
103 /* FIXME: should parse a possibly quoted string. */
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
);
112 gdb_assert (filename
!= NULL
);
114 fullname
= tilde_expand (filename
);
115 make_cleanup (xfree
, fullname
);
121 fopen_with_cleanup (char *filename
, const char *mode
)
123 FILE *file
= fopen (filename
, mode
);
125 perror_with_name (filename
);
126 make_cleanup_fclose (file
);
131 bfd_openr_with_cleanup (const char *filename
, const char *target
)
135 ibfd
= bfd_openr (filename
, target
);
137 error ("Failed to open %s: %s.", filename
,
138 bfd_errmsg (bfd_get_error ()));
140 make_cleanup_bfd_close (ibfd
);
141 if (!bfd_check_format (ibfd
, bfd_object
))
142 error ("'%s' is not a recognized file format.", filename
);
148 bfd_openw_with_cleanup (char *filename
, const char *target
, char *mode
)
152 if (*mode
== 'w') /* Write: create new file */
154 obfd
= bfd_openw (filename
, target
);
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 ()));
162 else if (*mode
== 'a') /* Append to existing file */
163 { /* FIXME -- doesn't work... */
164 error ("bfd_openw does not work with append.");
167 error ("bfd_openw_with_cleanup: unknown mode %s.", mode
);
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
;
181 dump_command (char *cmd
, int from_tty
)
183 printf_unfiltered ("\"dump\" must be followed by a subcommand.\n\n");
184 help_list (dump_cmdlist
, "dump ", -1, gdb_stdout
);
188 append_command (char *cmd
, int from_tty
)
190 printf_unfiltered ("\"append\" must be followed by a subcommand.\n\n");
191 help_list (dump_cmdlist
, "append ", -1, gdb_stdout
);
195 dump_binary_file (char *filename
, char *mode
,
201 file
= fopen_with_cleanup (filename
, mode
);
202 status
= fwrite (buf
, len
, 1, file
);
204 perror_with_name (filename
);
208 dump_bfd_file (char *filename
, char *mode
,
209 char *target
, CORE_ADDR vaddr
,
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
);
226 dump_memory_to_file (char *cmd
, char *mode
, char *file_format
)
228 struct cleanup
*old_cleanups
= make_cleanup (null_cleanup
, NULL
);
239 filename
= scan_filename_with_cleanup (&cmd
, NULL
);
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
);
246 /* Find the second address - rest of line. */
247 if (cmd
== NULL
|| *cmd
== '\0')
248 error ("Missing stop address.");
251 lo
= parse_and_eval_address (lo_exp
);
252 hi
= parse_and_eval_address (hi_exp
);
254 error ("Invalid memory address range (start >= end).");
257 /* FIXME: Should use read_memory_partial() and a magic blocking
259 buf
= xmalloc (count
);
260 make_cleanup (xfree
, buf
);
261 target_read_memory (lo
, buf
, count
);
263 /* Have everything. Open/write the data. */
264 if (file_format
== NULL
|| strcmp (file_format
, "binary") == 0)
266 dump_binary_file (filename
, mode
, buf
, count
);
270 dump_bfd_file (filename
, mode
, file_format
, lo
, buf
, count
);
273 do_cleanups (old_cleanups
);
277 dump_memory_command (char *cmd
, char *mode
)
279 dump_memory_to_file (cmd
, mode
, "binary");
283 dump_value_to_file (char *cmd
, char *mode
, char *file_format
)
285 struct cleanup
*old_cleanups
= make_cleanup (null_cleanup
, NULL
);
290 filename
= scan_filename_with_cleanup (&cmd
, NULL
);
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
);
297 error ("Invalid expression.");
299 /* Have everything. Open/write the data. */
300 if (file_format
== NULL
|| strcmp (file_format
, "binary") == 0)
302 dump_binary_file (filename
, mode
, VALUE_CONTENTS (val
),
303 TYPE_LENGTH (VALUE_TYPE (val
)));
309 if (VALUE_LVAL (val
))
311 vaddr
= VALUE_ADDRESS (val
);
316 warning ("value is not an lval: address assumed to be zero");
319 dump_bfd_file (filename
, mode
, file_format
, vaddr
,
320 VALUE_CONTENTS (val
),
321 TYPE_LENGTH (VALUE_TYPE (val
)));
324 do_cleanups (old_cleanups
);
328 dump_value_command (char *cmd
, char *mode
)
330 dump_value_to_file (cmd
, mode
, "binary");
334 dump_filetype (char *cmd
, char *mode
, char *filetype
)
338 if (cmd
== NULL
|| *cmd
== '\0')
339 error ("Missing subcommand: try 'help %s %s'.",
340 mode
[0] == 'a' ? "append" : "dump",
343 suffix
+= strcspn (cmd
, " \t");
347 if (strncmp ("memory", cmd
, suffix
- cmd
) == 0)
349 dump_memory_to_file (suffix
, mode
, filetype
);
352 else if (strncmp ("value", cmd
, suffix
- cmd
) == 0)
354 dump_value_to_file (suffix
, mode
, filetype
);
359 error ("dump %s: unknown subcommand '%s' -- try 'value' or 'memory'.",
364 dump_srec_memory (char *args
, int from_tty
)
366 dump_memory_to_file (args
, FOPEN_WB
, "srec");
370 dump_srec_value (char *args
, int from_tty
)
372 dump_value_to_file (args
, FOPEN_WB
, "srec");
376 dump_ihex_memory (char *args
, int from_tty
)
378 dump_memory_to_file (args
, FOPEN_WB
, "ihex");
382 dump_ihex_value (char *args
, int from_tty
)
384 dump_value_to_file (args
, FOPEN_WB
, "ihex");
388 dump_tekhex_memory (char *args
, int from_tty
)
390 dump_memory_to_file (args
, FOPEN_WB
, "tekhex");
394 dump_tekhex_value (char *args
, int from_tty
)
396 dump_value_to_file (args
, FOPEN_WB
, "tekhex");
400 dump_binary_memory (char *args
, int from_tty
)
402 dump_memory_to_file (args
, FOPEN_WB
, "binary");
406 dump_binary_value (char *args
, int from_tty
)
408 dump_value_to_file (args
, FOPEN_WB
, "binary");
412 append_binary_memory (char *args
, int from_tty
)
414 dump_memory_to_file (args
, FOPEN_AB
, "binary");
418 append_binary_value (char *args
, int from_tty
)
420 dump_value_to_file (args
, FOPEN_AB
, "binary");
425 void (*func
) (char *cmd
, char *mode
);
430 call_dump_func (struct cmd_list_element
*c
, char *args
, int from_tty
)
432 struct dump_context
*d
= get_cmd_context (c
);
433 d
->func (args
, d
->mode
);
437 add_dump_command (char *name
, void (*func
) (char *args
, char *mode
),
441 struct cmd_list_element
*c
;
442 struct dump_context
*d
;
444 c
= add_cmd (name
, all_commands
, NULL
, descr
, &dump_cmdlist
);
445 c
->completer
= filename_completer
;
446 d
= XMALLOC (struct dump_context
);
449 set_cmd_context (c
, d
);
450 c
->func
= call_dump_func
;
452 c
= add_cmd (name
, all_commands
, NULL
, descr
, &append_cmdlist
);
453 c
->completer
= filename_completer
;
454 d
= XMALLOC (struct dump_context
);
457 set_cmd_context (c
, d
);
458 c
->func
= call_dump_func
;
460 /* Replace "Dump " at start of docstring with "Append "
461 (borrowed from add_show_from_set). */
462 if ( c
->doc
[0] == 'W'
468 c
->doc
= concat ("Append ", c
->doc
+ 6, NULL
);
471 /* Opaque data for restore_section_callback. */
472 struct callback_data
{
473 unsigned long load_offset
;
474 CORE_ADDR load_start
;
478 /* Function: restore_section_callback.
480 Callback function for bfd_map_over_sections.
481 Selectively loads the sections into memory. */
484 restore_section_callback (bfd
*ibfd
, asection
*isec
, void *args
)
486 struct callback_data
*data
= args
;
487 bfd_vma sec_start
= bfd_section_vma (ibfd
, isec
);
488 bfd_size_type size
= bfd_section_size (ibfd
, isec
);
489 bfd_vma sec_end
= sec_start
+ size
;
490 bfd_size_type sec_offset
= 0;
491 bfd_size_type sec_load_count
= size
;
492 struct cleanup
*old_chain
;
496 /* Ignore non-loadable sections, eg. from elf files. */
497 if (!(bfd_get_section_flags (ibfd
, isec
) & SEC_LOAD
))
500 /* Does the section overlap with the desired restore range? */
501 if (sec_end
<= data
->load_start
502 || (data
->load_end
> 0 && sec_start
>= data
->load_end
))
504 /* No, no useable data in this section. */
505 printf_filtered ("skipping section %s...\n",
506 bfd_section_name (ibfd
, isec
));
510 /* Compare section address range with user-requested
511 address range (if any). Compute where the actual
512 transfer should start and end. */
513 if (sec_start
< data
->load_start
)
514 sec_offset
= data
->load_start
- sec_start
;
515 /* Size of a partial transfer: */
516 sec_load_count
-= sec_offset
;
517 if (data
->load_end
> 0 && sec_end
> data
->load_end
)
518 sec_load_count
-= sec_end
- data
->load_end
;
521 buf
= xmalloc (size
);
522 old_chain
= make_cleanup (xfree
, buf
);
523 if (!bfd_get_section_contents (ibfd
, isec
, buf
, 0, size
))
524 error ("Failed to read bfd file %s: '%s'.", bfd_get_filename (ibfd
),
525 bfd_errmsg (bfd_get_error ()));
527 printf_filtered ("Restoring section %s (0x%lx to 0x%lx)",
528 bfd_section_name (ibfd
, isec
),
529 (unsigned long) sec_start
,
530 (unsigned long) sec_end
);
532 if (data
->load_offset
!= 0 || data
->load_start
!= 0 || data
->load_end
!= 0)
533 printf_filtered (" into memory (0x%s to 0x%s)\n",
534 paddr_nz ((unsigned long) sec_start
535 + sec_offset
+ data
->load_offset
),
536 paddr_nz ((unsigned long) sec_start
+ sec_offset
537 + data
->load_offset
+ sec_load_count
));
539 puts_filtered ("\n");
541 /* Write the data. */
542 ret
= target_write_memory (sec_start
+ sec_offset
+ data
->load_offset
,
543 buf
+ sec_offset
, sec_load_count
);
545 warning ("restore: memory write failed (%s).", safe_strerror (ret
));
546 do_cleanups (old_chain
);
551 restore_binary_file (char *filename
, struct callback_data
*data
)
553 FILE *file
= fopen_with_cleanup (filename
, FOPEN_RB
);
558 /* Get the file size for reading. */
559 if (fseek (file
, 0, SEEK_END
) == 0)
562 perror_with_name (filename
);
564 if (len
<= data
->load_start
)
565 error ("Start address is greater than length of binary file %s.",
568 /* Chop off "len" if it exceeds the requested load_end addr. */
569 if (data
->load_end
!= 0 && data
->load_end
< len
)
570 len
= data
->load_end
;
571 /* Chop off "len" if the requested load_start addr skips some bytes. */
572 if (data
->load_start
> 0)
573 len
-= data
->load_start
;
576 ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n",
578 (unsigned long) data
->load_start
+ data
->load_offset
,
579 (unsigned long) data
->load_start
+ data
->load_offset
+ len
);
581 /* Now set the file pos to the requested load start pos. */
582 if (fseek (file
, data
->load_start
, SEEK_SET
) != 0)
583 perror_with_name (filename
);
585 /* Now allocate a buffer and read the file contents. */
587 make_cleanup (xfree
, buf
);
588 if (fread (buf
, 1, len
, file
) != len
)
589 perror_with_name (filename
);
591 /* Now write the buffer into target memory. */
592 len
= target_write_memory (data
->load_start
+ data
->load_offset
, buf
, len
);
594 warning ("restore: memory write failed (%s).", safe_strerror (len
));
599 restore_command (char *args
, int from_tty
)
602 struct callback_data data
;
606 if (!target_has_execution
)
609 data
.load_offset
= 0;
613 /* Parse the input arguments. First is filename (required). */
614 filename
= scan_filename_with_cleanup (&args
, NULL
);
615 if (args
!= NULL
&& *args
!= '\0')
617 char *binary_string
= "binary";
619 /* Look for optional "binary" flag. */
620 if (strncmp (args
, binary_string
, strlen (binary_string
)) == 0)
623 args
+= strlen (binary_string
);
624 args
= skip_spaces (args
);
626 /* Parse offset (optional). */
627 if (args
!= NULL
&& *args
!= '\0')
629 parse_and_eval_long (scan_expression_with_cleanup (&args
, NULL
));
630 if (args
!= NULL
&& *args
!= '\0')
632 /* Parse start address (optional). */
634 parse_and_eval_long (scan_expression_with_cleanup (&args
, NULL
));
635 if (args
!= NULL
&& *args
!= '\0')
637 /* Parse end address (optional). */
638 data
.load_end
= parse_and_eval_long (args
);
639 if (data
.load_end
<= data
.load_start
)
640 error ("Start must be less than end.");
646 printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n",
647 filename
, (unsigned long) data
.load_offset
,
648 (unsigned long) data
.load_start
,
649 (unsigned long) data
.load_end
);
653 restore_binary_file (filename
, &data
);
657 /* Open the file for loading. */
658 ibfd
= bfd_openr_with_cleanup (filename
, NULL
);
660 /* Process the sections. */
661 bfd_map_over_sections (ibfd
, restore_section_callback
, &data
);
667 srec_dump_command (char *cmd
, int from_tty
)
669 printf_unfiltered ("\"dump srec\" must be followed by a subcommand.\n");
670 help_list (srec_cmdlist
, "dump srec ", -1, gdb_stdout
);
674 ihex_dump_command (char *cmd
, int from_tty
)
676 printf_unfiltered ("\"dump ihex\" must be followed by a subcommand.\n");
677 help_list (ihex_cmdlist
, "dump ihex ", -1, gdb_stdout
);
681 tekhex_dump_command (char *cmd
, int from_tty
)
683 printf_unfiltered ("\"dump tekhex\" must be followed by a subcommand.\n");
684 help_list (tekhex_cmdlist
, "dump tekhex ", -1, gdb_stdout
);
688 binary_dump_command (char *cmd
, int from_tty
)
690 printf_unfiltered ("\"dump binary\" must be followed by a subcommand.\n");
691 help_list (binary_dump_cmdlist
, "dump binary ", -1, gdb_stdout
);
695 binary_append_command (char *cmd
, int from_tty
)
697 printf_unfiltered ("\"append binary\" must be followed by a subcommand.\n");
698 help_list (binary_append_cmdlist
, "append binary ", -1, gdb_stdout
);
702 _initialize_cli_dump (void)
704 struct cmd_list_element
*c
;
705 add_prefix_cmd ("dump", class_vars
, dump_command
, "\
706 Dump target code/data to a local file.",
707 &dump_cmdlist
, "dump ",
710 add_prefix_cmd ("append", class_vars
, append_command
, "\
711 Append target code/data to a local file.",
712 &append_cmdlist
, "append ",
716 add_dump_command ("memory", dump_memory_command
, "\
717 Write contents of memory to a raw binary file.\n\
718 Arguments are FILE START STOP. Writes the contents of memory within the\n\
719 range [START .. STOP) to the specifed FILE in raw target ordered bytes.");
721 add_dump_command ("value", dump_value_command
, "\
722 Write the value of an expression to a raw binary file.\n\
723 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\
724 the specified FILE in raw target ordered bytes.");
726 add_prefix_cmd ("srec", all_commands
, srec_dump_command
, "\
727 Write target code/data to an srec file.",
728 &srec_cmdlist
, "dump srec ",
732 add_prefix_cmd ("ihex", all_commands
, ihex_dump_command
, "\
733 Write target code/data to an intel hex file.",
734 &ihex_cmdlist
, "dump ihex ",
738 add_prefix_cmd ("tekhex", all_commands
, tekhex_dump_command
, "\
739 Write target code/data to a tekhex file.",
740 &tekhex_cmdlist
, "dump tekhex ",
744 add_prefix_cmd ("binary", all_commands
, binary_dump_command
, "\
745 Write target code/data to a raw binary file.",
746 &binary_dump_cmdlist
, "dump binary ",
750 add_prefix_cmd ("binary", all_commands
, binary_append_command
, "\
751 Append target code/data to a raw binary file.",
752 &binary_append_cmdlist
, "append binary ",
756 add_cmd ("memory", all_commands
, dump_srec_memory
, "\
757 Write contents of memory to an srec file.\n\
758 Arguments are FILE START STOP. Writes the contents of memory\n\
759 within the range [START .. STOP) to the specifed FILE in srec format.",
762 add_cmd ("value", all_commands
, dump_srec_value
, "\
763 Write the value of an expression to an srec file.\n\
764 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
765 to the specified FILE in srec format.",
768 add_cmd ("memory", all_commands
, dump_ihex_memory
, "\
769 Write contents of memory to an ihex file.\n\
770 Arguments are FILE START STOP. Writes the contents of memory within\n\
771 the range [START .. STOP) to the specifed FILE in intel hex format.",
774 add_cmd ("value", all_commands
, dump_ihex_value
, "\
775 Write the value of an expression to an ihex file.\n\
776 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
777 to the specified FILE in intel hex format.",
780 add_cmd ("memory", all_commands
, dump_tekhex_memory
, "\
781 Write contents of memory to a tekhex file.\n\
782 Arguments are FILE START STOP. Writes the contents of memory\n\
783 within the range [START .. STOP) to the specifed FILE in tekhex format.",
786 add_cmd ("value", all_commands
, dump_tekhex_value
, "\
787 Write the value of an expression to a tekhex file.\n\
788 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
789 to the specified FILE in tekhex format.",
792 add_cmd ("memory", all_commands
, dump_binary_memory
, "\
793 Write contents of memory to a raw binary file.\n\
794 Arguments are FILE START STOP. Writes the contents of memory\n\
795 within the range [START .. STOP) to the specifed FILE in binary format.",
796 &binary_dump_cmdlist
);
798 add_cmd ("value", all_commands
, dump_binary_value
, "\
799 Write the value of an expression to a raw binary file.\n\
800 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
801 to the specified FILE in raw target ordered bytes.",
802 &binary_dump_cmdlist
);
804 add_cmd ("memory", all_commands
, append_binary_memory
, "\
805 Append contents of memory to a raw binary file.\n\
806 Arguments are FILE START STOP. Writes the contents of memory within the\n\
807 range [START .. STOP) to the specifed FILE in raw target ordered bytes.",
808 &binary_append_cmdlist
);
810 add_cmd ("value", all_commands
, append_binary_value
, "\
811 Append the value of an expression to a raw binary file.\n\
812 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
813 to the specified FILE in raw target ordered bytes.",
814 &binary_append_cmdlist
);
816 c
= add_com ("restore", class_vars
, restore_command
,
817 "Restore the contents of FILE to target memory.\n\
818 Arguments are FILE OFFSET START END where all except FILE are optional.\n\
819 OFFSET will be added to the base address of the file (default zero).\n\
820 If START and END are given, only the file contents within that range\n\
821 (file relative) will be restored to target memory.");
822 c
->completer
= filename_completer
;
823 /* FIXME: completers for other commands. */