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