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