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