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