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 /* Selectively loads the sections into memory. */
377 restore_one_section (bfd
*ibfd
, asection
*isec
,
378 CORE_ADDR load_offset
,
379 CORE_ADDR load_start
,
382 bfd_vma sec_start
= bfd_section_vma (isec
);
383 bfd_size_type size
= bfd_section_size (isec
);
384 bfd_vma sec_end
= sec_start
+ size
;
385 bfd_size_type sec_offset
= 0;
386 bfd_size_type sec_load_count
= size
;
389 /* Ignore non-loadable sections, eg. from elf files. */
390 if (!(bfd_section_flags (isec
) & SEC_LOAD
))
393 /* Does the section overlap with the desired restore range? */
394 if (sec_end
<= load_start
395 || (load_end
> 0 && sec_start
>= load_end
))
397 /* No, no useable data in this section. */
398 printf_filtered (_("skipping section %s...\n"),
399 bfd_section_name (isec
));
403 /* Compare section address range with user-requested
404 address range (if any). Compute where the actual
405 transfer should start and end. */
406 if (sec_start
< load_start
)
407 sec_offset
= load_start
- sec_start
;
408 /* Size of a partial transfer. */
409 sec_load_count
-= sec_offset
;
410 if (load_end
> 0 && sec_end
> load_end
)
411 sec_load_count
-= sec_end
- load_end
;
414 gdb::byte_vector
buf (size
);
415 if (!bfd_get_section_contents (ibfd
, isec
, buf
.data (), 0, size
))
416 error (_("Failed to read bfd file %s: '%s'."), bfd_get_filename (ibfd
),
417 bfd_errmsg (bfd_get_error ()));
419 printf_filtered ("Restoring section %s (0x%lx to 0x%lx)",
420 bfd_section_name (isec
),
421 (unsigned long) sec_start
,
422 (unsigned long) sec_end
);
424 if (load_offset
!= 0 || load_start
!= 0 || load_end
!= 0)
425 printf_filtered (" into memory (%s to %s)\n",
426 paddress (target_gdbarch (),
427 (unsigned long) sec_start
428 + sec_offset
+ load_offset
),
429 paddress (target_gdbarch (),
430 (unsigned long) sec_start
+ sec_offset
431 + load_offset
+ sec_load_count
));
433 puts_filtered ("\n");
435 /* Write the data. */
436 ret
= target_write_memory (sec_start
+ sec_offset
+ load_offset
,
437 &buf
[sec_offset
], sec_load_count
);
439 warning (_("restore: memory write failed (%s)."), safe_strerror (ret
));
443 restore_binary_file (const char *filename
, CORE_ADDR load_offset
,
444 CORE_ADDR load_start
, CORE_ADDR load_end
)
447 gdb_file_up file
= gdb_fopen_cloexec (filename
, FOPEN_RB
);
451 error (_("Failed to open %s: %s"), filename
, safe_strerror (errno
));
453 /* Get the file size for reading. */
454 if (fseek (file
.get (), 0, SEEK_END
) == 0)
456 len
= ftell (file
.get ());
458 perror_with_name (filename
);
461 perror_with_name (filename
);
463 if (len
<= load_start
)
464 error (_("Start address is greater than length of binary file %s."),
467 /* Chop off "len" if it exceeds the requested load_end addr. */
468 if (load_end
!= 0 && load_end
< len
)
470 /* Chop off "len" if the requested load_start addr skips some bytes. */
475 ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n",
477 (unsigned long) (load_start
+ load_offset
),
478 (unsigned long) (load_start
+ load_offset
+ len
));
480 /* Now set the file pos to the requested load start pos. */
481 if (fseek (file
.get (), load_start
, SEEK_SET
) != 0)
482 perror_with_name (filename
);
484 /* Now allocate a buffer and read the file contents. */
485 gdb::byte_vector
buf (len
);
486 if (fread (buf
.data (), 1, len
, file
.get ()) != len
)
487 perror_with_name (filename
);
489 /* Now write the buffer into target memory. */
490 len
= target_write_memory (load_start
+ load_offset
, buf
.data (), len
);
492 warning (_("restore: memory write failed (%s)."), safe_strerror (len
));
496 restore_command (const char *args
, int from_tty
)
500 if (!target_has_execution
)
503 CORE_ADDR load_offset
= 0;
504 CORE_ADDR load_start
= 0;
505 CORE_ADDR load_end
= 0;
507 /* Parse the input arguments. First is filename (required). */
508 gdb::unique_xmalloc_ptr
<char> filename
= scan_filename (&args
, NULL
);
509 if (args
!= NULL
&& *args
!= '\0')
511 static const char binary_string
[] = "binary";
513 /* Look for optional "binary" flag. */
514 if (startswith (args
, binary_string
))
517 args
+= strlen (binary_string
);
518 args
= skip_spaces (args
);
520 /* Parse offset (optional). */
521 if (args
!= NULL
&& *args
!= '\0')
524 ? parse_and_eval_address (scan_expression (&args
, NULL
).get ())
525 : parse_and_eval_long (scan_expression (&args
, NULL
).get ()));
526 if (args
!= NULL
&& *args
!= '\0')
528 /* Parse start address (optional). */
530 parse_and_eval_long (scan_expression (&args
, NULL
).get ());
531 if (args
!= NULL
&& *args
!= '\0')
533 /* Parse end address (optional). */
534 load_end
= parse_and_eval_long (args
);
535 if (load_end
<= load_start
)
536 error (_("Start must be less than end."));
542 printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n",
543 filename
.get (), (unsigned long) load_offset
,
544 (unsigned long) load_start
,
545 (unsigned long) load_end
);
549 restore_binary_file (filename
.get (), load_offset
, load_start
,
554 /* Open the file for loading. */
555 gdb_bfd_ref_ptr
ibfd (bfd_openr_or_error (filename
.get (), NULL
));
557 /* Process the sections. */
558 for (asection
*sect
: gdb_bfd_sections (ibfd
))
559 restore_one_section (ibfd
.get (), sect
, load_offset
, load_start
,
564 void _initialize_cli_dump ();
566 _initialize_cli_dump ()
568 struct cmd_list_element
*c
;
570 add_basic_prefix_cmd ("dump", class_vars
,
571 _("Dump target code/data to a local file."),
572 &dump_cmdlist
, "dump ",
575 add_basic_prefix_cmd ("append", class_vars
,
576 _("Append target code/data to a local file."),
577 &append_cmdlist
, "append ",
581 add_dump_command ("memory", dump_memory_command
, "\
582 Write contents of memory to a raw binary file.\n\
583 Arguments are FILE START STOP. Writes the contents of memory within the\n\
584 range [START .. STOP) to the specified FILE in raw target ordered bytes.");
586 add_dump_command ("value", dump_value_command
, "\
587 Write the value of an expression to a raw binary file.\n\
588 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\
589 the specified FILE in raw target ordered bytes.");
591 add_basic_prefix_cmd ("srec", all_commands
,
592 _("Write target code/data to an srec file."),
593 &srec_cmdlist
, "dump srec ",
597 add_basic_prefix_cmd ("ihex", all_commands
,
598 _("Write target code/data to an intel hex file."),
599 &ihex_cmdlist
, "dump ihex ",
603 add_basic_prefix_cmd ("verilog", all_commands
,
604 _("Write target code/data to a verilog hex file."),
605 &verilog_cmdlist
, "dump verilog ",
609 add_basic_prefix_cmd ("tekhex", all_commands
,
610 _("Write target code/data to a tekhex file."),
611 &tekhex_cmdlist
, "dump tekhex ",
615 add_basic_prefix_cmd ("binary", all_commands
,
616 _("Write target code/data to a raw binary file."),
617 &binary_dump_cmdlist
, "dump binary ",
621 add_basic_prefix_cmd ("binary", all_commands
,
622 _("Append target code/data to a raw binary file."),
623 &binary_append_cmdlist
, "append binary ",
627 add_cmd ("memory", all_commands
, dump_srec_memory
, _("\
628 Write contents of memory to an srec file.\n\
629 Arguments are FILE START STOP. Writes the contents of memory\n\
630 within the range [START .. STOP) to the specified FILE in srec format."),
633 add_cmd ("value", all_commands
, dump_srec_value
, _("\
634 Write the value of an expression to an srec file.\n\
635 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
636 to the specified FILE in srec format."),
639 add_cmd ("memory", all_commands
, dump_ihex_memory
, _("\
640 Write contents of memory to an ihex file.\n\
641 Arguments are FILE START STOP. Writes the contents of memory within\n\
642 the range [START .. STOP) to the specified FILE in intel hex format."),
645 add_cmd ("value", all_commands
, dump_ihex_value
, _("\
646 Write the value of an expression to an ihex file.\n\
647 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
648 to the specified FILE in intel hex format."),
651 add_cmd ("memory", all_commands
, dump_verilog_memory
, _("\
652 Write contents of memory to a verilog hex file.\n\
653 Arguments are FILE START STOP. Writes the contents of memory within\n\
654 the range [START .. STOP) to the specified FILE in verilog hex format."),
657 add_cmd ("value", all_commands
, dump_verilog_value
, _("\
658 Write the value of an expression to a verilog hex file.\n\
659 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
660 to the specified FILE in verilog hex format."),
663 add_cmd ("memory", all_commands
, dump_tekhex_memory
, _("\
664 Write contents of memory to a tekhex file.\n\
665 Arguments are FILE START STOP. Writes the contents of memory\n\
666 within the range [START .. STOP) to the specified FILE in tekhex format."),
669 add_cmd ("value", all_commands
, dump_tekhex_value
, _("\
670 Write the value of an expression to a tekhex file.\n\
671 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
672 to the specified FILE in tekhex format."),
675 add_cmd ("memory", all_commands
, dump_binary_memory
, _("\
676 Write contents of memory to a raw binary file.\n\
677 Arguments are FILE START STOP. Writes the contents of memory\n\
678 within the range [START .. STOP) to the specified FILE in binary format."),
679 &binary_dump_cmdlist
);
681 add_cmd ("value", all_commands
, dump_binary_value
, _("\
682 Write the value of an expression to a raw binary file.\n\
683 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
684 to the specified FILE in raw target ordered bytes."),
685 &binary_dump_cmdlist
);
687 add_cmd ("memory", all_commands
, append_binary_memory
, _("\
688 Append contents of memory to a raw binary file.\n\
689 Arguments are FILE START STOP. Writes the contents of memory within the\n\
690 range [START .. STOP) to the specified FILE in raw target ordered bytes."),
691 &binary_append_cmdlist
);
693 add_cmd ("value", all_commands
, append_binary_value
, _("\
694 Append the value of an expression to a raw binary file.\n\
695 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
696 to the specified FILE in raw target ordered bytes."),
697 &binary_append_cmdlist
);
699 c
= add_com ("restore", class_vars
, restore_command
, _("\
700 Restore the contents of FILE to target memory.\n\
701 Arguments are FILE OFFSET START END where all except FILE are optional.\n\
702 OFFSET will be added to the base address of the file (default zero).\n\
703 If START and END are given, only the file contents within that range\n\
704 (file relative) will be restored to target memory."));
705 c
->completer
= filename_completer
;
706 /* FIXME: completers for other commands. */