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