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