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