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