CommandObjectMemory.cpp revision 52f792329be5db8e38961350589e97e8f2823acd
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// C++ Includes 16// Other libraries and framework includes 17// Project includes 18#include "lldb/Core/DataBufferHeap.h" 19#include "lldb/Core/DataExtractor.h" 20#include "lldb/Core/Debugger.h" 21#include "lldb/Core/Module.h" 22#include "lldb/Core/StreamString.h" 23#include "lldb/Core/ValueObjectMemory.h" 24#include "lldb/Interpreter/Args.h" 25#include "lldb/Interpreter/CommandReturnObject.h" 26#include "lldb/Interpreter/CommandInterpreter.h" 27#include "lldb/Interpreter/Options.h" 28#include "lldb/Interpreter/OptionGroupFormat.h" 29#include "lldb/Interpreter/OptionGroupOutputFile.h" 30#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" 31#include "lldb/Interpreter/OptionValueString.h" 32#include "lldb/Symbol/TypeList.h" 33#include "lldb/Target/Process.h" 34#include "lldb/Target/StackFrame.h" 35 36using namespace lldb; 37using namespace lldb_private; 38 39static OptionDefinition 40g_option_table[] = 41{ 42 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, 43 { LLDB_OPT_SET_2, false, "binary" ,'b', no_argument , 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."}, 44 { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, 45 { LLDB_OPT_SET_1| 46 LLDB_OPT_SET_2| 47 LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."}, 48}; 49 50 51 52class OptionGroupReadMemory : public OptionGroup 53{ 54public: 55 56 OptionGroupReadMemory () : 57 m_num_per_line (1,1), 58 m_output_as_binary (false), 59 m_view_as_type() 60 { 61 } 62 63 virtual 64 ~OptionGroupReadMemory () 65 { 66 } 67 68 69 virtual uint32_t 70 GetNumDefinitions () 71 { 72 return sizeof (g_option_table) / sizeof (OptionDefinition); 73 } 74 75 virtual const OptionDefinition* 76 GetDefinitions () 77 { 78 return g_option_table; 79 } 80 81 virtual Error 82 SetOptionValue (CommandInterpreter &interpreter, 83 uint32_t option_idx, 84 const char *option_arg) 85 { 86 Error error; 87 const int short_option = g_option_table[option_idx].short_option; 88 89 switch (short_option) 90 { 91 case 'l': 92 error = m_num_per_line.SetValueFromCString (option_arg); 93 if (m_num_per_line.GetCurrentValue() == 0) 94 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg); 95 break; 96 97 case 'b': 98 m_output_as_binary = true; 99 break; 100 101 case 't': 102 error = m_view_as_type.SetValueFromCString (option_arg); 103 break; 104 105 case 'r': 106 m_force = true; 107 break; 108 109 default: 110 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 111 break; 112 } 113 return error; 114 } 115 116 virtual void 117 OptionParsingStarting (CommandInterpreter &interpreter) 118 { 119 m_num_per_line.Clear(); 120 m_output_as_binary = false; 121 m_view_as_type.Clear(); 122 m_force = false; 123 } 124 125 Error 126 FinalizeSettings (Target *target, OptionGroupFormat& format_options) 127 { 128 Error error; 129 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue(); 130 OptionValueUInt64 &count_value = format_options.GetCountValue(); 131 const bool byte_size_option_set = byte_size_value.OptionWasSet(); 132 const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); 133 const bool count_option_set = format_options.GetCountValue().OptionWasSet(); 134 135 switch (format_options.GetFormat()) 136 { 137 default: 138 break; 139 140 case eFormatBoolean: 141 if (!byte_size_option_set) 142 byte_size_value = 1; 143 if (!num_per_line_option_set) 144 m_num_per_line = 1; 145 if (!count_option_set) 146 format_options.GetCountValue() = 8; 147 break; 148 149 case eFormatCString: 150 break; 151 152 case eFormatInstruction: 153 if (count_option_set) 154 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize(); 155 m_num_per_line = 1; 156 break; 157 158 case eFormatAddressInfo: 159 if (!byte_size_option_set) 160 byte_size_value = target->GetArchitecture().GetAddressByteSize(); 161 m_num_per_line = 1; 162 if (!count_option_set) 163 format_options.GetCountValue() = 8; 164 break; 165 166 case eFormatPointer: 167 byte_size_value = target->GetArchitecture().GetAddressByteSize(); 168 if (!num_per_line_option_set) 169 m_num_per_line = 4; 170 if (!count_option_set) 171 format_options.GetCountValue() = 8; 172 break; 173 174 case eFormatBinary: 175 case eFormatFloat: 176 case eFormatOctal: 177 case eFormatDecimal: 178 case eFormatEnum: 179 case eFormatUnicode16: 180 case eFormatUnicode32: 181 case eFormatUnsigned: 182 case eFormatHexFloat: 183 if (!byte_size_option_set) 184 byte_size_value = 4; 185 if (!num_per_line_option_set) 186 m_num_per_line = 1; 187 if (!count_option_set) 188 format_options.GetCountValue() = 8; 189 break; 190 191 case eFormatBytes: 192 case eFormatBytesWithASCII: 193 if (byte_size_option_set) 194 { 195 if (byte_size_value > 1) 196 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n" 197 "\tconsider using a different display format or don't specify the byte size", 198 byte_size_value.GetCurrentValue()); 199 } 200 else 201 byte_size_value = 1; 202 if (!num_per_line_option_set) 203 m_num_per_line = 16; 204 if (!count_option_set) 205 format_options.GetCountValue() = 32; 206 break; 207 case eFormatCharArray: 208 case eFormatChar: 209 case eFormatCharPrintable: 210 if (!byte_size_option_set) 211 byte_size_value = 1; 212 if (!num_per_line_option_set) 213 m_num_per_line = 32; 214 if (!count_option_set) 215 format_options.GetCountValue() = 64; 216 break; 217 case eFormatComplex: 218 if (!byte_size_option_set) 219 byte_size_value = 8; 220 if (!num_per_line_option_set) 221 m_num_per_line = 1; 222 if (!count_option_set) 223 format_options.GetCountValue() = 8; 224 break; 225 case eFormatComplexInteger: 226 if (!byte_size_option_set) 227 byte_size_value = 8; 228 if (!num_per_line_option_set) 229 m_num_per_line = 1; 230 if (!count_option_set) 231 format_options.GetCountValue() = 8; 232 break; 233 case eFormatHex: 234 if (!byte_size_option_set) 235 byte_size_value = 4; 236 if (!num_per_line_option_set) 237 { 238 switch (byte_size_value) 239 { 240 case 1: 241 case 2: 242 m_num_per_line = 8; 243 break; 244 case 4: 245 m_num_per_line = 4; 246 break; 247 case 8: 248 m_num_per_line = 2; 249 break; 250 default: 251 m_num_per_line = 1; 252 break; 253 } 254 } 255 if (!count_option_set) 256 count_value = 8; 257 break; 258 259 case eFormatVectorOfChar: 260 case eFormatVectorOfSInt8: 261 case eFormatVectorOfUInt8: 262 case eFormatVectorOfSInt16: 263 case eFormatVectorOfUInt16: 264 case eFormatVectorOfSInt32: 265 case eFormatVectorOfUInt32: 266 case eFormatVectorOfSInt64: 267 case eFormatVectorOfUInt64: 268 case eFormatVectorOfFloat32: 269 case eFormatVectorOfFloat64: 270 case eFormatVectorOfUInt128: 271 if (!byte_size_option_set) 272 byte_size_value = 128; 273 if (!num_per_line_option_set) 274 m_num_per_line = 1; 275 if (!count_option_set) 276 count_value = 4; 277 break; 278 } 279 return error; 280 } 281 282 bool 283 AnyOptionWasSet () const 284 { 285 return m_num_per_line.OptionWasSet() || 286 m_output_as_binary || 287 m_view_as_type.OptionWasSet(); 288 } 289 290 OptionValueUInt64 m_num_per_line; 291 bool m_output_as_binary; 292 OptionValueString m_view_as_type; 293 bool m_force; 294}; 295 296 297 298//---------------------------------------------------------------------- 299// Read memory from the inferior process 300//---------------------------------------------------------------------- 301class CommandObjectMemoryRead : public CommandObjectParsed 302{ 303public: 304 305 CommandObjectMemoryRead (CommandInterpreter &interpreter) : 306 CommandObjectParsed (interpreter, 307 "memory read", 308 "Read from the memory of the process being debugged.", 309 NULL, 310 eFlagRequiresTarget | eFlagProcessMustBePaused), 311 m_option_group (interpreter), 312 m_format_options (eFormatBytesWithASCII, 1, 8), 313 m_memory_options (), 314 m_outfile_options (), 315 m_varobj_options(), 316 m_next_addr(LLDB_INVALID_ADDRESS), 317 m_prev_byte_size(0), 318 m_prev_format_options (eFormatBytesWithASCII, 1, 8), 319 m_prev_memory_options (), 320 m_prev_outfile_options (), 321 m_prev_varobj_options() 322 { 323 CommandArgumentEntry arg1; 324 CommandArgumentEntry arg2; 325 CommandArgumentData start_addr_arg; 326 CommandArgumentData end_addr_arg; 327 328 // Define the first (and only) variant of this arg. 329 start_addr_arg.arg_type = eArgTypeAddressOrExpression; 330 start_addr_arg.arg_repetition = eArgRepeatPlain; 331 332 // There is only one variant this argument could be; put it into the argument entry. 333 arg1.push_back (start_addr_arg); 334 335 // Define the first (and only) variant of this arg. 336 end_addr_arg.arg_type = eArgTypeAddressOrExpression; 337 end_addr_arg.arg_repetition = eArgRepeatOptional; 338 339 // There is only one variant this argument could be; put it into the argument entry. 340 arg2.push_back (end_addr_arg); 341 342 // Push the data for the first argument into the m_arguments vector. 343 m_arguments.push_back (arg1); 344 m_arguments.push_back (arg2); 345 346 // Add the "--format" and "--count" options to group 1 and 3 347 m_option_group.Append (&m_format_options, 348 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT, 349 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 350 m_option_group.Append (&m_format_options, 351 OptionGroupFormat::OPTION_GROUP_GDB_FMT, 352 LLDB_OPT_SET_1 | LLDB_OPT_SET_3); 353 // Add the "--size" option to group 1 and 2 354 m_option_group.Append (&m_format_options, 355 OptionGroupFormat::OPTION_GROUP_SIZE, 356 LLDB_OPT_SET_1 | LLDB_OPT_SET_2); 357 m_option_group.Append (&m_memory_options); 358 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 359 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); 360 m_option_group.Finalize(); 361 } 362 363 virtual 364 ~CommandObjectMemoryRead () 365 { 366 } 367 368 Options * 369 GetOptions () 370 { 371 return &m_option_group; 372 } 373 374 virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 375 { 376 return m_cmd_name.c_str(); 377 } 378 379protected: 380 virtual bool 381 DoExecute (Args& command, CommandReturnObject &result) 382 { 383 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid 384 Target *target = m_exe_ctx.GetTargetPtr(); 385 386 const size_t argc = command.GetArgumentCount(); 387 388 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) 389 { 390 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str()); 391 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n"); 392 result.SetStatus(eReturnStatusFailed); 393 return false; 394 } 395 396 ClangASTType clang_ast_type; 397 Error error; 398 399 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); 400 if (view_as_type_cstr && view_as_type_cstr[0]) 401 { 402 // We are viewing memory as a type 403 404 SymbolContext sc; 405 const bool exact_match = false; 406 TypeList type_list; 407 uint32_t reference_count = 0; 408 uint32_t pointer_count = 0; 409 size_t idx; 410 411#define ALL_KEYWORDS \ 412 KEYWORD("const") \ 413 KEYWORD("volatile") \ 414 KEYWORD("restrict") \ 415 KEYWORD("struct") \ 416 KEYWORD("class") \ 417 KEYWORD("union") 418 419#define KEYWORD(s) s, 420 static const char *g_keywords[] = 421 { 422 ALL_KEYWORDS 423 }; 424#undef KEYWORD 425 426#define KEYWORD(s) (sizeof(s) - 1), 427 static const int g_keyword_lengths[] = 428 { 429 ALL_KEYWORDS 430 }; 431#undef KEYWORD 432 433#undef ALL_KEYWORDS 434 435 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *); 436 std::string type_str(view_as_type_cstr); 437 438 // Remove all instances of g_keywords that are followed by spaces 439 for (size_t i = 0; i < g_num_keywords; ++i) 440 { 441 const char *keyword = g_keywords[i]; 442 int keyword_len = g_keyword_lengths[i]; 443 444 idx = 0; 445 while ((idx = type_str.find (keyword, idx)) != std::string::npos) 446 { 447 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') 448 { 449 type_str.erase(idx, keyword_len+1); 450 idx = 0; 451 } 452 else 453 { 454 idx += keyword_len; 455 } 456 } 457 } 458 bool done = type_str.empty(); 459 // 460 idx = type_str.find_first_not_of (" \t"); 461 if (idx > 0 && idx != std::string::npos) 462 type_str.erase (0, idx); 463 while (!done) 464 { 465 // Strip trailing spaces 466 if (type_str.empty()) 467 done = true; 468 else 469 { 470 switch (type_str[type_str.size()-1]) 471 { 472 case '*': 473 ++pointer_count; 474 // fall through... 475 case ' ': 476 case '\t': 477 type_str.erase(type_str.size()-1); 478 break; 479 480 case '&': 481 if (reference_count == 0) 482 { 483 reference_count = 1; 484 type_str.erase(type_str.size()-1); 485 } 486 else 487 { 488 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); 489 result.SetStatus(eReturnStatusFailed); 490 return false; 491 } 492 break; 493 494 default: 495 done = true; 496 break; 497 } 498 } 499 } 500 501 ConstString lookup_type_name(type_str.c_str()); 502 StackFrame *frame = m_exe_ctx.GetFramePtr(); 503 if (frame) 504 { 505 sc = frame->GetSymbolContext (eSymbolContextModule); 506 if (sc.module_sp) 507 { 508 sc.module_sp->FindTypes (sc, 509 lookup_type_name, 510 exact_match, 511 1, 512 type_list); 513 } 514 } 515 if (type_list.GetSize() == 0) 516 { 517 target->GetImages().FindTypes (sc, 518 lookup_type_name, 519 exact_match, 520 1, 521 type_list); 522 } 523 524 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$') 525 { 526 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name)); 527 if (tdecl) 528 { 529 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl()); 530 } 531 } 532 533 if (clang_ast_type.IsValid() == false) 534 { 535 if (type_list.GetSize() == 0) 536 { 537 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", 538 lookup_type_name.GetCString(), 539 view_as_type_cstr); 540 result.SetStatus(eReturnStatusFailed); 541 return false; 542 } 543 else 544 { 545 TypeSP type_sp (type_list.GetTypeAtIndex(0)); 546 clang_ast_type = type_sp->GetClangFullType(); 547 } 548 } 549 550 while (pointer_count > 0) 551 { 552 ClangASTType pointer_type = clang_ast_type.GetPointerType(); 553 if (pointer_type.IsValid()) 554 clang_ast_type = pointer_type; 555 else 556 { 557 result.AppendError ("unable make a pointer type\n"); 558 result.SetStatus(eReturnStatusFailed); 559 return false; 560 } 561 --pointer_count; 562 } 563 564 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(); 565 566 if (m_format_options.GetByteSizeValue() == 0) 567 { 568 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 569 view_as_type_cstr); 570 result.SetStatus(eReturnStatusFailed); 571 return false; 572 } 573 574 if (!m_format_options.GetCountValue().OptionWasSet()) 575 m_format_options.GetCountValue() = 1; 576 } 577 else 578 { 579 error = m_memory_options.FinalizeSettings (target, m_format_options); 580 } 581 582 // Look for invalid combinations of settings 583 if (error.Fail()) 584 { 585 result.AppendError(error.AsCString()); 586 result.SetStatus(eReturnStatusFailed); 587 return false; 588 } 589 590 lldb::addr_t addr; 591 size_t total_byte_size = 0; 592 if (argc == 0) 593 { 594 // Use the last address and byte size and all options as they were 595 // if no options have been set 596 addr = m_next_addr; 597 total_byte_size = m_prev_byte_size; 598 clang_ast_type = m_prev_clang_ast_type; 599 if (!m_format_options.AnyOptionWasSet() && 600 !m_memory_options.AnyOptionWasSet() && 601 !m_outfile_options.AnyOptionWasSet() && 602 !m_varobj_options.AnyOptionWasSet()) 603 { 604 m_format_options = m_prev_format_options; 605 m_memory_options = m_prev_memory_options; 606 m_outfile_options = m_prev_outfile_options; 607 m_varobj_options = m_prev_varobj_options; 608 } 609 } 610 611 size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); 612 size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); 613 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); 614 615 if (total_byte_size == 0) 616 { 617 total_byte_size = item_count * item_byte_size; 618 if (total_byte_size == 0) 619 total_byte_size = 32; 620 } 621 622 if (argc > 0) 623 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error); 624 625 if (addr == LLDB_INVALID_ADDRESS) 626 { 627 result.AppendError("invalid start address expression."); 628 result.AppendError(error.AsCString()); 629 result.SetStatus(eReturnStatusFailed); 630 return false; 631 } 632 633 if (argc == 2) 634 { 635 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); 636 if (end_addr == LLDB_INVALID_ADDRESS) 637 { 638 result.AppendError("invalid end address expression."); 639 result.AppendError(error.AsCString()); 640 result.SetStatus(eReturnStatusFailed); 641 return false; 642 } 643 else if (end_addr <= addr) 644 { 645 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr); 646 result.SetStatus(eReturnStatusFailed); 647 return false; 648 } 649 else if (m_format_options.GetCountValue().OptionWasSet()) 650 { 651 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count); 652 result.SetStatus(eReturnStatusFailed); 653 return false; 654 } 655 656 total_byte_size = end_addr - addr; 657 item_count = total_byte_size / item_byte_size; 658 } 659 660 uint32_t max_unforced_size = target->GetMaximumMemReadSize(); 661 662 if (total_byte_size > max_unforced_size && !m_memory_options.m_force) 663 { 664 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size); 665 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n"); 666 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n"); 667 return false; 668 } 669 670 DataBufferSP data_sp; 671 size_t bytes_read = 0; 672 if (clang_ast_type.GetOpaqueQualType()) 673 { 674 // Make sure we don't display our type as ASCII bytes like the default memory read 675 if (m_format_options.GetFormatValue().OptionWasSet() == false) 676 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); 677 678 bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue(); 679 } 680 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) 681 { 682 data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); 683 Address address(addr, NULL); 684 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); 685 if (bytes_read == 0) 686 { 687 const char *error_cstr = error.AsCString(); 688 if (error_cstr && error_cstr[0]) 689 { 690 result.AppendError(error_cstr); 691 } 692 else 693 { 694 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 695 } 696 result.SetStatus(eReturnStatusFailed); 697 return false; 698 } 699 700 if (bytes_read < total_byte_size) 701 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr); 702 } 703 else 704 { 705 // we treat c-strings as a special case because they do not have a fixed size 706 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat()) 707 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); 708 else 709 item_byte_size = target->GetMaximumSizeOfStringSummary(); 710 if (!m_format_options.GetCountValue().OptionWasSet()) 711 item_count = 1; 712 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary 713 uint8_t *data_ptr = data_sp->GetBytes(); 714 auto data_addr = addr; 715 auto count = item_count; 716 item_count = 0; 717 while (item_count < count) 718 { 719 std::string buffer; 720 buffer.resize(item_byte_size+1,0); 721 Error error; 722 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error); 723 if (error.Fail()) 724 { 725 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 726 result.SetStatus(eReturnStatusFailed); 727 return false; 728 } 729 if (item_byte_size == read) 730 { 731 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr); 732 break; 733 } 734 read+=1; // account for final NULL byte 735 memcpy(data_ptr, &buffer[0], read); 736 data_ptr += read; 737 data_addr += read; 738 bytes_read += read; 739 item_count++; // if we break early we know we only read item_count strings 740 } 741 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1)); 742 } 743 744 m_next_addr = addr + bytes_read; 745 m_prev_byte_size = bytes_read; 746 m_prev_format_options = m_format_options; 747 m_prev_memory_options = m_memory_options; 748 m_prev_outfile_options = m_outfile_options; 749 m_prev_varobj_options = m_varobj_options; 750 m_prev_clang_ast_type = clang_ast_type; 751 752 StreamFile outfile_stream; 753 Stream *output_stream = NULL; 754 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 755 if (outfile_spec) 756 { 757 char path[PATH_MAX]; 758 outfile_spec.GetPath (path, sizeof(path)); 759 760 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 761 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 762 if (append) 763 open_options |= File::eOpenOptionAppend; 764 765 if (outfile_stream.GetFile ().Open (path, open_options).Success()) 766 { 767 if (m_memory_options.m_output_as_binary) 768 { 769 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 770 if (bytes_written > 0) 771 { 772 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n", 773 bytes_written, 774 append ? "appended" : "written", 775 path); 776 return true; 777 } 778 else 779 { 780 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path); 781 result.SetStatus(eReturnStatusFailed); 782 return false; 783 } 784 } 785 else 786 { 787 // We are going to write ASCII to the file just point the 788 // output_stream to our outfile_stream... 789 output_stream = &outfile_stream; 790 } 791 } 792 else 793 { 794 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); 795 result.SetStatus(eReturnStatusFailed); 796 return false; 797 } 798 } 799 else 800 { 801 output_stream = &result.GetOutputStream(); 802 } 803 804 805 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); 806 if (clang_ast_type.GetOpaqueQualType()) 807 { 808 for (uint32_t i = 0; i<item_count; ++i) 809 { 810 addr_t item_addr = addr + (i * item_byte_size); 811 Address address (item_addr); 812 StreamString name_strm; 813 name_strm.Printf ("0x%" PRIx64, item_addr); 814 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 815 name_strm.GetString().c_str(), 816 address, 817 clang_ast_type)); 818 if (valobj_sp) 819 { 820 Format format = m_format_options.GetFormat(); 821 if (format != eFormatDefault) 822 valobj_sp->SetFormat (format); 823 824 ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,format)); 825 826 ValueObject::DumpValueObject (*output_stream, 827 valobj_sp.get(), 828 options); 829 } 830 else 831 { 832 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 833 view_as_type_cstr, 834 name_strm.GetString().c_str()); 835 result.SetStatus(eReturnStatusFailed); 836 return false; 837 } 838 } 839 return true; 840 } 841 842 result.SetStatus(eReturnStatusSuccessFinishResult); 843 DataExtractor data (data_sp, 844 target->GetArchitecture().GetByteOrder(), 845 target->GetArchitecture().GetAddressByteSize()); 846 847 Format format = m_format_options.GetFormat(); 848 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) 849 && (item_byte_size != 1) 850 && (item_count == 1)) 851 { 852 // this turns requests such as 853 // memory read -fc -s10 -c1 *charPtrPtr 854 // which make no sense (what is a char of size 10?) 855 // into a request for fetching 10 chars of size 1 from the same memory location 856 format = eFormatCharArray; 857 item_count = item_byte_size; 858 item_byte_size = 1; 859 } 860 861 assert (output_stream); 862 size_t bytes_dumped = data.Dump (output_stream, 863 0, 864 format, 865 item_byte_size, 866 item_count, 867 num_per_line, 868 addr, 869 0, 870 0, 871 exe_scope); 872 m_next_addr = addr + bytes_dumped; 873 output_stream->EOL(); 874 return true; 875 } 876 877 OptionGroupOptions m_option_group; 878 OptionGroupFormat m_format_options; 879 OptionGroupReadMemory m_memory_options; 880 OptionGroupOutputFile m_outfile_options; 881 OptionGroupValueObjectDisplay m_varobj_options; 882 lldb::addr_t m_next_addr; 883 lldb::addr_t m_prev_byte_size; 884 OptionGroupFormat m_prev_format_options; 885 OptionGroupReadMemory m_prev_memory_options; 886 OptionGroupOutputFile m_prev_outfile_options; 887 OptionGroupValueObjectDisplay m_prev_varobj_options; 888 ClangASTType m_prev_clang_ast_type; 889}; 890 891 892OptionDefinition 893g_memory_write_option_table[] = 894{ 895{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 896{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."}, 897}; 898 899 900//---------------------------------------------------------------------- 901// Write memory to the inferior process 902//---------------------------------------------------------------------- 903class CommandObjectMemoryWrite : public CommandObjectParsed 904{ 905public: 906 907 class OptionGroupWriteMemory : public OptionGroup 908 { 909 public: 910 OptionGroupWriteMemory () : 911 OptionGroup() 912 { 913 } 914 915 virtual 916 ~OptionGroupWriteMemory () 917 { 918 } 919 920 virtual uint32_t 921 GetNumDefinitions () 922 { 923 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); 924 } 925 926 virtual const OptionDefinition* 927 GetDefinitions () 928 { 929 return g_memory_write_option_table; 930 } 931 932 virtual Error 933 SetOptionValue (CommandInterpreter &interpreter, 934 uint32_t option_idx, 935 const char *option_arg) 936 { 937 Error error; 938 const int short_option = g_memory_write_option_table[option_idx].short_option; 939 940 switch (short_option) 941 { 942 case 'i': 943 m_infile.SetFile (option_arg, true); 944 if (!m_infile.Exists()) 945 { 946 m_infile.Clear(); 947 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); 948 } 949 break; 950 951 case 'o': 952 { 953 bool success; 954 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success); 955 if (!success) 956 { 957 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); 958 } 959 } 960 break; 961 962 default: 963 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 964 break; 965 } 966 return error; 967 } 968 969 virtual void 970 OptionParsingStarting (CommandInterpreter &interpreter) 971 { 972 m_infile.Clear(); 973 m_infile_offset = 0; 974 } 975 976 FileSpec m_infile; 977 off_t m_infile_offset; 978 }; 979 980 CommandObjectMemoryWrite (CommandInterpreter &interpreter) : 981 CommandObjectParsed (interpreter, 982 "memory write", 983 "Write to the memory of the process being debugged.", 984 NULL, 985 eFlagRequiresProcess | eFlagProcessMustBeLaunched), 986 m_option_group (interpreter), 987 m_format_options (eFormatBytes, 1, UINT64_MAX), 988 m_memory_options () 989 { 990 CommandArgumentEntry arg1; 991 CommandArgumentEntry arg2; 992 CommandArgumentData addr_arg; 993 CommandArgumentData value_arg; 994 995 // Define the first (and only) variant of this arg. 996 addr_arg.arg_type = eArgTypeAddress; 997 addr_arg.arg_repetition = eArgRepeatPlain; 998 999 // There is only one variant this argument could be; put it into the argument entry. 1000 arg1.push_back (addr_arg); 1001 1002 // Define the first (and only) variant of this arg. 1003 value_arg.arg_type = eArgTypeValue; 1004 value_arg.arg_repetition = eArgRepeatPlus; 1005 1006 // There is only one variant this argument could be; put it into the argument entry. 1007 arg2.push_back (value_arg); 1008 1009 // Push the data for the first argument into the m_arguments vector. 1010 m_arguments.push_back (arg1); 1011 m_arguments.push_back (arg2); 1012 1013 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); 1014 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); 1015 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 1016 m_option_group.Finalize(); 1017 1018 } 1019 1020 virtual 1021 ~CommandObjectMemoryWrite () 1022 { 1023 } 1024 1025 Options * 1026 GetOptions () 1027 { 1028 return &m_option_group; 1029 } 1030 1031 bool 1032 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) 1033 { 1034 if (total_byte_size > 8) 1035 return false; 1036 1037 if (total_byte_size == 8) 1038 return true; 1039 1040 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; 1041 return uval64 <= max; 1042 } 1043 1044 bool 1045 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) 1046 { 1047 if (total_byte_size > 8) 1048 return false; 1049 1050 if (total_byte_size == 8) 1051 return true; 1052 1053 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; 1054 const int64_t min = ~(max); 1055 return min <= sval64 && sval64 <= max; 1056 } 1057 1058protected: 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 (m_memory_options.m_infile) 1068 { 1069 if (argc < 1) 1070 { 1071 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); 1072 result.SetStatus(eReturnStatusFailed); 1073 return false; 1074 } 1075 } 1076 else if (argc < 2) 1077 { 1078 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); 1079 result.SetStatus(eReturnStatusFailed); 1080 return false; 1081 } 1082 1083 StreamString buffer (Stream::eBinary, 1084 process->GetTarget().GetArchitecture().GetAddressByteSize(), 1085 process->GetTarget().GetArchitecture().GetByteOrder()); 1086 1087 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); 1088 size_t item_byte_size = byte_size_value.GetCurrentValue(); 1089 1090 Error error; 1091 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, 1092 command.GetArgumentAtIndex(0), 1093 LLDB_INVALID_ADDRESS, 1094 &error); 1095 1096 if (addr == LLDB_INVALID_ADDRESS) 1097 { 1098 result.AppendError("invalid address expression\n"); 1099 result.AppendError(error.AsCString()); 1100 result.SetStatus(eReturnStatusFailed); 1101 return false; 1102 } 1103 1104 if (m_memory_options.m_infile) 1105 { 1106 size_t length = SIZE_MAX; 1107 if (item_byte_size > 0) 1108 length = item_byte_size; 1109 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); 1110 if (data_sp) 1111 { 1112 length = data_sp->GetByteSize(); 1113 if (length > 0) 1114 { 1115 Error error; 1116 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); 1117 1118 if (bytes_written == length) 1119 { 1120 // All bytes written 1121 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr); 1122 result.SetStatus(eReturnStatusSuccessFinishResult); 1123 } 1124 else if (bytes_written > 0) 1125 { 1126 // Some byte written 1127 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr); 1128 result.SetStatus(eReturnStatusSuccessFinishResult); 1129 } 1130 else 1131 { 1132 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1133 result.SetStatus(eReturnStatusFailed); 1134 } 1135 } 1136 } 1137 else 1138 { 1139 result.AppendErrorWithFormat ("Unable to read contents of file.\n"); 1140 result.SetStatus(eReturnStatusFailed); 1141 } 1142 return result.Succeeded(); 1143 } 1144 else if (item_byte_size == 0) 1145 { 1146 if (m_format_options.GetFormat() == eFormatPointer) 1147 item_byte_size = buffer.GetAddressByteSize(); 1148 else 1149 item_byte_size = 1; 1150 } 1151 1152 command.Shift(); // shift off the address argument 1153 uint64_t uval64; 1154 int64_t sval64; 1155 bool success = false; 1156 const size_t num_value_args = command.GetArgumentCount(); 1157 for (size_t i=0; i<num_value_args; ++i) 1158 { 1159 const char *value_str = command.GetArgumentAtIndex(i); 1160 1161 switch (m_format_options.GetFormat()) 1162 { 1163 case kNumFormats: 1164 case eFormatFloat: // TODO: add support for floats soon 1165 case eFormatCharPrintable: 1166 case eFormatBytesWithASCII: 1167 case eFormatComplex: 1168 case eFormatEnum: 1169 case eFormatUnicode16: 1170 case eFormatUnicode32: 1171 case eFormatVectorOfChar: 1172 case eFormatVectorOfSInt8: 1173 case eFormatVectorOfUInt8: 1174 case eFormatVectorOfSInt16: 1175 case eFormatVectorOfUInt16: 1176 case eFormatVectorOfSInt32: 1177 case eFormatVectorOfUInt32: 1178 case eFormatVectorOfSInt64: 1179 case eFormatVectorOfUInt64: 1180 case eFormatVectorOfFloat32: 1181 case eFormatVectorOfFloat64: 1182 case eFormatVectorOfUInt128: 1183 case eFormatOSType: 1184 case eFormatComplexInteger: 1185 case eFormatAddressInfo: 1186 case eFormatHexFloat: 1187 case eFormatInstruction: 1188 case eFormatVoid: 1189 result.AppendError("unsupported format for writing memory"); 1190 result.SetStatus(eReturnStatusFailed); 1191 return false; 1192 1193 case eFormatDefault: 1194 case eFormatBytes: 1195 case eFormatHex: 1196 case eFormatHexUppercase: 1197 case eFormatPointer: 1198 1199 // Decode hex bytes 1200 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success); 1201 if (!success) 1202 { 1203 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); 1204 result.SetStatus(eReturnStatusFailed); 1205 return false; 1206 } 1207 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1208 { 1209 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1210 result.SetStatus(eReturnStatusFailed); 1211 return false; 1212 } 1213 buffer.PutMaxHex64 (uval64, item_byte_size); 1214 break; 1215 1216 case eFormatBoolean: 1217 uval64 = Args::StringToBoolean(value_str, false, &success); 1218 if (!success) 1219 { 1220 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); 1221 result.SetStatus(eReturnStatusFailed); 1222 return false; 1223 } 1224 buffer.PutMaxHex64 (uval64, item_byte_size); 1225 break; 1226 1227 case eFormatBinary: 1228 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success); 1229 if (!success) 1230 { 1231 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); 1232 result.SetStatus(eReturnStatusFailed); 1233 return false; 1234 } 1235 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1236 { 1237 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1238 result.SetStatus(eReturnStatusFailed); 1239 return false; 1240 } 1241 buffer.PutMaxHex64 (uval64, item_byte_size); 1242 break; 1243 1244 case eFormatCharArray: 1245 case eFormatChar: 1246 case eFormatCString: 1247 if (value_str[0]) 1248 { 1249 size_t len = strlen (value_str); 1250 // Include the NULL for C strings... 1251 if (m_format_options.GetFormat() == eFormatCString) 1252 ++len; 1253 Error error; 1254 if (process->WriteMemory (addr, value_str, len, error) == len) 1255 { 1256 addr += len; 1257 } 1258 else 1259 { 1260 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1261 result.SetStatus(eReturnStatusFailed); 1262 return false; 1263 } 1264 } 1265 break; 1266 1267 case eFormatDecimal: 1268 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); 1269 if (!success) 1270 { 1271 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); 1272 result.SetStatus(eReturnStatusFailed); 1273 return false; 1274 } 1275 else if (!SIntValueIsValidForSize (sval64, item_byte_size)) 1276 { 1277 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size); 1278 result.SetStatus(eReturnStatusFailed); 1279 return false; 1280 } 1281 buffer.PutMaxHex64 (sval64, item_byte_size); 1282 break; 1283 1284 case eFormatUnsigned: 1285 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); 1286 if (!success) 1287 { 1288 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); 1289 result.SetStatus(eReturnStatusFailed); 1290 return false; 1291 } 1292 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1293 { 1294 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1295 result.SetStatus(eReturnStatusFailed); 1296 return false; 1297 } 1298 buffer.PutMaxHex64 (uval64, item_byte_size); 1299 break; 1300 1301 case eFormatOctal: 1302 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success); 1303 if (!success) 1304 { 1305 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); 1306 result.SetStatus(eReturnStatusFailed); 1307 return false; 1308 } 1309 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1310 { 1311 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1312 result.SetStatus(eReturnStatusFailed); 1313 return false; 1314 } 1315 buffer.PutMaxHex64 (uval64, item_byte_size); 1316 break; 1317 } 1318 } 1319 1320 if (!buffer.GetString().empty()) 1321 { 1322 Error error; 1323 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) 1324 return true; 1325 else 1326 { 1327 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1328 result.SetStatus(eReturnStatusFailed); 1329 return false; 1330 } 1331 } 1332 return true; 1333 } 1334 1335 OptionGroupOptions m_option_group; 1336 OptionGroupFormat m_format_options; 1337 OptionGroupWriteMemory m_memory_options; 1338}; 1339 1340 1341//------------------------------------------------------------------------- 1342// CommandObjectMemory 1343//------------------------------------------------------------------------- 1344 1345CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : 1346 CommandObjectMultiword (interpreter, 1347 "memory", 1348 "A set of commands for operating on memory.", 1349 "memory <subcommand> [<subcommand-options>]") 1350{ 1351 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); 1352 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); 1353} 1354 1355CommandObjectMemory::~CommandObjectMemory () 1356{ 1357} 1358