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 bool 1092 DoExecute (Args& command, CommandReturnObject &result) override 1093 { 1094 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid 1095 Process *process = m_exe_ctx.GetProcessPtr(); 1096 1097 const size_t argc = command.GetArgumentCount(); 1098 1099 if (argc != 2) 1100 { 1101 result.AppendError("two addresses needed for memory find"); 1102 return false; 1103 } 1104 1105 Error error; 1106 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error); 1107 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) 1108 { 1109 result.AppendError("invalid low address"); 1110 return false; 1111 } 1112 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error); 1113 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) 1114 { 1115 result.AppendError("invalid high address"); 1116 return false; 1117 } 1118 1119 if (high_addr <= low_addr) 1120 { 1121 result.AppendError("starting address must be smaller than ending address"); 1122 return false; 1123 } 1124 1125 lldb::addr_t found_location = LLDB_INVALID_ADDRESS; 1126 1127 DataBufferHeap buffer; 1128 1129 if (m_memory_options.m_string.OptionWasSet()) 1130 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue())); 1131 else if (m_memory_options.m_expr.OptionWasSet()) 1132 { 1133 StackFrame* frame = m_exe_ctx.GetFramePtr(); 1134 ValueObjectSP result_sp; 1135 if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) && 1136 result_sp) 1137 { 1138 uint64_t value = result_sp->GetValueAsUnsigned(0); 1139 switch (result_sp->GetCompilerType().GetByteSize(nullptr)) 1140 { 1141 case 1: { 1142 uint8_t byte = (uint8_t)value; 1143 buffer.CopyData(&byte,1); 1144 } 1145 break; 1146 case 2: { 1147 uint16_t word = (uint16_t)value; 1148 buffer.CopyData(&word,2); 1149 } 1150 break; 1151 case 4: { 1152 uint32_t lword = (uint32_t)value; 1153 buffer.CopyData(&lword,4); 1154 } 1155 break; 1156 case 8: { 1157 buffer.CopyData(&value, 8); 1158 } 1159 break; 1160 case 3: 1161 case 5: 1162 case 6: 1163 case 7: 1164 result.AppendError("unknown type. pass a string instead"); 1165 return false; 1166 default: 1167 result.AppendError("result size larger than 8 bytes. pass a string instead"); 1168 return false; 1169 } 1170 } 1171 else 1172 { 1173 result.AppendError("expression evaluation failed. pass a string instead"); 1174 return false; 1175 } 1176 } 1177 else 1178 { 1179 result.AppendError("please pass either a block of text, or an expression to evaluate."); 1180 return false; 1181 } 1182 1183 size_t count = m_memory_options.m_count.GetCurrentValue(); 1184 found_location = low_addr; 1185 bool ever_found = false; 1186 while (count) 1187 { 1188 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize()); 1189 if (found_location == LLDB_INVALID_ADDRESS) 1190 { 1191 if (!ever_found) 1192 { 1193 result.AppendMessage("data not found within the range.\n"); 1194 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 1195 } 1196 else 1197 result.AppendMessage("no more matches within the range.\n"); 1198 break; 1199 } 1200 result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location); 1201 1202 DataBufferHeap dumpbuffer(32,0); 1203 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error); 1204 if (!error.Fail()) 1205 { 1206 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize()); 1207 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0); 1208 result.GetOutputStream().EOL(); 1209 } 1210 1211 --count; 1212 found_location++; 1213 ever_found = true; 1214 } 1215 1216 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 1217 return true; 1218 } 1219 1220 lldb::addr_t 1221 Search (lldb::addr_t low, 1222 lldb::addr_t high, 1223 uint8_t* buffer, 1224 size_t buffer_size) 1225 { 1226 Process *process = m_exe_ctx.GetProcessPtr(); 1227 DataBufferHeap heap(buffer_size, 0); 1228 for (auto ptr = low; 1229 ptr < high; 1230 ptr++) 1231 { 1232 Error error; 1233 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error); 1234 if (error.Fail()) 1235 return LLDB_INVALID_ADDRESS; 1236 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0) 1237 return ptr; 1238 } 1239 return LLDB_INVALID_ADDRESS; 1240 } 1241 1242 OptionGroupOptions m_option_group; 1243 OptionGroupFindMemory m_memory_options; 1244 }; 1245 1246 OptionDefinition 1247 g_memory_write_option_table[] = 1248 { 1249 // clang-format off 1250 {LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 1251 {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."}, 1252 // clang-format on 1253 }; 1254 1255 //---------------------------------------------------------------------- 1256 // Write memory to the inferior process 1257 //---------------------------------------------------------------------- 1258 class CommandObjectMemoryWrite : public CommandObjectParsed 1259 { 1260 public: 1261 class OptionGroupWriteMemory : public OptionGroup 1262 { 1263 public: 1264 OptionGroupWriteMemory () : 1265 OptionGroup() 1266 { 1267 } 1268 1269 ~OptionGroupWriteMemory() override = default; 1270 1271 uint32_t 1272 GetNumDefinitions () override 1273 { 1274 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); 1275 } 1276 1277 const OptionDefinition* 1278 GetDefinitions () override 1279 { 1280 return g_memory_write_option_table; 1281 } 1282 1283 Error 1284 SetOptionValue (uint32_t option_idx, 1285 const char *option_arg, 1286 ExecutionContext *execution_context) override 1287 { 1288 Error error; 1289 const int short_option = g_memory_write_option_table[option_idx].short_option; 1290 1291 switch (short_option) 1292 { 1293 case 'i': 1294 m_infile.SetFile (option_arg, true); 1295 if (!m_infile.Exists()) 1296 { 1297 m_infile.Clear(); 1298 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); 1299 } 1300 break; 1301 1302 case 'o': 1303 { 1304 bool success; 1305 m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success); 1306 if (!success) 1307 { 1308 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); 1309 } 1310 } 1311 break; 1312 1313 default: 1314 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 1315 break; 1316 } 1317 return error; 1318 } 1319 1320 void 1321 OptionParsingStarting(ExecutionContext *execution_context) override 1322 { 1323 m_infile.Clear(); 1324 m_infile_offset = 0; 1325 } 1326 1327 FileSpec m_infile; 1328 off_t m_infile_offset; 1329 }; 1330 1331 CommandObjectMemoryWrite(CommandInterpreter &interpreter) 1332 : CommandObjectParsed(interpreter, "memory write", "Write to the memory of the current target process.", 1333 nullptr, eCommandRequiresProcess | eCommandProcessMustBeLaunched), 1334 m_option_group(), 1335 m_format_options(eFormatBytes, 1, UINT64_MAX), 1336 m_memory_options() 1337 { 1338 CommandArgumentEntry arg1; 1339 CommandArgumentEntry arg2; 1340 CommandArgumentData addr_arg; 1341 CommandArgumentData value_arg; 1342 1343 // Define the first (and only) variant of this arg. 1344 addr_arg.arg_type = eArgTypeAddress; 1345 addr_arg.arg_repetition = eArgRepeatPlain; 1346 1347 // There is only one variant this argument could be; put it into the argument entry. 1348 arg1.push_back (addr_arg); 1349 1350 // Define the first (and only) variant of this arg. 1351 value_arg.arg_type = eArgTypeValue; 1352 value_arg.arg_repetition = eArgRepeatPlus; 1353 1354 // There is only one variant this argument could be; put it into the argument entry. 1355 arg2.push_back (value_arg); 1356 1357 // Push the data for the first argument into the m_arguments vector. 1358 m_arguments.push_back (arg1); 1359 m_arguments.push_back (arg2); 1360 1361 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); 1362 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); 1363 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 1364 m_option_group.Finalize(); 1365 } 1366 1367 ~CommandObjectMemoryWrite() override = default; 1368 1369 Options * 1370 GetOptions () override 1371 { 1372 return &m_option_group; 1373 } 1374 1375 bool 1376 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) 1377 { 1378 if (total_byte_size > 8) 1379 return false; 1380 1381 if (total_byte_size == 8) 1382 return true; 1383 1384 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; 1385 return uval64 <= max; 1386 } 1387 1388 bool 1389 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) 1390 { 1391 if (total_byte_size > 8) 1392 return false; 1393 1394 if (total_byte_size == 8) 1395 return true; 1396 1397 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; 1398 const int64_t min = ~(max); 1399 return min <= sval64 && sval64 <= max; 1400 } 1401 1402 protected: 1403 bool 1404 DoExecute (Args& command, CommandReturnObject &result) override 1405 { 1406 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid 1407 Process *process = m_exe_ctx.GetProcessPtr(); 1408 1409 const size_t argc = command.GetArgumentCount(); 1410 1411 if (m_memory_options.m_infile) 1412 { 1413 if (argc < 1) 1414 { 1415 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); 1416 result.SetStatus(eReturnStatusFailed); 1417 return false; 1418 } 1419 } 1420 else if (argc < 2) 1421 { 1422 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); 1423 result.SetStatus(eReturnStatusFailed); 1424 return false; 1425 } 1426 1427 StreamString buffer (Stream::eBinary, 1428 process->GetTarget().GetArchitecture().GetAddressByteSize(), 1429 process->GetTarget().GetArchitecture().GetByteOrder()); 1430 1431 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); 1432 size_t item_byte_size = byte_size_value.GetCurrentValue(); 1433 1434 Error error; 1435 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, 1436 command.GetArgumentAtIndex(0), 1437 LLDB_INVALID_ADDRESS, 1438 &error); 1439 1440 if (addr == LLDB_INVALID_ADDRESS) 1441 { 1442 result.AppendError("invalid address expression\n"); 1443 result.AppendError(error.AsCString()); 1444 result.SetStatus(eReturnStatusFailed); 1445 return false; 1446 } 1447 1448 if (m_memory_options.m_infile) 1449 { 1450 size_t length = SIZE_MAX; 1451 if (item_byte_size > 1) 1452 length = item_byte_size; 1453 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); 1454 if (data_sp) 1455 { 1456 length = data_sp->GetByteSize(); 1457 if (length > 0) 1458 { 1459 Error error; 1460 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); 1461 1462 if (bytes_written == length) 1463 { 1464 // All bytes written 1465 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr); 1466 result.SetStatus(eReturnStatusSuccessFinishResult); 1467 } 1468 else if (bytes_written > 0) 1469 { 1470 // Some byte written 1471 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr); 1472 result.SetStatus(eReturnStatusSuccessFinishResult); 1473 } 1474 else 1475 { 1476 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1477 result.SetStatus(eReturnStatusFailed); 1478 } 1479 } 1480 } 1481 else 1482 { 1483 result.AppendErrorWithFormat ("Unable to read contents of file.\n"); 1484 result.SetStatus(eReturnStatusFailed); 1485 } 1486 return result.Succeeded(); 1487 } 1488 else if (item_byte_size == 0) 1489 { 1490 if (m_format_options.GetFormat() == eFormatPointer) 1491 item_byte_size = buffer.GetAddressByteSize(); 1492 else 1493 item_byte_size = 1; 1494 } 1495 1496 command.Shift(); // shift off the address argument 1497 uint64_t uval64; 1498 int64_t sval64; 1499 bool success = false; 1500 const size_t num_value_args = command.GetArgumentCount(); 1501 for (size_t i=0; i<num_value_args; ++i) 1502 { 1503 const char *value_str = command.GetArgumentAtIndex(i); 1504 1505 switch (m_format_options.GetFormat()) 1506 { 1507 case kNumFormats: 1508 case eFormatFloat: // TODO: add support for floats soon 1509 case eFormatCharPrintable: 1510 case eFormatBytesWithASCII: 1511 case eFormatComplex: 1512 case eFormatEnum: 1513 case eFormatUnicode16: 1514 case eFormatUnicode32: 1515 case eFormatVectorOfChar: 1516 case eFormatVectorOfSInt8: 1517 case eFormatVectorOfUInt8: 1518 case eFormatVectorOfSInt16: 1519 case eFormatVectorOfUInt16: 1520 case eFormatVectorOfSInt32: 1521 case eFormatVectorOfUInt32: 1522 case eFormatVectorOfSInt64: 1523 case eFormatVectorOfUInt64: 1524 case eFormatVectorOfFloat16: 1525 case eFormatVectorOfFloat32: 1526 case eFormatVectorOfFloat64: 1527 case eFormatVectorOfUInt128: 1528 case eFormatOSType: 1529 case eFormatComplexInteger: 1530 case eFormatAddressInfo: 1531 case eFormatHexFloat: 1532 case eFormatInstruction: 1533 case eFormatVoid: 1534 result.AppendError("unsupported format for writing memory"); 1535 result.SetStatus(eReturnStatusFailed); 1536 return false; 1537 1538 case eFormatDefault: 1539 case eFormatBytes: 1540 case eFormatHex: 1541 case eFormatHexUppercase: 1542 case eFormatPointer: 1543 // Decode hex bytes 1544 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success); 1545 if (!success) 1546 { 1547 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); 1548 result.SetStatus(eReturnStatusFailed); 1549 return false; 1550 } 1551 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1552 { 1553 result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); 1554 result.SetStatus(eReturnStatusFailed); 1555 return false; 1556 } 1557 buffer.PutMaxHex64 (uval64, item_byte_size); 1558 break; 1559 1560 case eFormatBoolean: 1561 uval64 = Args::StringToBoolean(value_str, false, &success); 1562 if (!success) 1563 { 1564 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); 1565 result.SetStatus(eReturnStatusFailed); 1566 return false; 1567 } 1568 buffer.PutMaxHex64 (uval64, item_byte_size); 1569 break; 1570 1571 case eFormatBinary: 1572 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success); 1573 if (!success) 1574 { 1575 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); 1576 result.SetStatus(eReturnStatusFailed); 1577 return false; 1578 } 1579 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1580 { 1581 result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); 1582 result.SetStatus(eReturnStatusFailed); 1583 return false; 1584 } 1585 buffer.PutMaxHex64 (uval64, item_byte_size); 1586 break; 1587 1588 case eFormatCharArray: 1589 case eFormatChar: 1590 case eFormatCString: 1591 if (value_str[0]) 1592 { 1593 size_t len = strlen (value_str); 1594 // Include the NULL for C strings... 1595 if (m_format_options.GetFormat() == eFormatCString) 1596 ++len; 1597 Error error; 1598 if (process->WriteMemory (addr, value_str, len, error) == len) 1599 { 1600 addr += len; 1601 } 1602 else 1603 { 1604 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1605 result.SetStatus(eReturnStatusFailed); 1606 return false; 1607 } 1608 } 1609 break; 1610 1611 case eFormatDecimal: 1612 sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); 1613 if (!success) 1614 { 1615 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); 1616 result.SetStatus(eReturnStatusFailed); 1617 return false; 1618 } 1619 else if (!SIntValueIsValidForSize (sval64, item_byte_size)) 1620 { 1621 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %" PRIu64 " byte signed integer value.\n", sval64, (uint64_t)item_byte_size); 1622 result.SetStatus(eReturnStatusFailed); 1623 return false; 1624 } 1625 buffer.PutMaxHex64 (sval64, item_byte_size); 1626 break; 1627 1628 case eFormatUnsigned: 1629 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); 1630 if (!success) 1631 { 1632 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); 1633 result.SetStatus(eReturnStatusFailed); 1634 return false; 1635 } 1636 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1637 { 1638 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); 1639 result.SetStatus(eReturnStatusFailed); 1640 return false; 1641 } 1642 buffer.PutMaxHex64 (uval64, item_byte_size); 1643 break; 1644 1645 case eFormatOctal: 1646 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success); 1647 if (!success) 1648 { 1649 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); 1650 result.SetStatus(eReturnStatusFailed); 1651 return false; 1652 } 1653 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1654 { 1655 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); 1656 result.SetStatus(eReturnStatusFailed); 1657 return false; 1658 } 1659 buffer.PutMaxHex64 (uval64, item_byte_size); 1660 break; 1661 } 1662 } 1663 1664 if (!buffer.GetString().empty()) 1665 { 1666 Error error; 1667 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) 1668 return true; 1669 else 1670 { 1671 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1672 result.SetStatus(eReturnStatusFailed); 1673 return false; 1674 } 1675 } 1676 return true; 1677 } 1678 1679 OptionGroupOptions m_option_group; 1680 OptionGroupFormat m_format_options; 1681 OptionGroupWriteMemory m_memory_options; 1682 }; 1683 1684 //---------------------------------------------------------------------- 1685 // Get malloc/free history of a memory address. 1686 //---------------------------------------------------------------------- 1687 class CommandObjectMemoryHistory : public CommandObjectParsed 1688 { 1689 public: 1690 CommandObjectMemoryHistory(CommandInterpreter &interpreter) 1691 : CommandObjectParsed( 1692 interpreter, "memory history", 1693 "Print recorded stack traces for allocation/deallocation events associated with an address.", nullptr, 1694 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | 1695 eCommandProcessMustBeLaunched) 1696 { 1697 CommandArgumentEntry arg1; 1698 CommandArgumentData addr_arg; 1699 1700 // Define the first (and only) variant of this arg. 1701 addr_arg.arg_type = eArgTypeAddress; 1702 addr_arg.arg_repetition = eArgRepeatPlain; 1703 1704 // There is only one variant this argument could be; put it into the argument entry. 1705 arg1.push_back (addr_arg); 1706 1707 // Push the data for the first argument into the m_arguments vector. 1708 m_arguments.push_back (arg1); 1709 } 1710 1711 ~CommandObjectMemoryHistory() override = default; 1712 1713 const char * 1714 GetRepeatCommand (Args ¤t_command_args, uint32_t index) override 1715 { 1716 return m_cmd_name.c_str(); 1717 } 1718 1719 protected: 1720 bool 1721 DoExecute (Args& command, CommandReturnObject &result) override 1722 { 1723 const size_t argc = command.GetArgumentCount(); 1724 1725 if (argc == 0 || argc > 1) 1726 { 1727 result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str()); 1728 result.SetStatus(eReturnStatusFailed); 1729 return false; 1730 } 1731 1732 Error error; 1733 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, 1734 command.GetArgumentAtIndex(0), 1735 LLDB_INVALID_ADDRESS, 1736 &error); 1737 1738 if (addr == LLDB_INVALID_ADDRESS) 1739 { 1740 result.AppendError("invalid address expression"); 1741 result.AppendError(error.AsCString()); 1742 result.SetStatus(eReturnStatusFailed); 1743 return false; 1744 } 1745 1746 Stream *output_stream = &result.GetOutputStream(); 1747 1748 const ProcessSP &process_sp = m_exe_ctx.GetProcessSP(); 1749 const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp); 1750 1751 if (!memory_history) 1752 { 1753 result.AppendError("no available memory history provider"); 1754 result.SetStatus(eReturnStatusFailed); 1755 return false; 1756 } 1757 1758 HistoryThreads thread_list = memory_history->GetHistoryThreads(addr); 1759 1760 for (auto thread : thread_list) { 1761 thread->GetStatus(*output_stream, 0, UINT32_MAX, 0); 1762 } 1763 1764 result.SetStatus(eReturnStatusSuccessFinishResult); 1765 1766 return true; 1767 } 1768 }; 1769 1770 //------------------------------------------------------------------------- 1771 // CommandObjectMemoryRegion 1772 //------------------------------------------------------------------------- 1773 #pragma mark CommandObjectMemoryRegion 1774 1775 class CommandObjectMemoryRegion : public CommandObjectParsed 1776 { 1777 public: 1778 CommandObjectMemoryRegion(CommandInterpreter &interpreter) 1779 : CommandObjectParsed( 1780 interpreter, "memory region", 1781 "Get information on the memory region containing an address in the current target process.", 1782 "memory region ADDR", eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched), 1783 m_prev_end_addr(LLDB_INVALID_ADDRESS) 1784 { 1785 } 1786 1787 ~CommandObjectMemoryRegion() override = default; 1788 1789 protected: 1790 bool 1791 DoExecute(Args &command, CommandReturnObject &result) override 1792 { 1793 ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1794 if (process_sp) 1795 { 1796 Error error; 1797 lldb::addr_t load_addr = m_prev_end_addr; 1798 m_prev_end_addr = LLDB_INVALID_ADDRESS; 1799 1800 const size_t argc = command.GetArgumentCount(); 1801 if (argc > 1 || (argc == 0 && load_addr == LLDB_INVALID_ADDRESS)) 1802 { 1803 result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n", m_cmd_name.c_str(), 1804 m_cmd_syntax.c_str()); 1805 result.SetStatus(eReturnStatusFailed); 1806 } 1807 else 1808 { 1809 const char *load_addr_cstr = command.GetArgumentAtIndex(0); 1810 if (command.GetArgumentCount() == 1) 1811 { 1812 load_addr = Args::StringToAddress(&m_exe_ctx, load_addr_cstr, LLDB_INVALID_ADDRESS, &error); 1813 if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) 1814 { 1815 result.AppendErrorWithFormat("invalid address argument \"%s\": %s\n", load_addr_cstr, 1816 error.AsCString()); 1817 result.SetStatus(eReturnStatusFailed); 1818 } 1819 } 1820 1821 lldb_private::MemoryRegionInfo range_info; 1822 error = process_sp->GetMemoryRegionInfo(load_addr, range_info); 1823 if (error.Success()) 1824 { 1825 lldb_private::Address addr; 1826 ConstString section_name; 1827 if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr)) 1828 { 1829 SectionSP section_sp(addr.GetSection()); 1830 if (section_sp) 1831 { 1832 // Got the top most section, not the deepest section 1833 while (section_sp->GetParent()) 1834 section_sp = section_sp->GetParent(); 1835 section_name = section_sp->GetName(); 1836 } 1837 } 1838 result.AppendMessageWithFormat( 1839 "[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s\n", range_info.GetRange().GetRangeBase(), 1840 range_info.GetRange().GetRangeEnd(), range_info.GetReadable() ? 'r' : '-', 1841 range_info.GetWritable() ? 'w' : '-', range_info.GetExecutable() ? 'x' : '-', 1842 section_name ? " " : "", section_name ? section_name.AsCString() : ""); 1843 m_prev_end_addr = range_info.GetRange().GetRangeEnd(); 1844 result.SetStatus(eReturnStatusSuccessFinishResult); 1845 } 1846 else 1847 { 1848 result.SetStatus(eReturnStatusFailed); 1849 result.AppendErrorWithFormat("%s\n", error.AsCString()); 1850 } 1851 } 1852 } 1853 else 1854 { 1855 m_prev_end_addr = LLDB_INVALID_ADDRESS; 1856 result.AppendError("invalid process"); 1857 result.SetStatus(eReturnStatusFailed); 1858 } 1859 return result.Succeeded(); 1860 } 1861 1862 const char * 1863 GetRepeatCommand(Args ¤t_command_args, uint32_t index) override 1864 { 1865 // If we repeat this command, repeat it without any arguments so we can 1866 // show the next memory range 1867 return m_cmd_name.c_str(); 1868 } 1869 1870 lldb::addr_t m_prev_end_addr; 1871 }; 1872 1873 //------------------------------------------------------------------------- 1874 // CommandObjectMemory 1875 //------------------------------------------------------------------------- 1876 1877 CommandObjectMemory::CommandObjectMemory(CommandInterpreter &interpreter) 1878 : CommandObjectMultiword(interpreter, "memory", "Commands for operating on memory in the current target process.", 1879 "memory <subcommand> [<subcommand-options>]") 1880 { 1881 LoadSubCommand("find", CommandObjectSP(new CommandObjectMemoryFind(interpreter))); 1882 LoadSubCommand("read", CommandObjectSP(new CommandObjectMemoryRead(interpreter))); 1883 LoadSubCommand("write", CommandObjectSP(new CommandObjectMemoryWrite(interpreter))); 1884 LoadSubCommand("history", CommandObjectSP(new CommandObjectMemoryHistory(interpreter))); 1885 LoadSubCommand("region", CommandObjectSP(new CommandObjectMemoryRegion(interpreter))); 1886 } 1887 1888 CommandObjectMemory::~CommandObjectMemory() = default; 1889