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