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