1 /* Dump-to-file commands, for GDB, the GNU debugger. 2 3 Copyright (C) 2002-2023 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 if (file == nullptr) 139 perror_with_name (filename); 140 141 status = fwrite (buf, len, 1, file.get ()); 142 if (status != 1) 143 perror_with_name (filename); 144 } 145 146 static void 147 dump_bfd_file (const char *filename, const char *mode, 148 const char *target, CORE_ADDR vaddr, 149 const bfd_byte *buf, ULONGEST len) 150 { 151 asection *osection; 152 153 gdb_bfd_ref_ptr obfd (bfd_openw_or_error (filename, target, mode)); 154 osection = bfd_make_section_anyway (obfd.get (), ".newsec"); 155 bfd_set_section_size (osection, len); 156 bfd_set_section_vma (osection, vaddr); 157 bfd_set_section_alignment (osection, 0); 158 bfd_set_section_flags (osection, (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD)); 159 osection->entsize = 0; 160 if (!bfd_set_section_contents (obfd.get (), osection, buf, 0, len)) 161 warning (_("writing dump file '%s' (%s)"), filename, 162 bfd_errmsg (bfd_get_error ())); 163 } 164 165 static void 166 dump_memory_to_file (const char *cmd, const char *mode, const char *file_format) 167 { 168 CORE_ADDR lo; 169 CORE_ADDR hi; 170 ULONGEST count; 171 const char *hi_exp; 172 173 /* Open the file. */ 174 gdb::unique_xmalloc_ptr<char> filename = scan_filename (&cmd, NULL); 175 176 /* Find the low address. */ 177 if (cmd == NULL || *cmd == '\0') 178 error (_("Missing start address.")); 179 gdb::unique_xmalloc_ptr<char> lo_exp = scan_expression (&cmd, NULL); 180 181 /* Find the second address - rest of line. */ 182 if (cmd == NULL || *cmd == '\0') 183 error (_("Missing stop address.")); 184 hi_exp = cmd; 185 186 lo = parse_and_eval_address (lo_exp.get ()); 187 hi = parse_and_eval_address (hi_exp); 188 if (hi <= lo) 189 error (_("Invalid memory address range (start >= end).")); 190 count = hi - lo; 191 192 /* FIXME: Should use read_memory_partial() and a magic blocking 193 value. */ 194 gdb::byte_vector buf (count); 195 read_memory (lo, buf.data (), count); 196 197 /* Have everything. Open/write the data. */ 198 if (file_format == NULL || strcmp (file_format, "binary") == 0) 199 dump_binary_file (filename.get (), mode, buf.data (), count); 200 else 201 dump_bfd_file (filename.get (), mode, file_format, lo, buf.data (), count); 202 } 203 204 static void 205 dump_memory_command (const char *cmd, const char *mode) 206 { 207 dump_memory_to_file (cmd, mode, "binary"); 208 } 209 210 static void 211 dump_value_to_file (const char *cmd, const char *mode, const char *file_format) 212 { 213 struct value *val; 214 215 /* Open the file. */ 216 gdb::unique_xmalloc_ptr<char> filename = scan_filename (&cmd, NULL); 217 218 /* Find the value. */ 219 if (cmd == NULL || *cmd == '\0') 220 error (_("No value to %s."), *mode == 'a' ? "append" : "dump"); 221 val = parse_and_eval (cmd); 222 if (val == NULL) 223 error (_("Invalid expression.")); 224 225 /* Have everything. Open/write the data. */ 226 if (file_format == NULL || strcmp (file_format, "binary") == 0) 227 dump_binary_file (filename.get (), mode, value_contents (val).data (), 228 value_type (val)->length ()); 229 else 230 { 231 CORE_ADDR vaddr; 232 233 if (VALUE_LVAL (val)) 234 { 235 vaddr = value_address (val); 236 } 237 else 238 { 239 vaddr = 0; 240 warning (_("value is not an lval: address assumed to be zero")); 241 } 242 243 dump_bfd_file (filename.get (), mode, file_format, vaddr, 244 value_contents (val).data (), 245 value_type (val)->length ()); 246 } 247 } 248 249 static void 250 dump_value_command (const char *cmd, const char *mode) 251 { 252 dump_value_to_file (cmd, mode, "binary"); 253 } 254 255 static void 256 dump_srec_memory (const char *args, int from_tty) 257 { 258 dump_memory_to_file (args, FOPEN_WB, "srec"); 259 } 260 261 static void 262 dump_srec_value (const char *args, int from_tty) 263 { 264 dump_value_to_file (args, FOPEN_WB, "srec"); 265 } 266 267 static void 268 dump_ihex_memory (const char *args, int from_tty) 269 { 270 dump_memory_to_file (args, FOPEN_WB, "ihex"); 271 } 272 273 static void 274 dump_ihex_value (const char *args, int from_tty) 275 { 276 dump_value_to_file (args, FOPEN_WB, "ihex"); 277 } 278 279 static void 280 dump_verilog_memory (const char *args, int from_tty) 281 { 282 dump_memory_to_file (args, FOPEN_WB, "verilog"); 283 } 284 285 static void 286 dump_verilog_value (const char *args, int from_tty) 287 { 288 dump_value_to_file (args, FOPEN_WB, "verilog"); 289 } 290 291 static void 292 dump_tekhex_memory (const char *args, int from_tty) 293 { 294 dump_memory_to_file (args, FOPEN_WB, "tekhex"); 295 } 296 297 static void 298 dump_tekhex_value (const char *args, int from_tty) 299 { 300 dump_value_to_file (args, FOPEN_WB, "tekhex"); 301 } 302 303 static void 304 dump_binary_memory (const char *args, int from_tty) 305 { 306 dump_memory_to_file (args, FOPEN_WB, "binary"); 307 } 308 309 static void 310 dump_binary_value (const char *args, int from_tty) 311 { 312 dump_value_to_file (args, FOPEN_WB, "binary"); 313 } 314 315 static void 316 append_binary_memory (const char *args, int from_tty) 317 { 318 dump_memory_to_file (args, FOPEN_AB, "binary"); 319 } 320 321 static void 322 append_binary_value (const char *args, int from_tty) 323 { 324 dump_value_to_file (args, FOPEN_AB, "binary"); 325 } 326 327 struct dump_context 328 { 329 void (*func) (const char *cmd, const char *mode); 330 const char *mode; 331 }; 332 333 static void 334 call_dump_func (const char *args, int from_tty, cmd_list_element *c) 335 { 336 struct dump_context *d = (struct dump_context *) c->context (); 337 338 d->func (args, d->mode); 339 } 340 341 static void 342 add_dump_command (const char *name, 343 void (*func) (const char *args, const char *mode), 344 const char *descr) 345 346 { 347 struct cmd_list_element *c; 348 struct dump_context *d; 349 350 c = add_cmd (name, all_commands, descr, &dump_cmdlist); 351 c->completer = filename_completer; 352 d = XNEW (struct dump_context); 353 d->func = func; 354 d->mode = FOPEN_WB; 355 c->set_context (d); 356 c->func = call_dump_func; 357 358 c = add_cmd (name, all_commands, descr, &append_cmdlist); 359 c->completer = filename_completer; 360 d = XNEW (struct dump_context); 361 d->func = func; 362 d->mode = FOPEN_AB; 363 c->set_context (d); 364 c->func = call_dump_func; 365 366 /* Replace "Dump " at start of docstring with "Append " (borrowed 367 from [deleted] deprecated_add_show_from_set). */ 368 if ( c->doc[0] == 'W' 369 && c->doc[1] == 'r' 370 && c->doc[2] == 'i' 371 && c->doc[3] == 't' 372 && c->doc[4] == 'e' 373 && c->doc[5] == ' ') 374 c->doc = concat ("Append ", c->doc + 6, (char *)NULL); 375 } 376 377 /* Selectively loads the sections into memory. */ 378 379 static void 380 restore_one_section (bfd *ibfd, asection *isec, 381 CORE_ADDR load_offset, 382 CORE_ADDR load_start, 383 CORE_ADDR load_end) 384 { 385 bfd_vma sec_start = bfd_section_vma (isec); 386 bfd_size_type size = bfd_section_size (isec); 387 bfd_vma sec_end = sec_start + size; 388 bfd_size_type sec_offset = 0; 389 bfd_size_type sec_load_count = size; 390 int ret; 391 392 /* Ignore non-loadable sections, eg. from elf files. */ 393 if (!(bfd_section_flags (isec) & SEC_LOAD)) 394 return; 395 396 /* Does the section overlap with the desired restore range? */ 397 if (sec_end <= load_start 398 || (load_end > 0 && sec_start >= load_end)) 399 { 400 /* No, no useable data in this section. */ 401 gdb_printf (_("skipping section %s...\n"), 402 bfd_section_name (isec)); 403 return; 404 } 405 406 /* Compare section address range with user-requested 407 address range (if any). Compute where the actual 408 transfer should start and end. */ 409 if (sec_start < load_start) 410 sec_offset = load_start - sec_start; 411 /* Size of a partial transfer. */ 412 sec_load_count -= sec_offset; 413 if (load_end > 0 && sec_end > load_end) 414 sec_load_count -= sec_end - load_end; 415 416 /* Get the data. */ 417 gdb::byte_vector buf (size); 418 if (!bfd_get_section_contents (ibfd, isec, buf.data (), 0, size)) 419 error (_("Failed to read bfd file %s: '%s'."), bfd_get_filename (ibfd), 420 bfd_errmsg (bfd_get_error ())); 421 422 gdb_printf ("Restoring section %s (0x%lx to 0x%lx)", 423 bfd_section_name (isec), 424 (unsigned long) sec_start, 425 (unsigned long) sec_end); 426 427 if (load_offset != 0 || load_start != 0 || load_end != 0) 428 gdb_printf (" into memory (%s to %s)\n", 429 paddress (target_gdbarch (), 430 (unsigned long) sec_start 431 + sec_offset + load_offset), 432 paddress (target_gdbarch (), 433 (unsigned long) sec_start + sec_offset 434 + load_offset + sec_load_count)); 435 else 436 gdb_puts ("\n"); 437 438 /* Write the data. */ 439 ret = target_write_memory (sec_start + sec_offset + load_offset, 440 &buf[sec_offset], sec_load_count); 441 if (ret != 0) 442 warning (_("restore: memory write failed (%s)."), safe_strerror (ret)); 443 } 444 445 static void 446 restore_binary_file (const char *filename, CORE_ADDR load_offset, 447 CORE_ADDR load_start, CORE_ADDR load_end) 448 449 { 450 gdb_file_up file = gdb_fopen_cloexec (filename, FOPEN_RB); 451 long len; 452 453 if (file == NULL) 454 error (_("Failed to open %s: %s"), filename, safe_strerror (errno)); 455 456 /* Get the file size for reading. */ 457 if (fseek (file.get (), 0, SEEK_END) == 0) 458 { 459 len = ftell (file.get ()); 460 if (len < 0) 461 perror_with_name (filename); 462 } 463 else 464 perror_with_name (filename); 465 466 if (len <= load_start) 467 error (_("Start address is greater than length of binary file %s."), 468 filename); 469 470 /* Chop off "len" if it exceeds the requested load_end addr. */ 471 if (load_end != 0 && load_end < len) 472 len = load_end; 473 /* Chop off "len" if the requested load_start addr skips some bytes. */ 474 if (load_start > 0) 475 len -= load_start; 476 477 gdb_printf 478 ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n", 479 filename, 480 (unsigned long) (load_start + load_offset), 481 (unsigned long) (load_start + load_offset + len)); 482 483 /* Now set the file pos to the requested load start pos. */ 484 if (fseek (file.get (), load_start, SEEK_SET) != 0) 485 perror_with_name (filename); 486 487 /* Now allocate a buffer and read the file contents. */ 488 gdb::byte_vector buf (len); 489 if (fread (buf.data (), 1, len, file.get ()) != len) 490 perror_with_name (filename); 491 492 /* Now write the buffer into target memory. */ 493 len = target_write_memory (load_start + load_offset, buf.data (), len); 494 if (len != 0) 495 warning (_("restore: memory write failed (%s)."), safe_strerror (len)); 496 } 497 498 static void 499 restore_command (const char *args, int from_tty) 500 { 501 int binary_flag = 0; 502 503 if (!target_has_execution ()) 504 noprocess (); 505 506 CORE_ADDR load_offset = 0; 507 CORE_ADDR load_start = 0; 508 CORE_ADDR load_end = 0; 509 510 /* Parse the input arguments. First is filename (required). */ 511 gdb::unique_xmalloc_ptr<char> filename = scan_filename (&args, NULL); 512 if (args != NULL && *args != '\0') 513 { 514 static const char binary_string[] = "binary"; 515 516 /* Look for optional "binary" flag. */ 517 if (startswith (args, binary_string)) 518 { 519 binary_flag = 1; 520 args += strlen (binary_string); 521 args = skip_spaces (args); 522 } 523 /* Parse offset (optional). */ 524 if (args != NULL && *args != '\0') 525 load_offset 526 = (binary_flag 527 ? parse_and_eval_address (scan_expression (&args, NULL).get ()) 528 : parse_and_eval_long (scan_expression (&args, NULL).get ())); 529 if (args != NULL && *args != '\0') 530 { 531 /* Parse start address (optional). */ 532 load_start = 533 parse_and_eval_long (scan_expression (&args, NULL).get ()); 534 if (args != NULL && *args != '\0') 535 { 536 /* Parse end address (optional). */ 537 load_end = parse_and_eval_long (args); 538 if (load_end <= load_start) 539 error (_("Start must be less than end.")); 540 } 541 } 542 } 543 544 if (info_verbose) 545 gdb_printf ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n", 546 filename.get (), (unsigned long) load_offset, 547 (unsigned long) load_start, 548 (unsigned long) load_end); 549 550 if (binary_flag) 551 { 552 restore_binary_file (filename.get (), load_offset, load_start, 553 load_end); 554 } 555 else 556 { 557 /* Open the file for loading. */ 558 gdb_bfd_ref_ptr ibfd (bfd_openr_or_error (filename.get (), NULL)); 559 560 /* Process the sections. */ 561 for (asection *sect : gdb_bfd_sections (ibfd)) 562 restore_one_section (ibfd.get (), sect, load_offset, load_start, 563 load_end); 564 } 565 } 566 567 void _initialize_cli_dump (); 568 void 569 _initialize_cli_dump () 570 { 571 struct cmd_list_element *c; 572 573 add_basic_prefix_cmd ("dump", class_vars, 574 _("Dump target code/data to a local file."), 575 &dump_cmdlist, 576 0/*allow-unknown*/, 577 &cmdlist); 578 add_basic_prefix_cmd ("append", class_vars, 579 _("Append target code/data to a local file."), 580 &append_cmdlist, 581 0/*allow-unknown*/, 582 &cmdlist); 583 584 add_dump_command ("memory", dump_memory_command, "\ 585 Write contents of memory to a raw binary file.\n\ 586 Arguments are FILE START STOP. Writes the contents of memory within the\n\ 587 range [START .. STOP) to the specified FILE in raw target ordered bytes."); 588 589 add_dump_command ("value", dump_value_command, "\ 590 Write the value of an expression to a raw binary file.\n\ 591 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\ 592 the specified FILE in raw target ordered bytes."); 593 594 add_basic_prefix_cmd ("srec", all_commands, 595 _("Write target code/data to an srec file."), 596 &srec_cmdlist, 597 0 /*allow-unknown*/, 598 &dump_cmdlist); 599 600 add_basic_prefix_cmd ("ihex", all_commands, 601 _("Write target code/data to an intel hex file."), 602 &ihex_cmdlist, 603 0 /*allow-unknown*/, 604 &dump_cmdlist); 605 606 add_basic_prefix_cmd ("verilog", all_commands, 607 _("Write target code/data to a verilog hex file."), 608 &verilog_cmdlist, 609 0 /*allow-unknown*/, 610 &dump_cmdlist); 611 612 add_basic_prefix_cmd ("tekhex", all_commands, 613 _("Write target code/data to a tekhex file."), 614 &tekhex_cmdlist, 615 0 /*allow-unknown*/, 616 &dump_cmdlist); 617 618 add_basic_prefix_cmd ("binary", all_commands, 619 _("Write target code/data to a raw binary file."), 620 &binary_dump_cmdlist, 621 0 /*allow-unknown*/, 622 &dump_cmdlist); 623 624 add_basic_prefix_cmd ("binary", all_commands, 625 _("Append target code/data to a raw binary file."), 626 &binary_append_cmdlist, 627 0 /*allow-unknown*/, 628 &append_cmdlist); 629 630 add_cmd ("memory", all_commands, dump_srec_memory, _("\ 631 Write contents of memory to an srec file.\n\ 632 Arguments are FILE START STOP. Writes the contents of memory\n\ 633 within the range [START .. STOP) to the specified FILE in srec format."), 634 &srec_cmdlist); 635 636 add_cmd ("value", all_commands, dump_srec_value, _("\ 637 Write the value of an expression to an srec file.\n\ 638 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ 639 to the specified FILE in srec format."), 640 &srec_cmdlist); 641 642 add_cmd ("memory", all_commands, dump_ihex_memory, _("\ 643 Write contents of memory to an ihex file.\n\ 644 Arguments are FILE START STOP. Writes the contents of memory within\n\ 645 the range [START .. STOP) to the specified FILE in intel hex format."), 646 &ihex_cmdlist); 647 648 add_cmd ("value", all_commands, dump_ihex_value, _("\ 649 Write the value of an expression to an ihex file.\n\ 650 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ 651 to the specified FILE in intel hex format."), 652 &ihex_cmdlist); 653 654 add_cmd ("memory", all_commands, dump_verilog_memory, _("\ 655 Write contents of memory to a verilog hex file.\n\ 656 Arguments are FILE START STOP. Writes the contents of memory within\n\ 657 the range [START .. STOP) to the specified FILE in verilog hex format."), 658 &verilog_cmdlist); 659 660 add_cmd ("value", all_commands, dump_verilog_value, _("\ 661 Write the value of an expression to a verilog hex file.\n\ 662 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ 663 to the specified FILE in verilog hex format."), 664 &verilog_cmdlist); 665 666 add_cmd ("memory", all_commands, dump_tekhex_memory, _("\ 667 Write contents of memory to a tekhex file.\n\ 668 Arguments are FILE START STOP. Writes the contents of memory\n\ 669 within the range [START .. STOP) to the specified FILE in tekhex format."), 670 &tekhex_cmdlist); 671 672 add_cmd ("value", all_commands, dump_tekhex_value, _("\ 673 Write the value of an expression to a tekhex file.\n\ 674 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ 675 to the specified FILE in tekhex format."), 676 &tekhex_cmdlist); 677 678 add_cmd ("memory", all_commands, dump_binary_memory, _("\ 679 Write contents of memory to a raw binary file.\n\ 680 Arguments are FILE START STOP. Writes the contents of memory\n\ 681 within the range [START .. STOP) to the specified FILE in binary format."), 682 &binary_dump_cmdlist); 683 684 add_cmd ("value", all_commands, dump_binary_value, _("\ 685 Write the value of an expression to a raw binary file.\n\ 686 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ 687 to the specified FILE in raw target ordered bytes."), 688 &binary_dump_cmdlist); 689 690 add_cmd ("memory", all_commands, append_binary_memory, _("\ 691 Append contents of memory to a raw binary file.\n\ 692 Arguments are FILE START STOP. Writes the contents of memory within the\n\ 693 range [START .. STOP) to the specified FILE in raw target ordered bytes."), 694 &binary_append_cmdlist); 695 696 add_cmd ("value", all_commands, append_binary_value, _("\ 697 Append the value of an expression to a raw binary file.\n\ 698 Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ 699 to the specified FILE in raw target ordered bytes."), 700 &binary_append_cmdlist); 701 702 c = add_com ("restore", class_vars, restore_command, _("\ 703 Restore the contents of FILE to target memory.\n\ 704 Arguments are FILE OFFSET START END where all except FILE are optional.\n\ 705 OFFSET will be added to the base address of the file (default zero).\n\ 706 If START and END are given, only the file contents within that range\n\ 707 (file relative) will be restored to target memory.")); 708 c->completer = filename_completer; 709 /* FIXME: completers for other commands. */ 710 } 711