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 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, 55 { 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 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 }; 62 63 class OptionGroupReadMemory : public OptionGroup 64 { 65 public: 66 OptionGroupReadMemory () : 67 m_num_per_line (1,1), 68 m_output_as_binary (false), 69 m_view_as_type(), 70 m_offset(0,0) 71 { 72 } 73 74 ~OptionGroupReadMemory() override = default; 75 76 uint32_t 77 GetNumDefinitions () override 78 { 79 return sizeof (g_option_table) / sizeof (OptionDefinition); 80 } 81 82 const OptionDefinition* 83 GetDefinitions () override 84 { 85 return g_option_table; 86 } 87 88 Error 89 SetOptionValue (CommandInterpreter &interpreter, 90 uint32_t option_idx, 91 const char *option_arg) override 92 { 93 Error error; 94 const int short_option = g_option_table[option_idx].short_option; 95 96 switch (short_option) 97 { 98 case 'l': 99 error = m_num_per_line.SetValueFromString (option_arg); 100 if (m_num_per_line.GetCurrentValue() == 0) 101 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg); 102 break; 103 104 case 'b': 105 m_output_as_binary = true; 106 break; 107 108 case 't': 109 error = m_view_as_type.SetValueFromString (option_arg); 110 break; 111 112 case 'r': 113 m_force = true; 114 break; 115 116 case 'E': 117 error = m_offset.SetValueFromString(option_arg); 118 break; 119 120 default: 121 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 122 break; 123 } 124 return error; 125 } 126 127 void 128 OptionParsingStarting (CommandInterpreter &interpreter) override 129 { 130 m_num_per_line.Clear(); 131 m_output_as_binary = false; 132 m_view_as_type.Clear(); 133 m_force = false; 134 m_offset.Clear(); 135 } 136 137 Error 138 FinalizeSettings (Target *target, OptionGroupFormat& format_options) 139 { 140 Error error; 141 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue(); 142 OptionValueUInt64 &count_value = format_options.GetCountValue(); 143 const bool byte_size_option_set = byte_size_value.OptionWasSet(); 144 const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); 145 const bool count_option_set = format_options.GetCountValue().OptionWasSet(); 146 147 switch (format_options.GetFormat()) 148 { 149 default: 150 break; 151 152 case eFormatBoolean: 153 if (!byte_size_option_set) 154 byte_size_value = 1; 155 if (!num_per_line_option_set) 156 m_num_per_line = 1; 157 if (!count_option_set) 158 format_options.GetCountValue() = 8; 159 break; 160 161 case eFormatCString: 162 break; 163 164 case eFormatInstruction: 165 if (count_option_set) 166 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize(); 167 m_num_per_line = 1; 168 break; 169 170 case eFormatAddressInfo: 171 if (!byte_size_option_set) 172 byte_size_value = target->GetArchitecture().GetAddressByteSize(); 173 m_num_per_line = 1; 174 if (!count_option_set) 175 format_options.GetCountValue() = 8; 176 break; 177 178 case eFormatPointer: 179 byte_size_value = target->GetArchitecture().GetAddressByteSize(); 180 if (!num_per_line_option_set) 181 m_num_per_line = 4; 182 if (!count_option_set) 183 format_options.GetCountValue() = 8; 184 break; 185 186 case eFormatBinary: 187 case eFormatFloat: 188 case eFormatOctal: 189 case eFormatDecimal: 190 case eFormatEnum: 191 case eFormatUnicode16: 192 case eFormatUnicode32: 193 case eFormatUnsigned: 194 case eFormatHexFloat: 195 if (!byte_size_option_set) 196 byte_size_value = 4; 197 if (!num_per_line_option_set) 198 m_num_per_line = 1; 199 if (!count_option_set) 200 format_options.GetCountValue() = 8; 201 break; 202 203 case eFormatBytes: 204 case eFormatBytesWithASCII: 205 if (byte_size_option_set) 206 { 207 if (byte_size_value > 1) 208 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n" 209 "\tconsider using a different display format or don't specify the byte size", 210 byte_size_value.GetCurrentValue()); 211 } 212 else 213 byte_size_value = 1; 214 if (!num_per_line_option_set) 215 m_num_per_line = 16; 216 if (!count_option_set) 217 format_options.GetCountValue() = 32; 218 break; 219 220 case eFormatCharArray: 221 case eFormatChar: 222 case eFormatCharPrintable: 223 if (!byte_size_option_set) 224 byte_size_value = 1; 225 if (!num_per_line_option_set) 226 m_num_per_line = 32; 227 if (!count_option_set) 228 format_options.GetCountValue() = 64; 229 break; 230 231 case eFormatComplex: 232 if (!byte_size_option_set) 233 byte_size_value = 8; 234 if (!num_per_line_option_set) 235 m_num_per_line = 1; 236 if (!count_option_set) 237 format_options.GetCountValue() = 8; 238 break; 239 240 case eFormatComplexInteger: 241 if (!byte_size_option_set) 242 byte_size_value = 8; 243 if (!num_per_line_option_set) 244 m_num_per_line = 1; 245 if (!count_option_set) 246 format_options.GetCountValue() = 8; 247 break; 248 249 case eFormatHex: 250 if (!byte_size_option_set) 251 byte_size_value = 4; 252 if (!num_per_line_option_set) 253 { 254 switch (byte_size_value) 255 { 256 case 1: 257 case 2: 258 m_num_per_line = 8; 259 break; 260 case 4: 261 m_num_per_line = 4; 262 break; 263 case 8: 264 m_num_per_line = 2; 265 break; 266 default: 267 m_num_per_line = 1; 268 break; 269 } 270 } 271 if (!count_option_set) 272 count_value = 8; 273 break; 274 275 case eFormatVectorOfChar: 276 case eFormatVectorOfSInt8: 277 case eFormatVectorOfUInt8: 278 case eFormatVectorOfSInt16: 279 case eFormatVectorOfUInt16: 280 case eFormatVectorOfSInt32: 281 case eFormatVectorOfUInt32: 282 case eFormatVectorOfSInt64: 283 case eFormatVectorOfUInt64: 284 case eFormatVectorOfFloat16: 285 case eFormatVectorOfFloat32: 286 case eFormatVectorOfFloat64: 287 case eFormatVectorOfUInt128: 288 if (!byte_size_option_set) 289 byte_size_value = 128; 290 if (!num_per_line_option_set) 291 m_num_per_line = 1; 292 if (!count_option_set) 293 count_value = 4; 294 break; 295 } 296 return error; 297 } 298 299 bool 300 AnyOptionWasSet () const 301 { 302 return m_num_per_line.OptionWasSet() || 303 m_output_as_binary || 304 m_view_as_type.OptionWasSet() || 305 m_offset.OptionWasSet(); 306 } 307 308 OptionValueUInt64 m_num_per_line; 309 bool m_output_as_binary; 310 OptionValueString m_view_as_type; 311 bool m_force; 312 OptionValueUInt64 m_offset; 313 }; 314 315 //---------------------------------------------------------------------- 316 // Read memory from the inferior process 317 //---------------------------------------------------------------------- 318 class CommandObjectMemoryRead : public CommandObjectParsed 319 { 320 public: 321 CommandObjectMemoryRead (CommandInterpreter &interpreter) : 322 CommandObjectParsed(interpreter, 323 "memory read", 324 "Read from the memory of the process being debugged.", 325 nullptr, 326 eCommandRequiresTarget | eCommandProcessMustBePaused), 327 m_option_group (interpreter), 328 m_format_options (eFormatBytesWithASCII, 1, 8), 329 m_memory_options (), 330 m_outfile_options (), 331 m_varobj_options(), 332 m_next_addr(LLDB_INVALID_ADDRESS), 333 m_prev_byte_size(0), 334 m_prev_format_options (eFormatBytesWithASCII, 1, 8), 335 m_prev_memory_options (), 336 m_prev_outfile_options (), 337 m_prev_varobj_options() 338 { 339 CommandArgumentEntry arg1; 340 CommandArgumentEntry arg2; 341 CommandArgumentData start_addr_arg; 342 CommandArgumentData end_addr_arg; 343 344 // Define the first (and only) variant of this arg. 345 start_addr_arg.arg_type = eArgTypeAddressOrExpression; 346 start_addr_arg.arg_repetition = eArgRepeatPlain; 347 348 // There is only one variant this argument could be; put it into the argument entry. 349 arg1.push_back (start_addr_arg); 350 351 // Define the first (and only) variant of this arg. 352 end_addr_arg.arg_type = eArgTypeAddressOrExpression; 353 end_addr_arg.arg_repetition = eArgRepeatOptional; 354 355 // There is only one variant this argument could be; put it into the argument entry. 356 arg2.push_back (end_addr_arg); 357 358 // Push the data for the first argument into the m_arguments vector. 359 m_arguments.push_back (arg1); 360 m_arguments.push_back (arg2); 361 362 // Add the "--format" and "--count" options to group 1 and 3 363 m_option_group.Append (&m_format_options, 364 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT, 365 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 366 m_option_group.Append (&m_format_options, 367 OptionGroupFormat::OPTION_GROUP_GDB_FMT, 368 LLDB_OPT_SET_1 | LLDB_OPT_SET_3); 369 // Add the "--size" option to group 1 and 2 370 m_option_group.Append (&m_format_options, 371 OptionGroupFormat::OPTION_GROUP_SIZE, 372 LLDB_OPT_SET_1 | LLDB_OPT_SET_2); 373 m_option_group.Append (&m_memory_options); 374 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 375 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); 376 m_option_group.Finalize(); 377 } 378 379 ~CommandObjectMemoryRead() override = default; 380 381 Options * 382 GetOptions () override 383 { 384 return &m_option_group; 385 } 386 387 const char * 388 GetRepeatCommand (Args ¤t_command_args, uint32_t index) override 389 { 390 return m_cmd_name.c_str(); 391 } 392 393 protected: 394 bool 395 DoExecute (Args& command, CommandReturnObject &result) override 396 { 397 // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid 398 Target *target = m_exe_ctx.GetTargetPtr(); 399 400 const size_t argc = command.GetArgumentCount(); 401 402 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) 403 { 404 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str()); 405 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n"); 406 result.SetStatus(eReturnStatusFailed); 407 return false; 408 } 409 410 CompilerType clang_ast_type; 411 Error error; 412 413 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); 414 if (view_as_type_cstr && view_as_type_cstr[0]) 415 { 416 // We are viewing memory as a type 417 418 SymbolContext sc; 419 const bool exact_match = false; 420 TypeList type_list; 421 uint32_t reference_count = 0; 422 uint32_t pointer_count = 0; 423 size_t idx; 424 425 #define ALL_KEYWORDS \ 426 KEYWORD("const") \ 427 KEYWORD("volatile") \ 428 KEYWORD("restrict") \ 429 KEYWORD("struct") \ 430 KEYWORD("class") \ 431 KEYWORD("union") 432 433 #define KEYWORD(s) s, 434 static const char *g_keywords[] = 435 { 436 ALL_KEYWORDS 437 }; 438 #undef KEYWORD 439 440 #define KEYWORD(s) (sizeof(s) - 1), 441 static const int g_keyword_lengths[] = 442 { 443 ALL_KEYWORDS 444 }; 445 #undef KEYWORD 446 447 #undef ALL_KEYWORDS 448 449 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *); 450 std::string type_str(view_as_type_cstr); 451 452 // Remove all instances of g_keywords that are followed by spaces 453 for (size_t i = 0; i < g_num_keywords; ++i) 454 { 455 const char *keyword = g_keywords[i]; 456 int keyword_len = g_keyword_lengths[i]; 457 458 idx = 0; 459 while ((idx = type_str.find (keyword, idx)) != std::string::npos) 460 { 461 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') 462 { 463 type_str.erase(idx, keyword_len+1); 464 idx = 0; 465 } 466 else 467 { 468 idx += keyword_len; 469 } 470 } 471 } 472 bool done = type_str.empty(); 473 // 474 idx = type_str.find_first_not_of (" \t"); 475 if (idx > 0 && idx != std::string::npos) 476 type_str.erase (0, idx); 477 while (!done) 478 { 479 // Strip trailing spaces 480 if (type_str.empty()) 481 done = true; 482 else 483 { 484 switch (type_str[type_str.size()-1]) 485 { 486 case '*': 487 ++pointer_count; 488 LLVM_FALLTHROUGH; 489 case ' ': 490 case '\t': 491 type_str.erase(type_str.size()-1); 492 break; 493 494 case '&': 495 if (reference_count == 0) 496 { 497 reference_count = 1; 498 type_str.erase(type_str.size()-1); 499 } 500 else 501 { 502 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); 503 result.SetStatus(eReturnStatusFailed); 504 return false; 505 } 506 break; 507 508 default: 509 done = true; 510 break; 511 } 512 } 513 } 514 515 llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; 516 ConstString lookup_type_name(type_str.c_str()); 517 StackFrame *frame = m_exe_ctx.GetFramePtr(); 518 if (frame) 519 { 520 sc = frame->GetSymbolContext (eSymbolContextModule); 521 if (sc.module_sp) 522 { 523 sc.module_sp->FindTypes (sc, 524 lookup_type_name, 525 exact_match, 526 1, 527 searched_symbol_files, 528 type_list); 529 } 530 } 531 if (type_list.GetSize() == 0) 532 { 533 target->GetImages().FindTypes (sc, 534 lookup_type_name, 535 exact_match, 536 1, 537 searched_symbol_files, 538 type_list); 539 } 540 541 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$') 542 { 543 if (ClangPersistentVariables *persistent_vars = llvm::dyn_cast_or_null<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))) 544 { 545 clang::TypeDecl *tdecl = llvm::dyn_cast_or_null<clang::TypeDecl>(persistent_vars->GetPersistentDecl(ConstString(lookup_type_name))); 546 547 if (tdecl) 548 { 549 clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()), 550 reinterpret_cast<lldb::opaque_compiler_type_t>(const_cast<clang::Type*>(tdecl->getTypeForDecl()))); 551 } 552 } 553 } 554 555 if (!clang_ast_type.IsValid()) 556 { 557 if (type_list.GetSize() == 0) 558 { 559 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", 560 lookup_type_name.GetCString(), 561 view_as_type_cstr); 562 result.SetStatus(eReturnStatusFailed); 563 return false; 564 } 565 else 566 { 567 TypeSP type_sp (type_list.GetTypeAtIndex(0)); 568 clang_ast_type = type_sp->GetFullCompilerType (); 569 } 570 } 571 572 while (pointer_count > 0) 573 { 574 CompilerType pointer_type = clang_ast_type.GetPointerType(); 575 if (pointer_type.IsValid()) 576 clang_ast_type = pointer_type; 577 else 578 { 579 result.AppendError ("unable make a pointer type\n"); 580 result.SetStatus(eReturnStatusFailed); 581 return false; 582 } 583 --pointer_count; 584 } 585 586 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr); 587 588 if (m_format_options.GetByteSizeValue() == 0) 589 { 590 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 591 view_as_type_cstr); 592 result.SetStatus(eReturnStatusFailed); 593 return false; 594 } 595 596 if (!m_format_options.GetCountValue().OptionWasSet()) 597 m_format_options.GetCountValue() = 1; 598 } 599 else 600 { 601 error = m_memory_options.FinalizeSettings (target, m_format_options); 602 } 603 604 // Look for invalid combinations of settings 605 if (error.Fail()) 606 { 607 result.AppendError(error.AsCString()); 608 result.SetStatus(eReturnStatusFailed); 609 return false; 610 } 611 612 lldb::addr_t addr; 613 size_t total_byte_size = 0; 614 if (argc == 0) 615 { 616 // Use the last address and byte size and all options as they were 617 // if no options have been set 618 addr = m_next_addr; 619 total_byte_size = m_prev_byte_size; 620 clang_ast_type = m_prev_clang_ast_type; 621 if (!m_format_options.AnyOptionWasSet() && 622 !m_memory_options.AnyOptionWasSet() && 623 !m_outfile_options.AnyOptionWasSet() && 624 !m_varobj_options.AnyOptionWasSet()) 625 { 626 m_format_options = m_prev_format_options; 627 m_memory_options = m_prev_memory_options; 628 m_outfile_options = m_prev_outfile_options; 629 m_varobj_options = m_prev_varobj_options; 630 } 631 } 632 633 size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); 634 635 // TODO For non-8-bit byte addressable architectures this needs to be 636 // revisited to fully support all lldb's range of formatting options. 637 // Furthermore code memory reads (for those architectures) will not 638 // be correctly formatted even w/o formatting options. 639 size_t item_byte_size = 640 target->GetArchitecture().GetDataByteSize() > 1 ? 641 target->GetArchitecture().GetDataByteSize() : 642 m_format_options.GetByteSizeValue().GetCurrentValue(); 643 644 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); 645 646 if (total_byte_size == 0) 647 { 648 total_byte_size = item_count * item_byte_size; 649 if (total_byte_size == 0) 650 total_byte_size = 32; 651 } 652 653 if (argc > 0) 654 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error); 655 656 if (addr == LLDB_INVALID_ADDRESS) 657 { 658 result.AppendError("invalid start address expression."); 659 result.AppendError(error.AsCString()); 660 result.SetStatus(eReturnStatusFailed); 661 return false; 662 } 663 664 if (argc == 2) 665 { 666 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), 667 LLDB_INVALID_ADDRESS, nullptr); 668 if (end_addr == LLDB_INVALID_ADDRESS) 669 { 670 result.AppendError("invalid end address expression."); 671 result.AppendError(error.AsCString()); 672 result.SetStatus(eReturnStatusFailed); 673 return false; 674 } 675 else if (end_addr <= addr) 676 { 677 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr); 678 result.SetStatus(eReturnStatusFailed); 679 return false; 680 } 681 else if (m_format_options.GetCountValue().OptionWasSet()) 682 { 683 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count); 684 result.SetStatus(eReturnStatusFailed); 685 return false; 686 } 687 688 total_byte_size = end_addr - addr; 689 item_count = total_byte_size / item_byte_size; 690 } 691 692 uint32_t max_unforced_size = target->GetMaximumMemReadSize(); 693 694 if (total_byte_size > max_unforced_size && !m_memory_options.m_force) 695 { 696 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size); 697 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n"); 698 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n"); 699 return false; 700 } 701 702 DataBufferSP data_sp; 703 size_t bytes_read = 0; 704 if (clang_ast_type.GetOpaqueQualType()) 705 { 706 // Make sure we don't display our type as ASCII bytes like the default memory read 707 if (!m_format_options.GetFormatValue().OptionWasSet()) 708 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); 709 710 bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue(); 711 712 if (argc > 0) 713 addr = addr + (clang_ast_type.GetByteSize(nullptr) * m_memory_options.m_offset.GetCurrentValue()); 714 } 715 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) 716 { 717 data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); 718 if (data_sp->GetBytes() == nullptr) 719 { 720 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size); 721 result.SetStatus(eReturnStatusFailed); 722 return false; 723 } 724 725 Address address(addr, nullptr); 726 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); 727 if (bytes_read == 0) 728 { 729 const char *error_cstr = error.AsCString(); 730 if (error_cstr && error_cstr[0]) 731 { 732 result.AppendError(error_cstr); 733 } 734 else 735 { 736 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 737 } 738 result.SetStatus(eReturnStatusFailed); 739 return false; 740 } 741 742 if (bytes_read < total_byte_size) 743 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); 744 } 745 else 746 { 747 // we treat c-strings as a special case because they do not have a fixed size 748 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat()) 749 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); 750 else 751 item_byte_size = target->GetMaximumSizeOfStringSummary(); 752 if (!m_format_options.GetCountValue().OptionWasSet()) 753 item_count = 1; 754 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary 755 if (data_sp->GetBytes() == nullptr) 756 { 757 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)); 758 result.SetStatus(eReturnStatusFailed); 759 return false; 760 } 761 uint8_t *data_ptr = data_sp->GetBytes(); 762 auto data_addr = addr; 763 auto count = item_count; 764 item_count = 0; 765 bool break_on_no_NULL = false; 766 while (item_count < count) 767 { 768 std::string buffer; 769 buffer.resize(item_byte_size+1,0); 770 Error error; 771 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error); 772 if (error.Fail()) 773 { 774 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 775 result.SetStatus(eReturnStatusFailed); 776 return false; 777 } 778 779 if (item_byte_size == read) 780 { 781 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr); 782 --read; 783 break_on_no_NULL = true; 784 } 785 else 786 ++read; // account for final NULL byte 787 788 memcpy(data_ptr, &buffer[0], read); 789 data_ptr += read; 790 data_addr += read; 791 bytes_read += read; 792 item_count++; // if we break early we know we only read item_count strings 793 794 if (break_on_no_NULL) 795 break; 796 } 797 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1)); 798 } 799 800 m_next_addr = addr + bytes_read; 801 m_prev_byte_size = bytes_read; 802 m_prev_format_options = m_format_options; 803 m_prev_memory_options = m_memory_options; 804 m_prev_outfile_options = m_outfile_options; 805 m_prev_varobj_options = m_varobj_options; 806 m_prev_clang_ast_type = clang_ast_type; 807 808 StreamFile outfile_stream; 809 Stream *output_stream = nullptr; 810 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 811 if (outfile_spec) 812 { 813 char path[PATH_MAX]; 814 outfile_spec.GetPath (path, sizeof(path)); 815 816 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 817 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 818 if (append) 819 open_options |= File::eOpenOptionAppend; 820 821 if (outfile_stream.GetFile ().Open (path, open_options).Success()) 822 { 823 if (m_memory_options.m_output_as_binary) 824 { 825 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 826 if (bytes_written > 0) 827 { 828 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n", 829 bytes_written, 830 append ? "appended" : "written", 831 path); 832 return true; 833 } 834 else 835 { 836 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path); 837 result.SetStatus(eReturnStatusFailed); 838 return false; 839 } 840 } 841 else 842 { 843 // We are going to write ASCII to the file just point the 844 // output_stream to our outfile_stream... 845 output_stream = &outfile_stream; 846 } 847 } 848 else 849 { 850 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); 851 result.SetStatus(eReturnStatusFailed); 852 return false; 853 } 854 } 855 else 856 { 857 output_stream = &result.GetOutputStream(); 858 } 859 860 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); 861 if (clang_ast_type.GetOpaqueQualType()) 862 { 863 for (uint32_t i = 0; i<item_count; ++i) 864 { 865 addr_t item_addr = addr + (i * item_byte_size); 866 Address address (item_addr); 867 StreamString name_strm; 868 name_strm.Printf ("0x%" PRIx64, item_addr); 869 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 870 name_strm.GetString().c_str(), 871 address, 872 clang_ast_type)); 873 if (valobj_sp) 874 { 875 Format format = m_format_options.GetFormat(); 876 if (format != eFormatDefault) 877 valobj_sp->SetFormat (format); 878 879 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format)); 880 881 valobj_sp->Dump(*output_stream,options); 882 } 883 else 884 { 885 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 886 view_as_type_cstr, 887 name_strm.GetString().c_str()); 888 result.SetStatus(eReturnStatusFailed); 889 return false; 890 } 891 } 892 return true; 893 } 894 895 result.SetStatus(eReturnStatusSuccessFinishResult); 896 DataExtractor data (data_sp, 897 target->GetArchitecture().GetByteOrder(), 898 target->GetArchitecture().GetAddressByteSize(), 899 target->GetArchitecture().GetDataByteSize()); 900 901 Format format = m_format_options.GetFormat(); 902 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) 903 && (item_byte_size != 1)) 904 { 905 // if a count was not passed, or it is 1 906 if (!m_format_options.GetCountValue().OptionWasSet() || item_count == 1) 907 { 908 // this turns requests such as 909 // memory read -fc -s10 -c1 *charPtrPtr 910 // which make no sense (what is a char of size 10?) 911 // into a request for fetching 10 chars of size 1 from the same memory location 912 format = eFormatCharArray; 913 item_count = item_byte_size; 914 item_byte_size = 1; 915 } 916 else 917 { 918 // here we passed a count, and it was not 1 919 // so we have a byte_size and a count 920 // we could well multiply those, but instead let's just fail 921 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size); 922 result.SetStatus(eReturnStatusFailed); 923 return false; 924 } 925 } 926 927 assert (output_stream); 928 size_t bytes_dumped = data.Dump (output_stream, 929 0, 930 format, 931 item_byte_size, 932 item_count, 933 num_per_line / target->GetArchitecture().GetDataByteSize(), 934 addr, 935 0, 936 0, 937 exe_scope); 938 m_next_addr = addr + bytes_dumped; 939 output_stream->EOL(); 940 return true; 941 } 942 943 OptionGroupOptions m_option_group; 944 OptionGroupFormat m_format_options; 945 OptionGroupReadMemory m_memory_options; 946 OptionGroupOutputFile m_outfile_options; 947 OptionGroupValueObjectDisplay m_varobj_options; 948 lldb::addr_t m_next_addr; 949 lldb::addr_t m_prev_byte_size; 950 OptionGroupFormat m_prev_format_options; 951 OptionGroupReadMemory m_prev_memory_options; 952 OptionGroupOutputFile m_prev_outfile_options; 953 OptionGroupValueObjectDisplay m_prev_varobj_options; 954 CompilerType m_prev_clang_ast_type; 955 }; 956 957 OptionDefinition 958 g_memory_find_option_table[] = 959 { 960 { LLDB_OPT_SET_1, true, "expression", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."}, 961 { LLDB_OPT_SET_2, true, "string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Use text to find a byte pattern."}, 962 { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many times to perform the search."}, 963 { 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."}, 964 }; 965 966 //---------------------------------------------------------------------- 967 // Find the specified data in memory 968 //---------------------------------------------------------------------- 969 class CommandObjectMemoryFind : public CommandObjectParsed 970 { 971 public: 972 class OptionGroupFindMemory : public OptionGroup 973 { 974 public: 975 OptionGroupFindMemory () : 976 OptionGroup(), 977 m_count(1), 978 m_offset(0) 979 { 980 } 981 982 ~OptionGroupFindMemory() override = default; 983 984 uint32_t 985 GetNumDefinitions () override 986 { 987 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition); 988 } 989 990 const OptionDefinition* 991 GetDefinitions () override 992 { 993 return g_memory_find_option_table; 994 } 995 996 Error 997 SetOptionValue (CommandInterpreter &interpreter, 998 uint32_t option_idx, 999 const char *option_arg) override 1000 { 1001 Error error; 1002 const int short_option = g_memory_find_option_table[option_idx].short_option; 1003 1004 switch (short_option) 1005 { 1006 case 'e': 1007 m_expr.SetValueFromString(option_arg); 1008 break; 1009 1010 case 's': 1011 m_string.SetValueFromString(option_arg); 1012 break; 1013 1014 case 'c': 1015 if (m_count.SetValueFromString(option_arg).Fail()) 1016 error.SetErrorString("unrecognized value for count"); 1017 break; 1018 1019 case 'o': 1020 if (m_offset.SetValueFromString(option_arg).Fail()) 1021 error.SetErrorString("unrecognized value for dump-offset"); 1022 break; 1023 1024 default: 1025 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 1026 break; 1027 } 1028 return error; 1029 } 1030 1031 void 1032 OptionParsingStarting (CommandInterpreter &interpreter) override 1033 { 1034 m_expr.Clear(); 1035 m_string.Clear(); 1036 m_count.Clear(); 1037 } 1038 1039 OptionValueString m_expr; 1040 OptionValueString m_string; 1041 OptionValueUInt64 m_count; 1042 OptionValueUInt64 m_offset; 1043 }; 1044 1045 CommandObjectMemoryFind (CommandInterpreter &interpreter) : 1046 CommandObjectParsed(interpreter, 1047 "memory find", 1048 "Find a value in the memory of the process being debugged.", 1049 nullptr, 1050 eCommandRequiresProcess | eCommandProcessMustBeLaunched), 1051 m_option_group (interpreter), 1052 m_memory_options () 1053 { 1054 CommandArgumentEntry arg1; 1055 CommandArgumentEntry arg2; 1056 CommandArgumentData addr_arg; 1057 CommandArgumentData value_arg; 1058 1059 // Define the first (and only) variant of this arg. 1060 addr_arg.arg_type = eArgTypeAddressOrExpression; 1061 addr_arg.arg_repetition = eArgRepeatPlain; 1062 1063 // There is only one variant this argument could be; put it into the argument entry. 1064 arg1.push_back (addr_arg); 1065 1066 // Define the first (and only) variant of this arg. 1067 value_arg.arg_type = eArgTypeAddressOrExpression; 1068 value_arg.arg_repetition = eArgRepeatPlain; 1069 1070 // There is only one variant this argument could be; put it into the argument entry. 1071 arg2.push_back (value_arg); 1072 1073 // Push the data for the first argument into the m_arguments vector. 1074 m_arguments.push_back (arg1); 1075 m_arguments.push_back (arg2); 1076 1077 m_option_group.Append (&m_memory_options); 1078 m_option_group.Finalize(); 1079 } 1080 1081 ~CommandObjectMemoryFind() override = default; 1082 1083 Options * 1084 GetOptions () override 1085 { 1086 return &m_option_group; 1087 } 1088 1089 protected: 1090 bool 1091 DoExecute (Args& command, CommandReturnObject &result) override 1092 { 1093 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid 1094 Process *process = m_exe_ctx.GetProcessPtr(); 1095 1096 const size_t argc = command.GetArgumentCount(); 1097 1098 if (argc != 2) 1099 { 1100 result.AppendError("two addresses needed for memory find"); 1101 return false; 1102 } 1103 1104 Error error; 1105 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error); 1106 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) 1107 { 1108 result.AppendError("invalid low address"); 1109 return false; 1110 } 1111 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error); 1112 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) 1113 { 1114 result.AppendError("invalid high address"); 1115 return false; 1116 } 1117 1118 if (high_addr <= low_addr) 1119 { 1120 result.AppendError("starting address must be smaller than ending address"); 1121 return false; 1122 } 1123 1124 lldb::addr_t found_location = LLDB_INVALID_ADDRESS; 1125 1126 DataBufferHeap buffer; 1127 1128 if (m_memory_options.m_string.OptionWasSet()) 1129 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue())); 1130 else if (m_memory_options.m_expr.OptionWasSet()) 1131 { 1132 StackFrame* frame = m_exe_ctx.GetFramePtr(); 1133 ValueObjectSP result_sp; 1134 if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) && 1135 result_sp) 1136 { 1137 uint64_t value = result_sp->GetValueAsUnsigned(0); 1138 switch (result_sp->GetCompilerType().GetByteSize(nullptr)) 1139 { 1140 case 1: { 1141 uint8_t byte = (uint8_t)value; 1142 buffer.CopyData(&byte,1); 1143 } 1144 break; 1145 case 2: { 1146 uint16_t word = (uint16_t)value; 1147 buffer.CopyData(&word,2); 1148 } 1149 break; 1150 case 4: { 1151 uint32_t lword = (uint32_t)value; 1152 buffer.CopyData(&lword,4); 1153 } 1154 break; 1155 case 8: { 1156 buffer.CopyData(&value, 8); 1157 } 1158 break; 1159 case 3: 1160 case 5: 1161 case 6: 1162 case 7: 1163 result.AppendError("unknown type. pass a string instead"); 1164 return false; 1165 default: 1166 result.AppendError("result size larger than 8 bytes. pass a string instead"); 1167 return false; 1168 } 1169 } 1170 else 1171 { 1172 result.AppendError("expression evaluation failed. pass a string instead"); 1173 return false; 1174 } 1175 } 1176 else 1177 { 1178 result.AppendError("please pass either a block of text, or an expression to evaluate."); 1179 return false; 1180 } 1181 1182 size_t count = m_memory_options.m_count.GetCurrentValue(); 1183 found_location = low_addr; 1184 bool ever_found = false; 1185 while (count) 1186 { 1187 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize()); 1188 if (found_location == LLDB_INVALID_ADDRESS) 1189 { 1190 if (!ever_found) 1191 { 1192 result.AppendMessage("data not found within the range.\n"); 1193 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 1194 } 1195 else 1196 result.AppendMessage("no more matches within the range.\n"); 1197 break; 1198 } 1199 result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location); 1200 1201 DataBufferHeap dumpbuffer(32,0); 1202 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error); 1203 if (!error.Fail()) 1204 { 1205 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize()); 1206 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0); 1207 result.GetOutputStream().EOL(); 1208 } 1209 1210 --count; 1211 found_location++; 1212 ever_found = true; 1213 } 1214 1215 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 1216 return true; 1217 } 1218 1219 lldb::addr_t 1220 Search (lldb::addr_t low, 1221 lldb::addr_t high, 1222 uint8_t* buffer, 1223 size_t buffer_size) 1224 { 1225 Process *process = m_exe_ctx.GetProcessPtr(); 1226 DataBufferHeap heap(buffer_size, 0); 1227 for (auto ptr = low; 1228 ptr < high; 1229 ptr++) 1230 { 1231 Error error; 1232 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error); 1233 if (error.Fail()) 1234 return LLDB_INVALID_ADDRESS; 1235 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0) 1236 return ptr; 1237 } 1238 return LLDB_INVALID_ADDRESS; 1239 } 1240 1241 OptionGroupOptions m_option_group; 1242 OptionGroupFindMemory m_memory_options; 1243 }; 1244 1245 OptionDefinition 1246 g_memory_write_option_table[] = 1247 { 1248 { LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 1249 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."}, 1250 }; 1251 1252 //---------------------------------------------------------------------- 1253 // Write memory to the inferior process 1254 //---------------------------------------------------------------------- 1255 class CommandObjectMemoryWrite : public CommandObjectParsed 1256 { 1257 public: 1258 class OptionGroupWriteMemory : public OptionGroup 1259 { 1260 public: 1261 OptionGroupWriteMemory () : 1262 OptionGroup() 1263 { 1264 } 1265 1266 ~OptionGroupWriteMemory() override = default; 1267 1268 uint32_t 1269 GetNumDefinitions () override 1270 { 1271 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); 1272 } 1273 1274 const OptionDefinition* 1275 GetDefinitions () override 1276 { 1277 return g_memory_write_option_table; 1278 } 1279 1280 Error 1281 SetOptionValue (CommandInterpreter &interpreter, 1282 uint32_t option_idx, 1283 const char *option_arg) override 1284 { 1285 Error error; 1286 const int short_option = g_memory_write_option_table[option_idx].short_option; 1287 1288 switch (short_option) 1289 { 1290 case 'i': 1291 m_infile.SetFile (option_arg, true); 1292 if (!m_infile.Exists()) 1293 { 1294 m_infile.Clear(); 1295 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); 1296 } 1297 break; 1298 1299 case 'o': 1300 { 1301 bool success; 1302 m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success); 1303 if (!success) 1304 { 1305 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); 1306 } 1307 } 1308 break; 1309 1310 default: 1311 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 1312 break; 1313 } 1314 return error; 1315 } 1316 1317 void 1318 OptionParsingStarting (CommandInterpreter &interpreter) override 1319 { 1320 m_infile.Clear(); 1321 m_infile_offset = 0; 1322 } 1323 1324 FileSpec m_infile; 1325 off_t m_infile_offset; 1326 }; 1327 1328 CommandObjectMemoryWrite (CommandInterpreter &interpreter) : 1329 CommandObjectParsed(interpreter, 1330 "memory write", 1331 "Write to the memory of the process being debugged.", 1332 nullptr, 1333 eCommandRequiresProcess | eCommandProcessMustBeLaunched), 1334 m_option_group (interpreter), 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(interpreter, 1692 "memory history", 1693 "Prints out the recorded stack traces for allocation/deallocation of a memory address.", 1694 nullptr, 1695 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | 1696 eCommandProcessMustBeLaunched) 1697 { 1698 CommandArgumentEntry arg1; 1699 CommandArgumentData addr_arg; 1700 1701 // Define the first (and only) variant of this arg. 1702 addr_arg.arg_type = eArgTypeAddress; 1703 addr_arg.arg_repetition = eArgRepeatPlain; 1704 1705 // There is only one variant this argument could be; put it into the argument entry. 1706 arg1.push_back (addr_arg); 1707 1708 // Push the data for the first argument into the m_arguments vector. 1709 m_arguments.push_back (arg1); 1710 } 1711 1712 ~CommandObjectMemoryHistory() override = default; 1713 1714 const char * 1715 GetRepeatCommand (Args ¤t_command_args, uint32_t index) override 1716 { 1717 return m_cmd_name.c_str(); 1718 } 1719 1720 protected: 1721 bool 1722 DoExecute (Args& command, CommandReturnObject &result) override 1723 { 1724 const size_t argc = command.GetArgumentCount(); 1725 1726 if (argc == 0 || argc > 1) 1727 { 1728 result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str()); 1729 result.SetStatus(eReturnStatusFailed); 1730 return false; 1731 } 1732 1733 Error error; 1734 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, 1735 command.GetArgumentAtIndex(0), 1736 LLDB_INVALID_ADDRESS, 1737 &error); 1738 1739 if (addr == LLDB_INVALID_ADDRESS) 1740 { 1741 result.AppendError("invalid address expression"); 1742 result.AppendError(error.AsCString()); 1743 result.SetStatus(eReturnStatusFailed); 1744 return false; 1745 } 1746 1747 Stream *output_stream = &result.GetOutputStream(); 1748 1749 const ProcessSP &process_sp = m_exe_ctx.GetProcessSP(); 1750 const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp); 1751 1752 if (!memory_history) 1753 { 1754 result.AppendError("no available memory history provider"); 1755 result.SetStatus(eReturnStatusFailed); 1756 return false; 1757 } 1758 1759 HistoryThreads thread_list = memory_history->GetHistoryThreads(addr); 1760 1761 for (auto thread : thread_list) { 1762 thread->GetStatus(*output_stream, 0, UINT32_MAX, 0); 1763 } 1764 1765 result.SetStatus(eReturnStatusSuccessFinishResult); 1766 1767 return true; 1768 } 1769 }; 1770 1771 //------------------------------------------------------------------------- 1772 // CommandObjectMemoryRegion 1773 //------------------------------------------------------------------------- 1774 #pragma mark CommandObjectMemoryRegion 1775 1776 class CommandObjectMemoryRegion : public CommandObjectParsed 1777 { 1778 public: 1779 CommandObjectMemoryRegion(CommandInterpreter &interpreter) 1780 : CommandObjectParsed(interpreter, "memory region", 1781 "Get information on a memory region that contains an address in the current process.", 1782 "memory region ADDR", 1783 eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched), 1784 m_prev_end_addr(LLDB_INVALID_ADDRESS) 1785 { 1786 } 1787 1788 ~CommandObjectMemoryRegion() override = default; 1789 1790 protected: 1791 bool 1792 DoExecute(Args &command, CommandReturnObject &result) override 1793 { 1794 ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1795 if (process_sp) 1796 { 1797 Error error; 1798 lldb::addr_t load_addr = m_prev_end_addr; 1799 m_prev_end_addr = LLDB_INVALID_ADDRESS; 1800 1801 const size_t argc = command.GetArgumentCount(); 1802 if (argc > 1 || (argc == 0 && load_addr == LLDB_INVALID_ADDRESS)) 1803 { 1804 result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n", m_cmd_name.c_str(), 1805 m_cmd_syntax.c_str()); 1806 result.SetStatus(eReturnStatusFailed); 1807 } 1808 else 1809 { 1810 const char *load_addr_cstr = command.GetArgumentAtIndex(0); 1811 if (command.GetArgumentCount() == 1) 1812 { 1813 load_addr = Args::StringToAddress(&m_exe_ctx, load_addr_cstr, LLDB_INVALID_ADDRESS, &error); 1814 if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) 1815 { 1816 result.AppendErrorWithFormat("invalid address argument \"%s\": %s\n", load_addr_cstr, 1817 error.AsCString()); 1818 result.SetStatus(eReturnStatusFailed); 1819 } 1820 } 1821 1822 lldb_private::MemoryRegionInfo range_info; 1823 error = process_sp->GetMemoryRegionInfo(load_addr, range_info); 1824 if (error.Success()) 1825 { 1826 lldb_private::Address addr; 1827 ConstString section_name; 1828 if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr)) 1829 { 1830 SectionSP section_sp(addr.GetSection()); 1831 if (section_sp) 1832 { 1833 // Got the top most section, not the deepest section 1834 while (section_sp->GetParent()) 1835 section_sp = section_sp->GetParent(); 1836 section_name = section_sp->GetName(); 1837 } 1838 } 1839 result.AppendMessageWithFormat( 1840 "[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s\n", range_info.GetRange().GetRangeBase(), 1841 range_info.GetRange().GetRangeEnd(), range_info.GetReadable() ? 'r' : '-', 1842 range_info.GetWritable() ? 'w' : '-', range_info.GetExecutable() ? 'x' : '-', 1843 section_name ? " " : "", section_name ? section_name.AsCString() : ""); 1844 m_prev_end_addr = range_info.GetRange().GetRangeEnd(); 1845 result.SetStatus(eReturnStatusSuccessFinishResult); 1846 } 1847 else 1848 { 1849 result.SetStatus(eReturnStatusFailed); 1850 result.AppendErrorWithFormat("%s\n", error.AsCString()); 1851 } 1852 } 1853 } 1854 else 1855 { 1856 m_prev_end_addr = LLDB_INVALID_ADDRESS; 1857 result.AppendError("invalid process"); 1858 result.SetStatus(eReturnStatusFailed); 1859 } 1860 return result.Succeeded(); 1861 } 1862 1863 const char * 1864 GetRepeatCommand(Args ¤t_command_args, uint32_t index) override 1865 { 1866 // If we repeat this command, repeat it without any arguments so we can 1867 // show the next memory range 1868 return m_cmd_name.c_str(); 1869 } 1870 1871 lldb::addr_t m_prev_end_addr; 1872 }; 1873 1874 //------------------------------------------------------------------------- 1875 // CommandObjectMemory 1876 //------------------------------------------------------------------------- 1877 1878 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : 1879 CommandObjectMultiword (interpreter, 1880 "memory", 1881 "A set of commands for operating on memory.", 1882 "memory <subcommand> [<subcommand-options>]") 1883 { 1884 LoadSubCommand("find", CommandObjectSP(new CommandObjectMemoryFind(interpreter))); 1885 LoadSubCommand("read", CommandObjectSP(new CommandObjectMemoryRead(interpreter))); 1886 LoadSubCommand("write", CommandObjectSP(new CommandObjectMemoryWrite(interpreter))); 1887 LoadSubCommand("history", CommandObjectSP(new CommandObjectMemoryHistory(interpreter))); 1888 LoadSubCommand("region", CommandObjectSP(new CommandObjectMemoryRegion(interpreter))); 1889 } 1890 1891 CommandObjectMemory::~CommandObjectMemory() = default; 1892