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 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"}; 402 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *); 403 std::string type_str(view_as_type_cstr); 404 405 // Remove all instances of g_keywords that are followed by spaces 406 for (size_t i = 0; i < g_num_keywords; ++i) 407 { 408 const char *keyword = g_keywords[i]; 409 int keyword_len = ::strlen (keyword); 410 while ((idx = type_str.find (keyword)) != std::string::npos) 411 { 412 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') 413 type_str.erase(idx, keyword_len+1); 414 } 415 } 416 bool done = type_str.empty(); 417 // 418 idx = type_str.find_first_not_of (" \t"); 419 if (idx > 0 && idx != std::string::npos) 420 type_str.erase (0, idx); 421 while (!done) 422 { 423 // Strip trailing spaces 424 if (type_str.empty()) 425 done = true; 426 else 427 { 428 switch (type_str[type_str.size()-1]) 429 { 430 case '*': 431 ++pointer_count; 432 // fall through... 433 case ' ': 434 case '\t': 435 type_str.erase(type_str.size()-1); 436 break; 437 438 case '&': 439 if (reference_count == 0) 440 { 441 reference_count = 1; 442 type_str.erase(type_str.size()-1); 443 } 444 else 445 { 446 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); 447 result.SetStatus(eReturnStatusFailed); 448 return false; 449 } 450 break; 451 452 default: 453 done = true; 454 break; 455 } 456 } 457 } 458 459 ConstString lookup_type_name(type_str.c_str()); 460 StackFrame *frame = exe_ctx.GetFramePtr(); 461 if (frame) 462 { 463 sc = frame->GetSymbolContext (eSymbolContextModule); 464 if (sc.module_sp) 465 { 466 sc.module_sp->FindTypes (sc, 467 lookup_type_name, 468 exact_match, 469 1, 470 type_list); 471 } 472 } 473 if (type_list.GetSize() == 0) 474 { 475 target->GetImages().FindTypes (sc, 476 lookup_type_name, 477 exact_match, 478 1, 479 type_list); 480 } 481 482 if (type_list.GetSize() == 0) 483 { 484 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", 485 lookup_type_name.GetCString(), 486 view_as_type_cstr); 487 result.SetStatus(eReturnStatusFailed); 488 return false; 489 } 490 491 TypeSP type_sp (type_list.GetTypeAtIndex(0)); 492 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType()); 493 494 while (pointer_count > 0) 495 { 496 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType()); 497 if (pointer_type) 498 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type); 499 else 500 { 501 result.AppendError ("unable make a pointer type\n"); 502 result.SetStatus(eReturnStatusFailed); 503 return false; 504 } 505 --pointer_count; 506 } 507 508 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8; 509 510 if (m_format_options.GetByteSizeValue() == 0) 511 { 512 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 513 view_as_type_cstr); 514 result.SetStatus(eReturnStatusFailed); 515 return false; 516 } 517 518 if (!m_format_options.GetCountValue().OptionWasSet()) 519 m_format_options.GetCountValue() = 1; 520 } 521 else 522 { 523 error = m_memory_options.FinalizeSettings (target, m_format_options); 524 } 525 526 // Look for invalid combinations of settings 527 if (error.Fail()) 528 { 529 result.AppendErrorWithFormat("%s", error.AsCString()); 530 result.SetStatus(eReturnStatusFailed); 531 return false; 532 } 533 534 lldb::addr_t addr; 535 size_t total_byte_size = 0; 536 if (argc == 0) 537 { 538 // Use the last address and byte size and all options as they were 539 // if no options have been set 540 addr = m_next_addr; 541 total_byte_size = m_prev_byte_size; 542 if (!m_format_options.AnyOptionWasSet() && 543 !m_memory_options.AnyOptionWasSet() && 544 !m_outfile_options.AnyOptionWasSet() && 545 !m_varobj_options.AnyOptionWasSet()) 546 { 547 m_format_options = m_prev_format_options; 548 m_memory_options = m_prev_memory_options; 549 m_outfile_options = m_prev_outfile_options; 550 m_varobj_options = m_prev_varobj_options; 551 } 552 } 553 554 size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); 555 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); 556 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); 557 558 if (total_byte_size == 0) 559 { 560 total_byte_size = item_count * item_byte_size; 561 if (total_byte_size == 0) 562 total_byte_size = 32; 563 } 564 565 if (argc > 0) 566 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); 567 568 if (addr == LLDB_INVALID_ADDRESS) 569 { 570 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0)); 571 result.SetStatus(eReturnStatusFailed); 572 return false; 573 } 574 575 if (argc == 2) 576 { 577 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); 578 if (end_addr == LLDB_INVALID_ADDRESS) 579 { 580 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1)); 581 result.SetStatus(eReturnStatusFailed); 582 return false; 583 } 584 else if (end_addr <= addr) 585 { 586 result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr); 587 result.SetStatus(eReturnStatusFailed); 588 return false; 589 } 590 else if (m_format_options.GetCountValue().OptionWasSet()) 591 { 592 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count); 593 result.SetStatus(eReturnStatusFailed); 594 return false; 595 } 596 597 total_byte_size = end_addr - addr; 598 item_count = total_byte_size / item_byte_size; 599 } 600 601 if (total_byte_size > 1024 && !m_memory_options.m_force) 602 { 603 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n"); 604 result.AppendErrorWithFormat("Please use --force to override this restriction.\n"); 605 return false; 606 } 607 608 DataBufferSP data_sp; 609 size_t bytes_read = 0; 610 if (!clang_ast_type.GetOpaqueQualType()) 611 { 612 data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); 613 Address address(addr, NULL); 614 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); 615 if (bytes_read == 0) 616 { 617 const char *error_cstr = error.AsCString(); 618 if (error_cstr && error_cstr[0]) 619 { 620 result.AppendError(error_cstr); 621 } 622 else 623 { 624 result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr); 625 } 626 result.SetStatus(eReturnStatusFailed); 627 return false; 628 } 629 630 if (bytes_read < total_byte_size) 631 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr); 632 else 633 { 634 m_next_addr = addr + bytes_read; 635 m_prev_byte_size = bytes_read; 636 m_prev_format_options = m_format_options; 637 m_prev_memory_options = m_memory_options; 638 m_prev_outfile_options = m_outfile_options; 639 m_prev_varobj_options = m_varobj_options; 640 } 641 } 642 643 StreamFile outfile_stream; 644 Stream *output_stream = NULL; 645 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 646 if (outfile_spec) 647 { 648 char path[PATH_MAX]; 649 outfile_spec.GetPath (path, sizeof(path)); 650 651 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 652 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 653 if (append) 654 open_options |= File::eOpenOptionAppend; 655 656 if (outfile_stream.GetFile ().Open (path, open_options).Success()) 657 { 658 if (m_memory_options.m_output_as_binary) 659 { 660 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 661 if (bytes_written > 0) 662 { 663 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", 664 bytes_written, 665 append ? "appended" : "written", 666 path); 667 return true; 668 } 669 else 670 { 671 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path); 672 result.SetStatus(eReturnStatusFailed); 673 return false; 674 } 675 } 676 else 677 { 678 // We are going to write ASCII to the file just point the 679 // output_stream to our outfile_stream... 680 output_stream = &outfile_stream; 681 } 682 } 683 else 684 { 685 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); 686 result.SetStatus(eReturnStatusFailed); 687 return false; 688 } 689 } 690 else 691 { 692 output_stream = &result.GetOutputStream(); 693 } 694 695 696 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope(); 697 if (clang_ast_type.GetOpaqueQualType()) 698 { 699 for (uint32_t i = 0; i<item_count; ++i) 700 { 701 addr_t item_addr = addr + (i * item_byte_size); 702 Address address (item_addr); 703 StreamString name_strm; 704 name_strm.Printf ("0x%llx", item_addr); 705 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 706 name_strm.GetString().c_str(), 707 address, 708 clang_ast_type)); 709 if (valobj_sp) 710 { 711 if (format != eFormatDefault) 712 valobj_sp->SetFormat (format); 713 714 bool scope_already_checked = true; 715 716 ValueObject::DumpValueObjectOptions options; 717 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth) 718 .SetMaximumDepth(m_varobj_options.max_depth) 719 .SetShowLocation(m_varobj_options.show_location) 720 .SetShowTypes(m_varobj_options.show_types) 721 .SetUseObjectiveC(m_varobj_options.use_objc) 722 .SetScopeChecked(scope_already_checked) 723 .SetFlatOutput(m_varobj_options.flat_output) 724 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth) 725 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth) 726 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap) 727 .SetFormat(format) 728 .SetSummary(); 729 ValueObject::DumpValueObject (*output_stream, 730 valobj_sp.get(), 731 options); 732 } 733 else 734 { 735 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 736 view_as_type_cstr, 737 name_strm.GetString().c_str()); 738 result.SetStatus(eReturnStatusFailed); 739 return false; 740 } 741 } 742 return true; 743 } 744 745 result.SetStatus(eReturnStatusSuccessFinishResult); 746 DataExtractor data (data_sp, 747 target->GetArchitecture().GetByteOrder(), 748 target->GetArchitecture().GetAddressByteSize()); 749 750 751 assert (output_stream); 752 uint32_t bytes_dumped = data.Dump (output_stream, 753 0, 754 m_format_options.GetFormat(), 755 item_byte_size, 756 item_count, 757 num_per_line, 758 addr, 759 0, 760 0, 761 exe_scope); 762 m_next_addr = addr + bytes_dumped; 763 output_stream->EOL(); 764 return true; 765 } 766 767 OptionGroupOptions m_option_group; 768 OptionGroupFormat m_format_options; 769 OptionGroupReadMemory m_memory_options; 770 OptionGroupOutputFile m_outfile_options; 771 OptionGroupValueObjectDisplay m_varobj_options; 772 lldb::addr_t m_next_addr; 773 lldb::addr_t m_prev_byte_size; 774 OptionGroupFormat m_prev_format_options; 775 OptionGroupReadMemory m_prev_memory_options; 776 OptionGroupOutputFile m_prev_outfile_options; 777 OptionGroupValueObjectDisplay m_prev_varobj_options; 778 }; 779 780 781 OptionDefinition 782 g_memory_write_option_table[] = 783 { 784 { LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 785 { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."}, 786 }; 787 788 789 //---------------------------------------------------------------------- 790 // Write memory to the inferior process 791 //---------------------------------------------------------------------- 792 class CommandObjectMemoryWrite : public CommandObjectParsed 793 { 794 public: 795 796 class OptionGroupWriteMemory : public OptionGroup 797 { 798 public: 799 OptionGroupWriteMemory () : 800 OptionGroup() 801 { 802 } 803 804 virtual 805 ~OptionGroupWriteMemory () 806 { 807 } 808 809 virtual uint32_t 810 GetNumDefinitions () 811 { 812 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); 813 } 814 815 virtual const OptionDefinition* 816 GetDefinitions () 817 { 818 return g_memory_write_option_table; 819 } 820 821 virtual Error 822 SetOptionValue (CommandInterpreter &interpreter, 823 uint32_t option_idx, 824 const char *option_arg) 825 { 826 Error error; 827 char short_option = (char) g_memory_write_option_table[option_idx].short_option; 828 829 switch (short_option) 830 { 831 case 'i': 832 m_infile.SetFile (option_arg, true); 833 if (!m_infile.Exists()) 834 { 835 m_infile.Clear(); 836 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); 837 } 838 break; 839 840 case 'o': 841 { 842 bool success; 843 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success); 844 if (!success) 845 { 846 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); 847 } 848 } 849 break; 850 851 default: 852 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 853 break; 854 } 855 return error; 856 } 857 858 virtual void 859 OptionParsingStarting (CommandInterpreter &interpreter) 860 { 861 m_infile.Clear(); 862 m_infile_offset = 0; 863 } 864 865 FileSpec m_infile; 866 off_t m_infile_offset; 867 }; 868 869 CommandObjectMemoryWrite (CommandInterpreter &interpreter) : 870 CommandObjectParsed (interpreter, 871 "memory write", 872 "Write to the memory of the process being debugged.", 873 NULL, 874 eFlagProcessMustBeLaunched), 875 m_option_group (interpreter), 876 m_format_options (eFormatBytes, 1, UINT64_MAX), 877 m_memory_options () 878 { 879 CommandArgumentEntry arg1; 880 CommandArgumentEntry arg2; 881 CommandArgumentData addr_arg; 882 CommandArgumentData value_arg; 883 884 // Define the first (and only) variant of this arg. 885 addr_arg.arg_type = eArgTypeAddress; 886 addr_arg.arg_repetition = eArgRepeatPlain; 887 888 // There is only one variant this argument could be; put it into the argument entry. 889 arg1.push_back (addr_arg); 890 891 // Define the first (and only) variant of this arg. 892 value_arg.arg_type = eArgTypeValue; 893 value_arg.arg_repetition = eArgRepeatPlus; 894 895 // There is only one variant this argument could be; put it into the argument entry. 896 arg2.push_back (value_arg); 897 898 // Push the data for the first argument into the m_arguments vector. 899 m_arguments.push_back (arg1); 900 m_arguments.push_back (arg2); 901 902 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); 903 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); 904 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 905 m_option_group.Finalize(); 906 907 } 908 909 virtual 910 ~CommandObjectMemoryWrite () 911 { 912 } 913 914 Options * 915 GetOptions () 916 { 917 return &m_option_group; 918 } 919 920 bool 921 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) 922 { 923 if (total_byte_size > 8) 924 return false; 925 926 if (total_byte_size == 8) 927 return true; 928 929 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; 930 return uval64 <= max; 931 } 932 933 bool 934 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) 935 { 936 if (total_byte_size > 8) 937 return false; 938 939 if (total_byte_size == 8) 940 return true; 941 942 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; 943 const int64_t min = ~(max); 944 return min <= sval64 && sval64 <= max; 945 } 946 947 protected: 948 virtual bool 949 DoExecute (Args& command, CommandReturnObject &result) 950 { 951 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 952 if (process == NULL) 953 { 954 result.AppendError("need a process to read memory"); 955 result.SetStatus(eReturnStatusFailed); 956 return false; 957 } 958 959 const size_t argc = command.GetArgumentCount(); 960 961 if (m_memory_options.m_infile) 962 { 963 if (argc < 1) 964 { 965 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); 966 result.SetStatus(eReturnStatusFailed); 967 return false; 968 } 969 } 970 else if (argc < 2) 971 { 972 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); 973 result.SetStatus(eReturnStatusFailed); 974 return false; 975 } 976 977 StreamString buffer (Stream::eBinary, 978 process->GetTarget().GetArchitecture().GetAddressByteSize(), 979 process->GetTarget().GetArchitecture().GetByteOrder()); 980 981 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); 982 size_t item_byte_size = byte_size_value.GetCurrentValue(); 983 984 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); 985 986 if (addr == LLDB_INVALID_ADDRESS) 987 { 988 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0)); 989 result.SetStatus(eReturnStatusFailed); 990 return false; 991 } 992 993 if (m_memory_options.m_infile) 994 { 995 size_t length = SIZE_MAX; 996 if (item_byte_size > 0) 997 length = item_byte_size; 998 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); 999 if (data_sp) 1000 { 1001 length = data_sp->GetByteSize(); 1002 if (length > 0) 1003 { 1004 Error error; 1005 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); 1006 1007 if (bytes_written == length) 1008 { 1009 // All bytes written 1010 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr); 1011 result.SetStatus(eReturnStatusSuccessFinishResult); 1012 } 1013 else if (bytes_written > 0) 1014 { 1015 // Some byte written 1016 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr); 1017 result.SetStatus(eReturnStatusSuccessFinishResult); 1018 } 1019 else 1020 { 1021 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 1022 result.SetStatus(eReturnStatusFailed); 1023 } 1024 } 1025 } 1026 else 1027 { 1028 result.AppendErrorWithFormat ("Unable to read contents of file.\n"); 1029 result.SetStatus(eReturnStatusFailed); 1030 } 1031 return result.Succeeded(); 1032 } 1033 else if (item_byte_size == 0) 1034 { 1035 if (m_format_options.GetFormat() == eFormatPointer) 1036 item_byte_size = buffer.GetAddressByteSize(); 1037 else 1038 item_byte_size = 1; 1039 } 1040 1041 command.Shift(); // shift off the address argument 1042 uint64_t uval64; 1043 int64_t sval64; 1044 bool success = false; 1045 const uint32_t num_value_args = command.GetArgumentCount(); 1046 uint32_t i; 1047 for (i=0; i<num_value_args; ++i) 1048 { 1049 const char *value_str = command.GetArgumentAtIndex(i); 1050 1051 switch (m_format_options.GetFormat()) 1052 { 1053 case kNumFormats: 1054 case eFormatFloat: // TODO: add support for floats soon 1055 case eFormatCharPrintable: 1056 case eFormatBytesWithASCII: 1057 case eFormatComplex: 1058 case eFormatEnum: 1059 case eFormatUnicode16: 1060 case eFormatUnicode32: 1061 case eFormatVectorOfChar: 1062 case eFormatVectorOfSInt8: 1063 case eFormatVectorOfUInt8: 1064 case eFormatVectorOfSInt16: 1065 case eFormatVectorOfUInt16: 1066 case eFormatVectorOfSInt32: 1067 case eFormatVectorOfUInt32: 1068 case eFormatVectorOfSInt64: 1069 case eFormatVectorOfUInt64: 1070 case eFormatVectorOfFloat32: 1071 case eFormatVectorOfFloat64: 1072 case eFormatVectorOfUInt128: 1073 case eFormatOSType: 1074 case eFormatComplexInteger: 1075 case eFormatAddressInfo: 1076 case eFormatHexFloat: 1077 case eFormatInstruction: 1078 result.AppendError("unsupported format for writing memory"); 1079 result.SetStatus(eReturnStatusFailed); 1080 return false; 1081 1082 case eFormatDefault: 1083 case eFormatBytes: 1084 case eFormatHex: 1085 case eFormatPointer: 1086 1087 // Decode hex bytes 1088 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success); 1089 if (!success) 1090 { 1091 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); 1092 result.SetStatus(eReturnStatusFailed); 1093 return false; 1094 } 1095 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1096 { 1097 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1098 result.SetStatus(eReturnStatusFailed); 1099 return false; 1100 } 1101 buffer.PutMaxHex64 (uval64, item_byte_size); 1102 break; 1103 1104 case eFormatBoolean: 1105 uval64 = Args::StringToBoolean(value_str, false, &success); 1106 if (!success) 1107 { 1108 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); 1109 result.SetStatus(eReturnStatusFailed); 1110 return false; 1111 } 1112 buffer.PutMaxHex64 (uval64, item_byte_size); 1113 break; 1114 1115 case eFormatBinary: 1116 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success); 1117 if (!success) 1118 { 1119 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); 1120 result.SetStatus(eReturnStatusFailed); 1121 return false; 1122 } 1123 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1124 { 1125 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1126 result.SetStatus(eReturnStatusFailed); 1127 return false; 1128 } 1129 buffer.PutMaxHex64 (uval64, item_byte_size); 1130 break; 1131 1132 case eFormatCharArray: 1133 case eFormatChar: 1134 case eFormatCString: 1135 if (value_str[0]) 1136 { 1137 size_t len = strlen (value_str); 1138 // Include the NULL for C strings... 1139 if (m_format_options.GetFormat() == eFormatCString) 1140 ++len; 1141 Error error; 1142 if (process->WriteMemory (addr, value_str, len, error) == len) 1143 { 1144 addr += len; 1145 } 1146 else 1147 { 1148 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 1149 result.SetStatus(eReturnStatusFailed); 1150 return false; 1151 } 1152 } 1153 break; 1154 1155 case eFormatDecimal: 1156 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); 1157 if (!success) 1158 { 1159 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); 1160 result.SetStatus(eReturnStatusFailed); 1161 return false; 1162 } 1163 else if (!SIntValueIsValidForSize (sval64, item_byte_size)) 1164 { 1165 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size); 1166 result.SetStatus(eReturnStatusFailed); 1167 return false; 1168 } 1169 buffer.PutMaxHex64 (sval64, item_byte_size); 1170 break; 1171 1172 case eFormatUnsigned: 1173 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); 1174 if (!success) 1175 { 1176 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); 1177 result.SetStatus(eReturnStatusFailed); 1178 return false; 1179 } 1180 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1181 { 1182 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1183 result.SetStatus(eReturnStatusFailed); 1184 return false; 1185 } 1186 buffer.PutMaxHex64 (uval64, item_byte_size); 1187 break; 1188 1189 case eFormatOctal: 1190 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success); 1191 if (!success) 1192 { 1193 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); 1194 result.SetStatus(eReturnStatusFailed); 1195 return false; 1196 } 1197 else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1198 { 1199 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1200 result.SetStatus(eReturnStatusFailed); 1201 return false; 1202 } 1203 buffer.PutMaxHex64 (uval64, item_byte_size); 1204 break; 1205 } 1206 } 1207 1208 if (!buffer.GetString().empty()) 1209 { 1210 Error error; 1211 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) 1212 return true; 1213 else 1214 { 1215 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); 1216 result.SetStatus(eReturnStatusFailed); 1217 return false; 1218 } 1219 } 1220 return true; 1221 } 1222 1223 OptionGroupOptions m_option_group; 1224 OptionGroupFormat m_format_options; 1225 OptionGroupWriteMemory m_memory_options; 1226 }; 1227 1228 1229 //------------------------------------------------------------------------- 1230 // CommandObjectMemory 1231 //------------------------------------------------------------------------- 1232 1233 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : 1234 CommandObjectMultiword (interpreter, 1235 "memory", 1236 "A set of commands for operating on memory.", 1237 "memory <subcommand> [<subcommand-options>]") 1238 { 1239 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); 1240 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); 1241 } 1242 1243 CommandObjectMemory::~CommandObjectMemory () 1244 { 1245 } 1246