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