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