1 //===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CommandObjectMemory.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/DataBufferHeap.h" 17 #include "lldb/Core/DataExtractor.h" 18 #include "lldb/Core/Debugger.h" 19 #include "lldb/Core/StreamString.h" 20 #include "lldb/Interpreter/Args.h" 21 #include "lldb/Interpreter/CommandReturnObject.h" 22 #include "lldb/Interpreter/CommandInterpreter.h" 23 #include "lldb/Interpreter/Options.h" 24 #include "lldb/Target/Process.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 29 //---------------------------------------------------------------------- 30 // Read memory from the inferior process 31 //---------------------------------------------------------------------- 32 class CommandObjectMemoryRead : public CommandObject 33 { 34 public: 35 36 class CommandOptions : public Options 37 { 38 public: 39 CommandOptions () : 40 Options() 41 { 42 ResetOptionValues(); 43 } 44 45 virtual 46 ~CommandOptions () 47 { 48 } 49 50 virtual Error 51 SetOptionValue (int option_idx, const char *option_arg) 52 { 53 Error error; 54 char short_option = (char) m_getopt_table[option_idx].val; 55 56 switch (short_option) 57 { 58 case 'f': 59 error = Args::StringToFormat (option_arg, m_format); 60 61 switch (m_format) 62 { 63 default: 64 break; 65 66 case eFormatBoolean: 67 if (m_byte_size == 0) 68 m_byte_size = 1; 69 if (m_num_per_line == 0) 70 m_num_per_line = 1; 71 break; 72 73 case eFormatCString: 74 if (m_num_per_line == 0) 75 m_num_per_line = 1; 76 break; 77 78 case eFormatPointer: 79 break; 80 81 case eFormatBinary: 82 case eFormatFloat: 83 case eFormatOctal: 84 case eFormatDecimal: 85 case eFormatEnum: 86 case eFormatUnicode16: 87 case eFormatUnicode32: 88 case eFormatUnsigned: 89 if (m_byte_size == 0) 90 m_byte_size = 4; 91 if (m_num_per_line == 0) 92 m_num_per_line = 1; 93 break; 94 95 case eFormatBytes: 96 case eFormatBytesWithASCII: 97 case eFormatChar: 98 case eFormatCharPrintable: 99 if (m_byte_size == 0) 100 m_byte_size = 1; 101 break; 102 case eFormatComplex: 103 if (m_byte_size == 0) 104 m_byte_size = 8; 105 break; 106 case eFormatHex: 107 if (m_byte_size == 0) 108 m_byte_size = 4; 109 break; 110 111 case eFormatVectorOfChar: 112 case eFormatVectorOfSInt8: 113 case eFormatVectorOfUInt8: 114 case eFormatVectorOfSInt16: 115 case eFormatVectorOfUInt16: 116 case eFormatVectorOfSInt32: 117 case eFormatVectorOfUInt32: 118 case eFormatVectorOfSInt64: 119 case eFormatVectorOfUInt64: 120 case eFormatVectorOfFloat32: 121 case eFormatVectorOfFloat64: 122 case eFormatVectorOfUInt128: 123 break; 124 } 125 break; 126 127 case 'l': 128 m_num_per_line = Args::StringToUInt32 (option_arg, 0); 129 if (m_num_per_line == 0) 130 error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg); 131 break; 132 133 case 'c': 134 m_count = Args::StringToUInt32 (option_arg, 0); 135 if (m_count == 0) 136 error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg); 137 break; 138 139 case 's': 140 m_byte_size = Args::StringToUInt32 (option_arg, 0); 141 if (m_byte_size == 0) 142 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg); 143 break; 144 145 case 'o': 146 m_outfile_filespec.SetFile (option_arg, true); 147 break; 148 149 case 'b': 150 m_output_as_binary = true; 151 break; 152 153 case 'a': 154 m_append_to_outfile = true; 155 break; 156 157 default: 158 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option); 159 break; 160 } 161 return error; 162 } 163 164 void 165 ResetOptionValues () 166 { 167 Options::ResetOptionValues(); 168 m_format = eFormatBytesWithASCII; 169 m_byte_size = 0; 170 m_count = 0; 171 m_num_per_line = 0; 172 m_outfile_filespec.Clear(); 173 m_append_to_outfile = false; 174 m_output_as_binary = false; 175 } 176 177 const OptionDefinition* 178 GetDefinitions () 179 { 180 return g_option_table; 181 } 182 183 // Options table: Required for subclasses of Options. 184 185 static OptionDefinition g_option_table[]; 186 187 // Instance variables to hold the values for command options. 188 lldb::Format m_format; 189 uint32_t m_byte_size; 190 uint32_t m_count; 191 uint32_t m_num_per_line; 192 FileSpec m_outfile_filespec; 193 bool m_append_to_outfile; 194 bool m_output_as_binary; 195 }; 196 197 CommandObjectMemoryRead (CommandInterpreter &interpreter) : 198 CommandObject (interpreter, 199 "memory read", 200 "Read from the memory of the process being debugged.", 201 NULL, 202 eFlagProcessMustBeLaunched) 203 { 204 CommandArgumentEntry arg1; 205 CommandArgumentEntry arg2; 206 CommandArgumentData start_addr_arg; 207 CommandArgumentData end_addr_arg; 208 209 // Define the first (and only) variant of this arg. 210 start_addr_arg.arg_type = eArgTypeStartAddress; 211 start_addr_arg.arg_repetition = eArgRepeatPlain; 212 213 // There is only one variant this argument could be; put it into the argument entry. 214 arg1.push_back (start_addr_arg); 215 216 // Define the first (and only) variant of this arg. 217 end_addr_arg.arg_type = eArgTypeEndAddress; 218 end_addr_arg.arg_repetition = eArgRepeatOptional; 219 220 // There is only one variant this argument could be; put it into the argument entry. 221 arg2.push_back (end_addr_arg); 222 223 // Push the data for the first argument into the m_arguments vector. 224 m_arguments.push_back (arg1); 225 m_arguments.push_back (arg2); 226 } 227 228 virtual 229 ~CommandObjectMemoryRead () 230 { 231 } 232 233 Options * 234 GetOptions () 235 { 236 return &m_options; 237 } 238 239 virtual bool 240 Execute (Args& command, 241 CommandReturnObject &result) 242 { 243 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 244 if (process == NULL) 245 { 246 result.AppendError("need a process to read memory"); 247 result.SetStatus(eReturnStatusFailed); 248 return false; 249 } 250 const size_t argc = command.GetArgumentCount(); 251 252 if (argc == 0 || argc > 2) 253 { 254 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str()); 255 result.SetStatus(eReturnStatusFailed); 256 return false; 257 } 258 259 size_t item_byte_size = m_options.m_byte_size; 260 if (item_byte_size == 0) 261 { 262 if (m_options.m_format == eFormatPointer) 263 item_byte_size = process->GetTarget().GetArchitecture().GetAddressByteSize(); 264 else 265 item_byte_size = 1; 266 } 267 268 size_t item_count = m_options.m_count; 269 270 size_t num_per_line = m_options.m_num_per_line; 271 if (num_per_line == 0) 272 { 273 num_per_line = (16/item_byte_size); 274 if (num_per_line == 0) 275 num_per_line = 1; 276 } 277 278 size_t total_byte_size = m_options.m_count * item_byte_size; 279 if (total_byte_size == 0) 280 total_byte_size = 32; 281 282 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); 283 284 if (addr == LLDB_INVALID_ADDRESS) 285 { 286 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0)); 287 result.SetStatus(eReturnStatusFailed); 288 return false; 289 } 290 291 if (argc == 2) 292 { 293 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); 294 if (end_addr == LLDB_INVALID_ADDRESS) 295 { 296 result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1)); 297 result.SetStatus(eReturnStatusFailed); 298 return false; 299 } 300 else if (end_addr <= addr) 301 { 302 result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr); 303 result.SetStatus(eReturnStatusFailed); 304 return false; 305 } 306 else if (item_count != 0) 307 { 308 result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count); 309 result.SetStatus(eReturnStatusFailed); 310 return false; 311 } 312 313 total_byte_size = end_addr - addr; 314 item_count = total_byte_size / item_byte_size; 315 } 316 else 317 { 318 if (item_count == 0) 319 item_count = 32; 320 } 321 322 DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0')); 323 Error error; 324 size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error); 325 if (bytes_read == 0) 326 { 327 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr); 328 result.AppendError(error.AsCString()); 329 result.SetStatus(eReturnStatusFailed); 330 return false; 331 } 332 333 if (bytes_read < total_byte_size) 334 result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr); 335 336 result.SetStatus(eReturnStatusSuccessFinishResult); 337 DataExtractor data (data_sp, 338 process->GetTarget().GetArchitecture().GetByteOrder(), 339 process->GetTarget().GetArchitecture().GetAddressByteSize()); 340 341 StreamFile outfile_stream; 342 Stream *output_stream = NULL; 343 344 if (m_options.m_outfile_filespec) 345 { 346 char path[PATH_MAX]; 347 m_options.m_outfile_filespec.GetPath (path, sizeof(path)); 348 char mode[16] = { 'w', '\0' }; 349 if (m_options.m_append_to_outfile) 350 mode[0] = 'a'; 351 352 if (outfile_stream.GetFile ().Open (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success()) 353 { 354 if (m_options.m_output_as_binary) 355 { 356 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 357 if (bytes_written > 0) 358 { 359 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", 360 bytes_written, 361 m_options.m_append_to_outfile ? "appended" : "written", 362 path); 363 return true; 364 } 365 else 366 { 367 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path); 368 result.SetStatus(eReturnStatusFailed); 369 return false; 370 } 371 } 372 else 373 { 374 // We are going to write ASCII to the file just point the 375 // output_stream to our outfile_stream... 376 output_stream = &outfile_stream; 377 } 378 } 379 else 380 { 381 result.AppendErrorWithFormat("Failed to open file '%s' with a mode of '%s'.\n", path, mode); 382 result.SetStatus(eReturnStatusFailed); 383 return false; 384 } 385 } 386 else 387 { 388 output_stream = &result.GetOutputStream(); 389 } 390 391 assert (output_stream); 392 data.Dump (output_stream, 393 0, 394 m_options.m_format, 395 item_byte_size, 396 item_count, 397 num_per_line, 398 addr, 399 0, 400 0); 401 output_stream->EOL(); 402 return true; 403 } 404 405 protected: 406 CommandOptions m_options; 407 }; 408 409 #define SET1 LLDB_OPT_SET_1 410 #define SET2 LLDB_OPT_SET_2 411 412 OptionDefinition 413 CommandObjectMemoryRead::CommandOptions::g_option_table[] = 414 { 415 { SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format that will be used to display the memory. Defaults to bytes with ASCII (--format=Y)."}, 416 { SET1 , false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes to use when displaying with the selected format."}, 417 { SET1 , false, "num-per-line", 'l', required_argument, NULL, 0, eArgTypeNumberPerLine,"The number of items per line to display."}, 418 { SET1 , false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "The number of total items to display."}, 419 { SET1 | SET2, false, "outfile", 'o', required_argument, NULL, 0, eArgTypeFilename, "Dump memory read results into a file."}, 420 { SET1 | SET2, false, "append", 'a', no_argument, NULL, 0, eArgTypeNone, "Append memory read results to 'outfile'."}, 421 { SET2, false, "binary", 'b', no_argument, NULL, 0, eArgTypeNone, "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."}, 422 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 423 }; 424 425 #undef SET1 426 #undef SET2 427 428 //---------------------------------------------------------------------- 429 // Write memory to the inferior process 430 //---------------------------------------------------------------------- 431 class CommandObjectMemoryWrite : public CommandObject 432 { 433 public: 434 435 class CommandOptions : public Options 436 { 437 public: 438 CommandOptions () : 439 Options() 440 { 441 ResetOptionValues(); 442 } 443 444 virtual 445 ~CommandOptions () 446 { 447 } 448 449 virtual Error 450 SetOptionValue (int option_idx, const char *option_arg) 451 { 452 Error error; 453 char short_option = (char) m_getopt_table[option_idx].val; 454 switch (short_option) 455 { 456 case 'f': 457 error = Args::StringToFormat (option_arg, m_format); 458 break; 459 460 case 's': 461 m_byte_size = Args::StringToUInt32 (option_arg, 0); 462 if (m_byte_size == 0) 463 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg); 464 break; 465 466 case 'i': 467 m_infile.SetFile (option_arg, true); 468 if (!m_infile.Exists()) 469 { 470 m_infile.Clear(); 471 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg); 472 } 473 break; 474 475 case 'o': 476 { 477 bool success; 478 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success); 479 if (!success) 480 { 481 error.SetErrorStringWithFormat("Invalid offset string '%s'\n", option_arg); 482 } 483 } 484 break; 485 486 default: 487 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option); 488 break; 489 } 490 return error; 491 } 492 493 void 494 ResetOptionValues () 495 { 496 Options::ResetOptionValues(); 497 m_format = eFormatBytes; 498 m_byte_size = 1; 499 m_infile.Clear(); 500 m_infile_offset = 0; 501 } 502 503 const OptionDefinition* 504 GetDefinitions () 505 { 506 return g_option_table; 507 } 508 509 // Options table: Required for subclasses of Options. 510 511 static OptionDefinition g_option_table[]; 512 513 // Instance variables to hold the values for command options. 514 lldb::Format m_format; 515 uint32_t m_byte_size; 516 FileSpec m_infile; 517 off_t m_infile_offset; 518 }; 519 520 CommandObjectMemoryWrite (CommandInterpreter &interpreter) : 521 CommandObject (interpreter, 522 "memory write", 523 "Write to the memory of the process being debugged.", 524 //"memory write [<cmd-options>] <addr> [value1 value2 ...]", 525 NULL, 526 eFlagProcessMustBeLaunched) 527 { 528 CommandArgumentEntry arg1; 529 CommandArgumentEntry arg2; 530 CommandArgumentData addr_arg; 531 CommandArgumentData value_arg; 532 533 // Define the first (and only) variant of this arg. 534 addr_arg.arg_type = eArgTypeAddress; 535 addr_arg.arg_repetition = eArgRepeatPlain; 536 537 // There is only one variant this argument could be; put it into the argument entry. 538 arg1.push_back (addr_arg); 539 540 // Define the first (and only) variant of this arg. 541 value_arg.arg_type = eArgTypeValue; 542 value_arg.arg_repetition = eArgRepeatPlus; 543 544 // There is only one variant this argument could be; put it into the argument entry. 545 arg2.push_back (value_arg); 546 547 // Push the data for the first argument into the m_arguments vector. 548 m_arguments.push_back (arg1); 549 m_arguments.push_back (arg2); 550 } 551 552 virtual 553 ~CommandObjectMemoryWrite () 554 { 555 } 556 557 Options * 558 GetOptions () 559 { 560 return &m_options; 561 } 562 563 bool 564 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) 565 { 566 if (total_byte_size > 8) 567 return false; 568 569 if (total_byte_size == 8) 570 return true; 571 572 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; 573 return uval64 <= max; 574 } 575 576 bool 577 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) 578 { 579 if (total_byte_size > 8) 580 return false; 581 582 if (total_byte_size == 8) 583 return true; 584 585 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; 586 const int64_t min = ~(max); 587 return min <= sval64 && sval64 <= max; 588 } 589 590 virtual bool 591 Execute (Args& command, 592 CommandReturnObject &result) 593 { 594 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 595 if (process == NULL) 596 { 597 result.AppendError("need a process to read memory"); 598 result.SetStatus(eReturnStatusFailed); 599 return false; 600 } 601 602 const size_t argc = command.GetArgumentCount(); 603 604 if (m_options.m_infile) 605 { 606 if (argc < 1) 607 { 608 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); 609 result.SetStatus(eReturnStatusFailed); 610 return false; 611 } 612 } 613 else if (argc < 2) 614 { 615 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); 616 result.SetStatus(eReturnStatusFailed); 617 return false; 618 } 619 620 StreamString buffer (Stream::eBinary, 621 process->GetTarget().GetArchitecture().GetAddressByteSize(), 622 process->GetTarget().GetArchitecture().GetByteOrder()); 623 624 size_t item_byte_size = m_options.m_byte_size; 625 626 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); 627 628 if (addr == LLDB_INVALID_ADDRESS) 629 { 630 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0)); 631 result.SetStatus(eReturnStatusFailed); 632 return false; 633 } 634 635 if (m_options.m_infile) 636 { 637 size_t length = SIZE_MAX; 638 if (m_options.m_byte_size > 0) 639 length = m_options.m_byte_size; 640 lldb::DataBufferSP data_sp (m_options.m_infile.ReadFileContents (m_options.m_infile_offset, length)); 641 if (data_sp) 642 { 643 length = data_sp->GetByteSize(); 644 if (length > 0) 645 { 646 Error error; 647 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); 648 649 if (bytes_written == length) 650 { 651 // All bytes written 652 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr); 653 result.SetStatus(eReturnStatusSuccessFinishResult); 654 } 655 else if (bytes_written > 0) 656 { 657 // Some byte written 658 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr); 659 result.SetStatus(eReturnStatusSuccessFinishResult); 660 } 661 else 662 { 663 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 664 result.SetStatus(eReturnStatusFailed); 665 } 666 } 667 } 668 else 669 { 670 result.AppendErrorWithFormat ("Unable to read contents of file.\n"); 671 result.SetStatus(eReturnStatusFailed); 672 } 673 return result.Succeeded(); 674 } 675 else if (m_options.m_byte_size == 0) 676 { 677 if (m_options.m_format == eFormatPointer) 678 item_byte_size = buffer.GetAddressByteSize(); 679 else 680 item_byte_size = 1; 681 } 682 683 command.Shift(); // shift off the address argument 684 uint64_t uval64; 685 int64_t sval64; 686 bool success = false; 687 const uint32_t num_value_args = command.GetArgumentCount(); 688 uint32_t i; 689 for (i=0; i<num_value_args; ++i) 690 { 691 const char *value_str = command.GetArgumentAtIndex(i); 692 693 switch (m_options.m_format) 694 { 695 case eFormatFloat: // TODO: add support for floats soon 696 case eFormatCharPrintable: 697 case eFormatBytesWithASCII: 698 case eFormatComplex: 699 case eFormatEnum: 700 case eFormatUnicode16: 701 case eFormatUnicode32: 702 case eFormatVectorOfChar: 703 case eFormatVectorOfSInt8: 704 case eFormatVectorOfUInt8: 705 case eFormatVectorOfSInt16: 706 case eFormatVectorOfUInt16: 707 case eFormatVectorOfSInt32: 708 case eFormatVectorOfUInt32: 709 case eFormatVectorOfSInt64: 710 case eFormatVectorOfUInt64: 711 case eFormatVectorOfFloat32: 712 case eFormatVectorOfFloat64: 713 case eFormatVectorOfUInt128: 714 case eFormatOSType: 715 case eFormatComplexInteger: 716 result.AppendError("unsupported format for writing memory"); 717 result.SetStatus(eReturnStatusFailed); 718 return false; 719 720 case eFormatDefault: 721 case eFormatBytes: 722 case eFormatHex: 723 case eFormatPointer: 724 725 // Decode hex bytes 726 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success); 727 if (!success) 728 { 729 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); 730 result.SetStatus(eReturnStatusFailed); 731 return false; 732 } 733 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 734 { 735 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); 736 result.SetStatus(eReturnStatusFailed); 737 return false; 738 } 739 buffer.PutMaxHex64 (uval64, item_byte_size); 740 break; 741 742 case eFormatBoolean: 743 uval64 = Args::StringToBoolean(value_str, false, &success); 744 if (!success) 745 { 746 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); 747 result.SetStatus(eReturnStatusFailed); 748 return false; 749 } 750 buffer.PutMaxHex64 (uval64, item_byte_size); 751 break; 752 753 case eFormatBinary: 754 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success); 755 if (!success) 756 { 757 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); 758 result.SetStatus(eReturnStatusFailed); 759 return false; 760 } 761 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 762 { 763 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); 764 result.SetStatus(eReturnStatusFailed); 765 return false; 766 } 767 buffer.PutMaxHex64 (uval64, item_byte_size); 768 break; 769 770 case eFormatChar: 771 case eFormatCString: 772 if (value_str[0]) 773 { 774 size_t len = strlen (value_str); 775 // Include the NULL for C strings... 776 if (m_options.m_format == eFormatCString) 777 ++len; 778 Error error; 779 if (process->WriteMemory (addr, value_str, len, error) == len) 780 { 781 addr += len; 782 } 783 else 784 { 785 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 786 result.SetStatus(eReturnStatusFailed); 787 return false; 788 } 789 } 790 break; 791 792 case eFormatDecimal: 793 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); 794 if (!success) 795 { 796 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); 797 result.SetStatus(eReturnStatusFailed); 798 return false; 799 } 800 else if (!SIntValueIsValidForSize (sval64, item_byte_size)) 801 { 802 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size); 803 result.SetStatus(eReturnStatusFailed); 804 return false; 805 } 806 buffer.PutMaxHex64 (sval64, item_byte_size); 807 break; 808 809 case eFormatUnsigned: 810 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); 811 if (!success) 812 { 813 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); 814 result.SetStatus(eReturnStatusFailed); 815 return false; 816 } 817 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 818 { 819 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); 820 result.SetStatus(eReturnStatusFailed); 821 return false; 822 } 823 buffer.PutMaxHex64 (uval64, item_byte_size); 824 break; 825 826 case eFormatOctal: 827 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success); 828 if (!success) 829 { 830 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); 831 result.SetStatus(eReturnStatusFailed); 832 return false; 833 } 834 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 835 { 836 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); 837 result.SetStatus(eReturnStatusFailed); 838 return false; 839 } 840 buffer.PutMaxHex64 (uval64, item_byte_size); 841 break; 842 } 843 } 844 845 if (!buffer.GetString().empty()) 846 { 847 Error error; 848 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) 849 return true; 850 else 851 { 852 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 853 result.SetStatus(eReturnStatusFailed); 854 return false; 855 } 856 } 857 return true; 858 } 859 860 protected: 861 CommandOptions m_options; 862 }; 863 864 #define SET1 LLDB_OPT_SET_1 865 #define SET2 LLDB_OPT_SET_2 866 867 OptionDefinition 868 CommandObjectMemoryWrite::CommandOptions::g_option_table[] = 869 { 870 { SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format value types that will be decoded and written to memory."}, 871 { SET1 | SET2, false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes of the values to write to memory."}, 872 { SET2, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 873 { SET2, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."}, 874 { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL } 875 }; 876 877 #undef SET1 878 #undef SET2 879 880 //------------------------------------------------------------------------- 881 // CommandObjectMemory 882 //------------------------------------------------------------------------- 883 884 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : 885 CommandObjectMultiword (interpreter, 886 "memory", 887 "A set of commands for operating on memory.", 888 "memory <subcommand> [<subcommand-options>]") 889 { 890 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); 891 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); 892 } 893 894 CommandObjectMemory::~CommandObjectMemory () 895 { 896 } 897