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 eFlagRequiresTarget | 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 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid 375 Target *target = m_exe_ctx.GetTargetPtr(); 376 377 const size_t argc = command.GetArgumentCount(); 378 379 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) 380 { 381 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str()); 382 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n"); 383 result.SetStatus(eReturnStatusFailed); 384 return false; 385 } 386 387 ClangASTType clang_ast_type; 388 Error error; 389 390 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); 391 if (view_as_type_cstr && view_as_type_cstr[0]) 392 { 393 // We are viewing memory as a type 394 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 = m_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.AppendError(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 clang_ast_type = m_prev_clang_ast_type; 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::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error); 601 602 if (addr == LLDB_INVALID_ADDRESS) 603 { 604 result.AppendError("invalid start address expression."); 605 result.AppendError(error.AsCString()); 606 result.SetStatus(eReturnStatusFailed); 607 return false; 608 } 609 610 if (argc == 2) 611 { 612 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); 613 if (end_addr == LLDB_INVALID_ADDRESS) 614 { 615 result.AppendError("invalid end address expression."); 616 result.AppendError(error.AsCString()); 617 result.SetStatus(eReturnStatusFailed); 618 return false; 619 } 620 else if (end_addr <= addr) 621 { 622 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr); 623 result.SetStatus(eReturnStatusFailed); 624 return false; 625 } 626 else if (m_format_options.GetCountValue().OptionWasSet()) 627 { 628 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count); 629 result.SetStatus(eReturnStatusFailed); 630 return false; 631 } 632 633 total_byte_size = end_addr - addr; 634 item_count = total_byte_size / item_byte_size; 635 } 636 637 if (total_byte_size > 1024 && !m_memory_options.m_force) 638 { 639 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n"); 640 result.AppendErrorWithFormat("Please use --force to override this restriction.\n"); 641 return false; 642 } 643 644 DataBufferSP data_sp; 645 size_t bytes_read = 0; 646 if (clang_ast_type.GetOpaqueQualType()) 647 { 648 // Make sure we don't display our type as ASCII bytes like the default memory read 649 if (m_format_options.GetFormatValue().OptionWasSet() == false) 650 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); 651 652 bytes_read = clang_ast_type.GetTypeByteSize() * m_format_options.GetCountValue().GetCurrentValue(); 653 } 654 else 655 { 656 data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); 657 Address address(addr, NULL); 658 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); 659 if (bytes_read == 0) 660 { 661 const char *error_cstr = error.AsCString(); 662 if (error_cstr && error_cstr[0]) 663 { 664 result.AppendError(error_cstr); 665 } 666 else 667 { 668 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 669 } 670 result.SetStatus(eReturnStatusFailed); 671 return false; 672 } 673 674 if (bytes_read < total_byte_size) 675 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".", bytes_read, total_byte_size, addr); 676 } 677 678 m_next_addr = addr + bytes_read; 679 m_prev_byte_size = bytes_read; 680 m_prev_format_options = m_format_options; 681 m_prev_memory_options = m_memory_options; 682 m_prev_outfile_options = m_outfile_options; 683 m_prev_varobj_options = m_varobj_options; 684 m_prev_clang_ast_type = clang_ast_type; 685 686 StreamFile outfile_stream; 687 Stream *output_stream = NULL; 688 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 689 if (outfile_spec) 690 { 691 char path[PATH_MAX]; 692 outfile_spec.GetPath (path, sizeof(path)); 693 694 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 695 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 696 if (append) 697 open_options |= File::eOpenOptionAppend; 698 699 if (outfile_stream.GetFile ().Open (path, open_options).Success()) 700 { 701 if (m_memory_options.m_output_as_binary) 702 { 703 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 704 if (bytes_written > 0) 705 { 706 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", 707 bytes_written, 708 append ? "appended" : "written", 709 path); 710 return true; 711 } 712 else 713 { 714 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path); 715 result.SetStatus(eReturnStatusFailed); 716 return false; 717 } 718 } 719 else 720 { 721 // We are going to write ASCII to the file just point the 722 // output_stream to our outfile_stream... 723 output_stream = &outfile_stream; 724 } 725 } 726 else 727 { 728 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); 729 result.SetStatus(eReturnStatusFailed); 730 return false; 731 } 732 } 733 else 734 { 735 output_stream = &result.GetOutputStream(); 736 } 737 738 739 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); 740 if (clang_ast_type.GetOpaqueQualType()) 741 { 742 for (uint32_t i = 0; i<item_count; ++i) 743 { 744 addr_t item_addr = addr + (i * item_byte_size); 745 Address address (item_addr); 746 StreamString name_strm; 747 name_strm.Printf ("0x%" PRIx64, item_addr); 748 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 749 name_strm.GetString().c_str(), 750 address, 751 clang_ast_type)); 752 if (valobj_sp) 753 { 754 Format format = m_format_options.GetFormat(); 755 if (format != eFormatDefault) 756 valobj_sp->SetFormat (format); 757 758 bool scope_already_checked = true; 759 760 ValueObject::DumpValueObjectOptions options; 761 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth) 762 .SetMaximumDepth(m_varobj_options.max_depth) 763 .SetShowLocation(m_varobj_options.show_location) 764 .SetShowTypes(m_varobj_options.show_types) 765 .SetUseObjectiveC(m_varobj_options.use_objc) 766 .SetScopeChecked(scope_already_checked) 767 .SetFlatOutput(m_varobj_options.flat_output) 768 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth) 769 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth) 770 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap) 771 .SetFormat(format) 772 .SetSummary(); 773 ValueObject::DumpValueObject (*output_stream, 774 valobj_sp.get(), 775 options); 776 } 777 else 778 { 779 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 780 view_as_type_cstr, 781 name_strm.GetString().c_str()); 782 result.SetStatus(eReturnStatusFailed); 783 return false; 784 } 785 } 786 return true; 787 } 788 789 result.SetStatus(eReturnStatusSuccessFinishResult); 790 DataExtractor data (data_sp, 791 target->GetArchitecture().GetByteOrder(), 792 target->GetArchitecture().GetAddressByteSize()); 793 794 795 assert (output_stream); 796 uint32_t bytes_dumped = data.Dump (output_stream, 797 0, 798 m_format_options.GetFormat(), 799 item_byte_size, 800 item_count, 801 num_per_line, 802 addr, 803 0, 804 0, 805 exe_scope); 806 m_next_addr = addr + bytes_dumped; 807 output_stream->EOL(); 808 return true; 809 } 810 811 OptionGroupOptions m_option_group; 812 OptionGroupFormat m_format_options; 813 OptionGroupReadMemory m_memory_options; 814 OptionGroupOutputFile m_outfile_options; 815 OptionGroupValueObjectDisplay m_varobj_options; 816 lldb::addr_t m_next_addr; 817 lldb::addr_t m_prev_byte_size; 818 OptionGroupFormat m_prev_format_options; 819 OptionGroupReadMemory m_prev_memory_options; 820 OptionGroupOutputFile m_prev_outfile_options; 821 OptionGroupValueObjectDisplay m_prev_varobj_options; 822 ClangASTType m_prev_clang_ast_type; 823 }; 824 825 826 OptionDefinition 827 g_memory_write_option_table[] = 828 { 829 { LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 830 { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."}, 831 }; 832 833 834 //---------------------------------------------------------------------- 835 // Write memory to the inferior process 836 //---------------------------------------------------------------------- 837 class CommandObjectMemoryWrite : public CommandObjectParsed 838 { 839 public: 840 841 class OptionGroupWriteMemory : public OptionGroup 842 { 843 public: 844 OptionGroupWriteMemory () : 845 OptionGroup() 846 { 847 } 848 849 virtual 850 ~OptionGroupWriteMemory () 851 { 852 } 853 854 virtual uint32_t 855 GetNumDefinitions () 856 { 857 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); 858 } 859 860 virtual const OptionDefinition* 861 GetDefinitions () 862 { 863 return g_memory_write_option_table; 864 } 865 866 virtual Error 867 SetOptionValue (CommandInterpreter &interpreter, 868 uint32_t option_idx, 869 const char *option_arg) 870 { 871 Error error; 872 const int short_option = g_memory_write_option_table[option_idx].short_option; 873 874 switch (short_option) 875 { 876 case 'i': 877 m_infile.SetFile (option_arg, true); 878 if (!m_infile.Exists()) 879 { 880 m_infile.Clear(); 881 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); 882 } 883 break; 884 885 case 'o': 886 { 887 bool success; 888 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success); 889 if (!success) 890 { 891 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); 892 } 893 } 894 break; 895 896 default: 897 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 898 break; 899 } 900 return error; 901 } 902 903 virtual void 904 OptionParsingStarting (CommandInterpreter &interpreter) 905 { 906 m_infile.Clear(); 907 m_infile_offset = 0; 908 } 909 910 FileSpec m_infile; 911 off_t m_infile_offset; 912 }; 913 914 CommandObjectMemoryWrite (CommandInterpreter &interpreter) : 915 CommandObjectParsed (interpreter, 916 "memory write", 917 "Write to the memory of the process being debugged.", 918 NULL, 919 eFlagRequiresProcess | eFlagProcessMustBeLaunched), 920 m_option_group (interpreter), 921 m_format_options (eFormatBytes, 1, UINT64_MAX), 922 m_memory_options () 923 { 924 CommandArgumentEntry arg1; 925 CommandArgumentEntry arg2; 926 CommandArgumentData addr_arg; 927 CommandArgumentData value_arg; 928 929 // Define the first (and only) variant of this arg. 930 addr_arg.arg_type = eArgTypeAddress; 931 addr_arg.arg_repetition = eArgRepeatPlain; 932 933 // There is only one variant this argument could be; put it into the argument entry. 934 arg1.push_back (addr_arg); 935 936 // Define the first (and only) variant of this arg. 937 value_arg.arg_type = eArgTypeValue; 938 value_arg.arg_repetition = eArgRepeatPlus; 939 940 // There is only one variant this argument could be; put it into the argument entry. 941 arg2.push_back (value_arg); 942 943 // Push the data for the first argument into the m_arguments vector. 944 m_arguments.push_back (arg1); 945 m_arguments.push_back (arg2); 946 947 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); 948 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); 949 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 950 m_option_group.Finalize(); 951 952 } 953 954 virtual 955 ~CommandObjectMemoryWrite () 956 { 957 } 958 959 Options * 960 GetOptions () 961 { 962 return &m_option_group; 963 } 964 965 bool 966 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) 967 { 968 if (total_byte_size > 8) 969 return false; 970 971 if (total_byte_size == 8) 972 return true; 973 974 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; 975 return uval64 <= max; 976 } 977 978 bool 979 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) 980 { 981 if (total_byte_size > 8) 982 return false; 983 984 if (total_byte_size == 8) 985 return true; 986 987 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; 988 const int64_t min = ~(max); 989 return min <= sval64 && sval64 <= max; 990 } 991 992 protected: 993 virtual bool 994 DoExecute (Args& command, CommandReturnObject &result) 995 { 996 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid 997 Process *process = m_exe_ctx.GetProcessPtr(); 998 999 const size_t argc = command.GetArgumentCount(); 1000 1001 if (m_memory_options.m_infile) 1002 { 1003 if (argc < 1) 1004 { 1005 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); 1006 result.SetStatus(eReturnStatusFailed); 1007 return false; 1008 } 1009 } 1010 else if (argc < 2) 1011 { 1012 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); 1013 result.SetStatus(eReturnStatusFailed); 1014 return false; 1015 } 1016 1017 StreamString buffer (Stream::eBinary, 1018 process->GetTarget().GetArchitecture().GetAddressByteSize(), 1019 process->GetTarget().GetArchitecture().GetByteOrder()); 1020 1021 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); 1022 size_t item_byte_size = byte_size_value.GetCurrentValue(); 1023 1024 Error error; 1025 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, 1026 command.GetArgumentAtIndex(0), 1027 LLDB_INVALID_ADDRESS, 1028 &error); 1029 1030 if (addr == LLDB_INVALID_ADDRESS) 1031 { 1032 result.AppendError("invalid address expression\n"); 1033 result.AppendError(error.AsCString()); 1034 result.SetStatus(eReturnStatusFailed); 1035 return false; 1036 } 1037 1038 if (m_memory_options.m_infile) 1039 { 1040 size_t length = SIZE_MAX; 1041 if (item_byte_size > 0) 1042 length = item_byte_size; 1043 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); 1044 if (data_sp) 1045 { 1046 length = data_sp->GetByteSize(); 1047 if (length > 0) 1048 { 1049 Error error; 1050 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); 1051 1052 if (bytes_written == length) 1053 { 1054 // All bytes written 1055 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr); 1056 result.SetStatus(eReturnStatusSuccessFinishResult); 1057 } 1058 else if (bytes_written > 0) 1059 { 1060 // Some byte written 1061 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr); 1062 result.SetStatus(eReturnStatusSuccessFinishResult); 1063 } 1064 else 1065 { 1066 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1067 result.SetStatus(eReturnStatusFailed); 1068 } 1069 } 1070 } 1071 else 1072 { 1073 result.AppendErrorWithFormat ("Unable to read contents of file.\n"); 1074 result.SetStatus(eReturnStatusFailed); 1075 } 1076 return result.Succeeded(); 1077 } 1078 else if (item_byte_size == 0) 1079 { 1080 if (m_format_options.GetFormat() == eFormatPointer) 1081 item_byte_size = buffer.GetAddressByteSize(); 1082 else 1083 item_byte_size = 1; 1084 } 1085 1086 command.Shift(); // shift off the address argument 1087 uint64_t uval64; 1088 int64_t sval64; 1089 bool success = false; 1090 const uint32_t num_value_args = command.GetArgumentCount(); 1091 uint32_t i; 1092 for (i=0; i<num_value_args; ++i) 1093 { 1094 const char *value_str = command.GetArgumentAtIndex(i); 1095 1096 switch (m_format_options.GetFormat()) 1097 { 1098 case kNumFormats: 1099 case eFormatFloat: // TODO: add support for floats soon 1100 case eFormatCharPrintable: 1101 case eFormatBytesWithASCII: 1102 case eFormatComplex: 1103 case eFormatEnum: 1104 case eFormatUnicode16: 1105 case eFormatUnicode32: 1106 case eFormatVectorOfChar: 1107 case eFormatVectorOfSInt8: 1108 case eFormatVectorOfUInt8: 1109 case eFormatVectorOfSInt16: 1110 case eFormatVectorOfUInt16: 1111 case eFormatVectorOfSInt32: 1112 case eFormatVectorOfUInt32: 1113 case eFormatVectorOfSInt64: 1114 case eFormatVectorOfUInt64: 1115 case eFormatVectorOfFloat32: 1116 case eFormatVectorOfFloat64: 1117 case eFormatVectorOfUInt128: 1118 case eFormatOSType: 1119 case eFormatComplexInteger: 1120 case eFormatAddressInfo: 1121 case eFormatHexFloat: 1122 case eFormatInstruction: 1123 case eFormatVoid: 1124 result.AppendError("unsupported format for writing memory"); 1125 result.SetStatus(eReturnStatusFailed); 1126 return false; 1127 1128 case eFormatDefault: 1129 case eFormatBytes: 1130 case eFormatHex: 1131 case eFormatHexUppercase: 1132 case eFormatPointer: 1133 1134 // Decode hex bytes 1135 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success); 1136 if (!success) 1137 { 1138 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); 1139 result.SetStatus(eReturnStatusFailed); 1140 return false; 1141 } 1142 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1143 { 1144 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1145 result.SetStatus(eReturnStatusFailed); 1146 return false; 1147 } 1148 buffer.PutMaxHex64 (uval64, item_byte_size); 1149 break; 1150 1151 case eFormatBoolean: 1152 uval64 = Args::StringToBoolean(value_str, false, &success); 1153 if (!success) 1154 { 1155 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); 1156 result.SetStatus(eReturnStatusFailed); 1157 return false; 1158 } 1159 buffer.PutMaxHex64 (uval64, item_byte_size); 1160 break; 1161 1162 case eFormatBinary: 1163 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success); 1164 if (!success) 1165 { 1166 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); 1167 result.SetStatus(eReturnStatusFailed); 1168 return false; 1169 } 1170 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1171 { 1172 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1173 result.SetStatus(eReturnStatusFailed); 1174 return false; 1175 } 1176 buffer.PutMaxHex64 (uval64, item_byte_size); 1177 break; 1178 1179 case eFormatCharArray: 1180 case eFormatChar: 1181 case eFormatCString: 1182 if (value_str[0]) 1183 { 1184 size_t len = strlen (value_str); 1185 // Include the NULL for C strings... 1186 if (m_format_options.GetFormat() == eFormatCString) 1187 ++len; 1188 Error error; 1189 if (process->WriteMemory (addr, value_str, len, error) == len) 1190 { 1191 addr += len; 1192 } 1193 else 1194 { 1195 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1196 result.SetStatus(eReturnStatusFailed); 1197 return false; 1198 } 1199 } 1200 break; 1201 1202 case eFormatDecimal: 1203 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); 1204 if (!success) 1205 { 1206 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); 1207 result.SetStatus(eReturnStatusFailed); 1208 return false; 1209 } 1210 else if (!SIntValueIsValidForSize (sval64, item_byte_size)) 1211 { 1212 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size); 1213 result.SetStatus(eReturnStatusFailed); 1214 return false; 1215 } 1216 buffer.PutMaxHex64 (sval64, item_byte_size); 1217 break; 1218 1219 case eFormatUnsigned: 1220 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); 1221 if (!success) 1222 { 1223 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); 1224 result.SetStatus(eReturnStatusFailed); 1225 return false; 1226 } 1227 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1228 { 1229 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1230 result.SetStatus(eReturnStatusFailed); 1231 return false; 1232 } 1233 buffer.PutMaxHex64 (uval64, item_byte_size); 1234 break; 1235 1236 case eFormatOctal: 1237 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success); 1238 if (!success) 1239 { 1240 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); 1241 result.SetStatus(eReturnStatusFailed); 1242 return false; 1243 } 1244 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1245 { 1246 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1247 result.SetStatus(eReturnStatusFailed); 1248 return false; 1249 } 1250 buffer.PutMaxHex64 (uval64, item_byte_size); 1251 break; 1252 } 1253 } 1254 1255 if (!buffer.GetString().empty()) 1256 { 1257 Error error; 1258 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) 1259 return true; 1260 else 1261 { 1262 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1263 result.SetStatus(eReturnStatusFailed); 1264 return false; 1265 } 1266 } 1267 return true; 1268 } 1269 1270 OptionGroupOptions m_option_group; 1271 OptionGroupFormat m_format_options; 1272 OptionGroupWriteMemory m_memory_options; 1273 }; 1274 1275 1276 //------------------------------------------------------------------------- 1277 // CommandObjectMemory 1278 //------------------------------------------------------------------------- 1279 1280 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : 1281 CommandObjectMultiword (interpreter, 1282 "memory", 1283 "A set of commands for operating on memory.", 1284 "memory <subcommand> [<subcommand-options>]") 1285 { 1286 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); 1287 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); 1288 } 1289 1290 CommandObjectMemory::~CommandObjectMemory () 1291 { 1292 } 1293