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