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