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