1 /* Dump-to-file commands, for GDB, the GNU debugger. 2 3 Copyright (C) 2002-2020 Free Software Foundation, Inc. 4 5 Contributed by Red Hat. 6 7 This file is part of GDB. 8 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. 13 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. 18 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/>. */ 21 22 #include "defs.h" 23 #include "cli/cli-decode.h" 24 #include "cli/cli-cmds.h" 25 #include "value.h" 26 #include "completer.h" 27 #include <ctype.h> 28 #include "target.h" 29 #include "readline/tilde.h" 30 #include "gdbcore.h" 31 #include "cli/cli-utils.h" 32 #include "gdb_bfd.h" 33 #include "gdbsupport/filestuff.h" 34 #include "gdbsupport/byte-vector.h" 35 #include "gdbarch.h" 36 37 static gdb::unique_xmalloc_ptr<char> 38 scan_expression (const char **cmd, const char *def) 39 { 40 if ((*cmd) == NULL || (**cmd) == '\0') 41 return make_unique_xstrdup (def); 42 else 43 { 44 char *exp; 45 const char *end; 46 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); 51 } 52 } 53 54 55 static gdb::unique_xmalloc_ptr<char> 56 scan_filename (const char **cmd, const char *defname) 57 { 58 gdb::unique_xmalloc_ptr<char> filename; 59 60 /* FIXME: Need to get the ``/a(ppend)'' flag from somewhere. */ 61 62 /* File. */ 63 if ((*cmd) == NULL) 64 { 65 if (defname == NULL) 66 error (_("Missing filename.")); 67 filename.reset (xstrdup (defname)); 68 } 69 else 70 { 71 /* FIXME: should parse a possibly quoted string. */ 72 const char *end; 73 74 (*cmd) = skip_spaces (*cmd); 75 end = *cmd + strcspn (*cmd, " \t"); 76 filename.reset (savestring ((*cmd), end - (*cmd))); 77 (*cmd) = skip_spaces (end); 78 } 79 gdb_assert (filename != NULL); 80 81 return gdb::unique_xmalloc_ptr<char> (tilde_expand (filename.get ())); 82 } 83 84 static gdb_bfd_ref_ptr 85 bfd_openr_or_error (const char *filename, const char *target) 86 { 87 gdb_bfd_ref_ptr ibfd (gdb_bfd_openr (filename, target)); 88 if (ibfd == NULL) 89 error (_("Failed to open %s: %s."), filename, 90 bfd_errmsg (bfd_get_error ())); 91 92 if (!bfd_check_format (ibfd.get (), bfd_object)) 93 error (_("'%s' is not a recognized file format."), filename); 94 95 return ibfd; 96 } 97 98 static gdb_bfd_ref_ptr 99 bfd_openw_or_error (const char *filename, const char *target, const char *mode) 100 { 101 gdb_bfd_ref_ptr obfd; 102 103 if (*mode == 'w') /* Write: create new file */ 104 { 105 obfd = gdb_bfd_openw (filename, target); 106 if (obfd == NULL) 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 ())); 111 } 112 else if (*mode == 'a') /* Append to existing file. */ 113 { /* FIXME -- doesn't work... */ 114 error (_("bfd_openw does not work with append.")); 115 } 116 else 117 error (_("bfd_openw_or_error: unknown mode %s."), mode); 118 119 return obfd; 120 } 121 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; 130 131 static void 132 dump_binary_file (const char *filename, const char *mode, 133 const bfd_byte *buf, ULONGEST len) 134 { 135 int status; 136 137 gdb_file_up file = gdb_fopen_cloexec (filename, mode); 138 status = fwrite (buf, len, 1, file.get ()); 139 if (status != 1) 140 perror_with_name (filename); 141 } 142 143 static void 144 dump_bfd_file (const char *filename, const char *mode, 145 const char *target, CORE_ADDR vaddr, 146 const bfd_byte *buf, ULONGEST len) 147 { 148 asection *osection; 149 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 ())); 160 } 161 162 static void 163 dump_memory_to_file (const char *cmd, const char *mode, const char *file_format) 164 { 165 CORE_ADDR lo; 166 CORE_ADDR hi; 167 ULONGEST count; 168 const char *hi_exp; 169 170 /* Open the file. */ 171 gdb::unique_xmalloc_ptr<char> filename = scan_filename (&cmd, NULL); 172 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); 177 178 /* Find the second address - rest of line. */ 179 if (cmd == NULL || *cmd == '\0') 180 error (_("Missing stop address.")); 181 hi_exp = cmd; 182 183 lo = parse_and_eval_address (lo_exp.get ()); 184 hi = parse_and_eval_address (hi_exp); 185 if (hi <= lo) 186 error (_("Invalid memory address range (start >= end).")); 187 count = hi - lo; 188 189 /* FIXME: Should use read_memory_partial() and a magic blocking 190 value. */ 191 gdb::byte_vector buf (count); 192 read_memory (lo, buf.data (), count); 193 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); 197 else 198 dump_bfd_file (filename.get (), mode, file_format, lo, buf.data (), count); 199 } 200 201 static void 202 dump_memory_command (const char *cmd, const char *mode) 203 { 204 dump_memory_to_file (cmd, mode, "binary"); 205 } 206 207 static void 208 dump_value_to_file (const char *cmd, const char *mode, const char *file_format) 209 { 210 struct value *val; 211 212 /* Open the file. */ 213 gdb::unique_xmalloc_ptr<char> filename = scan_filename (&cmd, NULL); 214 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); 219 if (val == NULL) 220 error (_("Invalid expression.")); 221 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))); 226 else 227 { 228 CORE_ADDR vaddr; 229 230 if (VALUE_LVAL (val)) 231 { 232 vaddr = value_address (val); 233 } 234 else 235 { 236 vaddr = 0; 237 warning (_("value is not an lval: address assumed to be zero")); 238 } 239 240 dump_bfd_file (filename.get (), mode, file_format, vaddr, 241 value_contents (val), 242 TYPE_LENGTH (value_type (val))); 243 } 244 } 245 246 static void 247 dump_value_command (const char *cmd, const char *mode) 248 { 249 dump_value_to_file (cmd, mode, "binary"); 250 } 251 252 static void 253 dump_srec_memory (const char *args, int from_tty) 254 { 255 dump_memory_to_file (args, FOPEN_WB, "srec"); 256 } 257 258 static void 259 dump_srec_value (const char *args, int from_tty) 260 { 261 dump_value_to_file (args, FOPEN_WB, "srec"); 262 } 263 264 static void 265 dump_ihex_memory (const char *args, int from_tty) 266 { 267 dump_memory_to_file (args, FOPEN_WB, "ihex"); 268 } 269 270 static void 271 dump_ihex_value (const char *args, int from_tty) 272 { 273 dump_value_to_file (args, FOPEN_WB, "ihex"); 274 } 275 276 static void 277 dump_verilog_memory (const char *args, int from_tty) 278 { 279 dump_memory_to_file (args, FOPEN_WB, "verilog"); 280 } 281 282 static void 283 dump_verilog_value (const char *args, int from_tty) 284 { 285 dump_value_to_file (args, FOPEN_WB, "verilog"); 286 } 287 288 static void 289 dump_tekhex_memory (const char *args, int from_tty) 290 { 291 dump_memory_to_file (args, FOPEN_WB, "tekhex"); 292 } 293 294 static void 295 dump_tekhex_value (const char *args, int from_tty) 296 { 297 dump_value_to_file (args, FOPEN_WB, "tekhex"); 298 } 299 300 static void 301 dump_binary_memory (const char *args, int from_tty) 302 { 303 dump_memory_to_file (args, FOPEN_WB, "binary"); 304 } 305 306 static void 307 dump_binary_value (const char *args, int from_tty) 308 { 309 dump_value_to_file (args, FOPEN_WB, "binary"); 310 } 311 312 static void 313 append_binary_memory (const char *args, int from_tty) 314 { 315 dump_memory_to_file (args, FOPEN_AB, "binary"); 316 } 317 318 static void 319 append_binary_value (const char *args, int from_tty) 320 { 321 dump_value_to_file (args, FOPEN_AB, "binary"); 322 } 323 324 struct dump_context 325 { 326 void (*func) (const char *cmd, const char *mode); 327 const char *mode; 328 }; 329 330 static void 331 call_dump_func (struct cmd_list_element *c, const char *args, int from_tty) 332 { 333 struct dump_context *d = (struct dump_context *) get_cmd_context (c); 334 335 d->func (args, d->mode); 336 } 337 338 static void 339 add_dump_command (const char *name, 340 void (*func) (const char *args, const char *mode), 341 const char *descr) 342 343 { 344 struct cmd_list_element *c; 345 struct dump_context *d; 346 347 c = add_cmd (name, all_commands, descr, &dump_cmdlist); 348 c->completer = filename_completer; 349 d = XNEW (struct dump_context); 350 d->func = func; 351 d->mode = FOPEN_WB; 352 set_cmd_context (c, d); 353 c->func = call_dump_func; 354 355 c = add_cmd (name, all_commands, descr, &append_cmdlist); 356 c->completer = filename_completer; 357 d = XNEW (struct dump_context); 358 d->func = func; 359 d->mode = FOPEN_AB; 360 set_cmd_context (c, d); 361 c->func = call_dump_func; 362 363 /* Replace "Dump " at start of docstring with "Append " (borrowed 364 from [deleted] deprecated_add_show_from_set). */ 365 if ( c->doc[0] == 'W' 366 && c->doc[1] == 'r' 367 && c->doc[2] == 'i' 368 && c->doc[3] == 't' 369 && c->doc[4] == 'e' 370 && c->doc[5] == ' ') 371 c->doc = concat ("Append ", c->doc + 6, (char *)NULL); 372 } 373 374 /* Opaque data for restore_section_callback. */ 375 struct callback_data { 376 CORE_ADDR load_offset; 377 CORE_ADDR load_start; 378 CORE_ADDR load_end; 379 }; 380 381 /* Function: restore_section_callback. 382 383 Callback function for bfd_map_over_sections. 384 Selectively loads the sections into memory. */ 385 386 static void 387 restore_section_callback (bfd *ibfd, asection *isec, void *args) 388 { 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; 395 int ret; 396 397 /* Ignore non-loadable sections, eg. from elf files. */ 398 if (!(bfd_section_flags (isec) & SEC_LOAD)) 399 return; 400 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)) 404 { 405 /* No, no useable data in this section. */ 406 printf_filtered (_("skipping section %s...\n"), 407 bfd_section_name (isec)); 408 return; 409 } 410 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; 420 421 /* Get the data. */ 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 ())); 426 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); 431 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)); 440 else 441 puts_filtered ("\n"); 442 443 /* Write the data. */ 444 ret = target_write_memory (sec_start + sec_offset + data->load_offset, 445 &buf[sec_offset], sec_load_count); 446 if (ret != 0) 447 warning (_("restore: memory write failed (%s)."), safe_strerror (ret)); 448 } 449 450 static void 451 restore_binary_file (const char *filename, struct callback_data *data) 452 { 453 gdb_file_up file = gdb_fopen_cloexec (filename, FOPEN_RB); 454 long len; 455 456 if (file == NULL) 457 error (_("Failed to open %s: %s"), filename, safe_strerror (errno)); 458 459 /* Get the file size for reading. */ 460 if (fseek (file.get (), 0, SEEK_END) == 0) 461 { 462 len = ftell (file.get ()); 463 if (len < 0) 464 perror_with_name (filename); 465 } 466 else 467 perror_with_name (filename); 468 469 if (len <= data->load_start) 470 error (_("Start address is greater than length of binary file %s."), 471 filename); 472 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; 479 480 printf_filtered 481 ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n", 482 filename, 483 (unsigned long) (data->load_start + data->load_offset), 484 (unsigned long) (data->load_start + data->load_offset + len)); 485 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); 489 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); 494 495 /* Now write the buffer into target memory. */ 496 len = target_write_memory (data->load_start + data->load_offset, 497 buf.data (), len); 498 if (len != 0) 499 warning (_("restore: memory write failed (%s)."), safe_strerror (len)); 500 } 501 502 static void 503 restore_command (const char *args, int from_tty) 504 { 505 struct callback_data data; 506 int binary_flag = 0; 507 508 if (!target_has_execution) 509 noprocess (); 510 511 data.load_offset = 0; 512 data.load_start = 0; 513 data.load_end = 0; 514 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') 518 { 519 static const char binary_string[] = "binary"; 520 521 /* Look for optional "binary" flag. */ 522 if (startswith (args, binary_string)) 523 { 524 binary_flag = 1; 525 args += strlen (binary_string); 526 args = skip_spaces (args); 527 } 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') 534 { 535 /* Parse start address (optional). */ 536 data.load_start = 537 parse_and_eval_long (scan_expression (&args, NULL).get ()); 538 if (args != NULL && *args != '\0') 539 { 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.")); 544 } 545 } 546 } 547 548 if (info_verbose) 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); 553 554 if (binary_flag) 555 { 556 restore_binary_file (filename.get (), &data); 557 } 558 else 559 { 560 /* Open the file for loading. */ 561 gdb_bfd_ref_ptr ibfd (bfd_openr_or_error (filename.get (), NULL)); 562 563 /* Process the sections. */ 564 bfd_map_over_sections (ibfd.get (), restore_section_callback, &data); 565 } 566 } 567 568 void _initialize_cli_dump (); 569 void 570 _initialize_cli_dump () 571 { 572 struct cmd_list_element *c; 573 574 add_basic_prefix_cmd ("dump", class_vars, 575 _("Dump target code/data to a local file."), 576 &dump_cmdlist, "dump ", 577 0/*allow-unknown*/, 578 &cmdlist); 579 add_basic_prefix_cmd ("append", class_vars, 580 _("Append target code/data to a local file."), 581 &append_cmdlist, "append ", 582 0/*allow-unknown*/, 583 &cmdlist); 584 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."); 589 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."); 594 595 add_basic_prefix_cmd ("srec", all_commands, 596 _("Write target code/data to an srec file."), 597 &srec_cmdlist, "dump srec ", 598 0 /*allow-unknown*/, 599 &dump_cmdlist); 600 601 add_basic_prefix_cmd ("ihex", all_commands, 602 _("Write target code/data to an intel hex file."), 603 &ihex_cmdlist, "dump ihex ", 604 0 /*allow-unknown*/, 605 &dump_cmdlist); 606 607 add_basic_prefix_cmd ("verilog", all_commands, 608 _("Write target code/data to a verilog hex file."), 609 &verilog_cmdlist, "dump verilog ", 610 0 /*allow-unknown*/, 611 &dump_cmdlist); 612 613 add_basic_prefix_cmd ("tekhex", all_commands, 614 _("Write target code/data to a tekhex file."), 615 &tekhex_cmdlist, "dump tekhex ", 616 0 /*allow-unknown*/, 617 &dump_cmdlist); 618 619 add_basic_prefix_cmd ("binary", all_commands, 620 _("Write target code/data to a raw binary file."), 621 &binary_dump_cmdlist, "dump binary ", 622 0 /*allow-unknown*/, 623 &dump_cmdlist); 624 625 add_basic_prefix_cmd ("binary", all_commands, 626 _("Append target code/data to a raw binary file."), 627 &binary_append_cmdlist, "append binary ", 628 0 /*allow-unknown*/, 629 &append_cmdlist); 630 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."), 635 &srec_cmdlist); 636 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."), 641 &srec_cmdlist); 642 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."), 647 &ihex_cmdlist); 648 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."), 653 &ihex_cmdlist); 654 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."), 659 &verilog_cmdlist); 660 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."), 665 &verilog_cmdlist); 666 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."), 671 &tekhex_cmdlist); 672 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."), 677 &tekhex_cmdlist); 678 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); 684 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); 690 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); 696 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); 702 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. */ 711 } 712