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 "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" 27 #include "lldb/Host/StringConvert.h" 28 #include "lldb/Interpreter/Args.h" 29 #include "lldb/Interpreter/CommandReturnObject.h" 30 #include "lldb/Interpreter/CommandInterpreter.h" 31 #include "lldb/Interpreter/Options.h" 32 #include "lldb/Interpreter/OptionGroupFormat.h" 33 #include "lldb/Interpreter/OptionGroupOutputFile.h" 34 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" 35 #include "lldb/Interpreter/OptionValueString.h" 36 #include "lldb/Symbol/ClangASTContext.h" 37 #include "lldb/Symbol/TypeList.h" 38 #include "lldb/Target/MemoryHistory.h" 39 #include "lldb/Target/Process.h" 40 #include "lldb/Target/StackFrame.h" 41 #include "lldb/Target/Thread.h" 42 43 using namespace lldb; 44 using namespace lldb_private; 45 46 static OptionDefinition 47 g_option_table[] = 48 { 49 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, 50 { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."}, 51 { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, 52 { LLDB_OPT_SET_1| 53 LLDB_OPT_SET_2| 54 LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."}, 55 }; 56 57 58 59 class OptionGroupReadMemory : public OptionGroup 60 { 61 public: 62 63 OptionGroupReadMemory () : 64 m_num_per_line (1,1), 65 m_output_as_binary (false), 66 m_view_as_type() 67 { 68 } 69 70 ~OptionGroupReadMemory () override 71 { 72 } 73 74 75 uint32_t 76 GetNumDefinitions () override 77 { 78 return sizeof (g_option_table) / sizeof (OptionDefinition); 79 } 80 81 const OptionDefinition* 82 GetDefinitions () override 83 { 84 return g_option_table; 85 } 86 87 Error 88 SetOptionValue (CommandInterpreter &interpreter, 89 uint32_t option_idx, 90 const char *option_arg) override 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 void 123 OptionParsingStarting (CommandInterpreter &interpreter) override 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 ~CommandObjectMemoryRead () override 370 { 371 } 372 373 Options * 374 GetOptions () override 375 { 376 return &m_option_group; 377 } 378 379 const char * 380 GetRepeatCommand (Args ¤t_command_args, uint32_t index) override 381 { 382 return m_cmd_name.c_str(); 383 } 384 385 protected: 386 bool 387 DoExecute (Args& command, CommandReturnObject &result) override 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 CompilerType 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 if (ClangPersistentVariables *persistent_vars = llvm::dyn_cast_or_null<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))) 533 { 534 clang::TypeDecl *tdecl = persistent_vars->GetPersistentType(ConstString(lookup_type_name)); 535 536 if (tdecl) 537 { 538 clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()),(const lldb::opaque_compiler_type_t)tdecl->getTypeForDecl()); 539 } 540 } 541 } 542 543 if (clang_ast_type.IsValid() == false) 544 { 545 if (type_list.GetSize() == 0) 546 { 547 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", 548 lookup_type_name.GetCString(), 549 view_as_type_cstr); 550 result.SetStatus(eReturnStatusFailed); 551 return false; 552 } 553 else 554 { 555 TypeSP type_sp (type_list.GetTypeAtIndex(0)); 556 clang_ast_type = type_sp->GetFullCompilerType (); 557 } 558 } 559 560 while (pointer_count > 0) 561 { 562 CompilerType pointer_type = clang_ast_type.GetPointerType(); 563 if (pointer_type.IsValid()) 564 clang_ast_type = pointer_type; 565 else 566 { 567 result.AppendError ("unable make a pointer type\n"); 568 result.SetStatus(eReturnStatusFailed); 569 return false; 570 } 571 --pointer_count; 572 } 573 574 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr); 575 576 if (m_format_options.GetByteSizeValue() == 0) 577 { 578 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 579 view_as_type_cstr); 580 result.SetStatus(eReturnStatusFailed); 581 return false; 582 } 583 584 if (!m_format_options.GetCountValue().OptionWasSet()) 585 m_format_options.GetCountValue() = 1; 586 } 587 else 588 { 589 error = m_memory_options.FinalizeSettings (target, m_format_options); 590 } 591 592 // Look for invalid combinations of settings 593 if (error.Fail()) 594 { 595 result.AppendError(error.AsCString()); 596 result.SetStatus(eReturnStatusFailed); 597 return false; 598 } 599 600 lldb::addr_t addr; 601 size_t total_byte_size = 0; 602 if (argc == 0) 603 { 604 // Use the last address and byte size and all options as they were 605 // if no options have been set 606 addr = m_next_addr; 607 total_byte_size = m_prev_byte_size; 608 clang_ast_type = m_prev_clang_ast_type; 609 if (!m_format_options.AnyOptionWasSet() && 610 !m_memory_options.AnyOptionWasSet() && 611 !m_outfile_options.AnyOptionWasSet() && 612 !m_varobj_options.AnyOptionWasSet()) 613 { 614 m_format_options = m_prev_format_options; 615 m_memory_options = m_prev_memory_options; 616 m_outfile_options = m_prev_outfile_options; 617 m_varobj_options = m_prev_varobj_options; 618 } 619 } 620 621 size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); 622 623 // TODO For non-8-bit byte addressable architectures this needs to be 624 // revisited to fully support all lldb's range of formatting options. 625 // Furthermore code memory reads (for those architectures) will not 626 // be correctly formatted even w/o formatting options. 627 size_t item_byte_size = 628 target->GetArchitecture().GetDataByteSize() > 1 ? 629 target->GetArchitecture().GetDataByteSize() : 630 m_format_options.GetByteSizeValue().GetCurrentValue(); 631 632 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); 633 634 if (total_byte_size == 0) 635 { 636 total_byte_size = item_count * item_byte_size; 637 if (total_byte_size == 0) 638 total_byte_size = 32; 639 } 640 641 if (argc > 0) 642 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error); 643 644 if (addr == LLDB_INVALID_ADDRESS) 645 { 646 result.AppendError("invalid start address expression."); 647 result.AppendError(error.AsCString()); 648 result.SetStatus(eReturnStatusFailed); 649 return false; 650 } 651 652 if (argc == 2) 653 { 654 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); 655 if (end_addr == LLDB_INVALID_ADDRESS) 656 { 657 result.AppendError("invalid end address expression."); 658 result.AppendError(error.AsCString()); 659 result.SetStatus(eReturnStatusFailed); 660 return false; 661 } 662 else if (end_addr <= addr) 663 { 664 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr); 665 result.SetStatus(eReturnStatusFailed); 666 return false; 667 } 668 else if (m_format_options.GetCountValue().OptionWasSet()) 669 { 670 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count); 671 result.SetStatus(eReturnStatusFailed); 672 return false; 673 } 674 675 total_byte_size = end_addr - addr; 676 item_count = total_byte_size / item_byte_size; 677 } 678 679 uint32_t max_unforced_size = target->GetMaximumMemReadSize(); 680 681 if (total_byte_size > max_unforced_size && !m_memory_options.m_force) 682 { 683 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size); 684 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n"); 685 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n"); 686 return false; 687 } 688 689 DataBufferSP data_sp; 690 size_t bytes_read = 0; 691 if (clang_ast_type.GetOpaqueQualType()) 692 { 693 // Make sure we don't display our type as ASCII bytes like the default memory read 694 if (m_format_options.GetFormatValue().OptionWasSet() == false) 695 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); 696 697 bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue(); 698 } 699 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) 700 { 701 data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); 702 if (data_sp->GetBytes() == NULL) 703 { 704 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size); 705 result.SetStatus(eReturnStatusFailed); 706 return false; 707 } 708 709 Address address(addr, NULL); 710 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); 711 if (bytes_read == 0) 712 { 713 const char *error_cstr = error.AsCString(); 714 if (error_cstr && error_cstr[0]) 715 { 716 result.AppendError(error_cstr); 717 } 718 else 719 { 720 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 721 } 722 result.SetStatus(eReturnStatusFailed); 723 return false; 724 } 725 726 if (bytes_read < total_byte_size) 727 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); 728 } 729 else 730 { 731 // we treat c-strings as a special case because they do not have a fixed size 732 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat()) 733 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); 734 else 735 item_byte_size = target->GetMaximumSizeOfStringSummary(); 736 if (!m_format_options.GetCountValue().OptionWasSet()) 737 item_count = 1; 738 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary 739 if (data_sp->GetBytes() == NULL) 740 { 741 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)); 742 result.SetStatus(eReturnStatusFailed); 743 return false; 744 } 745 uint8_t *data_ptr = data_sp->GetBytes(); 746 auto data_addr = addr; 747 auto count = item_count; 748 item_count = 0; 749 bool break_on_no_NULL = false; 750 while (item_count < count) 751 { 752 std::string buffer; 753 buffer.resize(item_byte_size+1,0); 754 Error error; 755 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error); 756 if (error.Fail()) 757 { 758 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 759 result.SetStatus(eReturnStatusFailed); 760 return false; 761 } 762 763 if (item_byte_size == read) 764 { 765 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr); 766 --read; 767 break_on_no_NULL = true; 768 } 769 else 770 ++read; // account for final NULL byte 771 772 memcpy(data_ptr, &buffer[0], read); 773 data_ptr += read; 774 data_addr += read; 775 bytes_read += read; 776 item_count++; // if we break early we know we only read item_count strings 777 778 if (break_on_no_NULL) 779 break; 780 } 781 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1)); 782 } 783 784 m_next_addr = addr + bytes_read; 785 m_prev_byte_size = bytes_read; 786 m_prev_format_options = m_format_options; 787 m_prev_memory_options = m_memory_options; 788 m_prev_outfile_options = m_outfile_options; 789 m_prev_varobj_options = m_varobj_options; 790 m_prev_clang_ast_type = clang_ast_type; 791 792 StreamFile outfile_stream; 793 Stream *output_stream = NULL; 794 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 795 if (outfile_spec) 796 { 797 char path[PATH_MAX]; 798 outfile_spec.GetPath (path, sizeof(path)); 799 800 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 801 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 802 if (append) 803 open_options |= File::eOpenOptionAppend; 804 805 if (outfile_stream.GetFile ().Open (path, open_options).Success()) 806 { 807 if (m_memory_options.m_output_as_binary) 808 { 809 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 810 if (bytes_written > 0) 811 { 812 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n", 813 bytes_written, 814 append ? "appended" : "written", 815 path); 816 return true; 817 } 818 else 819 { 820 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path); 821 result.SetStatus(eReturnStatusFailed); 822 return false; 823 } 824 } 825 else 826 { 827 // We are going to write ASCII to the file just point the 828 // output_stream to our outfile_stream... 829 output_stream = &outfile_stream; 830 } 831 } 832 else 833 { 834 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); 835 result.SetStatus(eReturnStatusFailed); 836 return false; 837 } 838 } 839 else 840 { 841 output_stream = &result.GetOutputStream(); 842 } 843 844 845 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); 846 if (clang_ast_type.GetOpaqueQualType()) 847 { 848 for (uint32_t i = 0; i<item_count; ++i) 849 { 850 addr_t item_addr = addr + (i * item_byte_size); 851 Address address (item_addr); 852 StreamString name_strm; 853 name_strm.Printf ("0x%" PRIx64, item_addr); 854 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 855 name_strm.GetString().c_str(), 856 address, 857 clang_ast_type)); 858 if (valobj_sp) 859 { 860 Format format = m_format_options.GetFormat(); 861 if (format != eFormatDefault) 862 valobj_sp->SetFormat (format); 863 864 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format)); 865 866 valobj_sp->Dump(*output_stream,options); 867 } 868 else 869 { 870 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 871 view_as_type_cstr, 872 name_strm.GetString().c_str()); 873 result.SetStatus(eReturnStatusFailed); 874 return false; 875 } 876 } 877 return true; 878 } 879 880 result.SetStatus(eReturnStatusSuccessFinishResult); 881 DataExtractor data (data_sp, 882 target->GetArchitecture().GetByteOrder(), 883 target->GetArchitecture().GetAddressByteSize(), 884 target->GetArchitecture().GetDataByteSize()); 885 886 Format format = m_format_options.GetFormat(); 887 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) 888 && (item_byte_size != 1)) 889 { 890 // if a count was not passed, or it is 1 891 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1) 892 { 893 // this turns requests such as 894 // memory read -fc -s10 -c1 *charPtrPtr 895 // which make no sense (what is a char of size 10?) 896 // into a request for fetching 10 chars of size 1 from the same memory location 897 format = eFormatCharArray; 898 item_count = item_byte_size; 899 item_byte_size = 1; 900 } 901 else 902 { 903 // here we passed a count, and it was not 1 904 // so we have a byte_size and a count 905 // we could well multiply those, but instead let's just fail 906 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size); 907 result.SetStatus(eReturnStatusFailed); 908 return false; 909 } 910 } 911 912 assert (output_stream); 913 size_t bytes_dumped = data.Dump (output_stream, 914 0, 915 format, 916 item_byte_size, 917 item_count, 918 num_per_line / target->GetArchitecture().GetDataByteSize(), 919 addr, 920 0, 921 0, 922 exe_scope); 923 m_next_addr = addr + bytes_dumped; 924 output_stream->EOL(); 925 return true; 926 } 927 928 OptionGroupOptions m_option_group; 929 OptionGroupFormat m_format_options; 930 OptionGroupReadMemory m_memory_options; 931 OptionGroupOutputFile m_outfile_options; 932 OptionGroupValueObjectDisplay m_varobj_options; 933 lldb::addr_t m_next_addr; 934 lldb::addr_t m_prev_byte_size; 935 OptionGroupFormat m_prev_format_options; 936 OptionGroupReadMemory m_prev_memory_options; 937 OptionGroupOutputFile m_prev_outfile_options; 938 OptionGroupValueObjectDisplay m_prev_varobj_options; 939 CompilerType m_prev_clang_ast_type; 940 }; 941 942 OptionDefinition 943 g_memory_find_option_table[] = 944 { 945 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."}, 946 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."}, 947 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."}, 948 { 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."}, 949 }; 950 951 //---------------------------------------------------------------------- 952 // Find the specified data in memory 953 //---------------------------------------------------------------------- 954 class CommandObjectMemoryFind : public CommandObjectParsed 955 { 956 public: 957 958 class OptionGroupFindMemory : public OptionGroup 959 { 960 public: 961 OptionGroupFindMemory () : 962 OptionGroup(), 963 m_count(1), 964 m_offset(0) 965 { 966 } 967 968 ~OptionGroupFindMemory () override 969 { 970 } 971 972 uint32_t 973 GetNumDefinitions () override 974 { 975 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition); 976 } 977 978 const OptionDefinition* 979 GetDefinitions () override 980 { 981 return g_memory_find_option_table; 982 } 983 984 Error 985 SetOptionValue (CommandInterpreter &interpreter, 986 uint32_t option_idx, 987 const char *option_arg) override 988 { 989 Error error; 990 const int short_option = g_memory_find_option_table[option_idx].short_option; 991 992 switch (short_option) 993 { 994 case 'e': 995 m_expr.SetValueFromString(option_arg); 996 break; 997 998 case 's': 999 m_string.SetValueFromString(option_arg); 1000 break; 1001 1002 case 'c': 1003 if (m_count.SetValueFromString(option_arg).Fail()) 1004 error.SetErrorString("unrecognized value for count"); 1005 break; 1006 1007 case 'o': 1008 if (m_offset.SetValueFromString(option_arg).Fail()) 1009 error.SetErrorString("unrecognized value for dump-offset"); 1010 break; 1011 1012 default: 1013 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 1014 break; 1015 } 1016 return error; 1017 } 1018 1019 void 1020 OptionParsingStarting (CommandInterpreter &interpreter) override 1021 { 1022 m_expr.Clear(); 1023 m_string.Clear(); 1024 m_count.Clear(); 1025 } 1026 1027 OptionValueString m_expr; 1028 OptionValueString m_string; 1029 OptionValueUInt64 m_count; 1030 OptionValueUInt64 m_offset; 1031 }; 1032 1033 CommandObjectMemoryFind (CommandInterpreter &interpreter) : 1034 CommandObjectParsed (interpreter, 1035 "memory find", 1036 "Find a value in the memory of the process being debugged.", 1037 NULL, 1038 eCommandRequiresProcess | eCommandProcessMustBeLaunched), 1039 m_option_group (interpreter), 1040 m_memory_options () 1041 { 1042 CommandArgumentEntry arg1; 1043 CommandArgumentEntry arg2; 1044 CommandArgumentData addr_arg; 1045 CommandArgumentData value_arg; 1046 1047 // Define the first (and only) variant of this arg. 1048 addr_arg.arg_type = eArgTypeAddressOrExpression; 1049 addr_arg.arg_repetition = eArgRepeatPlain; 1050 1051 // There is only one variant this argument could be; put it into the argument entry. 1052 arg1.push_back (addr_arg); 1053 1054 // Define the first (and only) variant of this arg. 1055 value_arg.arg_type = eArgTypeAddressOrExpression; 1056 value_arg.arg_repetition = eArgRepeatPlain; 1057 1058 // There is only one variant this argument could be; put it into the argument entry. 1059 arg2.push_back (value_arg); 1060 1061 // Push the data for the first argument into the m_arguments vector. 1062 m_arguments.push_back (arg1); 1063 m_arguments.push_back (arg2); 1064 1065 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 1066 m_option_group.Finalize(); 1067 } 1068 1069 ~CommandObjectMemoryFind () override 1070 { 1071 } 1072 1073 Options * 1074 GetOptions () override 1075 { 1076 return &m_option_group; 1077 } 1078 1079 protected: 1080 bool 1081 DoExecute (Args& command, CommandReturnObject &result) override 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 ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) && 1125 result_sp.get()) 1126 { 1127 uint64_t value = result_sp->GetValueAsUnsigned(0); 1128 switch (result_sp->GetCompilerType().GetByteSize(nullptr)) 1129 { 1130 case 1: { 1131 uint8_t byte = (uint8_t)value; 1132 buffer.CopyData(&byte,1); 1133 } 1134 break; 1135 case 2: { 1136 uint16_t word = (uint16_t)value; 1137 buffer.CopyData(&word,2); 1138 } 1139 break; 1140 case 4: { 1141 uint32_t lword = (uint32_t)value; 1142 buffer.CopyData(&lword,4); 1143 } 1144 break; 1145 case 8: { 1146 buffer.CopyData(&value, 8); 1147 } 1148 break; 1149 case 3: 1150 case 5: 1151 case 6: 1152 case 7: 1153 result.AppendError("unknown type. pass a string instead"); 1154 return false; 1155 default: 1156 result.AppendError("result size larger than 8 bytes. pass a string instead"); 1157 return false; 1158 } 1159 } 1160 else 1161 { 1162 result.AppendError("expression evaluation failed. pass a string instead"); 1163 return false; 1164 } 1165 } 1166 else 1167 { 1168 result.AppendError("please pass either a block of text, or an expression to evaluate."); 1169 return false; 1170 } 1171 1172 size_t count = m_memory_options.m_count.GetCurrentValue(); 1173 found_location = low_addr; 1174 bool ever_found = false; 1175 while (count) 1176 { 1177 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize()); 1178 if (found_location == LLDB_INVALID_ADDRESS) 1179 { 1180 if (!ever_found) 1181 { 1182 result.AppendMessage("data not found within the range.\n"); 1183 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 1184 } 1185 else 1186 result.AppendMessage("no more matches within the range.\n"); 1187 break; 1188 } 1189 result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location); 1190 1191 DataBufferHeap dumpbuffer(32,0); 1192 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error); 1193 if (!error.Fail()) 1194 { 1195 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize()); 1196 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0); 1197 result.GetOutputStream().EOL(); 1198 } 1199 1200 --count; 1201 found_location++; 1202 ever_found = true; 1203 } 1204 1205 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 1206 return true; 1207 } 1208 1209 lldb::addr_t 1210 Search (lldb::addr_t low, 1211 lldb::addr_t high, 1212 uint8_t* buffer, 1213 size_t buffer_size) 1214 { 1215 Process *process = m_exe_ctx.GetProcessPtr(); 1216 DataBufferHeap heap(buffer_size, 0); 1217 for (auto ptr = low; 1218 ptr < high; 1219 ptr++) 1220 { 1221 Error error; 1222 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error); 1223 if (error.Fail()) 1224 return LLDB_INVALID_ADDRESS; 1225 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0) 1226 return ptr; 1227 } 1228 return LLDB_INVALID_ADDRESS; 1229 } 1230 1231 OptionGroupOptions m_option_group; 1232 OptionGroupFindMemory m_memory_options; 1233 }; 1234 1235 1236 OptionDefinition 1237 g_memory_write_option_table[] = 1238 { 1239 { LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 1240 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."}, 1241 }; 1242 1243 //---------------------------------------------------------------------- 1244 // Write memory to the inferior process 1245 //---------------------------------------------------------------------- 1246 class CommandObjectMemoryWrite : public CommandObjectParsed 1247 { 1248 public: 1249 1250 class OptionGroupWriteMemory : public OptionGroup 1251 { 1252 public: 1253 OptionGroupWriteMemory () : 1254 OptionGroup() 1255 { 1256 } 1257 1258 ~OptionGroupWriteMemory () override 1259 { 1260 } 1261 1262 uint32_t 1263 GetNumDefinitions () override 1264 { 1265 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); 1266 } 1267 1268 const OptionDefinition* 1269 GetDefinitions () override 1270 { 1271 return g_memory_write_option_table; 1272 } 1273 1274 Error 1275 SetOptionValue (CommandInterpreter &interpreter, 1276 uint32_t option_idx, 1277 const char *option_arg) override 1278 { 1279 Error error; 1280 const int short_option = g_memory_write_option_table[option_idx].short_option; 1281 1282 switch (short_option) 1283 { 1284 case 'i': 1285 m_infile.SetFile (option_arg, true); 1286 if (!m_infile.Exists()) 1287 { 1288 m_infile.Clear(); 1289 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); 1290 } 1291 break; 1292 1293 case 'o': 1294 { 1295 bool success; 1296 m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success); 1297 if (!success) 1298 { 1299 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); 1300 } 1301 } 1302 break; 1303 1304 default: 1305 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 1306 break; 1307 } 1308 return error; 1309 } 1310 1311 void 1312 OptionParsingStarting (CommandInterpreter &interpreter) override 1313 { 1314 m_infile.Clear(); 1315 m_infile_offset = 0; 1316 } 1317 1318 FileSpec m_infile; 1319 off_t m_infile_offset; 1320 }; 1321 1322 CommandObjectMemoryWrite (CommandInterpreter &interpreter) : 1323 CommandObjectParsed (interpreter, 1324 "memory write", 1325 "Write to the memory of the process being debugged.", 1326 NULL, 1327 eCommandRequiresProcess | eCommandProcessMustBeLaunched), 1328 m_option_group (interpreter), 1329 m_format_options (eFormatBytes, 1, UINT64_MAX), 1330 m_memory_options () 1331 { 1332 CommandArgumentEntry arg1; 1333 CommandArgumentEntry arg2; 1334 CommandArgumentData addr_arg; 1335 CommandArgumentData value_arg; 1336 1337 // Define the first (and only) variant of this arg. 1338 addr_arg.arg_type = eArgTypeAddress; 1339 addr_arg.arg_repetition = eArgRepeatPlain; 1340 1341 // There is only one variant this argument could be; put it into the argument entry. 1342 arg1.push_back (addr_arg); 1343 1344 // Define the first (and only) variant of this arg. 1345 value_arg.arg_type = eArgTypeValue; 1346 value_arg.arg_repetition = eArgRepeatPlus; 1347 1348 // There is only one variant this argument could be; put it into the argument entry. 1349 arg2.push_back (value_arg); 1350 1351 // Push the data for the first argument into the m_arguments vector. 1352 m_arguments.push_back (arg1); 1353 m_arguments.push_back (arg2); 1354 1355 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); 1356 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); 1357 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 1358 m_option_group.Finalize(); 1359 1360 } 1361 1362 ~CommandObjectMemoryWrite () override 1363 { 1364 } 1365 1366 Options * 1367 GetOptions () override 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 bool 1401 DoExecute (Args& command, CommandReturnObject &result) override 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 ~CommandObjectMemoryHistory () override 1710 { 1711 } 1712 1713 const char * 1714 GetRepeatCommand (Args ¤t_command_args, uint32_t index) override 1715 { 1716 return m_cmd_name.c_str(); 1717 } 1718 1719 protected: 1720 bool 1721 DoExecute (Args& command, CommandReturnObject &result) override 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