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