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 "lldb/lldb-python.h" 11 12 #include "CommandObjectMemory.h" 13 14 // C Includes 15 #include <inttypes.h> 16 17 // C++ Includes 18 // Other libraries and framework includes 19 #include "clang/AST/Decl.h" 20 // Project includes 21 #include "lldb/Core/DataBufferHeap.h" 22 #include "lldb/Core/DataExtractor.h" 23 #include "lldb/Core/Debugger.h" 24 #include "lldb/Core/Module.h" 25 #include "lldb/Core/StreamString.h" 26 #include "lldb/Core/ValueObjectMemory.h" 27 #include "lldb/DataFormatters/ValueObjectPrinter.h" 28 #include "lldb/Expression/ClangPersistentVariables.h" 29 #include "lldb/Host/StringConvert.h" 30 #include "lldb/Interpreter/Args.h" 31 #include "lldb/Interpreter/CommandReturnObject.h" 32 #include "lldb/Interpreter/CommandInterpreter.h" 33 #include "lldb/Interpreter/Options.h" 34 #include "lldb/Interpreter/OptionGroupFormat.h" 35 #include "lldb/Interpreter/OptionGroupOutputFile.h" 36 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" 37 #include "lldb/Interpreter/OptionValueString.h" 38 #include "lldb/Symbol/TypeList.h" 39 #include "lldb/Target/MemoryHistory.h" 40 #include "lldb/Target/Process.h" 41 #include "lldb/Target/StackFrame.h" 42 #include "lldb/Target/Thread.h" 43 44 using namespace lldb; 45 using namespace lldb_private; 46 47 static OptionDefinition 48 g_option_table[] = 49 { 50 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, 51 { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, 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."}, 52 { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, 53 { LLDB_OPT_SET_1| 54 LLDB_OPT_SET_2| 55 LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."}, 56 }; 57 58 59 60 class OptionGroupReadMemory : public OptionGroup 61 { 62 public: 63 64 OptionGroupReadMemory () : 65 m_num_per_line (1,1), 66 m_output_as_binary (false), 67 m_view_as_type() 68 { 69 } 70 71 virtual 72 ~OptionGroupReadMemory () 73 { 74 } 75 76 77 virtual uint32_t 78 GetNumDefinitions () 79 { 80 return sizeof (g_option_table) / sizeof (OptionDefinition); 81 } 82 83 virtual const OptionDefinition* 84 GetDefinitions () 85 { 86 return g_option_table; 87 } 88 89 virtual Error 90 SetOptionValue (CommandInterpreter &interpreter, 91 uint32_t option_idx, 92 const char *option_arg) 93 { 94 Error error; 95 const int short_option = g_option_table[option_idx].short_option; 96 97 switch (short_option) 98 { 99 case 'l': 100 error = m_num_per_line.SetValueFromString (option_arg); 101 if (m_num_per_line.GetCurrentValue() == 0) 102 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg); 103 break; 104 105 case 'b': 106 m_output_as_binary = true; 107 break; 108 109 case 't': 110 error = m_view_as_type.SetValueFromString (option_arg); 111 break; 112 113 case 'r': 114 m_force = true; 115 break; 116 117 default: 118 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 119 break; 120 } 121 return error; 122 } 123 124 virtual void 125 OptionParsingStarting (CommandInterpreter &interpreter) 126 { 127 m_num_per_line.Clear(); 128 m_output_as_binary = false; 129 m_view_as_type.Clear(); 130 m_force = false; 131 } 132 133 Error 134 FinalizeSettings (Target *target, OptionGroupFormat& format_options) 135 { 136 Error error; 137 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue(); 138 OptionValueUInt64 &count_value = format_options.GetCountValue(); 139 const bool byte_size_option_set = byte_size_value.OptionWasSet(); 140 const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); 141 const bool count_option_set = format_options.GetCountValue().OptionWasSet(); 142 143 switch (format_options.GetFormat()) 144 { 145 default: 146 break; 147 148 case eFormatBoolean: 149 if (!byte_size_option_set) 150 byte_size_value = 1; 151 if (!num_per_line_option_set) 152 m_num_per_line = 1; 153 if (!count_option_set) 154 format_options.GetCountValue() = 8; 155 break; 156 157 case eFormatCString: 158 break; 159 160 case eFormatInstruction: 161 if (count_option_set) 162 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize(); 163 m_num_per_line = 1; 164 break; 165 166 case eFormatAddressInfo: 167 if (!byte_size_option_set) 168 byte_size_value = target->GetArchitecture().GetAddressByteSize(); 169 m_num_per_line = 1; 170 if (!count_option_set) 171 format_options.GetCountValue() = 8; 172 break; 173 174 case eFormatPointer: 175 byte_size_value = target->GetArchitecture().GetAddressByteSize(); 176 if (!num_per_line_option_set) 177 m_num_per_line = 4; 178 if (!count_option_set) 179 format_options.GetCountValue() = 8; 180 break; 181 182 case eFormatBinary: 183 case eFormatFloat: 184 case eFormatOctal: 185 case eFormatDecimal: 186 case eFormatEnum: 187 case eFormatUnicode16: 188 case eFormatUnicode32: 189 case eFormatUnsigned: 190 case eFormatHexFloat: 191 if (!byte_size_option_set) 192 byte_size_value = 4; 193 if (!num_per_line_option_set) 194 m_num_per_line = 1; 195 if (!count_option_set) 196 format_options.GetCountValue() = 8; 197 break; 198 199 case eFormatBytes: 200 case eFormatBytesWithASCII: 201 if (byte_size_option_set) 202 { 203 if (byte_size_value > 1) 204 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n" 205 "\tconsider using a different display format or don't specify the byte size", 206 byte_size_value.GetCurrentValue()); 207 } 208 else 209 byte_size_value = 1; 210 if (!num_per_line_option_set) 211 m_num_per_line = 16; 212 if (!count_option_set) 213 format_options.GetCountValue() = 32; 214 break; 215 case eFormatCharArray: 216 case eFormatChar: 217 case eFormatCharPrintable: 218 if (!byte_size_option_set) 219 byte_size_value = 1; 220 if (!num_per_line_option_set) 221 m_num_per_line = 32; 222 if (!count_option_set) 223 format_options.GetCountValue() = 64; 224 break; 225 case eFormatComplex: 226 if (!byte_size_option_set) 227 byte_size_value = 8; 228 if (!num_per_line_option_set) 229 m_num_per_line = 1; 230 if (!count_option_set) 231 format_options.GetCountValue() = 8; 232 break; 233 case eFormatComplexInteger: 234 if (!byte_size_option_set) 235 byte_size_value = 8; 236 if (!num_per_line_option_set) 237 m_num_per_line = 1; 238 if (!count_option_set) 239 format_options.GetCountValue() = 8; 240 break; 241 case eFormatHex: 242 if (!byte_size_option_set) 243 byte_size_value = 4; 244 if (!num_per_line_option_set) 245 { 246 switch (byte_size_value) 247 { 248 case 1: 249 case 2: 250 m_num_per_line = 8; 251 break; 252 case 4: 253 m_num_per_line = 4; 254 break; 255 case 8: 256 m_num_per_line = 2; 257 break; 258 default: 259 m_num_per_line = 1; 260 break; 261 } 262 } 263 if (!count_option_set) 264 count_value = 8; 265 break; 266 267 case eFormatVectorOfChar: 268 case eFormatVectorOfSInt8: 269 case eFormatVectorOfUInt8: 270 case eFormatVectorOfSInt16: 271 case eFormatVectorOfUInt16: 272 case eFormatVectorOfSInt32: 273 case eFormatVectorOfUInt32: 274 case eFormatVectorOfSInt64: 275 case eFormatVectorOfUInt64: 276 case eFormatVectorOfFloat32: 277 case eFormatVectorOfFloat64: 278 case eFormatVectorOfUInt128: 279 if (!byte_size_option_set) 280 byte_size_value = 128; 281 if (!num_per_line_option_set) 282 m_num_per_line = 1; 283 if (!count_option_set) 284 count_value = 4; 285 break; 286 } 287 return error; 288 } 289 290 bool 291 AnyOptionWasSet () const 292 { 293 return m_num_per_line.OptionWasSet() || 294 m_output_as_binary || 295 m_view_as_type.OptionWasSet(); 296 } 297 298 OptionValueUInt64 m_num_per_line; 299 bool m_output_as_binary; 300 OptionValueString m_view_as_type; 301 bool m_force; 302 }; 303 304 305 306 //---------------------------------------------------------------------- 307 // Read memory from the inferior process 308 //---------------------------------------------------------------------- 309 class CommandObjectMemoryRead : public CommandObjectParsed 310 { 311 public: 312 313 CommandObjectMemoryRead (CommandInterpreter &interpreter) : 314 CommandObjectParsed (interpreter, 315 "memory read", 316 "Read from the memory of the process being debugged.", 317 NULL, 318 eFlagRequiresTarget | eFlagProcessMustBePaused), 319 m_option_group (interpreter), 320 m_format_options (eFormatBytesWithASCII, 1, 8), 321 m_memory_options (), 322 m_outfile_options (), 323 m_varobj_options(), 324 m_next_addr(LLDB_INVALID_ADDRESS), 325 m_prev_byte_size(0), 326 m_prev_format_options (eFormatBytesWithASCII, 1, 8), 327 m_prev_memory_options (), 328 m_prev_outfile_options (), 329 m_prev_varobj_options() 330 { 331 CommandArgumentEntry arg1; 332 CommandArgumentEntry arg2; 333 CommandArgumentData start_addr_arg; 334 CommandArgumentData end_addr_arg; 335 336 // Define the first (and only) variant of this arg. 337 start_addr_arg.arg_type = eArgTypeAddressOrExpression; 338 start_addr_arg.arg_repetition = eArgRepeatPlain; 339 340 // There is only one variant this argument could be; put it into the argument entry. 341 arg1.push_back (start_addr_arg); 342 343 // Define the first (and only) variant of this arg. 344 end_addr_arg.arg_type = eArgTypeAddressOrExpression; 345 end_addr_arg.arg_repetition = eArgRepeatOptional; 346 347 // There is only one variant this argument could be; put it into the argument entry. 348 arg2.push_back (end_addr_arg); 349 350 // Push the data for the first argument into the m_arguments vector. 351 m_arguments.push_back (arg1); 352 m_arguments.push_back (arg2); 353 354 // Add the "--format" and "--count" options to group 1 and 3 355 m_option_group.Append (&m_format_options, 356 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT, 357 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 358 m_option_group.Append (&m_format_options, 359 OptionGroupFormat::OPTION_GROUP_GDB_FMT, 360 LLDB_OPT_SET_1 | LLDB_OPT_SET_3); 361 // Add the "--size" option to group 1 and 2 362 m_option_group.Append (&m_format_options, 363 OptionGroupFormat::OPTION_GROUP_SIZE, 364 LLDB_OPT_SET_1 | LLDB_OPT_SET_2); 365 m_option_group.Append (&m_memory_options); 366 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 367 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); 368 m_option_group.Finalize(); 369 } 370 371 virtual 372 ~CommandObjectMemoryRead () 373 { 374 } 375 376 Options * 377 GetOptions () 378 { 379 return &m_option_group; 380 } 381 382 virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 383 { 384 return m_cmd_name.c_str(); 385 } 386 387 protected: 388 virtual bool 389 DoExecute (Args& command, CommandReturnObject &result) 390 { 391 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid 392 Target *target = m_exe_ctx.GetTargetPtr(); 393 394 const size_t argc = command.GetArgumentCount(); 395 396 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) 397 { 398 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str()); 399 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n"); 400 result.SetStatus(eReturnStatusFailed); 401 return false; 402 } 403 404 ClangASTType clang_ast_type; 405 Error error; 406 407 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); 408 if (view_as_type_cstr && view_as_type_cstr[0]) 409 { 410 // We are viewing memory as a type 411 412 SymbolContext sc; 413 const bool exact_match = false; 414 TypeList type_list; 415 uint32_t reference_count = 0; 416 uint32_t pointer_count = 0; 417 size_t idx; 418 419 #define ALL_KEYWORDS \ 420 KEYWORD("const") \ 421 KEYWORD("volatile") \ 422 KEYWORD("restrict") \ 423 KEYWORD("struct") \ 424 KEYWORD("class") \ 425 KEYWORD("union") 426 427 #define KEYWORD(s) s, 428 static const char *g_keywords[] = 429 { 430 ALL_KEYWORDS 431 }; 432 #undef KEYWORD 433 434 #define KEYWORD(s) (sizeof(s) - 1), 435 static const int g_keyword_lengths[] = 436 { 437 ALL_KEYWORDS 438 }; 439 #undef KEYWORD 440 441 #undef ALL_KEYWORDS 442 443 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *); 444 std::string type_str(view_as_type_cstr); 445 446 // Remove all instances of g_keywords that are followed by spaces 447 for (size_t i = 0; i < g_num_keywords; ++i) 448 { 449 const char *keyword = g_keywords[i]; 450 int keyword_len = g_keyword_lengths[i]; 451 452 idx = 0; 453 while ((idx = type_str.find (keyword, idx)) != std::string::npos) 454 { 455 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') 456 { 457 type_str.erase(idx, keyword_len+1); 458 idx = 0; 459 } 460 else 461 { 462 idx += keyword_len; 463 } 464 } 465 } 466 bool done = type_str.empty(); 467 // 468 idx = type_str.find_first_not_of (" \t"); 469 if (idx > 0 && idx != std::string::npos) 470 type_str.erase (0, idx); 471 while (!done) 472 { 473 // Strip trailing spaces 474 if (type_str.empty()) 475 done = true; 476 else 477 { 478 switch (type_str[type_str.size()-1]) 479 { 480 case '*': 481 ++pointer_count; 482 // fall through... 483 case ' ': 484 case '\t': 485 type_str.erase(type_str.size()-1); 486 break; 487 488 case '&': 489 if (reference_count == 0) 490 { 491 reference_count = 1; 492 type_str.erase(type_str.size()-1); 493 } 494 else 495 { 496 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); 497 result.SetStatus(eReturnStatusFailed); 498 return false; 499 } 500 break; 501 502 default: 503 done = true; 504 break; 505 } 506 } 507 } 508 509 ConstString lookup_type_name(type_str.c_str()); 510 StackFrame *frame = m_exe_ctx.GetFramePtr(); 511 if (frame) 512 { 513 sc = frame->GetSymbolContext (eSymbolContextModule); 514 if (sc.module_sp) 515 { 516 sc.module_sp->FindTypes (sc, 517 lookup_type_name, 518 exact_match, 519 1, 520 type_list); 521 } 522 } 523 if (type_list.GetSize() == 0) 524 { 525 target->GetImages().FindTypes (sc, 526 lookup_type_name, 527 exact_match, 528 1, 529 type_list); 530 } 531 532 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$') 533 { 534 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name)); 535 if (tdecl) 536 { 537 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl()); 538 } 539 } 540 541 if (clang_ast_type.IsValid() == false) 542 { 543 if (type_list.GetSize() == 0) 544 { 545 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", 546 lookup_type_name.GetCString(), 547 view_as_type_cstr); 548 result.SetStatus(eReturnStatusFailed); 549 return false; 550 } 551 else 552 { 553 TypeSP type_sp (type_list.GetTypeAtIndex(0)); 554 clang_ast_type = type_sp->GetClangFullType(); 555 } 556 } 557 558 while (pointer_count > 0) 559 { 560 ClangASTType pointer_type = clang_ast_type.GetPointerType(); 561 if (pointer_type.IsValid()) 562 clang_ast_type = pointer_type; 563 else 564 { 565 result.AppendError ("unable make a pointer type\n"); 566 result.SetStatus(eReturnStatusFailed); 567 return false; 568 } 569 --pointer_count; 570 } 571 572 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr); 573 574 if (m_format_options.GetByteSizeValue() == 0) 575 { 576 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 577 view_as_type_cstr); 578 result.SetStatus(eReturnStatusFailed); 579 return false; 580 } 581 582 if (!m_format_options.GetCountValue().OptionWasSet()) 583 m_format_options.GetCountValue() = 1; 584 } 585 else 586 { 587 error = m_memory_options.FinalizeSettings (target, m_format_options); 588 } 589 590 // Look for invalid combinations of settings 591 if (error.Fail()) 592 { 593 result.AppendError(error.AsCString()); 594 result.SetStatus(eReturnStatusFailed); 595 return false; 596 } 597 598 lldb::addr_t addr; 599 size_t total_byte_size = 0; 600 if (argc == 0) 601 { 602 // Use the last address and byte size and all options as they were 603 // if no options have been set 604 addr = m_next_addr; 605 total_byte_size = m_prev_byte_size; 606 clang_ast_type = m_prev_clang_ast_type; 607 if (!m_format_options.AnyOptionWasSet() && 608 !m_memory_options.AnyOptionWasSet() && 609 !m_outfile_options.AnyOptionWasSet() && 610 !m_varobj_options.AnyOptionWasSet()) 611 { 612 m_format_options = m_prev_format_options; 613 m_memory_options = m_prev_memory_options; 614 m_outfile_options = m_prev_outfile_options; 615 m_varobj_options = m_prev_varobj_options; 616 } 617 } 618 619 size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); 620 621 // TODO For non-8-bit byte addressable architectures this needs to be 622 // revisited to fully support all lldb's range of formatting options. 623 // Furthermore code memory reads (for those architectures) will not 624 // be correctly formatted even w/o formatting options. 625 size_t item_byte_size = 626 target->GetArchitecture().GetDataByteSize() > 1 ? 627 target->GetArchitecture().GetDataByteSize() : 628 m_format_options.GetByteSizeValue().GetCurrentValue(); 629 630 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); 631 632 if (total_byte_size == 0) 633 { 634 total_byte_size = item_count * item_byte_size; 635 if (total_byte_size == 0) 636 total_byte_size = 32; 637 } 638 639 if (argc > 0) 640 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error); 641 642 if (addr == LLDB_INVALID_ADDRESS) 643 { 644 result.AppendError("invalid start address expression."); 645 result.AppendError(error.AsCString()); 646 result.SetStatus(eReturnStatusFailed); 647 return false; 648 } 649 650 if (argc == 2) 651 { 652 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); 653 if (end_addr == LLDB_INVALID_ADDRESS) 654 { 655 result.AppendError("invalid end address expression."); 656 result.AppendError(error.AsCString()); 657 result.SetStatus(eReturnStatusFailed); 658 return false; 659 } 660 else if (end_addr <= addr) 661 { 662 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr); 663 result.SetStatus(eReturnStatusFailed); 664 return false; 665 } 666 else if (m_format_options.GetCountValue().OptionWasSet()) 667 { 668 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count); 669 result.SetStatus(eReturnStatusFailed); 670 return false; 671 } 672 673 total_byte_size = end_addr - addr; 674 item_count = total_byte_size / item_byte_size; 675 } 676 677 uint32_t max_unforced_size = target->GetMaximumMemReadSize(); 678 679 if (total_byte_size > max_unforced_size && !m_memory_options.m_force) 680 { 681 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size); 682 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n"); 683 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n"); 684 return false; 685 } 686 687 DataBufferSP data_sp; 688 size_t bytes_read = 0; 689 if (clang_ast_type.GetOpaqueQualType()) 690 { 691 // Make sure we don't display our type as ASCII bytes like the default memory read 692 if (m_format_options.GetFormatValue().OptionWasSet() == false) 693 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); 694 695 bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue(); 696 } 697 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) 698 { 699 data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); 700 if (data_sp->GetBytes() == NULL) 701 { 702 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size); 703 result.SetStatus(eReturnStatusFailed); 704 return false; 705 } 706 707 Address address(addr, NULL); 708 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); 709 if (bytes_read == 0) 710 { 711 const char *error_cstr = error.AsCString(); 712 if (error_cstr && error_cstr[0]) 713 { 714 result.AppendError(error_cstr); 715 } 716 else 717 { 718 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 719 } 720 result.SetStatus(eReturnStatusFailed); 721 return false; 722 } 723 724 if (bytes_read < total_byte_size) 725 result.AppendWarningWithFormat("Not all bytes (%" PRIu64 "/%" PRIu64 ") were able to be read from 0x%" PRIx64 ".\n", (uint64_t)bytes_read, (uint64_t)total_byte_size, addr); 726 } 727 else 728 { 729 // we treat c-strings as a special case because they do not have a fixed size 730 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat()) 731 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); 732 else 733 item_byte_size = target->GetMaximumSizeOfStringSummary(); 734 if (!m_format_options.GetCountValue().OptionWasSet()) 735 item_count = 1; 736 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary 737 if (data_sp->GetBytes() == NULL) 738 { 739 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx64 " bytes for the memory read buffer, specify a smaller size to read", (uint64_t)((item_byte_size+1) * item_count)); 740 result.SetStatus(eReturnStatusFailed); 741 return false; 742 } 743 uint8_t *data_ptr = data_sp->GetBytes(); 744 auto data_addr = addr; 745 auto count = item_count; 746 item_count = 0; 747 while (item_count < count) 748 { 749 std::string buffer; 750 buffer.resize(item_byte_size+1,0); 751 Error error; 752 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error); 753 if (error.Fail()) 754 { 755 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 756 result.SetStatus(eReturnStatusFailed); 757 return false; 758 } 759 if (item_byte_size == read) 760 { 761 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr); 762 break; 763 } 764 read+=1; // account for final NULL byte 765 memcpy(data_ptr, &buffer[0], read); 766 data_ptr += read; 767 data_addr += read; 768 bytes_read += read; 769 item_count++; // if we break early we know we only read item_count strings 770 } 771 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1)); 772 } 773 774 m_next_addr = addr + bytes_read; 775 m_prev_byte_size = bytes_read; 776 m_prev_format_options = m_format_options; 777 m_prev_memory_options = m_memory_options; 778 m_prev_outfile_options = m_outfile_options; 779 m_prev_varobj_options = m_varobj_options; 780 m_prev_clang_ast_type = clang_ast_type; 781 782 StreamFile outfile_stream; 783 Stream *output_stream = NULL; 784 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 785 if (outfile_spec) 786 { 787 char path[PATH_MAX]; 788 outfile_spec.GetPath (path, sizeof(path)); 789 790 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 791 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 792 if (append) 793 open_options |= File::eOpenOptionAppend; 794 795 if (outfile_stream.GetFile ().Open (path, open_options).Success()) 796 { 797 if (m_memory_options.m_output_as_binary) 798 { 799 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 800 if (bytes_written > 0) 801 { 802 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n", 803 bytes_written, 804 append ? "appended" : "written", 805 path); 806 return true; 807 } 808 else 809 { 810 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path); 811 result.SetStatus(eReturnStatusFailed); 812 return false; 813 } 814 } 815 else 816 { 817 // We are going to write ASCII to the file just point the 818 // output_stream to our outfile_stream... 819 output_stream = &outfile_stream; 820 } 821 } 822 else 823 { 824 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); 825 result.SetStatus(eReturnStatusFailed); 826 return false; 827 } 828 } 829 else 830 { 831 output_stream = &result.GetOutputStream(); 832 } 833 834 835 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); 836 if (clang_ast_type.GetOpaqueQualType()) 837 { 838 for (uint32_t i = 0; i<item_count; ++i) 839 { 840 addr_t item_addr = addr + (i * item_byte_size); 841 Address address (item_addr); 842 StreamString name_strm; 843 name_strm.Printf ("0x%" PRIx64, item_addr); 844 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 845 name_strm.GetString().c_str(), 846 address, 847 clang_ast_type)); 848 if (valobj_sp) 849 { 850 Format format = m_format_options.GetFormat(); 851 if (format != eFormatDefault) 852 valobj_sp->SetFormat (format); 853 854 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format)); 855 856 valobj_sp->Dump(*output_stream,options); 857 } 858 else 859 { 860 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 861 view_as_type_cstr, 862 name_strm.GetString().c_str()); 863 result.SetStatus(eReturnStatusFailed); 864 return false; 865 } 866 } 867 return true; 868 } 869 870 result.SetStatus(eReturnStatusSuccessFinishResult); 871 DataExtractor data (data_sp, 872 target->GetArchitecture().GetByteOrder(), 873 target->GetArchitecture().GetAddressByteSize(), 874 target->GetArchitecture().GetDataByteSize()); 875 876 Format format = m_format_options.GetFormat(); 877 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) 878 && (item_byte_size != 1)) 879 { 880 // if a count was not passed, or it is 1 881 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1) 882 { 883 // this turns requests such as 884 // memory read -fc -s10 -c1 *charPtrPtr 885 // which make no sense (what is a char of size 10?) 886 // into a request for fetching 10 chars of size 1 from the same memory location 887 format = eFormatCharArray; 888 item_count = item_byte_size; 889 item_byte_size = 1; 890 } 891 else 892 { 893 // here we passed a count, and it was not 1 894 // so we have a byte_size and a count 895 // we could well multiply those, but instead let's just fail 896 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size); 897 result.SetStatus(eReturnStatusFailed); 898 return false; 899 } 900 } 901 902 assert (output_stream); 903 size_t bytes_dumped = data.Dump (output_stream, 904 0, 905 format, 906 item_byte_size, 907 item_count, 908 num_per_line / target->GetArchitecture().GetDataByteSize(), 909 addr, 910 0, 911 0, 912 exe_scope); 913 m_next_addr = addr + bytes_dumped; 914 output_stream->EOL(); 915 return true; 916 } 917 918 OptionGroupOptions m_option_group; 919 OptionGroupFormat m_format_options; 920 OptionGroupReadMemory m_memory_options; 921 OptionGroupOutputFile m_outfile_options; 922 OptionGroupValueObjectDisplay m_varobj_options; 923 lldb::addr_t m_next_addr; 924 lldb::addr_t m_prev_byte_size; 925 OptionGroupFormat m_prev_format_options; 926 OptionGroupReadMemory m_prev_memory_options; 927 OptionGroupOutputFile m_prev_outfile_options; 928 OptionGroupValueObjectDisplay m_prev_varobj_options; 929 ClangASTType m_prev_clang_ast_type; 930 }; 931 932 OptionDefinition 933 g_memory_find_option_table[] = 934 { 935 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."}, 936 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."}, 937 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."}, 938 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."}, 939 }; 940 941 //---------------------------------------------------------------------- 942 // Find the specified data in memory 943 //---------------------------------------------------------------------- 944 class CommandObjectMemoryFind : public CommandObjectParsed 945 { 946 public: 947 948 class OptionGroupFindMemory : public OptionGroup 949 { 950 public: 951 OptionGroupFindMemory () : 952 OptionGroup(), 953 m_count(1), 954 m_offset(0) 955 { 956 } 957 958 virtual 959 ~OptionGroupFindMemory () 960 { 961 } 962 963 virtual uint32_t 964 GetNumDefinitions () 965 { 966 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition); 967 } 968 969 virtual const OptionDefinition* 970 GetDefinitions () 971 { 972 return g_memory_find_option_table; 973 } 974 975 virtual Error 976 SetOptionValue (CommandInterpreter &interpreter, 977 uint32_t option_idx, 978 const char *option_arg) 979 { 980 Error error; 981 const int short_option = g_memory_find_option_table[option_idx].short_option; 982 983 switch (short_option) 984 { 985 case 'e': 986 m_expr.SetValueFromString(option_arg); 987 break; 988 989 case 's': 990 m_string.SetValueFromString(option_arg); 991 break; 992 993 case 'c': 994 if (m_count.SetValueFromString(option_arg).Fail()) 995 error.SetErrorString("unrecognized value for count"); 996 break; 997 998 case 'o': 999 if (m_offset.SetValueFromString(option_arg).Fail()) 1000 error.SetErrorString("unrecognized value for dump-offset"); 1001 break; 1002 1003 default: 1004 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 1005 break; 1006 } 1007 return error; 1008 } 1009 1010 virtual void 1011 OptionParsingStarting (CommandInterpreter &interpreter) 1012 { 1013 m_expr.Clear(); 1014 m_string.Clear(); 1015 m_count.Clear(); 1016 } 1017 1018 OptionValueString m_expr; 1019 OptionValueString m_string; 1020 OptionValueUInt64 m_count; 1021 OptionValueUInt64 m_offset; 1022 }; 1023 1024 CommandObjectMemoryFind (CommandInterpreter &interpreter) : 1025 CommandObjectParsed (interpreter, 1026 "memory find", 1027 "Find a value in the memory of the process being debugged.", 1028 NULL, 1029 eFlagRequiresProcess | eFlagProcessMustBeLaunched), 1030 m_option_group (interpreter), 1031 m_memory_options () 1032 { 1033 CommandArgumentEntry arg1; 1034 CommandArgumentEntry arg2; 1035 CommandArgumentData addr_arg; 1036 CommandArgumentData value_arg; 1037 1038 // Define the first (and only) variant of this arg. 1039 addr_arg.arg_type = eArgTypeAddress; 1040 addr_arg.arg_repetition = eArgRepeatPlain; 1041 1042 // There is only one variant this argument could be; put it into the argument entry. 1043 arg1.push_back (addr_arg); 1044 1045 // Define the first (and only) variant of this arg. 1046 value_arg.arg_type = eArgTypeValue; 1047 value_arg.arg_repetition = eArgRepeatPlus; 1048 1049 // There is only one variant this argument could be; put it into the argument entry. 1050 arg2.push_back (value_arg); 1051 1052 // Push the data for the first argument into the m_arguments vector. 1053 m_arguments.push_back (arg1); 1054 m_arguments.push_back (arg2); 1055 1056 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 1057 m_option_group.Finalize(); 1058 } 1059 1060 virtual 1061 ~CommandObjectMemoryFind () 1062 { 1063 } 1064 1065 Options * 1066 GetOptions () 1067 { 1068 return &m_option_group; 1069 } 1070 1071 protected: 1072 virtual bool 1073 DoExecute (Args& command, CommandReturnObject &result) 1074 { 1075 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid 1076 Process *process = m_exe_ctx.GetProcessPtr(); 1077 1078 const size_t argc = command.GetArgumentCount(); 1079 1080 if (argc != 2) 1081 { 1082 result.AppendError("two addresses needed for memory find"); 1083 return false; 1084 } 1085 1086 Error error; 1087 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error); 1088 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) 1089 { 1090 result.AppendError("invalid low address"); 1091 return false; 1092 } 1093 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error); 1094 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) 1095 { 1096 result.AppendError("invalid high address"); 1097 return false; 1098 } 1099 1100 if (high_addr <= low_addr) 1101 { 1102 result.AppendError("starting address must be smaller than ending address"); 1103 return false; 1104 } 1105 1106 lldb::addr_t found_location = LLDB_INVALID_ADDRESS; 1107 1108 DataBufferHeap buffer; 1109 1110 if (m_memory_options.m_string.OptionWasSet()) 1111 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue())); 1112 else if (m_memory_options.m_expr.OptionWasSet()) 1113 { 1114 StackFrame* frame = m_exe_ctx.GetFramePtr(); 1115 ValueObjectSP result_sp; 1116 if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get()) 1117 { 1118 uint64_t value = result_sp->GetValueAsUnsigned(0); 1119 switch (result_sp->GetClangType().GetByteSize(nullptr)) 1120 { 1121 case 1: { 1122 uint8_t byte = (uint8_t)value; 1123 buffer.CopyData(&byte,1); 1124 } 1125 break; 1126 case 2: { 1127 uint16_t word = (uint16_t)value; 1128 buffer.CopyData(&word,2); 1129 } 1130 break; 1131 case 4: { 1132 uint32_t lword = (uint32_t)value; 1133 buffer.CopyData(&lword,4); 1134 } 1135 break; 1136 case 8: { 1137 buffer.CopyData(&value, 8); 1138 } 1139 break; 1140 case 3: 1141 case 5: 1142 case 6: 1143 case 7: 1144 result.AppendError("unknown type. pass a string instead"); 1145 return false; 1146 default: 1147 result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead"); 1148 return false; 1149 } 1150 } 1151 else 1152 { 1153 result.AppendError("expression evaluation failed. pass a string instead?"); 1154 return false; 1155 } 1156 } 1157 else 1158 { 1159 result.AppendError("please pass either a block of text, or an expression to evaluate."); 1160 return false; 1161 } 1162 1163 size_t count = m_memory_options.m_count.GetCurrentValue(); 1164 found_location = low_addr; 1165 bool ever_found = false; 1166 while (count) 1167 { 1168 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize()); 1169 if (found_location == LLDB_INVALID_ADDRESS) 1170 { 1171 if (!ever_found) 1172 { 1173 result.AppendMessage("Your data was not found within the range.\n"); 1174 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 1175 } 1176 else 1177 result.AppendMessage("No more matches found within the range.\n"); 1178 break; 1179 } 1180 result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location); 1181 1182 DataBufferHeap dumpbuffer(32,0); 1183 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error); 1184 if (!error.Fail()) 1185 { 1186 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize()); 1187 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0); 1188 result.GetOutputStream().EOL(); 1189 } 1190 1191 --count; 1192 found_location++; 1193 ever_found = true; 1194 } 1195 1196 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 1197 return true; 1198 } 1199 1200 lldb::addr_t 1201 Search (lldb::addr_t low, 1202 lldb::addr_t high, 1203 uint8_t* buffer, 1204 size_t buffer_size) 1205 { 1206 Process *process = m_exe_ctx.GetProcessPtr(); 1207 DataBufferHeap heap(buffer_size, 0); 1208 lldb::addr_t fictional_ptr = low; 1209 for (auto ptr = low; 1210 low < high; 1211 fictional_ptr++) 1212 { 1213 Error error; 1214 if (ptr == low || buffer_size == 1) 1215 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error); 1216 else 1217 { 1218 memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1); 1219 process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error); 1220 } 1221 if (error.Fail()) 1222 return LLDB_INVALID_ADDRESS; 1223 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0) 1224 return fictional_ptr; 1225 if (ptr == low) 1226 ptr += buffer_size; 1227 else 1228 ptr += 1; 1229 } 1230 return LLDB_INVALID_ADDRESS; 1231 } 1232 1233 OptionGroupOptions m_option_group; 1234 OptionGroupFindMemory m_memory_options; 1235 }; 1236 1237 1238 OptionDefinition 1239 g_memory_write_option_table[] = 1240 { 1241 { LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 1242 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."}, 1243 }; 1244 1245 //---------------------------------------------------------------------- 1246 // Write memory to the inferior process 1247 //---------------------------------------------------------------------- 1248 class CommandObjectMemoryWrite : public CommandObjectParsed 1249 { 1250 public: 1251 1252 class OptionGroupWriteMemory : public OptionGroup 1253 { 1254 public: 1255 OptionGroupWriteMemory () : 1256 OptionGroup() 1257 { 1258 } 1259 1260 virtual 1261 ~OptionGroupWriteMemory () 1262 { 1263 } 1264 1265 virtual uint32_t 1266 GetNumDefinitions () 1267 { 1268 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); 1269 } 1270 1271 virtual const OptionDefinition* 1272 GetDefinitions () 1273 { 1274 return g_memory_write_option_table; 1275 } 1276 1277 virtual Error 1278 SetOptionValue (CommandInterpreter &interpreter, 1279 uint32_t option_idx, 1280 const char *option_arg) 1281 { 1282 Error error; 1283 const int short_option = g_memory_write_option_table[option_idx].short_option; 1284 1285 switch (short_option) 1286 { 1287 case 'i': 1288 m_infile.SetFile (option_arg, true); 1289 if (!m_infile.Exists()) 1290 { 1291 m_infile.Clear(); 1292 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); 1293 } 1294 break; 1295 1296 case 'o': 1297 { 1298 bool success; 1299 m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success); 1300 if (!success) 1301 { 1302 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); 1303 } 1304 } 1305 break; 1306 1307 default: 1308 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 1309 break; 1310 } 1311 return error; 1312 } 1313 1314 virtual void 1315 OptionParsingStarting (CommandInterpreter &interpreter) 1316 { 1317 m_infile.Clear(); 1318 m_infile_offset = 0; 1319 } 1320 1321 FileSpec m_infile; 1322 off_t m_infile_offset; 1323 }; 1324 1325 CommandObjectMemoryWrite (CommandInterpreter &interpreter) : 1326 CommandObjectParsed (interpreter, 1327 "memory write", 1328 "Write to the memory of the process being debugged.", 1329 NULL, 1330 eFlagRequiresProcess | eFlagProcessMustBeLaunched), 1331 m_option_group (interpreter), 1332 m_format_options (eFormatBytes, 1, UINT64_MAX), 1333 m_memory_options () 1334 { 1335 CommandArgumentEntry arg1; 1336 CommandArgumentEntry arg2; 1337 CommandArgumentData addr_arg; 1338 CommandArgumentData value_arg; 1339 1340 // Define the first (and only) variant of this arg. 1341 addr_arg.arg_type = eArgTypeAddress; 1342 addr_arg.arg_repetition = eArgRepeatPlain; 1343 1344 // There is only one variant this argument could be; put it into the argument entry. 1345 arg1.push_back (addr_arg); 1346 1347 // Define the first (and only) variant of this arg. 1348 value_arg.arg_type = eArgTypeValue; 1349 value_arg.arg_repetition = eArgRepeatPlus; 1350 1351 // There is only one variant this argument could be; put it into the argument entry. 1352 arg2.push_back (value_arg); 1353 1354 // Push the data for the first argument into the m_arguments vector. 1355 m_arguments.push_back (arg1); 1356 m_arguments.push_back (arg2); 1357 1358 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); 1359 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); 1360 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 1361 m_option_group.Finalize(); 1362 1363 } 1364 1365 virtual 1366 ~CommandObjectMemoryWrite () 1367 { 1368 } 1369 1370 Options * 1371 GetOptions () 1372 { 1373 return &m_option_group; 1374 } 1375 1376 bool 1377 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) 1378 { 1379 if (total_byte_size > 8) 1380 return false; 1381 1382 if (total_byte_size == 8) 1383 return true; 1384 1385 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; 1386 return uval64 <= max; 1387 } 1388 1389 bool 1390 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) 1391 { 1392 if (total_byte_size > 8) 1393 return false; 1394 1395 if (total_byte_size == 8) 1396 return true; 1397 1398 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; 1399 const int64_t min = ~(max); 1400 return min <= sval64 && sval64 <= max; 1401 } 1402 1403 protected: 1404 virtual bool 1405 DoExecute (Args& command, CommandReturnObject &result) 1406 { 1407 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid 1408 Process *process = m_exe_ctx.GetProcessPtr(); 1409 1410 const size_t argc = command.GetArgumentCount(); 1411 1412 if (m_memory_options.m_infile) 1413 { 1414 if (argc < 1) 1415 { 1416 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); 1417 result.SetStatus(eReturnStatusFailed); 1418 return false; 1419 } 1420 } 1421 else if (argc < 2) 1422 { 1423 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); 1424 result.SetStatus(eReturnStatusFailed); 1425 return false; 1426 } 1427 1428 StreamString buffer (Stream::eBinary, 1429 process->GetTarget().GetArchitecture().GetAddressByteSize(), 1430 process->GetTarget().GetArchitecture().GetByteOrder()); 1431 1432 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); 1433 size_t item_byte_size = byte_size_value.GetCurrentValue(); 1434 1435 Error error; 1436 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, 1437 command.GetArgumentAtIndex(0), 1438 LLDB_INVALID_ADDRESS, 1439 &error); 1440 1441 if (addr == LLDB_INVALID_ADDRESS) 1442 { 1443 result.AppendError("invalid address expression\n"); 1444 result.AppendError(error.AsCString()); 1445 result.SetStatus(eReturnStatusFailed); 1446 return false; 1447 } 1448 1449 if (m_memory_options.m_infile) 1450 { 1451 size_t length = SIZE_MAX; 1452 if (item_byte_size > 1) 1453 length = item_byte_size; 1454 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); 1455 if (data_sp) 1456 { 1457 length = data_sp->GetByteSize(); 1458 if (length > 0) 1459 { 1460 Error error; 1461 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); 1462 1463 if (bytes_written == length) 1464 { 1465 // All bytes written 1466 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr); 1467 result.SetStatus(eReturnStatusSuccessFinishResult); 1468 } 1469 else if (bytes_written > 0) 1470 { 1471 // Some byte written 1472 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr); 1473 result.SetStatus(eReturnStatusSuccessFinishResult); 1474 } 1475 else 1476 { 1477 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1478 result.SetStatus(eReturnStatusFailed); 1479 } 1480 } 1481 } 1482 else 1483 { 1484 result.AppendErrorWithFormat ("Unable to read contents of file.\n"); 1485 result.SetStatus(eReturnStatusFailed); 1486 } 1487 return result.Succeeded(); 1488 } 1489 else if (item_byte_size == 0) 1490 { 1491 if (m_format_options.GetFormat() == eFormatPointer) 1492 item_byte_size = buffer.GetAddressByteSize(); 1493 else 1494 item_byte_size = 1; 1495 } 1496 1497 command.Shift(); // shift off the address argument 1498 uint64_t uval64; 1499 int64_t sval64; 1500 bool success = false; 1501 const size_t num_value_args = command.GetArgumentCount(); 1502 for (size_t i=0; i<num_value_args; ++i) 1503 { 1504 const char *value_str = command.GetArgumentAtIndex(i); 1505 1506 switch (m_format_options.GetFormat()) 1507 { 1508 case kNumFormats: 1509 case eFormatFloat: // TODO: add support for floats soon 1510 case eFormatCharPrintable: 1511 case eFormatBytesWithASCII: 1512 case eFormatComplex: 1513 case eFormatEnum: 1514 case eFormatUnicode16: 1515 case eFormatUnicode32: 1516 case eFormatVectorOfChar: 1517 case eFormatVectorOfSInt8: 1518 case eFormatVectorOfUInt8: 1519 case eFormatVectorOfSInt16: 1520 case eFormatVectorOfUInt16: 1521 case eFormatVectorOfSInt32: 1522 case eFormatVectorOfUInt32: 1523 case eFormatVectorOfSInt64: 1524 case eFormatVectorOfUInt64: 1525 case eFormatVectorOfFloat32: 1526 case eFormatVectorOfFloat64: 1527 case eFormatVectorOfUInt128: 1528 case eFormatOSType: 1529 case eFormatComplexInteger: 1530 case eFormatAddressInfo: 1531 case eFormatHexFloat: 1532 case eFormatInstruction: 1533 case eFormatVoid: 1534 result.AppendError("unsupported format for writing memory"); 1535 result.SetStatus(eReturnStatusFailed); 1536 return false; 1537 1538 case eFormatDefault: 1539 case eFormatBytes: 1540 case eFormatHex: 1541 case eFormatHexUppercase: 1542 case eFormatPointer: 1543 1544 // Decode hex bytes 1545 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success); 1546 if (!success) 1547 { 1548 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); 1549 result.SetStatus(eReturnStatusFailed); 1550 return false; 1551 } 1552 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1553 { 1554 result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); 1555 result.SetStatus(eReturnStatusFailed); 1556 return false; 1557 } 1558 buffer.PutMaxHex64 (uval64, item_byte_size); 1559 break; 1560 1561 case eFormatBoolean: 1562 uval64 = Args::StringToBoolean(value_str, false, &success); 1563 if (!success) 1564 { 1565 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); 1566 result.SetStatus(eReturnStatusFailed); 1567 return false; 1568 } 1569 buffer.PutMaxHex64 (uval64, item_byte_size); 1570 break; 1571 1572 case eFormatBinary: 1573 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success); 1574 if (!success) 1575 { 1576 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); 1577 result.SetStatus(eReturnStatusFailed); 1578 return false; 1579 } 1580 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1581 { 1582 result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); 1583 result.SetStatus(eReturnStatusFailed); 1584 return false; 1585 } 1586 buffer.PutMaxHex64 (uval64, item_byte_size); 1587 break; 1588 1589 case eFormatCharArray: 1590 case eFormatChar: 1591 case eFormatCString: 1592 if (value_str[0]) 1593 { 1594 size_t len = strlen (value_str); 1595 // Include the NULL for C strings... 1596 if (m_format_options.GetFormat() == eFormatCString) 1597 ++len; 1598 Error error; 1599 if (process->WriteMemory (addr, value_str, len, error) == len) 1600 { 1601 addr += len; 1602 } 1603 else 1604 { 1605 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1606 result.SetStatus(eReturnStatusFailed); 1607 return false; 1608 } 1609 } 1610 break; 1611 1612 case eFormatDecimal: 1613 sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); 1614 if (!success) 1615 { 1616 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); 1617 result.SetStatus(eReturnStatusFailed); 1618 return false; 1619 } 1620 else if (!SIntValueIsValidForSize (sval64, item_byte_size)) 1621 { 1622 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %" PRIu64 " byte signed integer value.\n", sval64, (uint64_t)item_byte_size); 1623 result.SetStatus(eReturnStatusFailed); 1624 return false; 1625 } 1626 buffer.PutMaxHex64 (sval64, item_byte_size); 1627 break; 1628 1629 case eFormatUnsigned: 1630 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); 1631 if (!success) 1632 { 1633 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); 1634 result.SetStatus(eReturnStatusFailed); 1635 return false; 1636 } 1637 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1638 { 1639 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); 1640 result.SetStatus(eReturnStatusFailed); 1641 return false; 1642 } 1643 buffer.PutMaxHex64 (uval64, item_byte_size); 1644 break; 1645 1646 case eFormatOctal: 1647 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success); 1648 if (!success) 1649 { 1650 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); 1651 result.SetStatus(eReturnStatusFailed); 1652 return false; 1653 } 1654 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1655 { 1656 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); 1657 result.SetStatus(eReturnStatusFailed); 1658 return false; 1659 } 1660 buffer.PutMaxHex64 (uval64, item_byte_size); 1661 break; 1662 } 1663 } 1664 1665 if (!buffer.GetString().empty()) 1666 { 1667 Error error; 1668 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) 1669 return true; 1670 else 1671 { 1672 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1673 result.SetStatus(eReturnStatusFailed); 1674 return false; 1675 } 1676 } 1677 return true; 1678 } 1679 1680 OptionGroupOptions m_option_group; 1681 OptionGroupFormat m_format_options; 1682 OptionGroupWriteMemory m_memory_options; 1683 }; 1684 1685 //---------------------------------------------------------------------- 1686 // Get malloc/free history of a memory address. 1687 //---------------------------------------------------------------------- 1688 class CommandObjectMemoryHistory : public CommandObjectParsed 1689 { 1690 public: 1691 1692 CommandObjectMemoryHistory (CommandInterpreter &interpreter) : 1693 CommandObjectParsed (interpreter, 1694 "memory history", 1695 "Prints out the recorded stack traces for allocation/deallocation of a memory address.", 1696 NULL, 1697 eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched) 1698 { 1699 CommandArgumentEntry arg1; 1700 CommandArgumentData addr_arg; 1701 1702 // Define the first (and only) variant of this arg. 1703 addr_arg.arg_type = eArgTypeAddress; 1704 addr_arg.arg_repetition = eArgRepeatPlain; 1705 1706 // There is only one variant this argument could be; put it into the argument entry. 1707 arg1.push_back (addr_arg); 1708 1709 // Push the data for the first argument into the m_arguments vector. 1710 m_arguments.push_back (arg1); 1711 } 1712 1713 virtual 1714 ~CommandObjectMemoryHistory () 1715 { 1716 } 1717 1718 virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 1719 { 1720 return m_cmd_name.c_str(); 1721 } 1722 1723 protected: 1724 virtual bool 1725 DoExecute (Args& command, CommandReturnObject &result) 1726 { 1727 const size_t argc = command.GetArgumentCount(); 1728 1729 if (argc == 0 || argc > 1) 1730 { 1731 result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str()); 1732 result.SetStatus(eReturnStatusFailed); 1733 return false; 1734 } 1735 1736 Error error; 1737 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, 1738 command.GetArgumentAtIndex(0), 1739 LLDB_INVALID_ADDRESS, 1740 &error); 1741 1742 if (addr == LLDB_INVALID_ADDRESS) 1743 { 1744 result.AppendError("invalid address expression"); 1745 result.AppendError(error.AsCString()); 1746 result.SetStatus(eReturnStatusFailed); 1747 return false; 1748 } 1749 1750 Stream *output_stream = &result.GetOutputStream(); 1751 1752 const ProcessSP &process_sp = m_exe_ctx.GetProcessSP(); 1753 const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp); 1754 1755 if (! memory_history.get()) 1756 { 1757 result.AppendError("no available memory history provider"); 1758 result.SetStatus(eReturnStatusFailed); 1759 return false; 1760 } 1761 1762 HistoryThreads thread_list = memory_history->GetHistoryThreads(addr); 1763 1764 for (auto thread : thread_list) { 1765 thread->GetStatus(*output_stream, 0, UINT32_MAX, 0); 1766 } 1767 1768 result.SetStatus(eReturnStatusSuccessFinishResult); 1769 1770 return true; 1771 } 1772 1773 }; 1774 1775 1776 //------------------------------------------------------------------------- 1777 // CommandObjectMemory 1778 //------------------------------------------------------------------------- 1779 1780 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : 1781 CommandObjectMultiword (interpreter, 1782 "memory", 1783 "A set of commands for operating on memory.", 1784 "memory <subcommand> [<subcommand-options>]") 1785 { 1786 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter))); 1787 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); 1788 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); 1789 LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter))); 1790 } 1791 1792 CommandObjectMemory::~CommandObjectMemory () 1793 { 1794 } 1795