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