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