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