1 /* Dump-to-file commands, for GDB, the GNU debugger.
3 Copyright (C) 2002-2020 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/tilde.h"
31 #include "cli/cli-utils.h"
33 #include "gdbsupport/filestuff.h"
34 #include "gdbsupport/byte-vector.h"
37 static gdb::unique_xmalloc_ptr
<char>
38 scan_expression (const char **cmd
, const char *def
)
40 if ((*cmd
) == NULL
|| (**cmd
) == '\0')
41 return make_unique_xstrdup (def
);
47 end
= (*cmd
) + strcspn (*cmd
, " \t");
48 exp
= savestring ((*cmd
), end
- (*cmd
));
49 (*cmd
) = skip_spaces (end
);
50 return gdb::unique_xmalloc_ptr
<char> (exp
);
55 static gdb::unique_xmalloc_ptr
<char>
56 scan_filename (const char **cmd
, const char *defname
)
58 gdb::unique_xmalloc_ptr
<char> filename
;
60 /* FIXME: Need to get the ``/a(ppend)'' flag from somewhere. */
66 error (_("Missing filename."));
67 filename
.reset (xstrdup (defname
));
71 /* FIXME: should parse a possibly quoted string. */
74 (*cmd
) = skip_spaces (*cmd
);
75 end
= *cmd
+ strcspn (*cmd
, " \t");
76 filename
.reset (savestring ((*cmd
), end
- (*cmd
)));
77 (*cmd
) = skip_spaces (end
);
79 gdb_assert (filename
!= NULL
);
81 return gdb::unique_xmalloc_ptr
<char> (tilde_expand (filename
.get ()));
84 static gdb_bfd_ref_ptr
85 bfd_openr_or_error (const char *filename
, const char *target
)
87 gdb_bfd_ref_ptr
ibfd (gdb_bfd_openr (filename
, target
));
89 error (_("Failed to open %s: %s."), filename
,
90 bfd_errmsg (bfd_get_error ()));
92 if (!bfd_check_format (ibfd
.get (), bfd_object
))
93 error (_("'%s' is not a recognized file format."), filename
);
98 static gdb_bfd_ref_ptr
99 bfd_openw_or_error (const char *filename
, const char *target
, const char *mode
)
101 gdb_bfd_ref_ptr obfd
;
103 if (*mode
== 'w') /* Write: create new file */
105 obfd
= gdb_bfd_openw (filename
, target
);
107 error (_("Failed to open %s: %s."), filename
,
108 bfd_errmsg (bfd_get_error ()));
109 if (!bfd_set_format (obfd
.get (), bfd_object
))
110 error (_("bfd_openw_or_error: %s."), bfd_errmsg (bfd_get_error ()));
112 else if (*mode
== 'a') /* Append to existing file. */
113 { /* FIXME -- doesn't work... */
114 error (_("bfd_openw does not work with append."));
117 error (_("bfd_openw_or_error: unknown mode %s."), mode
);
122 static struct cmd_list_element
*dump_cmdlist
;
123 static struct cmd_list_element
*append_cmdlist
;
124 static struct cmd_list_element
*srec_cmdlist
;
125 static struct cmd_list_element
*ihex_cmdlist
;
126 static struct cmd_list_element
*verilog_cmdlist
;
127 static struct cmd_list_element
*tekhex_cmdlist
;
128 static struct cmd_list_element
*binary_dump_cmdlist
;
129 static struct cmd_list_element
*binary_append_cmdlist
;
132 dump_binary_file (const char *filename
, const char *mode
,
133 const bfd_byte
*buf
, ULONGEST len
)
137 gdb_file_up file
= gdb_fopen_cloexec (filename
, mode
);
138 status
= fwrite (buf
, len
, 1, file
.get ());
140 perror_with_name (filename
);
144 dump_bfd_file (const char *filename
, const char *mode
,
145 const char *target
, CORE_ADDR vaddr
,
146 const bfd_byte
*buf
, ULONGEST len
)
150 gdb_bfd_ref_ptr
obfd (bfd_openw_or_error (filename
, target
, mode
));
151 osection
= bfd_make_section_anyway (obfd
.get (), ".newsec");
152 bfd_set_section_size (osection
, len
);
153 bfd_set_section_vma (osection
, vaddr
);
154 bfd_set_section_alignment (osection
, 0);
155 bfd_set_section_flags (osection
, (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
));
156 osection
->entsize
= 0;
157 if (!bfd_set_section_contents (obfd
.get (), osection
, buf
, 0, len
))
158 warning (_("writing dump file '%s' (%s)"), filename
,
159 bfd_errmsg (bfd_get_error ()));
163 dump_memory_to_file (const char *cmd
, const char *mode
, const char *file_format
)
171 gdb::unique_xmalloc_ptr
<char> filename
= scan_filename (&cmd
, NULL
);
173 /* Find the low address. */
174 if (cmd
== NULL
|| *cmd
== '\0')
175 error (_("Missing start address."));
176 gdb::unique_xmalloc_ptr
<char> lo_exp
= scan_expression (&cmd
, NULL
);
178 /* Find the second address - rest of line. */
179 if (cmd
== NULL
|| *cmd
== '\0')
180 error (_("Missing stop address."));
183 lo
= parse_and_eval_address (lo_exp
.get ());
184 hi
= parse_and_eval_address (hi_exp
);
186 error (_("Invalid memory address range (start >= end)."));
189 /* FIXME: Should use read_memory_partial() and a magic blocking
191 gdb::byte_vector
buf (count
);
192 read_memory (lo
, buf
.data (), count
);
194 /* Have everything. Open/write the data. */
195 if (file_format
== NULL
|| strcmp (file_format
, "binary") == 0)
196 dump_binary_file (filename
.get (), mode
, buf
.data (), count
);
198 dump_bfd_file (filename
.get (), mode
, file_format
, lo
, buf
.data (), count
);
202 dump_memory_command (const char *cmd
, const char *mode
)
204 dump_memory_to_file (cmd
, mode
, "binary");
208 dump_value_to_file (const char *cmd
, const char *mode
, const char *file_format
)
213 gdb::unique_xmalloc_ptr
<char> filename
= scan_filename (&cmd
, NULL
);
215 /* Find the value. */
216 if (cmd
== NULL
|| *cmd
== '\0')
217 error (_("No value to %s."), *mode
== 'a' ? "append" : "dump");
218 val
= parse_and_eval (cmd
);
220 error (_("Invalid expression."));
222 /* Have everything. Open/write the data. */
223 if (file_format
== NULL
|| strcmp (file_format
, "binary") == 0)
224 dump_binary_file (filename
.get (), mode
, value_contents (val
),
225 TYPE_LENGTH (value_type (val
)));
230 if (VALUE_LVAL (val
))
232 vaddr
= value_address (val
);
237 warning (_("value is not an lval: address assumed to be zero"));
240 dump_bfd_file (filename
.get (), mode
, file_format
, vaddr
,
241 value_contents (val
),
242 TYPE_LENGTH (value_type (val
)));
247 dump_value_command (const char *cmd
, const char *mode
)
249 dump_value_to_file (cmd
, mode
, "binary");
253 dump_srec_memory (const char *args
, int from_tty
)
255 dump_memory_to_file (args
, FOPEN_WB
, "srec");
259 dump_srec_value (const char *args
, int from_tty
)
261 dump_value_to_file (args
, FOPEN_WB
, "srec");
265 dump_ihex_memory (const char *args
, int from_tty
)
267 dump_memory_to_file (args
, FOPEN_WB
, "ihex");
271 dump_ihex_value (const char *args
, int from_tty
)
273 dump_value_to_file (args
, FOPEN_WB
, "ihex");
277 dump_verilog_memory (const char *args
, int from_tty
)
279 dump_memory_to_file (args
, FOPEN_WB
, "verilog");
283 dump_verilog_value (const char *args
, int from_tty
)
285 dump_value_to_file (args
, FOPEN_WB
, "verilog");
289 dump_tekhex_memory (const char *args
, int from_tty
)
291 dump_memory_to_file (args
, FOPEN_WB
, "tekhex");
295 dump_tekhex_value (const char *args
, int from_tty
)
297 dump_value_to_file (args
, FOPEN_WB
, "tekhex");
301 dump_binary_memory (const char *args
, int from_tty
)
303 dump_memory_to_file (args
, FOPEN_WB
, "binary");
307 dump_binary_value (const char *args
, int from_tty
)
309 dump_value_to_file (args
, FOPEN_WB
, "binary");
313 append_binary_memory (const char *args
, int from_tty
)
315 dump_memory_to_file (args
, FOPEN_AB
, "binary");
319 append_binary_value (const char *args
, int from_tty
)
321 dump_value_to_file (args
, FOPEN_AB
, "binary");
326 void (*func
) (const char *cmd
, const char *mode
);
331 call_dump_func (struct cmd_list_element
*c
, const char *args
, int from_tty
)
333 struct dump_context
*d
= (struct dump_context
*) get_cmd_context (c
);
335 d
->func (args
, d
->mode
);
339 add_dump_command (const char *name
,
340 void (*func
) (const char *args
, const char *mode
),
344 struct cmd_list_element
*c
;
345 struct dump_context
*d
;
347 c
= add_cmd (name
, all_commands
, descr
, &dump_cmdlist
);
348 c
->completer
= filename_completer
;
349 d
= XNEW (struct dump_context
);
352 set_cmd_context (c
, d
);
353 c
->func
= call_dump_func
;
355 c
= add_cmd (name
, all_commands
, descr
, &append_cmdlist
);
356 c
->completer
= filename_completer
;
357 d
= XNEW (struct dump_context
);
360 set_cmd_context (c
, d
);
361 c
->func
= call_dump_func
;
363 /* Replace "Dump " at start of docstring with "Append " (borrowed
364 from [deleted] deprecated_add_show_from_set). */
365 if ( c
->doc
[0] == 'W'
371 c
->doc
= concat ("Append ", c
->doc
+ 6, (char *)NULL
);
374 /* Opaque data for restore_section_callback. */
375 struct callback_data
{
376 CORE_ADDR load_offset
;
377 CORE_ADDR load_start
;
381 /* Function: restore_section_callback.
383 Callback function for bfd_map_over_sections.
384 Selectively loads the sections into memory. */
387 restore_section_callback (bfd
*ibfd
, asection
*isec
, void *args
)
389 struct callback_data
*data
= (struct callback_data
*) args
;
390 bfd_vma sec_start
= bfd_section_vma (isec
);
391 bfd_size_type size
= bfd_section_size (isec
);
392 bfd_vma sec_end
= sec_start
+ size
;
393 bfd_size_type sec_offset
= 0;
394 bfd_size_type sec_load_count
= size
;
397 /* Ignore non-loadable sections, eg. from elf files. */
398 if (!(bfd_section_flags (isec
) & SEC_LOAD
))
401 /* Does the section overlap with the desired restore range? */
402 if (sec_end
<= data
->load_start
403 || (data
->load_end
> 0 && sec_start
>= data
->load_end
))
405 /* No, no useable data in this section. */
406 printf_filtered (_("skipping section %s...\n"),
407 bfd_section_name (isec
));
411 /* Compare section address range with user-requested
412 address range (if any). Compute where the actual
413 transfer should start and end. */
414 if (sec_start
< data
->load_start
)
415 sec_offset
= data
->load_start
- sec_start
;
416 /* Size of a partial transfer. */
417 sec_load_count
-= sec_offset
;
418 if (data
->load_end
> 0 && sec_end
> data
->load_end
)
419 sec_load_count
-= sec_end
- data
->load_end
;
422 gdb::byte_vector
buf (size
);
423 if (!bfd_get_section_contents (ibfd
, isec
, buf
.data (), 0, size
))
424 error (_("Failed to read bfd file %s: '%s'."), bfd_get_filename (ibfd
),
425 bfd_errmsg (bfd_get_error ()));
427 printf_filtered ("Restoring section %s (0x%lx to 0x%lx)",
428 bfd_section_name (isec
),
429 (unsigned long) sec_start
,
430 (unsigned long) sec_end
);
432 if (data
->load_offset
!= 0 || data
->load_start
!= 0 || data
->load_end
!= 0)
433 printf_filtered (" into memory (%s to %s)\n",
434 paddress (target_gdbarch (),
435 (unsigned long) sec_start
436 + sec_offset
+ data
->load_offset
),
437 paddress (target_gdbarch (),
438 (unsigned long) sec_start
+ sec_offset
439 + data
->load_offset
+ sec_load_count
));
441 puts_filtered ("\n");
443 /* Write the data. */
444 ret
= target_write_memory (sec_start
+ sec_offset
+ data
->load_offset
,
445 &buf
[sec_offset
], sec_load_count
);
447 warning (_("restore: memory write failed (%s)."), safe_strerror (ret
));
451 restore_binary_file (const char *filename
, struct callback_data
*data
)
453 gdb_file_up file
= gdb_fopen_cloexec (filename
, FOPEN_RB
);
457 error (_("Failed to open %s: %s"), filename
, safe_strerror (errno
));
459 /* Get the file size for reading. */
460 if (fseek (file
.get (), 0, SEEK_END
) == 0)
462 len
= ftell (file
.get ());
464 perror_with_name (filename
);
467 perror_with_name (filename
);
469 if (len
<= data
->load_start
)
470 error (_("Start address is greater than length of binary file %s."),
473 /* Chop off "len" if it exceeds the requested load_end addr. */
474 if (data
->load_end
!= 0 && data
->load_end
< len
)
475 len
= data
->load_end
;
476 /* Chop off "len" if the requested load_start addr skips some bytes. */
477 if (data
->load_start
> 0)
478 len
-= data
->load_start
;
481 ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n",
483 (unsigned long) (data
->load_start
+ data
->load_offset
),
484 (unsigned long) (data
->load_start
+ data
->load_offset
+ len
));
486 /* Now set the file pos to the requested load start pos. */
487 if (fseek (file
.get (), data
->load_start
, SEEK_SET
) != 0)
488 perror_with_name (filename
);
490 /* Now allocate a buffer and read the file contents. */
491 gdb::byte_vector
buf (len
);
492 if (fread (buf
.data (), 1, len
, file
.get ()) != len
)
493 perror_with_name (filename
);
495 /* Now write the buffer into target memory. */
496 len
= target_write_memory (data
->load_start
+ data
->load_offset
,
499 warning (_("restore: memory write failed (%s)."), safe_strerror (len
));
503 restore_command (const char *args
, int from_tty
)
505 struct callback_data data
;
508 if (!target_has_execution
)
511 data
.load_offset
= 0;
515 /* Parse the input arguments. First is filename (required). */
516 gdb::unique_xmalloc_ptr
<char> filename
= scan_filename (&args
, NULL
);
517 if (args
!= NULL
&& *args
!= '\0')
519 static const char binary_string
[] = "binary";
521 /* Look for optional "binary" flag. */
522 if (startswith (args
, binary_string
))
525 args
+= strlen (binary_string
);
526 args
= skip_spaces (args
);
528 /* Parse offset (optional). */
529 if (args
!= NULL
&& *args
!= '\0')
530 data
.load_offset
= binary_flag
?
531 parse_and_eval_address (scan_expression (&args
, NULL
).get ()) :
532 parse_and_eval_long (scan_expression (&args
, NULL
).get ());
533 if (args
!= NULL
&& *args
!= '\0')
535 /* Parse start address (optional). */
537 parse_and_eval_long (scan_expression (&args
, NULL
).get ());
538 if (args
!= NULL
&& *args
!= '\0')
540 /* Parse end address (optional). */
541 data
.load_end
= parse_and_eval_long (args
);
542 if (data
.load_end
<= data
.load_start
)
543 error (_("Start must be less than end."));
549 printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n",
550 filename
.get (), (unsigned long) data
.load_offset
,
551 (unsigned long) data
.load_start
,
552 (unsigned long) data
.load_end
);
556 restore_binary_file (filename
.get (), &data
);
560 /* Open the file for loading. */
561 gdb_bfd_ref_ptr
ibfd (bfd_openr_or_error (filename
.get (), NULL
));
563 /* Process the sections. */
564 bfd_map_over_sections (ibfd
.get (), restore_section_callback
, &data
);
568 void _initialize_cli_dump ();
570 _initialize_cli_dump ()
572 struct cmd_list_element
*c
;
574 add_basic_prefix_cmd ("dump", class_vars
,
575 _("Dump target code/data to a local file."),
576 &dump_cmdlist
, "dump ",
579 add_basic_prefix_cmd ("append", class_vars
,
580 _("Append target code/data to a local file."),
581 &append_cmdlist
, "append ",
585 add_dump_command ("memory", dump_memory_command
, "\
586 Write contents of memory to a raw binary file.\n\
587 Arguments are FILE START STOP. Writes the contents of memory within the\n\
588 range [START .. STOP) to the specified FILE in raw target ordered bytes.");
590 add_dump_command ("value", dump_value_command
, "\
591 Write the value of an expression to a raw binary file.\n\
592 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\
593 the specified FILE in raw target ordered bytes.");
595 add_basic_prefix_cmd ("srec", all_commands
,
596 _("Write target code/data to an srec file."),
597 &srec_cmdlist
, "dump srec ",
601 add_basic_prefix_cmd ("ihex", all_commands
,
602 _("Write target code/data to an intel hex file."),
603 &ihex_cmdlist
, "dump ihex ",
607 add_basic_prefix_cmd ("verilog", all_commands
,
608 _("Write target code/data to a verilog hex file."),
609 &verilog_cmdlist
, "dump verilog ",
613 add_basic_prefix_cmd ("tekhex", all_commands
,
614 _("Write target code/data to a tekhex file."),
615 &tekhex_cmdlist
, "dump tekhex ",
619 add_basic_prefix_cmd ("binary", all_commands
,
620 _("Write target code/data to a raw binary file."),
621 &binary_dump_cmdlist
, "dump binary ",
625 add_basic_prefix_cmd ("binary", all_commands
,
626 _("Append target code/data to a raw binary file."),
627 &binary_append_cmdlist
, "append binary ",
631 add_cmd ("memory", all_commands
, dump_srec_memory
, _("\
632 Write contents of memory to an srec file.\n\
633 Arguments are FILE START STOP. Writes the contents of memory\n\
634 within the range [START .. STOP) to the specified FILE in srec format."),
637 add_cmd ("value", all_commands
, dump_srec_value
, _("\
638 Write the value of an expression to an srec file.\n\
639 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
640 to the specified FILE in srec format."),
643 add_cmd ("memory", all_commands
, dump_ihex_memory
, _("\
644 Write contents of memory to an ihex file.\n\
645 Arguments are FILE START STOP. Writes the contents of memory within\n\
646 the range [START .. STOP) to the specified FILE in intel hex format."),
649 add_cmd ("value", all_commands
, dump_ihex_value
, _("\
650 Write the value of an expression to an ihex file.\n\
651 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
652 to the specified FILE in intel hex format."),
655 add_cmd ("memory", all_commands
, dump_verilog_memory
, _("\
656 Write contents of memory to a verilog hex file.\n\
657 Arguments are FILE START STOP. Writes the contents of memory within\n\
658 the range [START .. STOP) to the specified FILE in verilog hex format."),
661 add_cmd ("value", all_commands
, dump_verilog_value
, _("\
662 Write the value of an expression to a verilog hex file.\n\
663 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
664 to the specified FILE in verilog hex format."),
667 add_cmd ("memory", all_commands
, dump_tekhex_memory
, _("\
668 Write contents of memory to a tekhex file.\n\
669 Arguments are FILE START STOP. Writes the contents of memory\n\
670 within the range [START .. STOP) to the specified FILE in tekhex format."),
673 add_cmd ("value", all_commands
, dump_tekhex_value
, _("\
674 Write the value of an expression to a tekhex file.\n\
675 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
676 to the specified FILE in tekhex format."),
679 add_cmd ("memory", all_commands
, dump_binary_memory
, _("\
680 Write contents of memory to a raw binary file.\n\
681 Arguments are FILE START STOP. Writes the contents of memory\n\
682 within the range [START .. STOP) to the specified FILE in binary format."),
683 &binary_dump_cmdlist
);
685 add_cmd ("value", all_commands
, dump_binary_value
, _("\
686 Write the value of an expression to a raw binary file.\n\
687 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
688 to the specified FILE in raw target ordered bytes."),
689 &binary_dump_cmdlist
);
691 add_cmd ("memory", all_commands
, append_binary_memory
, _("\
692 Append 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 specified FILE in raw target ordered bytes."),
695 &binary_append_cmdlist
);
697 add_cmd ("value", all_commands
, append_binary_value
, _("\
698 Append the value of an expression to a raw binary file.\n\
699 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
700 to the specified FILE in raw target ordered bytes."),
701 &binary_append_cmdlist
);
703 c
= add_com ("restore", class_vars
, restore_command
, _("\
704 Restore the contents of FILE to target memory.\n\
705 Arguments are FILE OFFSET START END where all except FILE are optional.\n\
706 OFFSET will be added to the base address of the file (default zero).\n\
707 If START and END are given, only the file contents within that range\n\
708 (file relative) will be restored to target memory."));
709 c
->completer
= filename_completer
;
710 /* FIXME: completers for other commands. */