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