1 //===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CommandObjectMemory.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/DataBufferHeap.h" 17 #include "lldb/Core/DataExtractor.h" 18 #include "lldb/Core/Debugger.h" 19 #include "lldb/Core/StreamString.h" 20 #include "lldb/Core/ValueObjectMemory.h" 21 #include "lldb/Interpreter/Args.h" 22 #include "lldb/Interpreter/CommandReturnObject.h" 23 #include "lldb/Interpreter/CommandInterpreter.h" 24 #include "lldb/Interpreter/Options.h" 25 #include "lldb/Interpreter/OptionGroupFormat.h" 26 #include "lldb/Interpreter/OptionGroupOutputFile.h" 27 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" 28 #include "lldb/Symbol/ClangNamespaceDecl.h" 29 #include "lldb/Target/Process.h" 30 #include "lldb/Target/StackFrame.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 static OptionDefinition 36 g_option_table[] = 37 { 38 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, 39 { 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."}, 40 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, 41 { LLDB_OPT_SET_4, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over 1024 bytes of memory."}, 42 }; 43 44 45 46 class OptionGroupReadMemory : public OptionGroup 47 { 48 public: 49 50 OptionGroupReadMemory () : 51 m_num_per_line (1,1), 52 m_output_as_binary (false), 53 m_view_as_type() 54 { 55 } 56 57 virtual 58 ~OptionGroupReadMemory () 59 { 60 } 61 62 63 virtual uint32_t 64 GetNumDefinitions () 65 { 66 return sizeof (g_option_table) / sizeof (OptionDefinition); 67 } 68 69 virtual const OptionDefinition* 70 GetDefinitions () 71 { 72 return g_option_table; 73 } 74 75 virtual Error 76 SetOptionValue (CommandInterpreter &interpreter, 77 uint32_t option_idx, 78 const char *option_arg) 79 { 80 Error error; 81 char short_option = (char) g_option_table[option_idx].short_option; 82 83 switch (short_option) 84 { 85 case 'l': 86 error = m_num_per_line.SetValueFromCString (option_arg); 87 if (m_num_per_line.GetCurrentValue() == 0) 88 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg); 89 break; 90 91 case 'b': 92 m_output_as_binary = true; 93 break; 94 95 case 't': 96 error = m_view_as_type.SetValueFromCString (option_arg); 97 break; 98 99 case 'r': 100 m_force = true; 101 break; 102 103 default: 104 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 105 break; 106 } 107 return error; 108 } 109 110 virtual void 111 OptionParsingStarting (CommandInterpreter &interpreter) 112 { 113 m_num_per_line.Clear(); 114 m_output_as_binary = false; 115 m_view_as_type.Clear(); 116 } 117 118 Error 119 FinalizeSettings (Target *target, OptionGroupFormat& format_options) 120 { 121 Error error; 122 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue(); 123 OptionValueUInt64 &count_value = format_options.GetCountValue(); 124 const bool byte_size_option_set = byte_size_value.OptionWasSet(); 125 const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); 126 const bool count_option_set = format_options.GetCountValue().OptionWasSet(); 127 128 switch (format_options.GetFormat()) 129 { 130 default: 131 break; 132 133 case eFormatBoolean: 134 if (!byte_size_option_set) 135 byte_size_value = 1; 136 if (!num_per_line_option_set) 137 m_num_per_line = 1; 138 if (!count_option_set) 139 format_options.GetCountValue() = 8; 140 break; 141 142 case eFormatCString: 143 break; 144 145 case eFormatInstruction: 146 if (count_option_set) 147 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize() * format_options.GetCountValue().GetCurrentValue(); 148 m_num_per_line = 1; 149 break; 150 151 case eFormatAddressInfo: 152 if (!byte_size_option_set) 153 byte_size_value = target->GetArchitecture().GetAddressByteSize(); 154 m_num_per_line = 1; 155 if (!count_option_set) 156 format_options.GetCountValue() = 8; 157 break; 158 159 case eFormatPointer: 160 byte_size_value = target->GetArchitecture().GetAddressByteSize(); 161 if (!num_per_line_option_set) 162 m_num_per_line = 4; 163 if (!count_option_set) 164 format_options.GetCountValue() = 8; 165 break; 166 167 case eFormatBinary: 168 case eFormatFloat: 169 case eFormatOctal: 170 case eFormatDecimal: 171 case eFormatEnum: 172 case eFormatUnicode16: 173 case eFormatUnicode32: 174 case eFormatUnsigned: 175 case eFormatHexFloat: 176 if (!byte_size_option_set) 177 byte_size_value = 4; 178 if (!num_per_line_option_set) 179 m_num_per_line = 1; 180 if (!count_option_set) 181 format_options.GetCountValue() = 8; 182 break; 183 184 case eFormatBytes: 185 case eFormatBytesWithASCII: 186 if (byte_size_option_set) 187 { 188 if (byte_size_value > 1) 189 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %llu\n" 190 "\tconsider using a different display format or don't specify the byte size", 191 byte_size_value.GetCurrentValue()); 192 } 193 else 194 byte_size_value = 1; 195 if (!num_per_line_option_set) 196 m_num_per_line = 16; 197 if (!count_option_set) 198 format_options.GetCountValue() = 32; 199 break; 200 case eFormatCharArray: 201 case eFormatChar: 202 case eFormatCharPrintable: 203 if (!byte_size_option_set) 204 byte_size_value = 1; 205 if (!num_per_line_option_set) 206 m_num_per_line = 32; 207 if (!count_option_set) 208 format_options.GetCountValue() = 64; 209 break; 210 case eFormatComplex: 211 if (!byte_size_option_set) 212 byte_size_value = 8; 213 if (!num_per_line_option_set) 214 m_num_per_line = 1; 215 if (!count_option_set) 216 format_options.GetCountValue() = 8; 217 break; 218 case eFormatHex: 219 if (!byte_size_option_set) 220 byte_size_value = 4; 221 if (!num_per_line_option_set) 222 { 223 switch (byte_size_value) 224 { 225 case 1: 226 case 2: 227 m_num_per_line = 8; 228 break; 229 case 4: 230 m_num_per_line = 4; 231 break; 232 case 8: 233 m_num_per_line = 2; 234 break; 235 default: 236 m_num_per_line = 1; 237 break; 238 } 239 } 240 if (!count_option_set) 241 count_value = 8; 242 break; 243 244 case eFormatVectorOfChar: 245 case eFormatVectorOfSInt8: 246 case eFormatVectorOfUInt8: 247 case eFormatVectorOfSInt16: 248 case eFormatVectorOfUInt16: 249 case eFormatVectorOfSInt32: 250 case eFormatVectorOfUInt32: 251 case eFormatVectorOfSInt64: 252 case eFormatVectorOfUInt64: 253 case eFormatVectorOfFloat32: 254 case eFormatVectorOfFloat64: 255 case eFormatVectorOfUInt128: 256 if (!byte_size_option_set) 257 byte_size_value = 128; 258 if (!num_per_line_option_set) 259 m_num_per_line = 1; 260 if (!count_option_set) 261 count_value = 4; 262 break; 263 } 264 return error; 265 } 266 267 bool 268 AnyOptionWasSet () const 269 { 270 return m_num_per_line.OptionWasSet() || 271 m_output_as_binary || 272 m_view_as_type.OptionWasSet(); 273 } 274 275 OptionValueUInt64 m_num_per_line; 276 bool m_output_as_binary; 277 OptionValueString m_view_as_type; 278 bool m_force; 279 }; 280 281 282 283 //---------------------------------------------------------------------- 284 // Read memory from the inferior process 285 //---------------------------------------------------------------------- 286 class CommandObjectMemoryRead : public CommandObjectParsed 287 { 288 public: 289 290 CommandObjectMemoryRead (CommandInterpreter &interpreter) : 291 CommandObjectParsed (interpreter, 292 "memory read", 293 "Read from the memory of the process being debugged.", 294 NULL, 295 eFlagProcessMustBePaused), 296 m_option_group (interpreter), 297 m_format_options (eFormatBytesWithASCII, 1, 8), 298 m_memory_options (), 299 m_outfile_options (), 300 m_varobj_options(), 301 m_next_addr(LLDB_INVALID_ADDRESS), 302 m_prev_byte_size(0), 303 m_prev_format_options (eFormatBytesWithASCII, 1, 8), 304 m_prev_memory_options (), 305 m_prev_outfile_options (), 306 m_prev_varobj_options() 307 { 308 CommandArgumentEntry arg1; 309 CommandArgumentEntry arg2; 310 CommandArgumentData start_addr_arg; 311 CommandArgumentData end_addr_arg; 312 313 // Define the first (and only) variant of this arg. 314 start_addr_arg.arg_type = eArgTypeStartAddress; 315 start_addr_arg.arg_repetition = eArgRepeatPlain; 316 317 // There is only one variant this argument could be; put it into the argument entry. 318 arg1.push_back (start_addr_arg); 319 320 // Define the first (and only) variant of this arg. 321 end_addr_arg.arg_type = eArgTypeEndAddress; 322 end_addr_arg.arg_repetition = eArgRepeatOptional; 323 324 // There is only one variant this argument could be; put it into the argument entry. 325 arg2.push_back (end_addr_arg); 326 327 // Push the data for the first argument into the m_arguments vector. 328 m_arguments.push_back (arg1); 329 m_arguments.push_back (arg2); 330 331 // Add the "--format" and "--count" options to group 1 and 3 332 m_option_group.Append (&m_format_options, 333 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT, 334 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 335 m_option_group.Append (&m_format_options, 336 OptionGroupFormat::OPTION_GROUP_GDB_FMT, 337 LLDB_OPT_SET_1 | LLDB_OPT_SET_3); 338 // Add the "--size" option to group 1 and 2 339 m_option_group.Append (&m_format_options, 340 OptionGroupFormat::OPTION_GROUP_SIZE, 341 LLDB_OPT_SET_1 | LLDB_OPT_SET_2); 342 m_option_group.Append (&m_memory_options); 343 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 344 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); 345 m_option_group.Finalize(); 346 } 347 348 virtual 349 ~CommandObjectMemoryRead () 350 { 351 } 352 353 Options * 354 GetOptions () 355 { 356 return &m_option_group; 357 } 358 359 virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 360 { 361 return m_cmd_name.c_str(); 362 } 363 364 protected: 365 virtual bool 366 DoExecute (Args& command, 367 CommandReturnObject &result) 368 { 369 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 370 Target *target = exe_ctx.GetTargetPtr(); 371 if (target == NULL) 372 { 373 result.AppendError("need at least a target to read memory"); 374 result.SetStatus(eReturnStatusFailed); 375 return false; 376 } 377 const size_t argc = command.GetArgumentCount(); 378 379 380 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) 381 { 382 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str()); 383 result.SetStatus(eReturnStatusFailed); 384 return false; 385 } 386 387 ClangASTType clang_ast_type; 388 Error error; 389 390 Format format = m_format_options.GetFormat(); 391 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); 392 if (view_as_type_cstr && view_as_type_cstr[0]) 393 { 394 // We are viewing memory as a type 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 = 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.AppendErrorWithFormat("%s", 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 if (!m_format_options.AnyOptionWasSet() && 576 !m_memory_options.AnyOptionWasSet() && 577 !m_outfile_options.AnyOptionWasSet() && 578 !m_varobj_options.AnyOptionWasSet()) 579 { 580 m_format_options = m_prev_format_options; 581 m_memory_options = m_prev_memory_options; 582 m_outfile_options = m_prev_outfile_options; 583 m_varobj_options = m_prev_varobj_options; 584 } 585 } 586 587 size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); 588 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); 589 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); 590 591 if (total_byte_size == 0) 592 { 593 total_byte_size = item_count * item_byte_size; 594 if (total_byte_size == 0) 595 total_byte_size = 32; 596 } 597 598 if (argc > 0) 599 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); 600 601 if (addr == LLDB_INVALID_ADDRESS) 602 { 603 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0)); 604 result.SetStatus(eReturnStatusFailed); 605 return false; 606 } 607 608 if (argc == 2) 609 { 610 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); 611 if (end_addr == LLDB_INVALID_ADDRESS) 612 { 613 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1)); 614 result.SetStatus(eReturnStatusFailed); 615 return false; 616 } 617 else if (end_addr <= addr) 618 { 619 result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr); 620 result.SetStatus(eReturnStatusFailed); 621 return false; 622 } 623 else if (m_format_options.GetCountValue().OptionWasSet()) 624 { 625 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count); 626 result.SetStatus(eReturnStatusFailed); 627 return false; 628 } 629 630 total_byte_size = end_addr - addr; 631 item_count = total_byte_size / item_byte_size; 632 } 633 634 if (total_byte_size > 1024 && !m_memory_options.m_force) 635 { 636 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n"); 637 result.AppendErrorWithFormat("Please use --force to override this restriction.\n"); 638 return false; 639 } 640 641 DataBufferSP data_sp; 642 size_t bytes_read = 0; 643 if (!clang_ast_type.GetOpaqueQualType()) 644 { 645 data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); 646 Address address(addr, NULL); 647 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); 648 if (bytes_read == 0) 649 { 650 const char *error_cstr = error.AsCString(); 651 if (error_cstr && error_cstr[0]) 652 { 653 result.AppendError(error_cstr); 654 } 655 else 656 { 657 result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr); 658 } 659 result.SetStatus(eReturnStatusFailed); 660 return false; 661 } 662 663 if (bytes_read < total_byte_size) 664 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr); 665 else 666 { 667 m_next_addr = addr + bytes_read; 668 m_prev_byte_size = bytes_read; 669 m_prev_format_options = m_format_options; 670 m_prev_memory_options = m_memory_options; 671 m_prev_outfile_options = m_outfile_options; 672 m_prev_varobj_options = m_varobj_options; 673 } 674 } 675 676 StreamFile outfile_stream; 677 Stream *output_stream = NULL; 678 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 679 if (outfile_spec) 680 { 681 char path[PATH_MAX]; 682 outfile_spec.GetPath (path, sizeof(path)); 683 684 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 685 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 686 if (append) 687 open_options |= File::eOpenOptionAppend; 688 689 if (outfile_stream.GetFile ().Open (path, open_options).Success()) 690 { 691 if (m_memory_options.m_output_as_binary) 692 { 693 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 694 if (bytes_written > 0) 695 { 696 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", 697 bytes_written, 698 append ? "appended" : "written", 699 path); 700 return true; 701 } 702 else 703 { 704 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path); 705 result.SetStatus(eReturnStatusFailed); 706 return false; 707 } 708 } 709 else 710 { 711 // We are going to write ASCII to the file just point the 712 // output_stream to our outfile_stream... 713 output_stream = &outfile_stream; 714 } 715 } 716 else 717 { 718 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); 719 result.SetStatus(eReturnStatusFailed); 720 return false; 721 } 722 } 723 else 724 { 725 output_stream = &result.GetOutputStream(); 726 } 727 728 729 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope(); 730 if (clang_ast_type.GetOpaqueQualType()) 731 { 732 for (uint32_t i = 0; i<item_count; ++i) 733 { 734 addr_t item_addr = addr + (i * item_byte_size); 735 Address address (item_addr); 736 StreamString name_strm; 737 name_strm.Printf ("0x%llx", item_addr); 738 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 739 name_strm.GetString().c_str(), 740 address, 741 clang_ast_type)); 742 if (valobj_sp) 743 { 744 if (format != eFormatDefault) 745 valobj_sp->SetFormat (format); 746 747 bool scope_already_checked = true; 748 749 ValueObject::DumpValueObjectOptions options; 750 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth) 751 .SetMaximumDepth(m_varobj_options.max_depth) 752 .SetShowLocation(m_varobj_options.show_location) 753 .SetShowTypes(m_varobj_options.show_types) 754 .SetUseObjectiveC(m_varobj_options.use_objc) 755 .SetScopeChecked(scope_already_checked) 756 .SetFlatOutput(m_varobj_options.flat_output) 757 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth) 758 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth) 759 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap) 760 .SetFormat(format) 761 .SetSummary(); 762 ValueObject::DumpValueObject (*output_stream, 763 valobj_sp.get(), 764 options); 765 } 766 else 767 { 768 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 769 view_as_type_cstr, 770 name_strm.GetString().c_str()); 771 result.SetStatus(eReturnStatusFailed); 772 return false; 773 } 774 } 775 return true; 776 } 777 778 result.SetStatus(eReturnStatusSuccessFinishResult); 779 DataExtractor data (data_sp, 780 target->GetArchitecture().GetByteOrder(), 781 target->GetArchitecture().GetAddressByteSize()); 782 783 784 assert (output_stream); 785 uint32_t bytes_dumped = data.Dump (output_stream, 786 0, 787 m_format_options.GetFormat(), 788 item_byte_size, 789 item_count, 790 num_per_line, 791 addr, 792 0, 793 0, 794 exe_scope); 795 m_next_addr = addr + bytes_dumped; 796 output_stream->EOL(); 797 return true; 798 } 799 800 OptionGroupOptions m_option_group; 801 OptionGroupFormat m_format_options; 802 OptionGroupReadMemory m_memory_options; 803 OptionGroupOutputFile m_outfile_options; 804 OptionGroupValueObjectDisplay m_varobj_options; 805 lldb::addr_t m_next_addr; 806 lldb::addr_t m_prev_byte_size; 807 OptionGroupFormat m_prev_format_options; 808 OptionGroupReadMemory m_prev_memory_options; 809 OptionGroupOutputFile m_prev_outfile_options; 810 OptionGroupValueObjectDisplay m_prev_varobj_options; 811 }; 812 813 814 OptionDefinition 815 g_memory_write_option_table[] = 816 { 817 { LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 818 { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."}, 819 }; 820 821 822 //---------------------------------------------------------------------- 823 // Write memory to the inferior process 824 //---------------------------------------------------------------------- 825 class CommandObjectMemoryWrite : public CommandObjectParsed 826 { 827 public: 828 829 class OptionGroupWriteMemory : public OptionGroup 830 { 831 public: 832 OptionGroupWriteMemory () : 833 OptionGroup() 834 { 835 } 836 837 virtual 838 ~OptionGroupWriteMemory () 839 { 840 } 841 842 virtual uint32_t 843 GetNumDefinitions () 844 { 845 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); 846 } 847 848 virtual const OptionDefinition* 849 GetDefinitions () 850 { 851 return g_memory_write_option_table; 852 } 853 854 virtual Error 855 SetOptionValue (CommandInterpreter &interpreter, 856 uint32_t option_idx, 857 const char *option_arg) 858 { 859 Error error; 860 char short_option = (char) g_memory_write_option_table[option_idx].short_option; 861 862 switch (short_option) 863 { 864 case 'i': 865 m_infile.SetFile (option_arg, true); 866 if (!m_infile.Exists()) 867 { 868 m_infile.Clear(); 869 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); 870 } 871 break; 872 873 case 'o': 874 { 875 bool success; 876 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success); 877 if (!success) 878 { 879 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); 880 } 881 } 882 break; 883 884 default: 885 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 886 break; 887 } 888 return error; 889 } 890 891 virtual void 892 OptionParsingStarting (CommandInterpreter &interpreter) 893 { 894 m_infile.Clear(); 895 m_infile_offset = 0; 896 } 897 898 FileSpec m_infile; 899 off_t m_infile_offset; 900 }; 901 902 CommandObjectMemoryWrite (CommandInterpreter &interpreter) : 903 CommandObjectParsed (interpreter, 904 "memory write", 905 "Write to the memory of the process being debugged.", 906 NULL, 907 eFlagProcessMustBeLaunched), 908 m_option_group (interpreter), 909 m_format_options (eFormatBytes, 1, UINT64_MAX), 910 m_memory_options () 911 { 912 CommandArgumentEntry arg1; 913 CommandArgumentEntry arg2; 914 CommandArgumentData addr_arg; 915 CommandArgumentData value_arg; 916 917 // Define the first (and only) variant of this arg. 918 addr_arg.arg_type = eArgTypeAddress; 919 addr_arg.arg_repetition = eArgRepeatPlain; 920 921 // There is only one variant this argument could be; put it into the argument entry. 922 arg1.push_back (addr_arg); 923 924 // Define the first (and only) variant of this arg. 925 value_arg.arg_type = eArgTypeValue; 926 value_arg.arg_repetition = eArgRepeatPlus; 927 928 // There is only one variant this argument could be; put it into the argument entry. 929 arg2.push_back (value_arg); 930 931 // Push the data for the first argument into the m_arguments vector. 932 m_arguments.push_back (arg1); 933 m_arguments.push_back (arg2); 934 935 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); 936 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); 937 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 938 m_option_group.Finalize(); 939 940 } 941 942 virtual 943 ~CommandObjectMemoryWrite () 944 { 945 } 946 947 Options * 948 GetOptions () 949 { 950 return &m_option_group; 951 } 952 953 bool 954 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) 955 { 956 if (total_byte_size > 8) 957 return false; 958 959 if (total_byte_size == 8) 960 return true; 961 962 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; 963 return uval64 <= max; 964 } 965 966 bool 967 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) 968 { 969 if (total_byte_size > 8) 970 return false; 971 972 if (total_byte_size == 8) 973 return true; 974 975 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; 976 const int64_t min = ~(max); 977 return min <= sval64 && sval64 <= max; 978 } 979 980 protected: 981 virtual bool 982 DoExecute (Args& command, CommandReturnObject &result) 983 { 984 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 985 if (process == NULL) 986 { 987 result.AppendError("need a process to read memory"); 988 result.SetStatus(eReturnStatusFailed); 989 return false; 990 } 991 992 const size_t argc = command.GetArgumentCount(); 993 994 if (m_memory_options.m_infile) 995 { 996 if (argc < 1) 997 { 998 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); 999 result.SetStatus(eReturnStatusFailed); 1000 return false; 1001 } 1002 } 1003 else if (argc < 2) 1004 { 1005 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); 1006 result.SetStatus(eReturnStatusFailed); 1007 return false; 1008 } 1009 1010 StreamString buffer (Stream::eBinary, 1011 process->GetTarget().GetArchitecture().GetAddressByteSize(), 1012 process->GetTarget().GetArchitecture().GetByteOrder()); 1013 1014 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); 1015 size_t item_byte_size = byte_size_value.GetCurrentValue(); 1016 1017 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); 1018 1019 if (addr == LLDB_INVALID_ADDRESS) 1020 { 1021 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0)); 1022 result.SetStatus(eReturnStatusFailed); 1023 return false; 1024 } 1025 1026 if (m_memory_options.m_infile) 1027 { 1028 size_t length = SIZE_MAX; 1029 if (item_byte_size > 0) 1030 length = item_byte_size; 1031 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); 1032 if (data_sp) 1033 { 1034 length = data_sp->GetByteSize(); 1035 if (length > 0) 1036 { 1037 Error error; 1038 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); 1039 1040 if (bytes_written == length) 1041 { 1042 // All bytes written 1043 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr); 1044 result.SetStatus(eReturnStatusSuccessFinishResult); 1045 } 1046 else if (bytes_written > 0) 1047 { 1048 // Some byte written 1049 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr); 1050 result.SetStatus(eReturnStatusSuccessFinishResult); 1051 } 1052 else 1053 { 1054 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 1055 result.SetStatus(eReturnStatusFailed); 1056 } 1057 } 1058 } 1059 else 1060 { 1061 result.AppendErrorWithFormat ("Unable to read contents of file.\n"); 1062 result.SetStatus(eReturnStatusFailed); 1063 } 1064 return result.Succeeded(); 1065 } 1066 else if (item_byte_size == 0) 1067 { 1068 if (m_format_options.GetFormat() == eFormatPointer) 1069 item_byte_size = buffer.GetAddressByteSize(); 1070 else 1071 item_byte_size = 1; 1072 } 1073 1074 command.Shift(); // shift off the address argument 1075 uint64_t uval64; 1076 int64_t sval64; 1077 bool success = false; 1078 const uint32_t num_value_args = command.GetArgumentCount(); 1079 uint32_t i; 1080 for (i=0; i<num_value_args; ++i) 1081 { 1082 const char *value_str = command.GetArgumentAtIndex(i); 1083 1084 switch (m_format_options.GetFormat()) 1085 { 1086 case kNumFormats: 1087 case eFormatFloat: // TODO: add support for floats soon 1088 case eFormatCharPrintable: 1089 case eFormatBytesWithASCII: 1090 case eFormatComplex: 1091 case eFormatEnum: 1092 case eFormatUnicode16: 1093 case eFormatUnicode32: 1094 case eFormatVectorOfChar: 1095 case eFormatVectorOfSInt8: 1096 case eFormatVectorOfUInt8: 1097 case eFormatVectorOfSInt16: 1098 case eFormatVectorOfUInt16: 1099 case eFormatVectorOfSInt32: 1100 case eFormatVectorOfUInt32: 1101 case eFormatVectorOfSInt64: 1102 case eFormatVectorOfUInt64: 1103 case eFormatVectorOfFloat32: 1104 case eFormatVectorOfFloat64: 1105 case eFormatVectorOfUInt128: 1106 case eFormatOSType: 1107 case eFormatComplexInteger: 1108 case eFormatAddressInfo: 1109 case eFormatHexFloat: 1110 case eFormatInstruction: 1111 case eFormatVoid: 1112 result.AppendError("unsupported format for writing memory"); 1113 result.SetStatus(eReturnStatusFailed); 1114 return false; 1115 1116 case eFormatDefault: 1117 case eFormatBytes: 1118 case eFormatHex: 1119 case eFormatHexUppercase: 1120 case eFormatPointer: 1121 1122 // Decode hex bytes 1123 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success); 1124 if (!success) 1125 { 1126 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); 1127 result.SetStatus(eReturnStatusFailed); 1128 return false; 1129 } 1130 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1131 { 1132 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1133 result.SetStatus(eReturnStatusFailed); 1134 return false; 1135 } 1136 buffer.PutMaxHex64 (uval64, item_byte_size); 1137 break; 1138 1139 case eFormatBoolean: 1140 uval64 = Args::StringToBoolean(value_str, false, &success); 1141 if (!success) 1142 { 1143 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); 1144 result.SetStatus(eReturnStatusFailed); 1145 return false; 1146 } 1147 buffer.PutMaxHex64 (uval64, item_byte_size); 1148 break; 1149 1150 case eFormatBinary: 1151 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success); 1152 if (!success) 1153 { 1154 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); 1155 result.SetStatus(eReturnStatusFailed); 1156 return false; 1157 } 1158 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1159 { 1160 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1161 result.SetStatus(eReturnStatusFailed); 1162 return false; 1163 } 1164 buffer.PutMaxHex64 (uval64, item_byte_size); 1165 break; 1166 1167 case eFormatCharArray: 1168 case eFormatChar: 1169 case eFormatCString: 1170 if (value_str[0]) 1171 { 1172 size_t len = strlen (value_str); 1173 // Include the NULL for C strings... 1174 if (m_format_options.GetFormat() == eFormatCString) 1175 ++len; 1176 Error error; 1177 if (process->WriteMemory (addr, value_str, len, error) == len) 1178 { 1179 addr += len; 1180 } 1181 else 1182 { 1183 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 1184 result.SetStatus(eReturnStatusFailed); 1185 return false; 1186 } 1187 } 1188 break; 1189 1190 case eFormatDecimal: 1191 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); 1192 if (!success) 1193 { 1194 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); 1195 result.SetStatus(eReturnStatusFailed); 1196 return false; 1197 } 1198 else if (!SIntValueIsValidForSize (sval64, item_byte_size)) 1199 { 1200 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size); 1201 result.SetStatus(eReturnStatusFailed); 1202 return false; 1203 } 1204 buffer.PutMaxHex64 (sval64, item_byte_size); 1205 break; 1206 1207 case eFormatUnsigned: 1208 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); 1209 if (!success) 1210 { 1211 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); 1212 result.SetStatus(eReturnStatusFailed); 1213 return false; 1214 } 1215 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1216 { 1217 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1218 result.SetStatus(eReturnStatusFailed); 1219 return false; 1220 } 1221 buffer.PutMaxHex64 (uval64, item_byte_size); 1222 break; 1223 1224 case eFormatOctal: 1225 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success); 1226 if (!success) 1227 { 1228 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); 1229 result.SetStatus(eReturnStatusFailed); 1230 return false; 1231 } 1232 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1233 { 1234 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1235 result.SetStatus(eReturnStatusFailed); 1236 return false; 1237 } 1238 buffer.PutMaxHex64 (uval64, item_byte_size); 1239 break; 1240 } 1241 } 1242 1243 if (!buffer.GetString().empty()) 1244 { 1245 Error error; 1246 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) 1247 return true; 1248 else 1249 { 1250 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 1251 result.SetStatus(eReturnStatusFailed); 1252 return false; 1253 } 1254 } 1255 return true; 1256 } 1257 1258 OptionGroupOptions m_option_group; 1259 OptionGroupFormat m_format_options; 1260 OptionGroupWriteMemory m_memory_options; 1261 }; 1262 1263 1264 //------------------------------------------------------------------------- 1265 // CommandObjectMemory 1266 //------------------------------------------------------------------------- 1267 1268 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : 1269 CommandObjectMultiword (interpreter, 1270 "memory", 1271 "A set of commands for operating on memory.", 1272 "memory <subcommand> [<subcommand-options>]") 1273 { 1274 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); 1275 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); 1276 } 1277 1278 CommandObjectMemory::~CommandObjectMemory () 1279 { 1280 } 1281