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