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