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