1 //===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CommandObjectMemory.h" 11 12 // C Includes 13 #include <inttypes.h> 14 15 // C++ Includes 16 // Other libraries and framework includes 17 #include "clang/AST/Decl.h" 18 // Project includes 19 #include "lldb/Core/DataBufferHeap.h" 20 #include "lldb/Core/DataExtractor.h" 21 #include "lldb/Core/Debugger.h" 22 #include "lldb/Core/Module.h" 23 #include "lldb/Core/StreamString.h" 24 #include "lldb/Core/ValueObjectMemory.h" 25 #include "lldb/DataFormatters/ValueObjectPrinter.h" 26 #include "lldb/Expression/ClangPersistentVariables.h" 27 #include "lldb/Host/StringConvert.h" 28 #include "lldb/Interpreter/Args.h" 29 #include "lldb/Interpreter/CommandReturnObject.h" 30 #include "lldb/Interpreter/CommandInterpreter.h" 31 #include "lldb/Interpreter/Options.h" 32 #include "lldb/Interpreter/OptionGroupFormat.h" 33 #include "lldb/Interpreter/OptionGroupOutputFile.h" 34 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" 35 #include "lldb/Interpreter/OptionValueString.h" 36 #include "lldb/Symbol/ClangASTContext.h" 37 #include "lldb/Symbol/TypeList.h" 38 #include "lldb/Target/MemoryHistory.h" 39 #include "lldb/Target/Process.h" 40 #include "lldb/Target/StackFrame.h" 41 #include "lldb/Target/Thread.h" 42 43 using namespace lldb; 44 using namespace lldb_private; 45 46 static OptionDefinition 47 g_option_table[] = 48 { 49 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, 50 { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."}, 51 { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, 52 { LLDB_OPT_SET_1| 53 LLDB_OPT_SET_2| 54 LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."}, 55 }; 56 57 58 59 class OptionGroupReadMemory : public OptionGroup 60 { 61 public: 62 63 OptionGroupReadMemory () : 64 m_num_per_line (1,1), 65 m_output_as_binary (false), 66 m_view_as_type() 67 { 68 } 69 70 virtual 71 ~OptionGroupReadMemory () 72 { 73 } 74 75 76 virtual uint32_t 77 GetNumDefinitions () 78 { 79 return sizeof (g_option_table) / sizeof (OptionDefinition); 80 } 81 82 virtual const OptionDefinition* 83 GetDefinitions () 84 { 85 return g_option_table; 86 } 87 88 virtual Error 89 SetOptionValue (CommandInterpreter &interpreter, 90 uint32_t option_idx, 91 const char *option_arg) 92 { 93 Error error; 94 const int short_option = g_option_table[option_idx].short_option; 95 96 switch (short_option) 97 { 98 case 'l': 99 error = m_num_per_line.SetValueFromString (option_arg); 100 if (m_num_per_line.GetCurrentValue() == 0) 101 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg); 102 break; 103 104 case 'b': 105 m_output_as_binary = true; 106 break; 107 108 case 't': 109 error = m_view_as_type.SetValueFromString (option_arg); 110 break; 111 112 case 'r': 113 m_force = true; 114 break; 115 116 default: 117 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 118 break; 119 } 120 return error; 121 } 122 123 virtual void 124 OptionParsingStarting (CommandInterpreter &interpreter) 125 { 126 m_num_per_line.Clear(); 127 m_output_as_binary = false; 128 m_view_as_type.Clear(); 129 m_force = false; 130 } 131 132 Error 133 FinalizeSettings (Target *target, OptionGroupFormat& format_options) 134 { 135 Error error; 136 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue(); 137 OptionValueUInt64 &count_value = format_options.GetCountValue(); 138 const bool byte_size_option_set = byte_size_value.OptionWasSet(); 139 const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); 140 const bool count_option_set = format_options.GetCountValue().OptionWasSet(); 141 142 switch (format_options.GetFormat()) 143 { 144 default: 145 break; 146 147 case eFormatBoolean: 148 if (!byte_size_option_set) 149 byte_size_value = 1; 150 if (!num_per_line_option_set) 151 m_num_per_line = 1; 152 if (!count_option_set) 153 format_options.GetCountValue() = 8; 154 break; 155 156 case eFormatCString: 157 break; 158 159 case eFormatInstruction: 160 if (count_option_set) 161 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize(); 162 m_num_per_line = 1; 163 break; 164 165 case eFormatAddressInfo: 166 if (!byte_size_option_set) 167 byte_size_value = target->GetArchitecture().GetAddressByteSize(); 168 m_num_per_line = 1; 169 if (!count_option_set) 170 format_options.GetCountValue() = 8; 171 break; 172 173 case eFormatPointer: 174 byte_size_value = target->GetArchitecture().GetAddressByteSize(); 175 if (!num_per_line_option_set) 176 m_num_per_line = 4; 177 if (!count_option_set) 178 format_options.GetCountValue() = 8; 179 break; 180 181 case eFormatBinary: 182 case eFormatFloat: 183 case eFormatOctal: 184 case eFormatDecimal: 185 case eFormatEnum: 186 case eFormatUnicode16: 187 case eFormatUnicode32: 188 case eFormatUnsigned: 189 case eFormatHexFloat: 190 if (!byte_size_option_set) 191 byte_size_value = 4; 192 if (!num_per_line_option_set) 193 m_num_per_line = 1; 194 if (!count_option_set) 195 format_options.GetCountValue() = 8; 196 break; 197 198 case eFormatBytes: 199 case eFormatBytesWithASCII: 200 if (byte_size_option_set) 201 { 202 if (byte_size_value > 1) 203 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n" 204 "\tconsider using a different display format or don't specify the byte size", 205 byte_size_value.GetCurrentValue()); 206 } 207 else 208 byte_size_value = 1; 209 if (!num_per_line_option_set) 210 m_num_per_line = 16; 211 if (!count_option_set) 212 format_options.GetCountValue() = 32; 213 break; 214 case eFormatCharArray: 215 case eFormatChar: 216 case eFormatCharPrintable: 217 if (!byte_size_option_set) 218 byte_size_value = 1; 219 if (!num_per_line_option_set) 220 m_num_per_line = 32; 221 if (!count_option_set) 222 format_options.GetCountValue() = 64; 223 break; 224 case eFormatComplex: 225 if (!byte_size_option_set) 226 byte_size_value = 8; 227 if (!num_per_line_option_set) 228 m_num_per_line = 1; 229 if (!count_option_set) 230 format_options.GetCountValue() = 8; 231 break; 232 case eFormatComplexInteger: 233 if (!byte_size_option_set) 234 byte_size_value = 8; 235 if (!num_per_line_option_set) 236 m_num_per_line = 1; 237 if (!count_option_set) 238 format_options.GetCountValue() = 8; 239 break; 240 case eFormatHex: 241 if (!byte_size_option_set) 242 byte_size_value = 4; 243 if (!num_per_line_option_set) 244 { 245 switch (byte_size_value) 246 { 247 case 1: 248 case 2: 249 m_num_per_line = 8; 250 break; 251 case 4: 252 m_num_per_line = 4; 253 break; 254 case 8: 255 m_num_per_line = 2; 256 break; 257 default: 258 m_num_per_line = 1; 259 break; 260 } 261 } 262 if (!count_option_set) 263 count_value = 8; 264 break; 265 266 case eFormatVectorOfChar: 267 case eFormatVectorOfSInt8: 268 case eFormatVectorOfUInt8: 269 case eFormatVectorOfSInt16: 270 case eFormatVectorOfUInt16: 271 case eFormatVectorOfSInt32: 272 case eFormatVectorOfUInt32: 273 case eFormatVectorOfSInt64: 274 case eFormatVectorOfUInt64: 275 case eFormatVectorOfFloat32: 276 case eFormatVectorOfFloat64: 277 case eFormatVectorOfUInt128: 278 if (!byte_size_option_set) 279 byte_size_value = 128; 280 if (!num_per_line_option_set) 281 m_num_per_line = 1; 282 if (!count_option_set) 283 count_value = 4; 284 break; 285 } 286 return error; 287 } 288 289 bool 290 AnyOptionWasSet () const 291 { 292 return m_num_per_line.OptionWasSet() || 293 m_output_as_binary || 294 m_view_as_type.OptionWasSet(); 295 } 296 297 OptionValueUInt64 m_num_per_line; 298 bool m_output_as_binary; 299 OptionValueString m_view_as_type; 300 bool m_force; 301 }; 302 303 304 305 //---------------------------------------------------------------------- 306 // Read memory from the inferior process 307 //---------------------------------------------------------------------- 308 class CommandObjectMemoryRead : public CommandObjectParsed 309 { 310 public: 311 312 CommandObjectMemoryRead (CommandInterpreter &interpreter) : 313 CommandObjectParsed (interpreter, 314 "memory read", 315 "Read from the memory of the process being debugged.", 316 NULL, 317 eCommandRequiresTarget | eCommandProcessMustBePaused), 318 m_option_group (interpreter), 319 m_format_options (eFormatBytesWithASCII, 1, 8), 320 m_memory_options (), 321 m_outfile_options (), 322 m_varobj_options(), 323 m_next_addr(LLDB_INVALID_ADDRESS), 324 m_prev_byte_size(0), 325 m_prev_format_options (eFormatBytesWithASCII, 1, 8), 326 m_prev_memory_options (), 327 m_prev_outfile_options (), 328 m_prev_varobj_options() 329 { 330 CommandArgumentEntry arg1; 331 CommandArgumentEntry arg2; 332 CommandArgumentData start_addr_arg; 333 CommandArgumentData end_addr_arg; 334 335 // Define the first (and only) variant of this arg. 336 start_addr_arg.arg_type = eArgTypeAddressOrExpression; 337 start_addr_arg.arg_repetition = eArgRepeatPlain; 338 339 // There is only one variant this argument could be; put it into the argument entry. 340 arg1.push_back (start_addr_arg); 341 342 // Define the first (and only) variant of this arg. 343 end_addr_arg.arg_type = eArgTypeAddressOrExpression; 344 end_addr_arg.arg_repetition = eArgRepeatOptional; 345 346 // There is only one variant this argument could be; put it into the argument entry. 347 arg2.push_back (end_addr_arg); 348 349 // Push the data for the first argument into the m_arguments vector. 350 m_arguments.push_back (arg1); 351 m_arguments.push_back (arg2); 352 353 // Add the "--format" and "--count" options to group 1 and 3 354 m_option_group.Append (&m_format_options, 355 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT, 356 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 357 m_option_group.Append (&m_format_options, 358 OptionGroupFormat::OPTION_GROUP_GDB_FMT, 359 LLDB_OPT_SET_1 | LLDB_OPT_SET_3); 360 // Add the "--size" option to group 1 and 2 361 m_option_group.Append (&m_format_options, 362 OptionGroupFormat::OPTION_GROUP_SIZE, 363 LLDB_OPT_SET_1 | LLDB_OPT_SET_2); 364 m_option_group.Append (&m_memory_options); 365 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 366 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); 367 m_option_group.Finalize(); 368 } 369 370 virtual 371 ~CommandObjectMemoryRead () 372 { 373 } 374 375 Options * 376 GetOptions () 377 { 378 return &m_option_group; 379 } 380 381 virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 382 { 383 return m_cmd_name.c_str(); 384 } 385 386 protected: 387 virtual bool 388 DoExecute (Args& command, CommandReturnObject &result) 389 { 390 // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid 391 Target *target = m_exe_ctx.GetTargetPtr(); 392 393 const size_t argc = command.GetArgumentCount(); 394 395 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) 396 { 397 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str()); 398 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n"); 399 result.SetStatus(eReturnStatusFailed); 400 return false; 401 } 402 403 CompilerType clang_ast_type; 404 Error error; 405 406 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); 407 if (view_as_type_cstr && view_as_type_cstr[0]) 408 { 409 // We are viewing memory as a type 410 411 SymbolContext sc; 412 const bool exact_match = false; 413 TypeList type_list; 414 uint32_t reference_count = 0; 415 uint32_t pointer_count = 0; 416 size_t idx; 417 418 #define ALL_KEYWORDS \ 419 KEYWORD("const") \ 420 KEYWORD("volatile") \ 421 KEYWORD("restrict") \ 422 KEYWORD("struct") \ 423 KEYWORD("class") \ 424 KEYWORD("union") 425 426 #define KEYWORD(s) s, 427 static const char *g_keywords[] = 428 { 429 ALL_KEYWORDS 430 }; 431 #undef KEYWORD 432 433 #define KEYWORD(s) (sizeof(s) - 1), 434 static const int g_keyword_lengths[] = 435 { 436 ALL_KEYWORDS 437 }; 438 #undef KEYWORD 439 440 #undef ALL_KEYWORDS 441 442 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *); 443 std::string type_str(view_as_type_cstr); 444 445 // Remove all instances of g_keywords that are followed by spaces 446 for (size_t i = 0; i < g_num_keywords; ++i) 447 { 448 const char *keyword = g_keywords[i]; 449 int keyword_len = g_keyword_lengths[i]; 450 451 idx = 0; 452 while ((idx = type_str.find (keyword, idx)) != std::string::npos) 453 { 454 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') 455 { 456 type_str.erase(idx, keyword_len+1); 457 idx = 0; 458 } 459 else 460 { 461 idx += keyword_len; 462 } 463 } 464 } 465 bool done = type_str.empty(); 466 // 467 idx = type_str.find_first_not_of (" \t"); 468 if (idx > 0 && idx != std::string::npos) 469 type_str.erase (0, idx); 470 while (!done) 471 { 472 // Strip trailing spaces 473 if (type_str.empty()) 474 done = true; 475 else 476 { 477 switch (type_str[type_str.size()-1]) 478 { 479 case '*': 480 ++pointer_count; 481 // fall through... 482 case ' ': 483 case '\t': 484 type_str.erase(type_str.size()-1); 485 break; 486 487 case '&': 488 if (reference_count == 0) 489 { 490 reference_count = 1; 491 type_str.erase(type_str.size()-1); 492 } 493 else 494 { 495 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); 496 result.SetStatus(eReturnStatusFailed); 497 return false; 498 } 499 break; 500 501 default: 502 done = true; 503 break; 504 } 505 } 506 } 507 508 ConstString lookup_type_name(type_str.c_str()); 509 StackFrame *frame = m_exe_ctx.GetFramePtr(); 510 if (frame) 511 { 512 sc = frame->GetSymbolContext (eSymbolContextModule); 513 if (sc.module_sp) 514 { 515 sc.module_sp->FindTypes (sc, 516 lookup_type_name, 517 exact_match, 518 1, 519 type_list); 520 } 521 } 522 if (type_list.GetSize() == 0) 523 { 524 target->GetImages().FindTypes (sc, 525 lookup_type_name, 526 exact_match, 527 1, 528 type_list); 529 } 530 531 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$') 532 { 533 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name)); 534 if (tdecl) 535 { 536 clang_ast_type.SetClangType(ClangASTContext::GetASTContext(&tdecl->getASTContext()),(const lldb::clang_type_t)tdecl->getTypeForDecl()); 537 } 538 } 539 540 if (clang_ast_type.IsValid() == false) 541 { 542 if (type_list.GetSize() == 0) 543 { 544 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", 545 lookup_type_name.GetCString(), 546 view_as_type_cstr); 547 result.SetStatus(eReturnStatusFailed); 548 return false; 549 } 550 else 551 { 552 TypeSP type_sp (type_list.GetTypeAtIndex(0)); 553 clang_ast_type = type_sp->GetClangFullType(); 554 } 555 } 556 557 while (pointer_count > 0) 558 { 559 CompilerType pointer_type = clang_ast_type.GetPointerType(); 560 if (pointer_type.IsValid()) 561 clang_ast_type = pointer_type; 562 else 563 { 564 result.AppendError ("unable make a pointer type\n"); 565 result.SetStatus(eReturnStatusFailed); 566 return false; 567 } 568 --pointer_count; 569 } 570 571 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr); 572 573 if (m_format_options.GetByteSizeValue() == 0) 574 { 575 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 576 view_as_type_cstr); 577 result.SetStatus(eReturnStatusFailed); 578 return false; 579 } 580 581 if (!m_format_options.GetCountValue().OptionWasSet()) 582 m_format_options.GetCountValue() = 1; 583 } 584 else 585 { 586 error = m_memory_options.FinalizeSettings (target, m_format_options); 587 } 588 589 // Look for invalid combinations of settings 590 if (error.Fail()) 591 { 592 result.AppendError(error.AsCString()); 593 result.SetStatus(eReturnStatusFailed); 594 return false; 595 } 596 597 lldb::addr_t addr; 598 size_t total_byte_size = 0; 599 if (argc == 0) 600 { 601 // Use the last address and byte size and all options as they were 602 // if no options have been set 603 addr = m_next_addr; 604 total_byte_size = m_prev_byte_size; 605 clang_ast_type = m_prev_clang_ast_type; 606 if (!m_format_options.AnyOptionWasSet() && 607 !m_memory_options.AnyOptionWasSet() && 608 !m_outfile_options.AnyOptionWasSet() && 609 !m_varobj_options.AnyOptionWasSet()) 610 { 611 m_format_options = m_prev_format_options; 612 m_memory_options = m_prev_memory_options; 613 m_outfile_options = m_prev_outfile_options; 614 m_varobj_options = m_prev_varobj_options; 615 } 616 } 617 618 size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); 619 620 // TODO For non-8-bit byte addressable architectures this needs to be 621 // revisited to fully support all lldb's range of formatting options. 622 // Furthermore code memory reads (for those architectures) will not 623 // be correctly formatted even w/o formatting options. 624 size_t item_byte_size = 625 target->GetArchitecture().GetDataByteSize() > 1 ? 626 target->GetArchitecture().GetDataByteSize() : 627 m_format_options.GetByteSizeValue().GetCurrentValue(); 628 629 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); 630 631 if (total_byte_size == 0) 632 { 633 total_byte_size = item_count * item_byte_size; 634 if (total_byte_size == 0) 635 total_byte_size = 32; 636 } 637 638 if (argc > 0) 639 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error); 640 641 if (addr == LLDB_INVALID_ADDRESS) 642 { 643 result.AppendError("invalid start address expression."); 644 result.AppendError(error.AsCString()); 645 result.SetStatus(eReturnStatusFailed); 646 return false; 647 } 648 649 if (argc == 2) 650 { 651 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); 652 if (end_addr == LLDB_INVALID_ADDRESS) 653 { 654 result.AppendError("invalid end address expression."); 655 result.AppendError(error.AsCString()); 656 result.SetStatus(eReturnStatusFailed); 657 return false; 658 } 659 else if (end_addr <= addr) 660 { 661 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr); 662 result.SetStatus(eReturnStatusFailed); 663 return false; 664 } 665 else if (m_format_options.GetCountValue().OptionWasSet()) 666 { 667 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count); 668 result.SetStatus(eReturnStatusFailed); 669 return false; 670 } 671 672 total_byte_size = end_addr - addr; 673 item_count = total_byte_size / item_byte_size; 674 } 675 676 uint32_t max_unforced_size = target->GetMaximumMemReadSize(); 677 678 if (total_byte_size > max_unforced_size && !m_memory_options.m_force) 679 { 680 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size); 681 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n"); 682 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n"); 683 return false; 684 } 685 686 DataBufferSP data_sp; 687 size_t bytes_read = 0; 688 if (clang_ast_type.GetOpaqueQualType()) 689 { 690 // Make sure we don't display our type as ASCII bytes like the default memory read 691 if (m_format_options.GetFormatValue().OptionWasSet() == false) 692 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); 693 694 bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue(); 695 } 696 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) 697 { 698 data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); 699 if (data_sp->GetBytes() == NULL) 700 { 701 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size); 702 result.SetStatus(eReturnStatusFailed); 703 return false; 704 } 705 706 Address address(addr, NULL); 707 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); 708 if (bytes_read == 0) 709 { 710 const char *error_cstr = error.AsCString(); 711 if (error_cstr && error_cstr[0]) 712 { 713 result.AppendError(error_cstr); 714 } 715 else 716 { 717 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 718 } 719 result.SetStatus(eReturnStatusFailed); 720 return false; 721 } 722 723 if (bytes_read < total_byte_size) 724 result.AppendWarningWithFormat("Not all bytes (%" PRIu64 "/%" PRIu64 ") were able to be read from 0x%" PRIx64 ".\n", (uint64_t)bytes_read, (uint64_t)total_byte_size, addr); 725 } 726 else 727 { 728 // we treat c-strings as a special case because they do not have a fixed size 729 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat()) 730 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); 731 else 732 item_byte_size = target->GetMaximumSizeOfStringSummary(); 733 if (!m_format_options.GetCountValue().OptionWasSet()) 734 item_count = 1; 735 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary 736 if (data_sp->GetBytes() == NULL) 737 { 738 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx64 " bytes for the memory read buffer, specify a smaller size to read", (uint64_t)((item_byte_size+1) * item_count)); 739 result.SetStatus(eReturnStatusFailed); 740 return false; 741 } 742 uint8_t *data_ptr = data_sp->GetBytes(); 743 auto data_addr = addr; 744 auto count = item_count; 745 item_count = 0; 746 bool break_on_no_NULL = false; 747 while (item_count < count) 748 { 749 std::string buffer; 750 buffer.resize(item_byte_size+1,0); 751 Error error; 752 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error); 753 if (error.Fail()) 754 { 755 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 756 result.SetStatus(eReturnStatusFailed); 757 return false; 758 } 759 760 if (item_byte_size == read) 761 { 762 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr); 763 --read; 764 break_on_no_NULL = true; 765 } 766 else 767 ++read; // account for final NULL byte 768 769 memcpy(data_ptr, &buffer[0], read); 770 data_ptr += read; 771 data_addr += read; 772 bytes_read += read; 773 item_count++; // if we break early we know we only read item_count strings 774 775 if (break_on_no_NULL) 776 break; 777 } 778 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1)); 779 } 780 781 m_next_addr = addr + bytes_read; 782 m_prev_byte_size = bytes_read; 783 m_prev_format_options = m_format_options; 784 m_prev_memory_options = m_memory_options; 785 m_prev_outfile_options = m_outfile_options; 786 m_prev_varobj_options = m_varobj_options; 787 m_prev_clang_ast_type = clang_ast_type; 788 789 StreamFile outfile_stream; 790 Stream *output_stream = NULL; 791 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 792 if (outfile_spec) 793 { 794 char path[PATH_MAX]; 795 outfile_spec.GetPath (path, sizeof(path)); 796 797 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 798 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 799 if (append) 800 open_options |= File::eOpenOptionAppend; 801 802 if (outfile_stream.GetFile ().Open (path, open_options).Success()) 803 { 804 if (m_memory_options.m_output_as_binary) 805 { 806 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 807 if (bytes_written > 0) 808 { 809 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n", 810 bytes_written, 811 append ? "appended" : "written", 812 path); 813 return true; 814 } 815 else 816 { 817 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path); 818 result.SetStatus(eReturnStatusFailed); 819 return false; 820 } 821 } 822 else 823 { 824 // We are going to write ASCII to the file just point the 825 // output_stream to our outfile_stream... 826 output_stream = &outfile_stream; 827 } 828 } 829 else 830 { 831 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); 832 result.SetStatus(eReturnStatusFailed); 833 return false; 834 } 835 } 836 else 837 { 838 output_stream = &result.GetOutputStream(); 839 } 840 841 842 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); 843 if (clang_ast_type.GetOpaqueQualType()) 844 { 845 for (uint32_t i = 0; i<item_count; ++i) 846 { 847 addr_t item_addr = addr + (i * item_byte_size); 848 Address address (item_addr); 849 StreamString name_strm; 850 name_strm.Printf ("0x%" PRIx64, item_addr); 851 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 852 name_strm.GetString().c_str(), 853 address, 854 clang_ast_type)); 855 if (valobj_sp) 856 { 857 Format format = m_format_options.GetFormat(); 858 if (format != eFormatDefault) 859 valobj_sp->SetFormat (format); 860 861 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format)); 862 863 valobj_sp->Dump(*output_stream,options); 864 } 865 else 866 { 867 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 868 view_as_type_cstr, 869 name_strm.GetString().c_str()); 870 result.SetStatus(eReturnStatusFailed); 871 return false; 872 } 873 } 874 return true; 875 } 876 877 result.SetStatus(eReturnStatusSuccessFinishResult); 878 DataExtractor data (data_sp, 879 target->GetArchitecture().GetByteOrder(), 880 target->GetArchitecture().GetAddressByteSize(), 881 target->GetArchitecture().GetDataByteSize()); 882 883 Format format = m_format_options.GetFormat(); 884 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) 885 && (item_byte_size != 1)) 886 { 887 // if a count was not passed, or it is 1 888 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1) 889 { 890 // this turns requests such as 891 // memory read -fc -s10 -c1 *charPtrPtr 892 // which make no sense (what is a char of size 10?) 893 // into a request for fetching 10 chars of size 1 from the same memory location 894 format = eFormatCharArray; 895 item_count = item_byte_size; 896 item_byte_size = 1; 897 } 898 else 899 { 900 // here we passed a count, and it was not 1 901 // so we have a byte_size and a count 902 // we could well multiply those, but instead let's just fail 903 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size); 904 result.SetStatus(eReturnStatusFailed); 905 return false; 906 } 907 } 908 909 assert (output_stream); 910 size_t bytes_dumped = data.Dump (output_stream, 911 0, 912 format, 913 item_byte_size, 914 item_count, 915 num_per_line / target->GetArchitecture().GetDataByteSize(), 916 addr, 917 0, 918 0, 919 exe_scope); 920 m_next_addr = addr + bytes_dumped; 921 output_stream->EOL(); 922 return true; 923 } 924 925 OptionGroupOptions m_option_group; 926 OptionGroupFormat m_format_options; 927 OptionGroupReadMemory m_memory_options; 928 OptionGroupOutputFile m_outfile_options; 929 OptionGroupValueObjectDisplay m_varobj_options; 930 lldb::addr_t m_next_addr; 931 lldb::addr_t m_prev_byte_size; 932 OptionGroupFormat m_prev_format_options; 933 OptionGroupReadMemory m_prev_memory_options; 934 OptionGroupOutputFile m_prev_outfile_options; 935 OptionGroupValueObjectDisplay m_prev_varobj_options; 936 CompilerType m_prev_clang_ast_type; 937 }; 938 939 OptionDefinition 940 g_memory_find_option_table[] = 941 { 942 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."}, 943 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."}, 944 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."}, 945 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."}, 946 }; 947 948 //---------------------------------------------------------------------- 949 // Find the specified data in memory 950 //---------------------------------------------------------------------- 951 class CommandObjectMemoryFind : public CommandObjectParsed 952 { 953 public: 954 955 class OptionGroupFindMemory : public OptionGroup 956 { 957 public: 958 OptionGroupFindMemory () : 959 OptionGroup(), 960 m_count(1), 961 m_offset(0) 962 { 963 } 964 965 virtual 966 ~OptionGroupFindMemory () 967 { 968 } 969 970 virtual uint32_t 971 GetNumDefinitions () 972 { 973 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition); 974 } 975 976 virtual const OptionDefinition* 977 GetDefinitions () 978 { 979 return g_memory_find_option_table; 980 } 981 982 virtual Error 983 SetOptionValue (CommandInterpreter &interpreter, 984 uint32_t option_idx, 985 const char *option_arg) 986 { 987 Error error; 988 const int short_option = g_memory_find_option_table[option_idx].short_option; 989 990 switch (short_option) 991 { 992 case 'e': 993 m_expr.SetValueFromString(option_arg); 994 break; 995 996 case 's': 997 m_string.SetValueFromString(option_arg); 998 break; 999 1000 case 'c': 1001 if (m_count.SetValueFromString(option_arg).Fail()) 1002 error.SetErrorString("unrecognized value for count"); 1003 break; 1004 1005 case 'o': 1006 if (m_offset.SetValueFromString(option_arg).Fail()) 1007 error.SetErrorString("unrecognized value for dump-offset"); 1008 break; 1009 1010 default: 1011 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 1012 break; 1013 } 1014 return error; 1015 } 1016 1017 virtual void 1018 OptionParsingStarting (CommandInterpreter &interpreter) 1019 { 1020 m_expr.Clear(); 1021 m_string.Clear(); 1022 m_count.Clear(); 1023 } 1024 1025 OptionValueString m_expr; 1026 OptionValueString m_string; 1027 OptionValueUInt64 m_count; 1028 OptionValueUInt64 m_offset; 1029 }; 1030 1031 CommandObjectMemoryFind (CommandInterpreter &interpreter) : 1032 CommandObjectParsed (interpreter, 1033 "memory find", 1034 "Find a value in the memory of the process being debugged.", 1035 NULL, 1036 eCommandRequiresProcess | eCommandProcessMustBeLaunched), 1037 m_option_group (interpreter), 1038 m_memory_options () 1039 { 1040 CommandArgumentEntry arg1; 1041 CommandArgumentEntry arg2; 1042 CommandArgumentData addr_arg; 1043 CommandArgumentData value_arg; 1044 1045 // Define the first (and only) variant of this arg. 1046 addr_arg.arg_type = eArgTypeAddressOrExpression; 1047 addr_arg.arg_repetition = eArgRepeatPlain; 1048 1049 // There is only one variant this argument could be; put it into the argument entry. 1050 arg1.push_back (addr_arg); 1051 1052 // Define the first (and only) variant of this arg. 1053 value_arg.arg_type = eArgTypeAddressOrExpression; 1054 value_arg.arg_repetition = eArgRepeatPlain; 1055 1056 // There is only one variant this argument could be; put it into the argument entry. 1057 arg2.push_back (value_arg); 1058 1059 // Push the data for the first argument into the m_arguments vector. 1060 m_arguments.push_back (arg1); 1061 m_arguments.push_back (arg2); 1062 1063 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 1064 m_option_group.Finalize(); 1065 } 1066 1067 virtual 1068 ~CommandObjectMemoryFind () 1069 { 1070 } 1071 1072 Options * 1073 GetOptions () 1074 { 1075 return &m_option_group; 1076 } 1077 1078 protected: 1079 virtual bool 1080 DoExecute (Args& command, CommandReturnObject &result) 1081 { 1082 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid 1083 Process *process = m_exe_ctx.GetProcessPtr(); 1084 1085 const size_t argc = command.GetArgumentCount(); 1086 1087 if (argc != 2) 1088 { 1089 result.AppendError("two addresses needed for memory find"); 1090 return false; 1091 } 1092 1093 Error error; 1094 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error); 1095 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) 1096 { 1097 result.AppendError("invalid low address"); 1098 return false; 1099 } 1100 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error); 1101 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) 1102 { 1103 result.AppendError("invalid high address"); 1104 return false; 1105 } 1106 1107 if (high_addr <= low_addr) 1108 { 1109 result.AppendError("starting address must be smaller than ending address"); 1110 return false; 1111 } 1112 1113 lldb::addr_t found_location = LLDB_INVALID_ADDRESS; 1114 1115 DataBufferHeap buffer; 1116 1117 if (m_memory_options.m_string.OptionWasSet()) 1118 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue())); 1119 else if (m_memory_options.m_expr.OptionWasSet()) 1120 { 1121 StackFrame* frame = m_exe_ctx.GetFramePtr(); 1122 ValueObjectSP result_sp; 1123 if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) && 1124 result_sp.get()) 1125 { 1126 uint64_t value = result_sp->GetValueAsUnsigned(0); 1127 switch (result_sp->GetClangType().GetByteSize(nullptr)) 1128 { 1129 case 1: { 1130 uint8_t byte = (uint8_t)value; 1131 buffer.CopyData(&byte,1); 1132 } 1133 break; 1134 case 2: { 1135 uint16_t word = (uint16_t)value; 1136 buffer.CopyData(&word,2); 1137 } 1138 break; 1139 case 4: { 1140 uint32_t lword = (uint32_t)value; 1141 buffer.CopyData(&lword,4); 1142 } 1143 break; 1144 case 8: { 1145 buffer.CopyData(&value, 8); 1146 } 1147 break; 1148 case 3: 1149 case 5: 1150 case 6: 1151 case 7: 1152 result.AppendError("unknown type. pass a string instead"); 1153 return false; 1154 default: 1155 result.AppendError("result size larger than 8 bytes. pass a string instead"); 1156 return false; 1157 } 1158 } 1159 else 1160 { 1161 result.AppendError("expression evaluation failed. pass a string instead"); 1162 return false; 1163 } 1164 } 1165 else 1166 { 1167 result.AppendError("please pass either a block of text, or an expression to evaluate."); 1168 return false; 1169 } 1170 1171 size_t count = m_memory_options.m_count.GetCurrentValue(); 1172 found_location = low_addr; 1173 bool ever_found = false; 1174 while (count) 1175 { 1176 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize()); 1177 if (found_location == LLDB_INVALID_ADDRESS) 1178 { 1179 if (!ever_found) 1180 { 1181 result.AppendMessage("data not found within the range.\n"); 1182 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 1183 } 1184 else 1185 result.AppendMessage("no more matches within the range.\n"); 1186 break; 1187 } 1188 result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location); 1189 1190 DataBufferHeap dumpbuffer(32,0); 1191 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error); 1192 if (!error.Fail()) 1193 { 1194 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize()); 1195 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0); 1196 result.GetOutputStream().EOL(); 1197 } 1198 1199 --count; 1200 found_location++; 1201 ever_found = true; 1202 } 1203 1204 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 1205 return true; 1206 } 1207 1208 lldb::addr_t 1209 Search (lldb::addr_t low, 1210 lldb::addr_t high, 1211 uint8_t* buffer, 1212 size_t buffer_size) 1213 { 1214 Process *process = m_exe_ctx.GetProcessPtr(); 1215 DataBufferHeap heap(buffer_size, 0); 1216 for (auto ptr = low; 1217 ptr < high; 1218 ptr++) 1219 { 1220 Error error; 1221 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error); 1222 if (error.Fail()) 1223 return LLDB_INVALID_ADDRESS; 1224 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0) 1225 return ptr; 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 = StringConvert::ToUInt64(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 eCommandRequiresProcess | eCommandProcessMustBeLaunched), 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 eCommandRequiresProcess 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 > 1) 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 = StringConvert::ToUInt64(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 = StringConvert::ToUInt64(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 = StringConvert::ToSInt64(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 = StringConvert::ToUInt64(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 = StringConvert::ToUInt64(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 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | eCommandProcessMustBeLaunched) 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