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