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/Core/ValueObjectMemory.h" 21 #include "lldb/Interpreter/Args.h" 22 #include "lldb/Interpreter/CommandReturnObject.h" 23 #include "lldb/Interpreter/CommandInterpreter.h" 24 #include "lldb/Interpreter/Options.h" 25 #include "lldb/Interpreter/OptionGroupFormat.h" 26 #include "lldb/Interpreter/OptionGroupOutputFile.h" 27 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" 28 #include "lldb/Target/Process.h" 29 #include "lldb/Target/StackFrame.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 static OptionDefinition 35 g_option_table[] = 36 { 37 { LLDB_OPT_SET_1| 38 LLDB_OPT_SET_2, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize ,"The size in bytes to use when displaying with the selected format."}, 39 { LLDB_OPT_SET_1| 40 LLDB_OPT_SET_3, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount ,"The number of total items to display."}, 41 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, 42 { LLDB_OPT_SET_2, 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."}, 43 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, 44 }; 45 46 47 48 class OptionGroupReadMemory : public OptionGroup 49 { 50 public: 51 52 OptionGroupReadMemory () : 53 m_byte_size (1,1), 54 m_count (8,8), 55 m_num_per_line (1,1), 56 m_output_as_binary (false), 57 m_view_as_type() 58 { 59 } 60 61 virtual 62 ~OptionGroupReadMemory () 63 { 64 } 65 66 67 virtual uint32_t 68 GetNumDefinitions () 69 { 70 return sizeof (g_option_table) / sizeof (OptionDefinition); 71 } 72 73 virtual const OptionDefinition* 74 GetDefinitions () 75 { 76 return g_option_table; 77 } 78 79 virtual Error 80 SetOptionValue (CommandInterpreter &interpreter, 81 uint32_t option_idx, 82 const char *option_arg) 83 { 84 Error error; 85 char short_option = (char) g_option_table[option_idx].short_option; 86 87 switch (short_option) 88 { 89 case 'l': 90 error = m_num_per_line.SetValueFromCString (option_arg); 91 if (m_num_per_line.GetCurrentValue() == 0) 92 error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg); 93 break; 94 95 case 'c': 96 error = m_count.SetValueFromCString (option_arg); 97 if (m_count.GetCurrentValue() == 0) 98 error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg); 99 break; 100 101 case 's': 102 error = m_byte_size.SetValueFromCString (option_arg); 103 if (m_byte_size.GetCurrentValue() == 0) 104 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg); 105 break; 106 107 case 'b': 108 m_output_as_binary = true; 109 break; 110 111 case 't': 112 error = m_view_as_type.SetValueFromCString (option_arg); 113 break; 114 115 default: 116 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option); 117 break; 118 } 119 return error; 120 } 121 122 virtual void 123 OptionParsingStarting (CommandInterpreter &interpreter) 124 { 125 m_byte_size.Clear(); 126 m_count.Clear(); 127 m_num_per_line.Clear(); 128 m_output_as_binary = false; 129 m_view_as_type.Clear(); 130 } 131 132 Error 133 FinalizeSettings (Target *target, const OptionGroupFormat& format_options) 134 { 135 Error error; 136 bool byte_size_option_set = m_byte_size.OptionWasSet(); 137 const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); 138 const bool count_option_set = m_count.OptionWasSet(); 139 140 uint32_t format_byte_size = format_options.GetByteSize(); 141 if (byte_size_option_set) 142 { 143 if (format_byte_size > 0) 144 { 145 error.SetErrorString("can't specify the byte size in both the '--size <num>' option and the '--format [<byte-size>]<format-char>' options."); 146 return error; 147 } 148 } 149 else 150 { 151 if (format_byte_size != 0) 152 { 153 byte_size_option_set = true; 154 m_byte_size = format_byte_size; 155 } 156 } 157 158 switch (format_options.GetFormat()) 159 { 160 default: 161 break; 162 163 case eFormatBoolean: 164 if (!byte_size_option_set) 165 m_byte_size = 1; 166 if (!num_per_line_option_set) 167 m_num_per_line = 1; 168 if (!count_option_set) 169 m_count = 8; 170 break; 171 172 case eFormatCString: 173 break; 174 175 case eFormatPointer: 176 m_byte_size = target->GetArchitecture().GetAddressByteSize(); 177 if (!num_per_line_option_set) 178 m_num_per_line = 4; 179 if (!count_option_set) 180 m_count = 8; 181 break; 182 183 case eFormatBinary: 184 case eFormatFloat: 185 case eFormatOctal: 186 case eFormatDecimal: 187 case eFormatEnum: 188 case eFormatUnicode16: 189 case eFormatUnicode32: 190 case eFormatUnsigned: 191 if (!byte_size_option_set) 192 m_byte_size = 4; 193 if (!num_per_line_option_set) 194 m_num_per_line = 1; 195 if (!count_option_set) 196 m_count = 8; 197 break; 198 199 case eFormatBytes: 200 case eFormatBytesWithASCII: 201 if (m_byte_size.OptionWasSet()) 202 { 203 if (m_byte_size > 1) 204 error.SetErrorString ("use --count option to specify an end address to display a number of bytes"); 205 } 206 else 207 m_byte_size = 1; 208 if (!num_per_line_option_set) 209 m_num_per_line = 16; 210 if (!count_option_set) 211 m_count = 32; 212 break; 213 case eFormatCharArray: 214 case eFormatChar: 215 case eFormatCharPrintable: 216 if (!byte_size_option_set) 217 m_byte_size = 1; 218 if (!num_per_line_option_set) 219 m_num_per_line = 32; 220 if (!count_option_set) 221 m_count = 64; 222 break; 223 case eFormatComplex: 224 if (!byte_size_option_set) 225 m_byte_size = 8; 226 if (!num_per_line_option_set) 227 m_num_per_line = 1; 228 if (!count_option_set) 229 m_count = 8; 230 break; 231 case eFormatHex: 232 if (!byte_size_option_set) 233 m_byte_size = 4; 234 if (!num_per_line_option_set) 235 { 236 switch (m_byte_size) 237 { 238 case 1: 239 case 2: 240 m_num_per_line = 8; 241 break; 242 case 4: 243 m_num_per_line = 4; 244 break; 245 case 8: 246 m_num_per_line = 2; 247 break; 248 default: 249 m_num_per_line = 1; 250 break; 251 } 252 } 253 if (!count_option_set) 254 m_count = 8; 255 break; 256 257 case eFormatVectorOfChar: 258 case eFormatVectorOfSInt8: 259 case eFormatVectorOfUInt8: 260 case eFormatVectorOfSInt16: 261 case eFormatVectorOfUInt16: 262 case eFormatVectorOfSInt32: 263 case eFormatVectorOfUInt32: 264 case eFormatVectorOfSInt64: 265 case eFormatVectorOfUInt64: 266 case eFormatVectorOfFloat32: 267 case eFormatVectorOfFloat64: 268 case eFormatVectorOfUInt128: 269 if (!byte_size_option_set) 270 m_byte_size = 128; 271 if (!num_per_line_option_set) 272 m_num_per_line = 1; 273 if (!count_option_set) 274 m_count = 4; 275 break; 276 } 277 return error; 278 } 279 280 OptionValueUInt64 m_byte_size; 281 OptionValueUInt64 m_count; 282 OptionValueUInt64 m_num_per_line; 283 bool m_output_as_binary; 284 OptionValueString m_view_as_type; 285 }; 286 287 288 289 //---------------------------------------------------------------------- 290 // Read memory from the inferior process 291 //---------------------------------------------------------------------- 292 class CommandObjectMemoryRead : public CommandObject 293 { 294 public: 295 296 CommandObjectMemoryRead (CommandInterpreter &interpreter) : 297 CommandObject (interpreter, 298 "memory read", 299 "Read from the memory of the process being debugged.", 300 NULL, 301 eFlagProcessMustBePaused), 302 m_option_group (interpreter), 303 m_format_options (eFormatBytesWithASCII, 0, true), 304 m_memory_options (), 305 m_outfile_options (), 306 m_varobj_options() 307 { 308 CommandArgumentEntry arg1; 309 CommandArgumentEntry arg2; 310 CommandArgumentData start_addr_arg; 311 CommandArgumentData end_addr_arg; 312 313 // Define the first (and only) variant of this arg. 314 start_addr_arg.arg_type = eArgTypeStartAddress; 315 start_addr_arg.arg_repetition = eArgRepeatPlain; 316 317 // There is only one variant this argument could be; put it into the argument entry. 318 arg1.push_back (start_addr_arg); 319 320 // Define the first (and only) variant of this arg. 321 end_addr_arg.arg_type = eArgTypeEndAddress; 322 end_addr_arg.arg_repetition = eArgRepeatOptional; 323 324 // There is only one variant this argument could be; put it into the argument entry. 325 arg2.push_back (end_addr_arg); 326 327 // Push the data for the first argument into the m_arguments vector. 328 m_arguments.push_back (arg1); 329 m_arguments.push_back (arg2); 330 331 m_option_group.Append (&m_format_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_3); 332 m_option_group.Append (&m_memory_options); 333 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 334 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); 335 m_option_group.Finalize(); 336 } 337 338 virtual 339 ~CommandObjectMemoryRead () 340 { 341 } 342 343 Options * 344 GetOptions () 345 { 346 return &m_option_group; 347 } 348 349 virtual bool 350 Execute (Args& command, 351 CommandReturnObject &result) 352 { 353 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 354 if (exe_ctx.target == NULL) 355 { 356 result.AppendError("need at least a target to read memory"); 357 result.SetStatus(eReturnStatusFailed); 358 return false; 359 } 360 const size_t argc = command.GetArgumentCount(); 361 362 363 if (argc == 0 || argc > 2) 364 { 365 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str()); 366 result.SetStatus(eReturnStatusFailed); 367 return false; 368 } 369 370 ClangASTType clang_ast_type; 371 Error error; 372 373 Format format = m_format_options.GetFormat(); 374 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); 375 if (view_as_type_cstr && view_as_type_cstr[0]) 376 { 377 // We are viewing memory as a type 378 SymbolContext sc; 379 const bool append = true; 380 TypeList type_list; 381 uint32_t reference_count = 0; 382 uint32_t pointer_count = 0; 383 size_t idx; 384 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"}; 385 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *); 386 std::string type_str(view_as_type_cstr); 387 388 // Remove all instances of g_keywords that are followed by spaces 389 for (size_t i = 0; i < g_num_keywords; ++i) 390 { 391 const char *keyword = g_keywords[i]; 392 int keyword_len = ::strlen (keyword); 393 while ((idx = type_str.find (keyword)) != std::string::npos) 394 { 395 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') 396 type_str.erase(idx, keyword_len+1); 397 } 398 } 399 bool done = type_str.empty(); 400 // 401 idx = type_str.find_first_not_of (" \t"); 402 if (idx > 0 && idx != std::string::npos) 403 type_str.erase (0, idx); 404 while (!done) 405 { 406 // Strip trailing spaces 407 if (type_str.empty()) 408 done = true; 409 else 410 { 411 switch (type_str[type_str.size()-1]) 412 { 413 case '*': 414 ++pointer_count; 415 // fall through... 416 case ' ': 417 case '\t': 418 type_str.erase(type_str.size()-1); 419 break; 420 421 case '&': 422 if (reference_count == 0) 423 { 424 reference_count = 1; 425 type_str.erase(type_str.size()-1); 426 } 427 else 428 { 429 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); 430 result.SetStatus(eReturnStatusFailed); 431 return false; 432 } 433 break; 434 435 default: 436 done = true; 437 break; 438 } 439 } 440 } 441 442 ConstString lookup_type_name(type_str.c_str()); 443 if (exe_ctx.frame) 444 { 445 sc = exe_ctx.frame->GetSymbolContext (eSymbolContextModule); 446 if (sc.module_sp) 447 { 448 sc.module_sp->FindTypes (sc, 449 lookup_type_name, 450 append, 451 1, 452 type_list); 453 } 454 } 455 if (type_list.GetSize() == 0) 456 { 457 exe_ctx.target->GetImages().FindTypes (sc, 458 lookup_type_name, 459 append, 460 1, 461 type_list); 462 } 463 464 if (type_list.GetSize() == 0) 465 { 466 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", 467 lookup_type_name.GetCString(), 468 view_as_type_cstr); 469 result.SetStatus(eReturnStatusFailed); 470 return false; 471 } 472 473 TypeSP type_sp (type_list.GetTypeAtIndex(0)); 474 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType()); 475 476 while (pointer_count > 0) 477 { 478 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType()); 479 if (pointer_type) 480 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type); 481 else 482 { 483 result.AppendError ("unable make a pointer type\n"); 484 result.SetStatus(eReturnStatusFailed); 485 return false; 486 } 487 --pointer_count; 488 } 489 490 m_memory_options.m_byte_size = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8; 491 492 if (m_memory_options.m_byte_size == 0) 493 { 494 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 495 view_as_type_cstr); 496 result.SetStatus(eReturnStatusFailed); 497 return false; 498 } 499 500 if (!m_memory_options.m_count.OptionWasSet()) 501 m_memory_options.m_count = 1; 502 } 503 else 504 { 505 error = m_memory_options.FinalizeSettings (exe_ctx.target, m_format_options); 506 } 507 508 // Look for invalid combinations of settings 509 if (error.Fail()) 510 { 511 result.AppendErrorWithFormat("%s", error.AsCString()); 512 result.SetStatus(eReturnStatusFailed); 513 return false; 514 } 515 516 size_t item_count = m_memory_options.m_count.GetCurrentValue(); 517 const size_t item_byte_size = m_memory_options.m_byte_size; 518 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); 519 520 size_t total_byte_size = item_count * item_byte_size; 521 if (total_byte_size == 0) 522 total_byte_size = 32; 523 524 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); 525 526 if (addr == LLDB_INVALID_ADDRESS) 527 { 528 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0)); 529 result.SetStatus(eReturnStatusFailed); 530 return false; 531 } 532 533 if (argc == 2) 534 { 535 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); 536 if (end_addr == LLDB_INVALID_ADDRESS) 537 { 538 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1)); 539 result.SetStatus(eReturnStatusFailed); 540 return false; 541 } 542 else if (end_addr <= addr) 543 { 544 result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr); 545 result.SetStatus(eReturnStatusFailed); 546 return false; 547 } 548 else if (m_memory_options.m_count.OptionWasSet()) 549 { 550 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count); 551 result.SetStatus(eReturnStatusFailed); 552 return false; 553 } 554 555 total_byte_size = end_addr - addr; 556 item_count = total_byte_size / item_byte_size; 557 } 558 559 DataBufferSP data_sp; 560 size_t bytes_read = 0; 561 if (!clang_ast_type.GetOpaqueQualType()) 562 { 563 data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); 564 Address address(NULL, addr); 565 bytes_read = exe_ctx.target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); 566 if (bytes_read == 0) 567 { 568 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr); 569 result.AppendError(error.AsCString()); 570 result.SetStatus(eReturnStatusFailed); 571 return false; 572 } 573 574 if (bytes_read < total_byte_size) 575 result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr); 576 } 577 578 StreamFile outfile_stream; 579 Stream *output_stream = NULL; 580 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 581 if (outfile_spec) 582 { 583 char path[PATH_MAX]; 584 outfile_spec.GetPath (path, sizeof(path)); 585 586 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 587 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 588 if (append) 589 open_options |= File::eOpenOptionAppend; 590 591 if (outfile_stream.GetFile ().Open (path, open_options).Success()) 592 { 593 if (m_memory_options.m_output_as_binary) 594 { 595 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 596 if (bytes_written > 0) 597 { 598 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", 599 bytes_written, 600 append ? "appended" : "written", 601 path); 602 return true; 603 } 604 else 605 { 606 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path); 607 result.SetStatus(eReturnStatusFailed); 608 return false; 609 } 610 } 611 else 612 { 613 // We are going to write ASCII to the file just point the 614 // output_stream to our outfile_stream... 615 output_stream = &outfile_stream; 616 } 617 } 618 else 619 { 620 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); 621 result.SetStatus(eReturnStatusFailed); 622 return false; 623 } 624 } 625 else 626 { 627 output_stream = &result.GetOutputStream(); 628 } 629 630 631 if (clang_ast_type.GetOpaqueQualType()) 632 { 633 for (uint32_t i = 0; i<item_count; ++i) 634 { 635 addr_t item_addr = addr + (i * item_byte_size); 636 Address address (NULL, item_addr); 637 StreamString name_strm; 638 name_strm.Printf ("0x%llx", item_addr); 639 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(), 640 name_strm.GetString().c_str(), 641 address, 642 clang_ast_type)); 643 if (valobj_sp) 644 { 645 if (format != eFormatDefault) 646 valobj_sp->SetFormat (format); 647 648 bool scope_already_checked = true; 649 650 ValueObject::DumpValueObject (*output_stream, 651 valobj_sp.get(), 652 NULL, 653 m_varobj_options.ptr_depth, 654 0, 655 m_varobj_options.max_depth, 656 m_varobj_options.show_types, 657 m_varobj_options.show_location, 658 m_varobj_options.use_objc, 659 m_varobj_options.use_dynamic, 660 m_varobj_options.be_raw ? false : m_varobj_options.use_synth, 661 scope_already_checked, 662 m_varobj_options.flat_output, 663 m_varobj_options.be_raw ? UINT32_MAX : 0); 664 } 665 else 666 { 667 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 668 view_as_type_cstr, 669 name_strm.GetString().c_str()); 670 result.SetStatus(eReturnStatusFailed); 671 return false; 672 } 673 } 674 return true; 675 } 676 677 result.SetStatus(eReturnStatusSuccessFinishResult); 678 DataExtractor data (data_sp, 679 exe_ctx.target->GetArchitecture().GetByteOrder(), 680 exe_ctx.target->GetArchitecture().GetAddressByteSize()); 681 682 683 assert (output_stream); 684 data.Dump (output_stream, 685 0, 686 m_format_options.GetFormat(), 687 item_byte_size, 688 item_count, 689 num_per_line, 690 addr, 691 0, 692 0); 693 output_stream->EOL(); 694 return true; 695 } 696 697 protected: 698 OptionGroupOptions m_option_group; 699 OptionGroupFormat m_format_options; 700 OptionGroupReadMemory m_memory_options; 701 OptionGroupOutputFile m_outfile_options; 702 OptionGroupValueObjectDisplay m_varobj_options; 703 704 }; 705 706 //---------------------------------------------------------------------- 707 // Write memory to the inferior process 708 //---------------------------------------------------------------------- 709 class CommandObjectMemoryWrite : public CommandObject 710 { 711 public: 712 713 class CommandOptions : public Options 714 { 715 public: 716 CommandOptions (CommandInterpreter &interpreter) : 717 Options(interpreter) 718 { 719 OptionParsingStarting(); 720 } 721 722 virtual 723 ~CommandOptions () 724 { 725 } 726 727 virtual Error 728 SetOptionValue (uint32_t option_idx, const char *option_arg) 729 { 730 Error error; 731 char short_option = (char) m_getopt_table[option_idx].val; 732 switch (short_option) 733 { 734 case 'f': 735 error = Args::StringToFormat (option_arg, m_format, &m_byte_size); 736 break; 737 738 case 's': 739 m_byte_size = Args::StringToUInt32 (option_arg, 0); 740 if (m_byte_size == 0) 741 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg); 742 break; 743 744 case 'i': 745 m_infile.SetFile (option_arg, true); 746 if (!m_infile.Exists()) 747 { 748 m_infile.Clear(); 749 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg); 750 } 751 break; 752 753 case 'o': 754 { 755 bool success; 756 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success); 757 if (!success) 758 { 759 error.SetErrorStringWithFormat("Invalid offset string '%s'\n", option_arg); 760 } 761 } 762 break; 763 764 default: 765 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option); 766 break; 767 } 768 return error; 769 } 770 771 void 772 OptionParsingStarting () 773 { 774 m_format = eFormatBytes; 775 m_byte_size = 1; 776 m_infile.Clear(); 777 m_infile_offset = 0; 778 } 779 780 const OptionDefinition* 781 GetDefinitions () 782 { 783 return g_option_table; 784 } 785 786 // Options table: Required for subclasses of Options. 787 788 static OptionDefinition g_option_table[]; 789 790 // Instance variables to hold the values for command options. 791 lldb::Format m_format; 792 uint32_t m_byte_size; 793 FileSpec m_infile; 794 off_t m_infile_offset; 795 }; 796 797 CommandObjectMemoryWrite (CommandInterpreter &interpreter) : 798 CommandObject (interpreter, 799 "memory write", 800 "Write to the memory of the process being debugged.", 801 //"memory write [<cmd-options>] <addr> [value1 value2 ...]", 802 NULL, 803 eFlagProcessMustBeLaunched), 804 m_options (interpreter) 805 { 806 CommandArgumentEntry arg1; 807 CommandArgumentEntry arg2; 808 CommandArgumentData addr_arg; 809 CommandArgumentData value_arg; 810 811 // Define the first (and only) variant of this arg. 812 addr_arg.arg_type = eArgTypeAddress; 813 addr_arg.arg_repetition = eArgRepeatPlain; 814 815 // There is only one variant this argument could be; put it into the argument entry. 816 arg1.push_back (addr_arg); 817 818 // Define the first (and only) variant of this arg. 819 value_arg.arg_type = eArgTypeValue; 820 value_arg.arg_repetition = eArgRepeatPlus; 821 822 // There is only one variant this argument could be; put it into the argument entry. 823 arg2.push_back (value_arg); 824 825 // Push the data for the first argument into the m_arguments vector. 826 m_arguments.push_back (arg1); 827 m_arguments.push_back (arg2); 828 } 829 830 virtual 831 ~CommandObjectMemoryWrite () 832 { 833 } 834 835 Options * 836 GetOptions () 837 { 838 return &m_options; 839 } 840 841 bool 842 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) 843 { 844 if (total_byte_size > 8) 845 return false; 846 847 if (total_byte_size == 8) 848 return true; 849 850 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; 851 return uval64 <= max; 852 } 853 854 bool 855 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) 856 { 857 if (total_byte_size > 8) 858 return false; 859 860 if (total_byte_size == 8) 861 return true; 862 863 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; 864 const int64_t min = ~(max); 865 return min <= sval64 && sval64 <= max; 866 } 867 868 virtual bool 869 Execute (Args& command, 870 CommandReturnObject &result) 871 { 872 Process *process = m_interpreter.GetExecutionContext().process; 873 if (process == NULL) 874 { 875 result.AppendError("need a process to read memory"); 876 result.SetStatus(eReturnStatusFailed); 877 return false; 878 } 879 880 const size_t argc = command.GetArgumentCount(); 881 882 if (m_options.m_infile) 883 { 884 if (argc < 1) 885 { 886 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); 887 result.SetStatus(eReturnStatusFailed); 888 return false; 889 } 890 } 891 else if (argc < 2) 892 { 893 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); 894 result.SetStatus(eReturnStatusFailed); 895 return false; 896 } 897 898 StreamString buffer (Stream::eBinary, 899 process->GetTarget().GetArchitecture().GetAddressByteSize(), 900 process->GetTarget().GetArchitecture().GetByteOrder()); 901 902 size_t item_byte_size = m_options.m_byte_size; 903 904 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); 905 906 if (addr == LLDB_INVALID_ADDRESS) 907 { 908 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0)); 909 result.SetStatus(eReturnStatusFailed); 910 return false; 911 } 912 913 if (m_options.m_infile) 914 { 915 size_t length = SIZE_MAX; 916 if (m_options.m_byte_size > 0) 917 length = m_options.m_byte_size; 918 lldb::DataBufferSP data_sp (m_options.m_infile.ReadFileContents (m_options.m_infile_offset, length)); 919 if (data_sp) 920 { 921 length = data_sp->GetByteSize(); 922 if (length > 0) 923 { 924 Error error; 925 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); 926 927 if (bytes_written == length) 928 { 929 // All bytes written 930 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr); 931 result.SetStatus(eReturnStatusSuccessFinishResult); 932 } 933 else if (bytes_written > 0) 934 { 935 // Some byte written 936 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr); 937 result.SetStatus(eReturnStatusSuccessFinishResult); 938 } 939 else 940 { 941 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 942 result.SetStatus(eReturnStatusFailed); 943 } 944 } 945 } 946 else 947 { 948 result.AppendErrorWithFormat ("Unable to read contents of file.\n"); 949 result.SetStatus(eReturnStatusFailed); 950 } 951 return result.Succeeded(); 952 } 953 else if (m_options.m_byte_size == 0) 954 { 955 if (m_options.m_format == eFormatPointer) 956 item_byte_size = buffer.GetAddressByteSize(); 957 else 958 item_byte_size = 1; 959 } 960 961 command.Shift(); // shift off the address argument 962 uint64_t uval64; 963 int64_t sval64; 964 bool success = false; 965 const uint32_t num_value_args = command.GetArgumentCount(); 966 uint32_t i; 967 for (i=0; i<num_value_args; ++i) 968 { 969 const char *value_str = command.GetArgumentAtIndex(i); 970 971 switch (m_options.m_format) 972 { 973 case kNumFormats: 974 case eFormatFloat: // TODO: add support for floats soon 975 case eFormatCharPrintable: 976 case eFormatBytesWithASCII: 977 case eFormatComplex: 978 case eFormatEnum: 979 case eFormatUnicode16: 980 case eFormatUnicode32: 981 case eFormatVectorOfChar: 982 case eFormatVectorOfSInt8: 983 case eFormatVectorOfUInt8: 984 case eFormatVectorOfSInt16: 985 case eFormatVectorOfUInt16: 986 case eFormatVectorOfSInt32: 987 case eFormatVectorOfUInt32: 988 case eFormatVectorOfSInt64: 989 case eFormatVectorOfUInt64: 990 case eFormatVectorOfFloat32: 991 case eFormatVectorOfFloat64: 992 case eFormatVectorOfUInt128: 993 case eFormatOSType: 994 case eFormatComplexInteger: 995 result.AppendError("unsupported format for writing memory"); 996 result.SetStatus(eReturnStatusFailed); 997 return false; 998 999 case eFormatDefault: 1000 case eFormatBytes: 1001 case eFormatHex: 1002 case eFormatPointer: 1003 1004 // Decode hex bytes 1005 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success); 1006 if (!success) 1007 { 1008 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); 1009 result.SetStatus(eReturnStatusFailed); 1010 return false; 1011 } 1012 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1013 { 1014 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); 1015 result.SetStatus(eReturnStatusFailed); 1016 return false; 1017 } 1018 buffer.PutMaxHex64 (uval64, item_byte_size); 1019 break; 1020 1021 case eFormatBoolean: 1022 uval64 = Args::StringToBoolean(value_str, false, &success); 1023 if (!success) 1024 { 1025 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); 1026 result.SetStatus(eReturnStatusFailed); 1027 return false; 1028 } 1029 buffer.PutMaxHex64 (uval64, item_byte_size); 1030 break; 1031 1032 case eFormatBinary: 1033 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success); 1034 if (!success) 1035 { 1036 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); 1037 result.SetStatus(eReturnStatusFailed); 1038 return false; 1039 } 1040 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1041 { 1042 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); 1043 result.SetStatus(eReturnStatusFailed); 1044 return false; 1045 } 1046 buffer.PutMaxHex64 (uval64, item_byte_size); 1047 break; 1048 1049 case eFormatCharArray: 1050 case eFormatChar: 1051 case eFormatCString: 1052 if (value_str[0]) 1053 { 1054 size_t len = strlen (value_str); 1055 // Include the NULL for C strings... 1056 if (m_options.m_format == eFormatCString) 1057 ++len; 1058 Error error; 1059 if (process->WriteMemory (addr, value_str, len, error) == len) 1060 { 1061 addr += len; 1062 } 1063 else 1064 { 1065 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 1066 result.SetStatus(eReturnStatusFailed); 1067 return false; 1068 } 1069 } 1070 break; 1071 1072 case eFormatDecimal: 1073 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); 1074 if (!success) 1075 { 1076 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); 1077 result.SetStatus(eReturnStatusFailed); 1078 return false; 1079 } 1080 else if (!SIntValueIsValidForSize (sval64, item_byte_size)) 1081 { 1082 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size); 1083 result.SetStatus(eReturnStatusFailed); 1084 return false; 1085 } 1086 buffer.PutMaxHex64 (sval64, item_byte_size); 1087 break; 1088 1089 case eFormatUnsigned: 1090 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); 1091 if (!success) 1092 { 1093 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); 1094 result.SetStatus(eReturnStatusFailed); 1095 return false; 1096 } 1097 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1098 { 1099 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); 1100 result.SetStatus(eReturnStatusFailed); 1101 return false; 1102 } 1103 buffer.PutMaxHex64 (uval64, item_byte_size); 1104 break; 1105 1106 case eFormatOctal: 1107 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success); 1108 if (!success) 1109 { 1110 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); 1111 result.SetStatus(eReturnStatusFailed); 1112 return false; 1113 } 1114 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1115 { 1116 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); 1117 result.SetStatus(eReturnStatusFailed); 1118 return false; 1119 } 1120 buffer.PutMaxHex64 (uval64, item_byte_size); 1121 break; 1122 } 1123 } 1124 1125 if (!buffer.GetString().empty()) 1126 { 1127 Error error; 1128 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) 1129 return true; 1130 else 1131 { 1132 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 1133 result.SetStatus(eReturnStatusFailed); 1134 return false; 1135 } 1136 } 1137 return true; 1138 } 1139 1140 protected: 1141 CommandOptions m_options; 1142 }; 1143 1144 #define SET1 LLDB_OPT_SET_1 1145 #define SET2 LLDB_OPT_SET_2 1146 1147 OptionDefinition 1148 CommandObjectMemoryWrite::CommandOptions::g_option_table[] = 1149 { 1150 { SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format value types that will be decoded and written to memory."}, 1151 { SET1 | SET2, false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes of the values to write to memory."}, 1152 { SET2, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 1153 { SET2, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."}, 1154 { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL } 1155 }; 1156 1157 #undef SET1 1158 #undef SET2 1159 1160 //------------------------------------------------------------------------- 1161 // CommandObjectMemory 1162 //------------------------------------------------------------------------- 1163 1164 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : 1165 CommandObjectMultiword (interpreter, 1166 "memory", 1167 "A set of commands for operating on memory.", 1168 "memory <subcommand> [<subcommand-options>]") 1169 { 1170 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); 1171 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); 1172 } 1173 1174 CommandObjectMemory::~CommandObjectMemory () 1175 { 1176 } 1177