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