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