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