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