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