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