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 if ((ibfd = bfd_openr (filename, target)) == NULL)
136 error ("Failed to open %s: %s.", filename,
137 bfd_errmsg (bfd_get_error ()));
139 make_cleanup_bfd_close (ibfd);
140 if (!bfd_check_format (ibfd, bfd_object))
141 error ("'%s' is not a recognized file format.", filename);
147 bfd_openw_with_cleanup (char *filename, const char *target, char *mode)
151 if (*mode == 'w') /* Write: create new file */
153 if ((obfd = bfd_openw (filename, target)) == NULL)
154 error ("Failed to open %s: %s.", filename,
155 bfd_errmsg (bfd_get_error ()));
156 make_cleanup_bfd_close (obfd);
157 if (!bfd_set_format (obfd, bfd_object))
158 error ("bfd_openw_with_cleanup: %s.", bfd_errmsg (bfd_get_error ()));
160 else if (*mode == 'a') /* Append to existing file */
161 { /* FIXME -- doesn't work... */
162 error ("bfd_openw does not work with append.");
165 error ("bfd_openw_with_cleanup: unknown mode %s.", mode);
170 struct cmd_list_element *dump_cmdlist;
171 struct cmd_list_element *append_cmdlist;
172 struct cmd_list_element *srec_cmdlist;
173 struct cmd_list_element *ihex_cmdlist;
174 struct cmd_list_element *tekhex_cmdlist;
175 struct cmd_list_element *binary_dump_cmdlist;
176 struct cmd_list_element *binary_append_cmdlist;
179 dump_command (char *cmd, int from_tty)
181 printf_unfiltered ("\"dump\" must be followed by a subcommand.\n\n");
182 help_list (dump_cmdlist, "dump ", -1, gdb_stdout);
186 append_command (char *cmd, int from_tty)
188 printf_unfiltered ("\"append\" must be followed by a subcommand.\n\n");
189 help_list (dump_cmdlist, "append ", -1, gdb_stdout);
193 dump_binary_file (char *filename, char *mode,
199 file = fopen_with_cleanup (filename, mode);
200 status = fwrite (buf, len, 1, file);
202 perror_with_name (filename);
206 dump_bfd_file (char *filename, char *mode,
207 char *target, CORE_ADDR vaddr,
213 obfd = bfd_openw_with_cleanup (filename, target, mode);
214 osection = bfd_make_section_anyway (obfd, ".newsec");
215 bfd_set_section_size (obfd, osection, len);
216 bfd_set_section_vma (obfd, osection, vaddr);
217 bfd_set_section_alignment (obfd, osection, 0);
218 bfd_set_section_flags (obfd, osection, 0x203);
219 osection->entsize = 0;
220 bfd_set_section_contents (obfd, osection, buf, 0, len);
224 dump_memory_to_file (char *cmd, char *mode, char *file_format)
226 struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
237 filename = scan_filename_with_cleanup (&cmd, NULL);
239 /* Find the low address. */
240 if (cmd == NULL || *cmd == '\0')
241 error ("Missing start address.");
242 lo_exp = scan_expression_with_cleanup (&cmd, NULL);
244 /* Find the second address - rest of line. */
245 if (cmd == NULL || *cmd == '\0')
246 error ("Missing stop address.");
249 lo = parse_and_eval_address (lo_exp);
250 hi = parse_and_eval_address (hi_exp);
252 error ("Invalid memory address range (start >= end).");
255 /* FIXME: Should use read_memory_partial() and a magic blocking
257 buf = xmalloc (count);
258 make_cleanup (xfree, buf);
259 target_read_memory (lo, buf, count);
261 /* Have everything. Open/write the data. */
262 if (file_format == NULL || strcmp (file_format, "binary") == 0)
264 dump_binary_file (filename, mode, buf, count);
268 dump_bfd_file (filename, mode, file_format, lo, buf, count);
271 do_cleanups (old_cleanups);
275 dump_memory_command (char *cmd, char *mode)
277 dump_memory_to_file (cmd, mode, "binary");
281 dump_value_to_file (char *cmd, char *mode, char *file_format)
283 struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
288 filename = scan_filename_with_cleanup (&cmd, NULL);
290 /* Find the value. */
291 if (cmd == NULL || *cmd == '\0')
292 error ("No value to %s.", *mode == 'a' ? "append" : "dump");
293 val = parse_and_eval (cmd);
295 error ("Invalid expression.");
297 /* Have everything. Open/write the data. */
298 if (file_format == NULL || strcmp (file_format, "binary") == 0)
300 dump_binary_file (filename, mode, VALUE_CONTENTS (val),
301 TYPE_LENGTH (VALUE_TYPE (val)));
307 if (VALUE_LVAL (val))
309 vaddr = VALUE_ADDRESS (val);
314 warning ("value is not an lval: address assumed to be zero");
317 dump_bfd_file (filename, mode, file_format, vaddr,
318 VALUE_CONTENTS (val),
319 TYPE_LENGTH (VALUE_TYPE (val)));
322 do_cleanups (old_cleanups);
326 dump_value_command (char *cmd, char *mode)
328 dump_value_to_file (cmd, mode, "binary");
332 dump_filetype (char *cmd, char *mode, char *filetype)
336 if (cmd == NULL || *cmd == '\0')
337 error ("Missing subcommand: try 'help %s %s'.",
338 mode[0] == 'a' ? "append" : "dump",
341 suffix += strcspn (cmd, " \t");
345 if (strncmp ("memory", cmd, suffix - cmd) == 0)
347 dump_memory_to_file (suffix, mode, filetype);
350 else if (strncmp ("value", cmd, suffix - cmd) == 0)
352 dump_value_to_file (suffix, mode, filetype);
357 error ("dump %s: unknown subcommand '%s' -- try 'value' or 'memory'.",
362 dump_srec_memory (char *args, int from_tty)
364 dump_memory_to_file (args, FOPEN_WB, "srec");
368 dump_srec_value (char *args, int from_tty)
370 dump_value_to_file (args, FOPEN_WB, "srec");
374 dump_ihex_memory (char *args, int from_tty)
376 dump_memory_to_file (args, FOPEN_WB, "ihex");
380 dump_ihex_value (char *args, int from_tty)
382 dump_value_to_file (args, FOPEN_WB, "ihex");
386 dump_tekhex_memory (char *args, int from_tty)
388 dump_memory_to_file (args, FOPEN_WB, "tekhex");
392 dump_tekhex_value (char *args, int from_tty)
394 dump_value_to_file (args, FOPEN_WB, "tekhex");
398 dump_binary_memory (char *args, int from_tty)
400 dump_memory_to_file (args, FOPEN_WB, "binary");
404 dump_binary_value (char *args, int from_tty)
406 dump_value_to_file (args, FOPEN_WB, "binary");
410 append_binary_memory (char *args, int from_tty)
412 dump_memory_to_file (args, FOPEN_AB, "binary");
416 append_binary_value (char *args, int from_tty)
418 dump_value_to_file (args, FOPEN_AB, "binary");
423 void (*func) (char *cmd, char *mode);
428 call_dump_func (struct cmd_list_element *c, char *args, int from_tty)
430 struct dump_context *d = get_cmd_context (c);
431 d->func (args, d->mode);
435 add_dump_command (char *name, void (*func) (char *args, char *mode),
439 struct cmd_list_element *c;
440 struct dump_context *d;
442 c = add_cmd (name, all_commands, NULL, descr, &dump_cmdlist);
443 c->completer = filename_completer;
444 d = XMALLOC (struct dump_context);
447 set_cmd_context (c, d);
448 c->func = call_dump_func;
450 c = add_cmd (name, all_commands, NULL, descr, &append_cmdlist);
451 c->completer = filename_completer;
452 d = XMALLOC (struct dump_context);
455 set_cmd_context (c, d);
456 c->func = call_dump_func;
458 /* Replace "Dump " at start of docstring with "Append "
459 (borrowed from add_show_from_set). */
460 if ( c->doc[0] == 'W'
466 c->doc = concat ("Append ", c->doc + 6, NULL);
469 /* Opaque data for restore_section_callback. */
470 struct callback_data {
471 unsigned long load_offset;
472 CORE_ADDR load_start;
476 /* Function: restore_section_callback.
478 Callback function for bfd_map_over_sections.
479 Selectively loads the sections into memory. */
482 restore_section_callback (bfd *ibfd, asection *isec, void *args)
484 struct callback_data *data = args;
485 bfd_vma sec_start = bfd_section_vma (ibfd, isec);
486 bfd_size_type size = bfd_section_size (ibfd, isec);
487 bfd_vma sec_end = sec_start + size;
488 bfd_size_type sec_offset = 0;
489 bfd_size_type sec_load_count = size;
490 struct cleanup *old_chain;
494 /* Ignore non-loadable sections, eg. from elf files. */
495 if (!(bfd_get_section_flags (ibfd, isec) & SEC_LOAD))
498 /* Does the section overlap with the desired restore range? */
499 if (sec_end <= data->load_start
500 || (data->load_end > 0 && sec_start >= data->load_end))
502 /* No, no useable data in this section. */
503 printf_filtered ("skipping section %s...\n",
504 bfd_section_name (ibfd, isec));
508 /* Compare section address range with user-requested
509 address range (if any). Compute where the actual
510 transfer should start and end. */
511 if (sec_start < data->load_start)
512 sec_offset = data->load_start - sec_start;
513 /* Size of a partial transfer: */
514 sec_load_count -= sec_offset;
515 if (data->load_end > 0 && sec_end > data->load_end)
516 sec_load_count -= sec_end - data->load_end;
519 buf = xmalloc (size);
520 old_chain = make_cleanup (xfree, buf);
521 if (!bfd_get_section_contents (ibfd, isec, buf, 0, size))
522 error ("Failed to read bfd file %s: '%s'.", bfd_get_filename (ibfd),
523 bfd_errmsg (bfd_get_error ()));
525 printf_filtered ("Restoring section %s (0x%lx to 0x%lx)",
526 bfd_section_name (ibfd, isec),
527 (unsigned long) sec_start,
528 (unsigned long) sec_end);
530 if (data->load_offset != 0 || data->load_start != 0 || data->load_end != 0)
531 printf_filtered (" into memory (0x%s to 0x%s)\n",
532 paddr_nz ((unsigned long) sec_start
533 + sec_offset + data->load_offset),
534 paddr_nz ((unsigned long) sec_start + sec_offset
535 + data->load_offset + sec_load_count));
537 puts_filtered ("\n");
539 /* Write the data. */
540 ret = target_write_memory (sec_start + sec_offset + data->load_offset,
541 buf + sec_offset, sec_load_count);
543 warning ("restore: memory write failed (%s).", safe_strerror (ret));
544 do_cleanups (old_chain);
549 restore_binary_file (char *filename, struct callback_data *data)
551 FILE *file = fopen_with_cleanup (filename, FOPEN_RB);
556 /* Get the file size for reading. */
557 if (fseek (file, 0, SEEK_END) == 0)
560 perror_with_name (filename);
562 if (len <= data->load_start)
563 error ("Start address is greater than length of binary file %s.",
566 /* Chop off "len" if it exceeds the requested load_end addr. */
567 if (data->load_end != 0 && data->load_end < len)
568 len = data->load_end;
569 /* Chop off "len" if the requested load_start addr skips some bytes. */
570 if (data->load_start > 0)
571 len -= data->load_start;
574 ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n",
576 (unsigned long) data->load_start + data->load_offset,
577 (unsigned long) data->load_start + data->load_offset + len);
579 /* Now set the file pos to the requested load start pos. */
580 if (fseek (file, data->load_start, SEEK_SET) != 0)
581 perror_with_name (filename);
583 /* Now allocate a buffer and read the file contents. */
585 make_cleanup (xfree, buf);
586 if (fread (buf, 1, len, file) != len)
587 perror_with_name (filename);
589 /* Now write the buffer into target memory. */
590 len = target_write_memory (data->load_start + data->load_offset, buf, len);
592 warning ("restore: memory write failed (%s).", safe_strerror (len));
597 restore_command (char *args, int from_tty)
600 struct callback_data data;
604 if (!target_has_execution)
607 data.load_offset = 0;
611 /* Parse the input arguments. First is filename (required). */
612 filename = scan_filename_with_cleanup (&args, NULL);
613 if (args != NULL && *args != '\0')
615 char *binary_string = "binary";
617 /* Look for optional "binary" flag. */
618 if (strncmp (args, binary_string, strlen (binary_string)) == 0)
621 args += strlen (binary_string);
622 args = skip_spaces (args);
624 /* Parse offset (optional). */
625 if (args != NULL && *args != '\0')
627 parse_and_eval_long (scan_expression_with_cleanup (&args, NULL));
628 if (args != NULL && *args != '\0')
630 /* Parse start address (optional). */
632 parse_and_eval_long (scan_expression_with_cleanup (&args, NULL));
633 if (args != NULL && *args != '\0')
635 /* Parse end address (optional). */
636 data.load_end = parse_and_eval_long (args);
637 if (data.load_end <= data.load_start)
638 error ("Start must be less than end.");
644 printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n",
645 filename, (unsigned long) data.load_offset,
646 (unsigned long) data.load_start,
647 (unsigned long) data.load_end);
651 restore_binary_file (filename, &data);
655 /* Open the file for loading. */
656 ibfd = bfd_openr_with_cleanup (filename, NULL);
658 /* Process the sections. */
659 bfd_map_over_sections (ibfd, restore_section_callback, &data);
665 srec_dump_command (char *cmd, int from_tty)
667 printf_unfiltered ("\"dump srec\" must be followed by a subcommand.\n");
668 help_list (srec_cmdlist, "dump srec ", -1, gdb_stdout);
672 ihex_dump_command (char *cmd, int from_tty)
674 printf_unfiltered ("\"dump ihex\" must be followed by a subcommand.\n");
675 help_list (ihex_cmdlist, "dump ihex ", -1, gdb_stdout);
679 tekhex_dump_command (char *cmd, int from_tty)
681 printf_unfiltered ("\"dump tekhex\" must be followed by a subcommand.\n");
682 help_list (tekhex_cmdlist, "dump tekhex ", -1, gdb_stdout);
686 binary_dump_command (char *cmd, int from_tty)
688 printf_unfiltered ("\"dump binary\" must be followed by a subcommand.\n");
689 help_list (binary_dump_cmdlist, "dump binary ", -1, gdb_stdout);
693 binary_append_command (char *cmd, int from_tty)
695 printf_unfiltered ("\"append binary\" must be followed by a subcommand.\n");
696 help_list (binary_append_cmdlist, "append binary ", -1, gdb_stdout);
700 _initialize_cli_dump (void)
702 struct cmd_list_element *c;
703 add_prefix_cmd ("dump", class_vars, dump_command, "\
704 Dump target code/data to a local file.",
705 &dump_cmdlist, "dump ",
708 add_prefix_cmd ("append", class_vars, append_command, "\
709 Append target code/data to a local file.",
710 &append_cmdlist, "append ",
714 add_dump_command ("memory", dump_memory_command, "\
715 Write contents of memory to a raw binary file.\n\
716 Arguments are FILE START STOP. Writes the contents of memory within the\n\
717 range [START .. STOP) to the specifed FILE in raw target ordered bytes.");
719 add_dump_command ("value", dump_value_command, "\
720 Write the value of an expression to a raw binary file.\n\
721 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\
722 the specified FILE in raw target ordered bytes.");
724 add_prefix_cmd ("srec", all_commands, srec_dump_command, "\
725 Write target code/data to an srec file.",
726 &srec_cmdlist, "dump srec ",
730 add_prefix_cmd ("ihex", all_commands, ihex_dump_command, "\
731 Write target code/data to an intel hex file.",
732 &ihex_cmdlist, "dump ihex ",
736 add_prefix_cmd ("tekhex", all_commands, tekhex_dump_command, "\
737 Write target code/data to a tekhex file.",
738 &tekhex_cmdlist, "dump tekhex ",
742 add_prefix_cmd ("binary", all_commands, binary_dump_command, "\
743 Write target code/data to a raw binary file.",
744 &binary_dump_cmdlist, "dump binary ",
748 add_prefix_cmd ("binary", all_commands, binary_append_command, "\
749 Append target code/data to a raw binary file.",
750 &binary_append_cmdlist, "append binary ",
754 add_cmd ("memory", all_commands, dump_srec_memory, "\
755 Write contents of memory to an srec file.\n\
756 Arguments are FILE START STOP. Writes the contents of memory\n\
757 within the range [START .. STOP) to the specifed FILE in srec format.",
760 add_cmd ("value", all_commands, dump_srec_value, "\
761 Write the value of an expression to an srec file.\n\
762 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
763 to the specified FILE in srec format.",
766 add_cmd ("memory", all_commands, dump_ihex_memory, "\
767 Write contents of memory to an ihex file.\n\
768 Arguments are FILE START STOP. Writes the contents of memory within\n\
769 the range [START .. STOP) to the specifed FILE in intel hex format.",
772 add_cmd ("value", all_commands, dump_ihex_value, "\
773 Write the value of an expression to an ihex file.\n\
774 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
775 to the specified FILE in intel hex format.",
778 add_cmd ("memory", all_commands, dump_tekhex_memory, "\
779 Write contents of memory to a tekhex file.\n\
780 Arguments are FILE START STOP. Writes the contents of memory\n\
781 within the range [START .. STOP) to the specifed FILE in tekhex format.",
784 add_cmd ("value", all_commands, dump_tekhex_value, "\
785 Write the value of an expression to a tekhex file.\n\
786 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
787 to the specified FILE in tekhex format.",
790 add_cmd ("memory", all_commands, dump_binary_memory, "\
791 Write contents of memory to a raw binary file.\n\
792 Arguments are FILE START STOP. Writes the contents of memory\n\
793 within the range [START .. STOP) to the specifed FILE in binary format.",
794 &binary_dump_cmdlist);
796 add_cmd ("value", all_commands, dump_binary_value, "\
797 Write the value of an expression to a raw binary file.\n\
798 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
799 to the specified FILE in raw target ordered bytes.",
800 &binary_dump_cmdlist);
802 add_cmd ("memory", all_commands, append_binary_memory, "\
803 Append contents of memory to a raw binary file.\n\
804 Arguments are FILE START STOP. Writes the contents of memory within the\n\
805 range [START .. STOP) to the specifed FILE in raw target ordered bytes.",
806 &binary_append_cmdlist);
808 add_cmd ("value", all_commands, append_binary_value, "\
809 Append the value of an expression to a raw binary file.\n\
810 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
811 to the specified FILE in raw target ordered bytes.",
812 &binary_append_cmdlist);
814 c = add_com ("restore", class_vars, restore_command,
815 "Restore the contents of FILE to target memory.\n\
816 Arguments are FILE OFFSET START END where all except FILE are optional.\n\
817 OFFSET will be added to the base address of the file (default zero).\n\
818 If START and END are given, only the file contents within that range\n\
819 (file relative) will be restored to target memory.");
820 c->completer = filename_completer;
821 /* FIXME: completers for other commands. */