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