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