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