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