1254721Semaste//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/lldb-python.h" 11254721Semaste 12254721Semaste#include "CommandObjectMemory.h" 13254721Semaste 14254721Semaste// C Includes 15254721Semaste// C++ Includes 16254721Semaste// Other libraries and framework includes 17254721Semaste// Project includes 18254721Semaste#include "lldb/Core/DataBufferHeap.h" 19254721Semaste#include "lldb/Core/DataExtractor.h" 20254721Semaste#include "lldb/Core/Debugger.h" 21254721Semaste#include "lldb/Core/Module.h" 22254721Semaste#include "lldb/Core/StreamString.h" 23254721Semaste#include "lldb/Core/ValueObjectMemory.h" 24254721Semaste#include "lldb/Interpreter/Args.h" 25254721Semaste#include "lldb/Interpreter/CommandReturnObject.h" 26254721Semaste#include "lldb/Interpreter/CommandInterpreter.h" 27254721Semaste#include "lldb/Interpreter/Options.h" 28254721Semaste#include "lldb/Interpreter/OptionGroupFormat.h" 29254721Semaste#include "lldb/Interpreter/OptionGroupOutputFile.h" 30254721Semaste#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" 31254721Semaste#include "lldb/Interpreter/OptionValueString.h" 32254721Semaste#include "lldb/Symbol/TypeList.h" 33254721Semaste#include "lldb/Target/Process.h" 34254721Semaste#include "lldb/Target/StackFrame.h" 35254721Semaste 36254721Semasteusing namespace lldb; 37254721Semasteusing namespace lldb_private; 38254721Semaste 39254721Semastestatic OptionDefinition 40254721Semasteg_option_table[] = 41254721Semaste{ 42254721Semaste { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, 43254721Semaste { 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."}, 44254721Semaste { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, 45254721Semaste { LLDB_OPT_SET_1| 46254721Semaste LLDB_OPT_SET_2| 47254721Semaste LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."}, 48254721Semaste}; 49254721Semaste 50254721Semaste 51254721Semaste 52254721Semasteclass OptionGroupReadMemory : public OptionGroup 53254721Semaste{ 54254721Semastepublic: 55254721Semaste 56254721Semaste OptionGroupReadMemory () : 57254721Semaste m_num_per_line (1,1), 58254721Semaste m_output_as_binary (false), 59254721Semaste m_view_as_type() 60254721Semaste { 61254721Semaste } 62254721Semaste 63254721Semaste virtual 64254721Semaste ~OptionGroupReadMemory () 65254721Semaste { 66254721Semaste } 67254721Semaste 68254721Semaste 69254721Semaste virtual uint32_t 70254721Semaste GetNumDefinitions () 71254721Semaste { 72254721Semaste return sizeof (g_option_table) / sizeof (OptionDefinition); 73254721Semaste } 74254721Semaste 75254721Semaste virtual const OptionDefinition* 76254721Semaste GetDefinitions () 77254721Semaste { 78254721Semaste return g_option_table; 79254721Semaste } 80254721Semaste 81254721Semaste virtual Error 82254721Semaste SetOptionValue (CommandInterpreter &interpreter, 83254721Semaste uint32_t option_idx, 84254721Semaste const char *option_arg) 85254721Semaste { 86254721Semaste Error error; 87254721Semaste const int short_option = g_option_table[option_idx].short_option; 88254721Semaste 89254721Semaste switch (short_option) 90254721Semaste { 91254721Semaste case 'l': 92254721Semaste error = m_num_per_line.SetValueFromCString (option_arg); 93254721Semaste if (m_num_per_line.GetCurrentValue() == 0) 94254721Semaste error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg); 95254721Semaste break; 96254721Semaste 97254721Semaste case 'b': 98254721Semaste m_output_as_binary = true; 99254721Semaste break; 100254721Semaste 101254721Semaste case 't': 102254721Semaste error = m_view_as_type.SetValueFromCString (option_arg); 103254721Semaste break; 104254721Semaste 105254721Semaste case 'r': 106254721Semaste m_force = true; 107254721Semaste break; 108254721Semaste 109254721Semaste default: 110254721Semaste error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 111254721Semaste break; 112254721Semaste } 113254721Semaste return error; 114254721Semaste } 115254721Semaste 116254721Semaste virtual void 117254721Semaste OptionParsingStarting (CommandInterpreter &interpreter) 118254721Semaste { 119254721Semaste m_num_per_line.Clear(); 120254721Semaste m_output_as_binary = false; 121254721Semaste m_view_as_type.Clear(); 122254721Semaste m_force = false; 123254721Semaste } 124254721Semaste 125254721Semaste Error 126254721Semaste FinalizeSettings (Target *target, OptionGroupFormat& format_options) 127254721Semaste { 128254721Semaste Error error; 129254721Semaste OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue(); 130254721Semaste OptionValueUInt64 &count_value = format_options.GetCountValue(); 131254721Semaste const bool byte_size_option_set = byte_size_value.OptionWasSet(); 132254721Semaste const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); 133254721Semaste const bool count_option_set = format_options.GetCountValue().OptionWasSet(); 134254721Semaste 135254721Semaste switch (format_options.GetFormat()) 136254721Semaste { 137254721Semaste default: 138254721Semaste break; 139254721Semaste 140254721Semaste case eFormatBoolean: 141254721Semaste if (!byte_size_option_set) 142254721Semaste byte_size_value = 1; 143254721Semaste if (!num_per_line_option_set) 144254721Semaste m_num_per_line = 1; 145254721Semaste if (!count_option_set) 146254721Semaste format_options.GetCountValue() = 8; 147254721Semaste break; 148254721Semaste 149254721Semaste case eFormatCString: 150254721Semaste break; 151254721Semaste 152254721Semaste case eFormatInstruction: 153254721Semaste if (count_option_set) 154254721Semaste byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize(); 155254721Semaste m_num_per_line = 1; 156254721Semaste break; 157254721Semaste 158254721Semaste case eFormatAddressInfo: 159254721Semaste if (!byte_size_option_set) 160254721Semaste byte_size_value = target->GetArchitecture().GetAddressByteSize(); 161254721Semaste m_num_per_line = 1; 162254721Semaste if (!count_option_set) 163254721Semaste format_options.GetCountValue() = 8; 164254721Semaste break; 165254721Semaste 166254721Semaste case eFormatPointer: 167254721Semaste byte_size_value = target->GetArchitecture().GetAddressByteSize(); 168254721Semaste if (!num_per_line_option_set) 169254721Semaste m_num_per_line = 4; 170254721Semaste if (!count_option_set) 171254721Semaste format_options.GetCountValue() = 8; 172254721Semaste break; 173254721Semaste 174254721Semaste case eFormatBinary: 175254721Semaste case eFormatFloat: 176254721Semaste case eFormatOctal: 177254721Semaste case eFormatDecimal: 178254721Semaste case eFormatEnum: 179254721Semaste case eFormatUnicode16: 180254721Semaste case eFormatUnicode32: 181254721Semaste case eFormatUnsigned: 182254721Semaste case eFormatHexFloat: 183254721Semaste if (!byte_size_option_set) 184254721Semaste byte_size_value = 4; 185254721Semaste if (!num_per_line_option_set) 186254721Semaste m_num_per_line = 1; 187254721Semaste if (!count_option_set) 188254721Semaste format_options.GetCountValue() = 8; 189254721Semaste break; 190254721Semaste 191254721Semaste case eFormatBytes: 192254721Semaste case eFormatBytesWithASCII: 193254721Semaste if (byte_size_option_set) 194254721Semaste { 195254721Semaste if (byte_size_value > 1) 196254721Semaste error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n" 197254721Semaste "\tconsider using a different display format or don't specify the byte size", 198254721Semaste byte_size_value.GetCurrentValue()); 199254721Semaste } 200254721Semaste else 201254721Semaste byte_size_value = 1; 202254721Semaste if (!num_per_line_option_set) 203254721Semaste m_num_per_line = 16; 204254721Semaste if (!count_option_set) 205254721Semaste format_options.GetCountValue() = 32; 206254721Semaste break; 207254721Semaste case eFormatCharArray: 208254721Semaste case eFormatChar: 209254721Semaste case eFormatCharPrintable: 210254721Semaste if (!byte_size_option_set) 211254721Semaste byte_size_value = 1; 212254721Semaste if (!num_per_line_option_set) 213254721Semaste m_num_per_line = 32; 214254721Semaste if (!count_option_set) 215254721Semaste format_options.GetCountValue() = 64; 216254721Semaste break; 217254721Semaste case eFormatComplex: 218254721Semaste if (!byte_size_option_set) 219254721Semaste byte_size_value = 8; 220254721Semaste if (!num_per_line_option_set) 221254721Semaste m_num_per_line = 1; 222254721Semaste if (!count_option_set) 223254721Semaste format_options.GetCountValue() = 8; 224254721Semaste break; 225254721Semaste case eFormatComplexInteger: 226254721Semaste if (!byte_size_option_set) 227254721Semaste byte_size_value = 8; 228254721Semaste if (!num_per_line_option_set) 229254721Semaste m_num_per_line = 1; 230254721Semaste if (!count_option_set) 231254721Semaste format_options.GetCountValue() = 8; 232254721Semaste break; 233254721Semaste case eFormatHex: 234254721Semaste if (!byte_size_option_set) 235254721Semaste byte_size_value = 4; 236254721Semaste if (!num_per_line_option_set) 237254721Semaste { 238254721Semaste switch (byte_size_value) 239254721Semaste { 240254721Semaste case 1: 241254721Semaste case 2: 242254721Semaste m_num_per_line = 8; 243254721Semaste break; 244254721Semaste case 4: 245254721Semaste m_num_per_line = 4; 246254721Semaste break; 247254721Semaste case 8: 248254721Semaste m_num_per_line = 2; 249254721Semaste break; 250254721Semaste default: 251254721Semaste m_num_per_line = 1; 252254721Semaste break; 253254721Semaste } 254254721Semaste } 255254721Semaste if (!count_option_set) 256254721Semaste count_value = 8; 257254721Semaste break; 258254721Semaste 259254721Semaste case eFormatVectorOfChar: 260254721Semaste case eFormatVectorOfSInt8: 261254721Semaste case eFormatVectorOfUInt8: 262254721Semaste case eFormatVectorOfSInt16: 263254721Semaste case eFormatVectorOfUInt16: 264254721Semaste case eFormatVectorOfSInt32: 265254721Semaste case eFormatVectorOfUInt32: 266254721Semaste case eFormatVectorOfSInt64: 267254721Semaste case eFormatVectorOfUInt64: 268254721Semaste case eFormatVectorOfFloat32: 269254721Semaste case eFormatVectorOfFloat64: 270254721Semaste case eFormatVectorOfUInt128: 271254721Semaste if (!byte_size_option_set) 272254721Semaste byte_size_value = 128; 273254721Semaste if (!num_per_line_option_set) 274254721Semaste m_num_per_line = 1; 275254721Semaste if (!count_option_set) 276254721Semaste count_value = 4; 277254721Semaste break; 278254721Semaste } 279254721Semaste return error; 280254721Semaste } 281254721Semaste 282254721Semaste bool 283254721Semaste AnyOptionWasSet () const 284254721Semaste { 285254721Semaste return m_num_per_line.OptionWasSet() || 286254721Semaste m_output_as_binary || 287254721Semaste m_view_as_type.OptionWasSet(); 288254721Semaste } 289254721Semaste 290254721Semaste OptionValueUInt64 m_num_per_line; 291254721Semaste bool m_output_as_binary; 292254721Semaste OptionValueString m_view_as_type; 293254721Semaste bool m_force; 294254721Semaste}; 295254721Semaste 296254721Semaste 297254721Semaste 298254721Semaste//---------------------------------------------------------------------- 299254721Semaste// Read memory from the inferior process 300254721Semaste//---------------------------------------------------------------------- 301254721Semasteclass CommandObjectMemoryRead : public CommandObjectParsed 302254721Semaste{ 303254721Semastepublic: 304254721Semaste 305254721Semaste CommandObjectMemoryRead (CommandInterpreter &interpreter) : 306254721Semaste CommandObjectParsed (interpreter, 307254721Semaste "memory read", 308254721Semaste "Read from the memory of the process being debugged.", 309254721Semaste NULL, 310254721Semaste eFlagRequiresTarget | eFlagProcessMustBePaused), 311254721Semaste m_option_group (interpreter), 312254721Semaste m_format_options (eFormatBytesWithASCII, 1, 8), 313254721Semaste m_memory_options (), 314254721Semaste m_outfile_options (), 315254721Semaste m_varobj_options(), 316254721Semaste m_next_addr(LLDB_INVALID_ADDRESS), 317254721Semaste m_prev_byte_size(0), 318254721Semaste m_prev_format_options (eFormatBytesWithASCII, 1, 8), 319254721Semaste m_prev_memory_options (), 320254721Semaste m_prev_outfile_options (), 321254721Semaste m_prev_varobj_options() 322254721Semaste { 323254721Semaste CommandArgumentEntry arg1; 324254721Semaste CommandArgumentEntry arg2; 325254721Semaste CommandArgumentData start_addr_arg; 326254721Semaste CommandArgumentData end_addr_arg; 327254721Semaste 328254721Semaste // Define the first (and only) variant of this arg. 329254721Semaste start_addr_arg.arg_type = eArgTypeAddressOrExpression; 330254721Semaste start_addr_arg.arg_repetition = eArgRepeatPlain; 331254721Semaste 332254721Semaste // There is only one variant this argument could be; put it into the argument entry. 333254721Semaste arg1.push_back (start_addr_arg); 334254721Semaste 335254721Semaste // Define the first (and only) variant of this arg. 336254721Semaste end_addr_arg.arg_type = eArgTypeAddressOrExpression; 337254721Semaste end_addr_arg.arg_repetition = eArgRepeatOptional; 338254721Semaste 339254721Semaste // There is only one variant this argument could be; put it into the argument entry. 340254721Semaste arg2.push_back (end_addr_arg); 341254721Semaste 342254721Semaste // Push the data for the first argument into the m_arguments vector. 343254721Semaste m_arguments.push_back (arg1); 344254721Semaste m_arguments.push_back (arg2); 345254721Semaste 346254721Semaste // Add the "--format" and "--count" options to group 1 and 3 347254721Semaste m_option_group.Append (&m_format_options, 348254721Semaste OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT, 349254721Semaste LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 350254721Semaste m_option_group.Append (&m_format_options, 351254721Semaste OptionGroupFormat::OPTION_GROUP_GDB_FMT, 352254721Semaste LLDB_OPT_SET_1 | LLDB_OPT_SET_3); 353254721Semaste // Add the "--size" option to group 1 and 2 354254721Semaste m_option_group.Append (&m_format_options, 355254721Semaste OptionGroupFormat::OPTION_GROUP_SIZE, 356254721Semaste LLDB_OPT_SET_1 | LLDB_OPT_SET_2); 357254721Semaste m_option_group.Append (&m_memory_options); 358254721Semaste m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 359254721Semaste m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); 360254721Semaste m_option_group.Finalize(); 361254721Semaste } 362254721Semaste 363254721Semaste virtual 364254721Semaste ~CommandObjectMemoryRead () 365254721Semaste { 366254721Semaste } 367254721Semaste 368254721Semaste Options * 369254721Semaste GetOptions () 370254721Semaste { 371254721Semaste return &m_option_group; 372254721Semaste } 373254721Semaste 374254721Semaste virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 375254721Semaste { 376254721Semaste return m_cmd_name.c_str(); 377254721Semaste } 378254721Semaste 379254721Semasteprotected: 380254721Semaste virtual bool 381254721Semaste DoExecute (Args& command, CommandReturnObject &result) 382254721Semaste { 383254721Semaste // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid 384254721Semaste Target *target = m_exe_ctx.GetTargetPtr(); 385254721Semaste 386254721Semaste const size_t argc = command.GetArgumentCount(); 387254721Semaste 388254721Semaste if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) 389254721Semaste { 390254721Semaste result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str()); 391254721Semaste result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n"); 392254721Semaste result.SetStatus(eReturnStatusFailed); 393254721Semaste return false; 394254721Semaste } 395254721Semaste 396254721Semaste ClangASTType clang_ast_type; 397254721Semaste Error error; 398254721Semaste 399254721Semaste const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); 400254721Semaste if (view_as_type_cstr && view_as_type_cstr[0]) 401254721Semaste { 402254721Semaste // We are viewing memory as a type 403254721Semaste 404254721Semaste SymbolContext sc; 405254721Semaste const bool exact_match = false; 406254721Semaste TypeList type_list; 407254721Semaste uint32_t reference_count = 0; 408254721Semaste uint32_t pointer_count = 0; 409254721Semaste size_t idx; 410254721Semaste 411254721Semaste#define ALL_KEYWORDS \ 412254721Semaste KEYWORD("const") \ 413254721Semaste KEYWORD("volatile") \ 414254721Semaste KEYWORD("restrict") \ 415254721Semaste KEYWORD("struct") \ 416254721Semaste KEYWORD("class") \ 417254721Semaste KEYWORD("union") 418254721Semaste 419254721Semaste#define KEYWORD(s) s, 420254721Semaste static const char *g_keywords[] = 421254721Semaste { 422254721Semaste ALL_KEYWORDS 423254721Semaste }; 424254721Semaste#undef KEYWORD 425254721Semaste 426254721Semaste#define KEYWORD(s) (sizeof(s) - 1), 427254721Semaste static const int g_keyword_lengths[] = 428254721Semaste { 429254721Semaste ALL_KEYWORDS 430254721Semaste }; 431254721Semaste#undef KEYWORD 432254721Semaste 433254721Semaste#undef ALL_KEYWORDS 434254721Semaste 435254721Semaste static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *); 436254721Semaste std::string type_str(view_as_type_cstr); 437254721Semaste 438254721Semaste // Remove all instances of g_keywords that are followed by spaces 439254721Semaste for (size_t i = 0; i < g_num_keywords; ++i) 440254721Semaste { 441254721Semaste const char *keyword = g_keywords[i]; 442254721Semaste int keyword_len = g_keyword_lengths[i]; 443254721Semaste 444254721Semaste idx = 0; 445254721Semaste while ((idx = type_str.find (keyword, idx)) != std::string::npos) 446254721Semaste { 447254721Semaste if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') 448254721Semaste { 449254721Semaste type_str.erase(idx, keyword_len+1); 450254721Semaste idx = 0; 451254721Semaste } 452254721Semaste else 453254721Semaste { 454254721Semaste idx += keyword_len; 455254721Semaste } 456254721Semaste } 457254721Semaste } 458254721Semaste bool done = type_str.empty(); 459254721Semaste // 460254721Semaste idx = type_str.find_first_not_of (" \t"); 461254721Semaste if (idx > 0 && idx != std::string::npos) 462254721Semaste type_str.erase (0, idx); 463254721Semaste while (!done) 464254721Semaste { 465254721Semaste // Strip trailing spaces 466254721Semaste if (type_str.empty()) 467254721Semaste done = true; 468254721Semaste else 469254721Semaste { 470254721Semaste switch (type_str[type_str.size()-1]) 471254721Semaste { 472254721Semaste case '*': 473254721Semaste ++pointer_count; 474254721Semaste // fall through... 475254721Semaste case ' ': 476254721Semaste case '\t': 477254721Semaste type_str.erase(type_str.size()-1); 478254721Semaste break; 479254721Semaste 480254721Semaste case '&': 481254721Semaste if (reference_count == 0) 482254721Semaste { 483254721Semaste reference_count = 1; 484254721Semaste type_str.erase(type_str.size()-1); 485254721Semaste } 486254721Semaste else 487254721Semaste { 488254721Semaste result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); 489254721Semaste result.SetStatus(eReturnStatusFailed); 490254721Semaste return false; 491254721Semaste } 492254721Semaste break; 493254721Semaste 494254721Semaste default: 495254721Semaste done = true; 496254721Semaste break; 497254721Semaste } 498254721Semaste } 499254721Semaste } 500254721Semaste 501254721Semaste ConstString lookup_type_name(type_str.c_str()); 502254721Semaste StackFrame *frame = m_exe_ctx.GetFramePtr(); 503254721Semaste if (frame) 504254721Semaste { 505254721Semaste sc = frame->GetSymbolContext (eSymbolContextModule); 506254721Semaste if (sc.module_sp) 507254721Semaste { 508254721Semaste sc.module_sp->FindTypes (sc, 509254721Semaste lookup_type_name, 510254721Semaste exact_match, 511254721Semaste 1, 512254721Semaste type_list); 513254721Semaste } 514254721Semaste } 515254721Semaste if (type_list.GetSize() == 0) 516254721Semaste { 517254721Semaste target->GetImages().FindTypes (sc, 518254721Semaste lookup_type_name, 519254721Semaste exact_match, 520254721Semaste 1, 521254721Semaste type_list); 522254721Semaste } 523254721Semaste 524254721Semaste if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$') 525254721Semaste { 526254721Semaste clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name)); 527254721Semaste if (tdecl) 528254721Semaste { 529254721Semaste clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl()); 530254721Semaste } 531254721Semaste } 532254721Semaste 533254721Semaste if (clang_ast_type.IsValid() == false) 534254721Semaste { 535254721Semaste if (type_list.GetSize() == 0) 536254721Semaste { 537254721Semaste result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", 538254721Semaste lookup_type_name.GetCString(), 539254721Semaste view_as_type_cstr); 540254721Semaste result.SetStatus(eReturnStatusFailed); 541254721Semaste return false; 542254721Semaste } 543254721Semaste else 544254721Semaste { 545254721Semaste TypeSP type_sp (type_list.GetTypeAtIndex(0)); 546254721Semaste clang_ast_type = type_sp->GetClangFullType(); 547254721Semaste } 548254721Semaste } 549254721Semaste 550254721Semaste while (pointer_count > 0) 551254721Semaste { 552254721Semaste ClangASTType pointer_type = clang_ast_type.GetPointerType(); 553254721Semaste if (pointer_type.IsValid()) 554254721Semaste clang_ast_type = pointer_type; 555254721Semaste else 556254721Semaste { 557254721Semaste result.AppendError ("unable make a pointer type\n"); 558254721Semaste result.SetStatus(eReturnStatusFailed); 559254721Semaste return false; 560254721Semaste } 561254721Semaste --pointer_count; 562254721Semaste } 563254721Semaste 564254721Semaste m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(); 565254721Semaste 566254721Semaste if (m_format_options.GetByteSizeValue() == 0) 567254721Semaste { 568254721Semaste result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 569254721Semaste view_as_type_cstr); 570254721Semaste result.SetStatus(eReturnStatusFailed); 571254721Semaste return false; 572254721Semaste } 573254721Semaste 574254721Semaste if (!m_format_options.GetCountValue().OptionWasSet()) 575254721Semaste m_format_options.GetCountValue() = 1; 576254721Semaste } 577254721Semaste else 578254721Semaste { 579254721Semaste error = m_memory_options.FinalizeSettings (target, m_format_options); 580254721Semaste } 581254721Semaste 582254721Semaste // Look for invalid combinations of settings 583254721Semaste if (error.Fail()) 584254721Semaste { 585254721Semaste result.AppendError(error.AsCString()); 586254721Semaste result.SetStatus(eReturnStatusFailed); 587254721Semaste return false; 588254721Semaste } 589254721Semaste 590254721Semaste lldb::addr_t addr; 591254721Semaste size_t total_byte_size = 0; 592254721Semaste if (argc == 0) 593254721Semaste { 594254721Semaste // Use the last address and byte size and all options as they were 595254721Semaste // if no options have been set 596254721Semaste addr = m_next_addr; 597254721Semaste total_byte_size = m_prev_byte_size; 598254721Semaste clang_ast_type = m_prev_clang_ast_type; 599254721Semaste if (!m_format_options.AnyOptionWasSet() && 600254721Semaste !m_memory_options.AnyOptionWasSet() && 601254721Semaste !m_outfile_options.AnyOptionWasSet() && 602254721Semaste !m_varobj_options.AnyOptionWasSet()) 603254721Semaste { 604254721Semaste m_format_options = m_prev_format_options; 605254721Semaste m_memory_options = m_prev_memory_options; 606254721Semaste m_outfile_options = m_prev_outfile_options; 607254721Semaste m_varobj_options = m_prev_varobj_options; 608254721Semaste } 609254721Semaste } 610254721Semaste 611254721Semaste size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); 612254721Semaste size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); 613254721Semaste const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); 614254721Semaste 615254721Semaste if (total_byte_size == 0) 616254721Semaste { 617254721Semaste total_byte_size = item_count * item_byte_size; 618254721Semaste if (total_byte_size == 0) 619254721Semaste total_byte_size = 32; 620254721Semaste } 621254721Semaste 622254721Semaste if (argc > 0) 623254721Semaste addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error); 624254721Semaste 625254721Semaste if (addr == LLDB_INVALID_ADDRESS) 626254721Semaste { 627254721Semaste result.AppendError("invalid start address expression."); 628254721Semaste result.AppendError(error.AsCString()); 629254721Semaste result.SetStatus(eReturnStatusFailed); 630254721Semaste return false; 631254721Semaste } 632254721Semaste 633254721Semaste if (argc == 2) 634254721Semaste { 635254721Semaste lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); 636254721Semaste if (end_addr == LLDB_INVALID_ADDRESS) 637254721Semaste { 638254721Semaste result.AppendError("invalid end address expression."); 639254721Semaste result.AppendError(error.AsCString()); 640254721Semaste result.SetStatus(eReturnStatusFailed); 641254721Semaste return false; 642254721Semaste } 643254721Semaste else if (end_addr <= addr) 644254721Semaste { 645254721Semaste result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr); 646254721Semaste result.SetStatus(eReturnStatusFailed); 647254721Semaste return false; 648254721Semaste } 649254721Semaste else if (m_format_options.GetCountValue().OptionWasSet()) 650254721Semaste { 651254721Semaste result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count); 652254721Semaste result.SetStatus(eReturnStatusFailed); 653254721Semaste return false; 654254721Semaste } 655254721Semaste 656254721Semaste total_byte_size = end_addr - addr; 657254721Semaste item_count = total_byte_size / item_byte_size; 658254721Semaste } 659254721Semaste 660254721Semaste uint32_t max_unforced_size = target->GetMaximumMemReadSize(); 661254721Semaste 662254721Semaste if (total_byte_size > max_unforced_size && !m_memory_options.m_force) 663254721Semaste { 664254721Semaste result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size); 665254721Semaste result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n"); 666254721Semaste result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n"); 667254721Semaste return false; 668254721Semaste } 669254721Semaste 670254721Semaste DataBufferSP data_sp; 671254721Semaste size_t bytes_read = 0; 672254721Semaste if (clang_ast_type.GetOpaqueQualType()) 673254721Semaste { 674254721Semaste // Make sure we don't display our type as ASCII bytes like the default memory read 675254721Semaste if (m_format_options.GetFormatValue().OptionWasSet() == false) 676254721Semaste m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); 677254721Semaste 678254721Semaste bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue(); 679254721Semaste } 680254721Semaste else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) 681254721Semaste { 682254721Semaste data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); 683254721Semaste if (data_sp->GetBytes() == NULL) 684254721Semaste { 685254721Semaste result.AppendErrorWithFormat ("can't allocate 0x%zx bytes for the memory read buffer, specify a smaller size to read", total_byte_size); 686254721Semaste result.SetStatus(eReturnStatusFailed); 687254721Semaste return false; 688254721Semaste } 689254721Semaste 690254721Semaste Address address(addr, NULL); 691254721Semaste bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); 692254721Semaste if (bytes_read == 0) 693254721Semaste { 694254721Semaste const char *error_cstr = error.AsCString(); 695254721Semaste if (error_cstr && error_cstr[0]) 696254721Semaste { 697254721Semaste result.AppendError(error_cstr); 698254721Semaste } 699254721Semaste else 700254721Semaste { 701254721Semaste result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 702254721Semaste } 703254721Semaste result.SetStatus(eReturnStatusFailed); 704254721Semaste return false; 705254721Semaste } 706254721Semaste 707254721Semaste if (bytes_read < total_byte_size) 708254721Semaste result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr); 709254721Semaste } 710254721Semaste else 711254721Semaste { 712254721Semaste // we treat c-strings as a special case because they do not have a fixed size 713254721Semaste if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat()) 714254721Semaste item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); 715254721Semaste else 716254721Semaste item_byte_size = target->GetMaximumSizeOfStringSummary(); 717254721Semaste if (!m_format_options.GetCountValue().OptionWasSet()) 718254721Semaste item_count = 1; 719254721Semaste data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary 720254721Semaste if (data_sp->GetBytes() == NULL) 721254721Semaste { 722254721Semaste 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)); 723254721Semaste result.SetStatus(eReturnStatusFailed); 724254721Semaste return false; 725254721Semaste } 726254721Semaste uint8_t *data_ptr = data_sp->GetBytes(); 727254721Semaste auto data_addr = addr; 728254721Semaste auto count = item_count; 729254721Semaste item_count = 0; 730254721Semaste while (item_count < count) 731254721Semaste { 732254721Semaste std::string buffer; 733254721Semaste buffer.resize(item_byte_size+1,0); 734254721Semaste Error error; 735254721Semaste size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error); 736254721Semaste if (error.Fail()) 737254721Semaste { 738254721Semaste result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); 739254721Semaste result.SetStatus(eReturnStatusFailed); 740254721Semaste return false; 741254721Semaste } 742254721Semaste if (item_byte_size == read) 743254721Semaste { 744254721Semaste result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr); 745254721Semaste break; 746254721Semaste } 747254721Semaste read+=1; // account for final NULL byte 748254721Semaste memcpy(data_ptr, &buffer[0], read); 749254721Semaste data_ptr += read; 750254721Semaste data_addr += read; 751254721Semaste bytes_read += read; 752254721Semaste item_count++; // if we break early we know we only read item_count strings 753254721Semaste } 754254721Semaste data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1)); 755254721Semaste } 756254721Semaste 757254721Semaste m_next_addr = addr + bytes_read; 758254721Semaste m_prev_byte_size = bytes_read; 759254721Semaste m_prev_format_options = m_format_options; 760254721Semaste m_prev_memory_options = m_memory_options; 761254721Semaste m_prev_outfile_options = m_outfile_options; 762254721Semaste m_prev_varobj_options = m_varobj_options; 763254721Semaste m_prev_clang_ast_type = clang_ast_type; 764254721Semaste 765254721Semaste StreamFile outfile_stream; 766254721Semaste Stream *output_stream = NULL; 767254721Semaste const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 768254721Semaste if (outfile_spec) 769254721Semaste { 770254721Semaste char path[PATH_MAX]; 771254721Semaste outfile_spec.GetPath (path, sizeof(path)); 772254721Semaste 773254721Semaste uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 774254721Semaste const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 775254721Semaste if (append) 776254721Semaste open_options |= File::eOpenOptionAppend; 777254721Semaste 778254721Semaste if (outfile_stream.GetFile ().Open (path, open_options).Success()) 779254721Semaste { 780254721Semaste if (m_memory_options.m_output_as_binary) 781254721Semaste { 782254721Semaste const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); 783254721Semaste if (bytes_written > 0) 784254721Semaste { 785254721Semaste result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n", 786254721Semaste bytes_written, 787254721Semaste append ? "appended" : "written", 788254721Semaste path); 789254721Semaste return true; 790254721Semaste } 791254721Semaste else 792254721Semaste { 793254721Semaste result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path); 794254721Semaste result.SetStatus(eReturnStatusFailed); 795254721Semaste return false; 796254721Semaste } 797254721Semaste } 798254721Semaste else 799254721Semaste { 800254721Semaste // We are going to write ASCII to the file just point the 801254721Semaste // output_stream to our outfile_stream... 802254721Semaste output_stream = &outfile_stream; 803254721Semaste } 804254721Semaste } 805254721Semaste else 806254721Semaste { 807254721Semaste result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); 808254721Semaste result.SetStatus(eReturnStatusFailed); 809254721Semaste return false; 810254721Semaste } 811254721Semaste } 812254721Semaste else 813254721Semaste { 814254721Semaste output_stream = &result.GetOutputStream(); 815254721Semaste } 816254721Semaste 817254721Semaste 818254721Semaste ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); 819254721Semaste if (clang_ast_type.GetOpaqueQualType()) 820254721Semaste { 821254721Semaste for (uint32_t i = 0; i<item_count; ++i) 822254721Semaste { 823254721Semaste addr_t item_addr = addr + (i * item_byte_size); 824254721Semaste Address address (item_addr); 825254721Semaste StreamString name_strm; 826254721Semaste name_strm.Printf ("0x%" PRIx64, item_addr); 827254721Semaste ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 828254721Semaste name_strm.GetString().c_str(), 829254721Semaste address, 830254721Semaste clang_ast_type)); 831254721Semaste if (valobj_sp) 832254721Semaste { 833254721Semaste Format format = m_format_options.GetFormat(); 834254721Semaste if (format != eFormatDefault) 835254721Semaste valobj_sp->SetFormat (format); 836254721Semaste 837254721Semaste ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,format)); 838254721Semaste 839254721Semaste ValueObject::DumpValueObject (*output_stream, 840254721Semaste valobj_sp.get(), 841254721Semaste options); 842254721Semaste } 843254721Semaste else 844254721Semaste { 845254721Semaste result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 846254721Semaste view_as_type_cstr, 847254721Semaste name_strm.GetString().c_str()); 848254721Semaste result.SetStatus(eReturnStatusFailed); 849254721Semaste return false; 850254721Semaste } 851254721Semaste } 852254721Semaste return true; 853254721Semaste } 854254721Semaste 855254721Semaste result.SetStatus(eReturnStatusSuccessFinishResult); 856254721Semaste DataExtractor data (data_sp, 857254721Semaste target->GetArchitecture().GetByteOrder(), 858254721Semaste target->GetArchitecture().GetAddressByteSize()); 859254721Semaste 860254721Semaste Format format = m_format_options.GetFormat(); 861254721Semaste if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) 862254721Semaste && (item_byte_size != 1) 863254721Semaste && (item_count == 1)) 864254721Semaste { 865254721Semaste // this turns requests such as 866254721Semaste // memory read -fc -s10 -c1 *charPtrPtr 867254721Semaste // which make no sense (what is a char of size 10?) 868254721Semaste // into a request for fetching 10 chars of size 1 from the same memory location 869254721Semaste format = eFormatCharArray; 870254721Semaste item_count = item_byte_size; 871254721Semaste item_byte_size = 1; 872254721Semaste } 873254721Semaste 874254721Semaste assert (output_stream); 875254721Semaste size_t bytes_dumped = data.Dump (output_stream, 876254721Semaste 0, 877254721Semaste format, 878254721Semaste item_byte_size, 879254721Semaste item_count, 880254721Semaste num_per_line, 881254721Semaste addr, 882254721Semaste 0, 883254721Semaste 0, 884254721Semaste exe_scope); 885254721Semaste m_next_addr = addr + bytes_dumped; 886254721Semaste output_stream->EOL(); 887254721Semaste return true; 888254721Semaste } 889254721Semaste 890254721Semaste OptionGroupOptions m_option_group; 891254721Semaste OptionGroupFormat m_format_options; 892254721Semaste OptionGroupReadMemory m_memory_options; 893254721Semaste OptionGroupOutputFile m_outfile_options; 894254721Semaste OptionGroupValueObjectDisplay m_varobj_options; 895254721Semaste lldb::addr_t m_next_addr; 896254721Semaste lldb::addr_t m_prev_byte_size; 897254721Semaste OptionGroupFormat m_prev_format_options; 898254721Semaste OptionGroupReadMemory m_prev_memory_options; 899254721Semaste OptionGroupOutputFile m_prev_outfile_options; 900254721Semaste OptionGroupValueObjectDisplay m_prev_varobj_options; 901254721Semaste ClangASTType m_prev_clang_ast_type; 902254721Semaste}; 903254721Semaste 904254721Semaste 905254721SemasteOptionDefinition 906254721Semasteg_memory_write_option_table[] = 907254721Semaste{ 908254721Semaste{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, 909254721Semaste{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."}, 910254721Semaste}; 911254721Semaste 912254721Semaste 913254721Semaste//---------------------------------------------------------------------- 914254721Semaste// Write memory to the inferior process 915254721Semaste//---------------------------------------------------------------------- 916254721Semasteclass CommandObjectMemoryWrite : public CommandObjectParsed 917254721Semaste{ 918254721Semastepublic: 919254721Semaste 920254721Semaste class OptionGroupWriteMemory : public OptionGroup 921254721Semaste { 922254721Semaste public: 923254721Semaste OptionGroupWriteMemory () : 924254721Semaste OptionGroup() 925254721Semaste { 926254721Semaste } 927254721Semaste 928254721Semaste virtual 929254721Semaste ~OptionGroupWriteMemory () 930254721Semaste { 931254721Semaste } 932254721Semaste 933254721Semaste virtual uint32_t 934254721Semaste GetNumDefinitions () 935254721Semaste { 936254721Semaste return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); 937254721Semaste } 938254721Semaste 939254721Semaste virtual const OptionDefinition* 940254721Semaste GetDefinitions () 941254721Semaste { 942254721Semaste return g_memory_write_option_table; 943254721Semaste } 944254721Semaste 945254721Semaste virtual Error 946254721Semaste SetOptionValue (CommandInterpreter &interpreter, 947254721Semaste uint32_t option_idx, 948254721Semaste const char *option_arg) 949254721Semaste { 950254721Semaste Error error; 951254721Semaste const int short_option = g_memory_write_option_table[option_idx].short_option; 952254721Semaste 953254721Semaste switch (short_option) 954254721Semaste { 955254721Semaste case 'i': 956254721Semaste m_infile.SetFile (option_arg, true); 957254721Semaste if (!m_infile.Exists()) 958254721Semaste { 959254721Semaste m_infile.Clear(); 960254721Semaste error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); 961254721Semaste } 962254721Semaste break; 963254721Semaste 964254721Semaste case 'o': 965254721Semaste { 966254721Semaste bool success; 967254721Semaste m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success); 968254721Semaste if (!success) 969254721Semaste { 970254721Semaste error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); 971254721Semaste } 972254721Semaste } 973254721Semaste break; 974254721Semaste 975254721Semaste default: 976254721Semaste error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 977254721Semaste break; 978254721Semaste } 979254721Semaste return error; 980254721Semaste } 981254721Semaste 982254721Semaste virtual void 983254721Semaste OptionParsingStarting (CommandInterpreter &interpreter) 984254721Semaste { 985254721Semaste m_infile.Clear(); 986254721Semaste m_infile_offset = 0; 987254721Semaste } 988254721Semaste 989254721Semaste FileSpec m_infile; 990254721Semaste off_t m_infile_offset; 991254721Semaste }; 992254721Semaste 993254721Semaste CommandObjectMemoryWrite (CommandInterpreter &interpreter) : 994254721Semaste CommandObjectParsed (interpreter, 995254721Semaste "memory write", 996254721Semaste "Write to the memory of the process being debugged.", 997254721Semaste NULL, 998254721Semaste eFlagRequiresProcess | eFlagProcessMustBeLaunched), 999254721Semaste m_option_group (interpreter), 1000254721Semaste m_format_options (eFormatBytes, 1, UINT64_MAX), 1001254721Semaste m_memory_options () 1002254721Semaste { 1003254721Semaste CommandArgumentEntry arg1; 1004254721Semaste CommandArgumentEntry arg2; 1005254721Semaste CommandArgumentData addr_arg; 1006254721Semaste CommandArgumentData value_arg; 1007254721Semaste 1008254721Semaste // Define the first (and only) variant of this arg. 1009254721Semaste addr_arg.arg_type = eArgTypeAddress; 1010254721Semaste addr_arg.arg_repetition = eArgRepeatPlain; 1011254721Semaste 1012254721Semaste // There is only one variant this argument could be; put it into the argument entry. 1013254721Semaste arg1.push_back (addr_arg); 1014254721Semaste 1015254721Semaste // Define the first (and only) variant of this arg. 1016254721Semaste value_arg.arg_type = eArgTypeValue; 1017254721Semaste value_arg.arg_repetition = eArgRepeatPlus; 1018254721Semaste 1019254721Semaste // There is only one variant this argument could be; put it into the argument entry. 1020254721Semaste arg2.push_back (value_arg); 1021254721Semaste 1022254721Semaste // Push the data for the first argument into the m_arguments vector. 1023254721Semaste m_arguments.push_back (arg1); 1024254721Semaste m_arguments.push_back (arg2); 1025254721Semaste 1026254721Semaste m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); 1027254721Semaste m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); 1028254721Semaste m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); 1029254721Semaste m_option_group.Finalize(); 1030254721Semaste 1031254721Semaste } 1032254721Semaste 1033254721Semaste virtual 1034254721Semaste ~CommandObjectMemoryWrite () 1035254721Semaste { 1036254721Semaste } 1037254721Semaste 1038254721Semaste Options * 1039254721Semaste GetOptions () 1040254721Semaste { 1041254721Semaste return &m_option_group; 1042254721Semaste } 1043254721Semaste 1044254721Semaste bool 1045254721Semaste UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) 1046254721Semaste { 1047254721Semaste if (total_byte_size > 8) 1048254721Semaste return false; 1049254721Semaste 1050254721Semaste if (total_byte_size == 8) 1051254721Semaste return true; 1052254721Semaste 1053254721Semaste const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; 1054254721Semaste return uval64 <= max; 1055254721Semaste } 1056254721Semaste 1057254721Semaste bool 1058254721Semaste SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) 1059254721Semaste { 1060254721Semaste if (total_byte_size > 8) 1061254721Semaste return false; 1062254721Semaste 1063254721Semaste if (total_byte_size == 8) 1064254721Semaste return true; 1065254721Semaste 1066254721Semaste const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; 1067254721Semaste const int64_t min = ~(max); 1068254721Semaste return min <= sval64 && sval64 <= max; 1069254721Semaste } 1070254721Semaste 1071254721Semasteprotected: 1072254721Semaste virtual bool 1073254721Semaste DoExecute (Args& command, CommandReturnObject &result) 1074254721Semaste { 1075254721Semaste // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid 1076254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 1077254721Semaste 1078254721Semaste const size_t argc = command.GetArgumentCount(); 1079254721Semaste 1080254721Semaste if (m_memory_options.m_infile) 1081254721Semaste { 1082254721Semaste if (argc < 1) 1083254721Semaste { 1084254721Semaste result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); 1085254721Semaste result.SetStatus(eReturnStatusFailed); 1086254721Semaste return false; 1087254721Semaste } 1088254721Semaste } 1089254721Semaste else if (argc < 2) 1090254721Semaste { 1091254721Semaste result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); 1092254721Semaste result.SetStatus(eReturnStatusFailed); 1093254721Semaste return false; 1094254721Semaste } 1095254721Semaste 1096254721Semaste StreamString buffer (Stream::eBinary, 1097254721Semaste process->GetTarget().GetArchitecture().GetAddressByteSize(), 1098254721Semaste process->GetTarget().GetArchitecture().GetByteOrder()); 1099254721Semaste 1100254721Semaste OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); 1101254721Semaste size_t item_byte_size = byte_size_value.GetCurrentValue(); 1102254721Semaste 1103254721Semaste Error error; 1104254721Semaste lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, 1105254721Semaste command.GetArgumentAtIndex(0), 1106254721Semaste LLDB_INVALID_ADDRESS, 1107254721Semaste &error); 1108254721Semaste 1109254721Semaste if (addr == LLDB_INVALID_ADDRESS) 1110254721Semaste { 1111254721Semaste result.AppendError("invalid address expression\n"); 1112254721Semaste result.AppendError(error.AsCString()); 1113254721Semaste result.SetStatus(eReturnStatusFailed); 1114254721Semaste return false; 1115254721Semaste } 1116254721Semaste 1117254721Semaste if (m_memory_options.m_infile) 1118254721Semaste { 1119254721Semaste size_t length = SIZE_MAX; 1120254721Semaste if (item_byte_size > 0) 1121254721Semaste length = item_byte_size; 1122254721Semaste lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); 1123254721Semaste if (data_sp) 1124254721Semaste { 1125254721Semaste length = data_sp->GetByteSize(); 1126254721Semaste if (length > 0) 1127254721Semaste { 1128254721Semaste Error error; 1129254721Semaste size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); 1130254721Semaste 1131254721Semaste if (bytes_written == length) 1132254721Semaste { 1133254721Semaste // All bytes written 1134254721Semaste result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr); 1135254721Semaste result.SetStatus(eReturnStatusSuccessFinishResult); 1136254721Semaste } 1137254721Semaste else if (bytes_written > 0) 1138254721Semaste { 1139254721Semaste // Some byte written 1140254721Semaste result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr); 1141254721Semaste result.SetStatus(eReturnStatusSuccessFinishResult); 1142254721Semaste } 1143254721Semaste else 1144254721Semaste { 1145254721Semaste result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1146254721Semaste result.SetStatus(eReturnStatusFailed); 1147254721Semaste } 1148254721Semaste } 1149254721Semaste } 1150254721Semaste else 1151254721Semaste { 1152254721Semaste result.AppendErrorWithFormat ("Unable to read contents of file.\n"); 1153254721Semaste result.SetStatus(eReturnStatusFailed); 1154254721Semaste } 1155254721Semaste return result.Succeeded(); 1156254721Semaste } 1157254721Semaste else if (item_byte_size == 0) 1158254721Semaste { 1159254721Semaste if (m_format_options.GetFormat() == eFormatPointer) 1160254721Semaste item_byte_size = buffer.GetAddressByteSize(); 1161254721Semaste else 1162254721Semaste item_byte_size = 1; 1163254721Semaste } 1164254721Semaste 1165254721Semaste command.Shift(); // shift off the address argument 1166254721Semaste uint64_t uval64; 1167254721Semaste int64_t sval64; 1168254721Semaste bool success = false; 1169254721Semaste const size_t num_value_args = command.GetArgumentCount(); 1170254721Semaste for (size_t i=0; i<num_value_args; ++i) 1171254721Semaste { 1172254721Semaste const char *value_str = command.GetArgumentAtIndex(i); 1173254721Semaste 1174254721Semaste switch (m_format_options.GetFormat()) 1175254721Semaste { 1176254721Semaste case kNumFormats: 1177254721Semaste case eFormatFloat: // TODO: add support for floats soon 1178254721Semaste case eFormatCharPrintable: 1179254721Semaste case eFormatBytesWithASCII: 1180254721Semaste case eFormatComplex: 1181254721Semaste case eFormatEnum: 1182254721Semaste case eFormatUnicode16: 1183254721Semaste case eFormatUnicode32: 1184254721Semaste case eFormatVectorOfChar: 1185254721Semaste case eFormatVectorOfSInt8: 1186254721Semaste case eFormatVectorOfUInt8: 1187254721Semaste case eFormatVectorOfSInt16: 1188254721Semaste case eFormatVectorOfUInt16: 1189254721Semaste case eFormatVectorOfSInt32: 1190254721Semaste case eFormatVectorOfUInt32: 1191254721Semaste case eFormatVectorOfSInt64: 1192254721Semaste case eFormatVectorOfUInt64: 1193254721Semaste case eFormatVectorOfFloat32: 1194254721Semaste case eFormatVectorOfFloat64: 1195254721Semaste case eFormatVectorOfUInt128: 1196254721Semaste case eFormatOSType: 1197254721Semaste case eFormatComplexInteger: 1198254721Semaste case eFormatAddressInfo: 1199254721Semaste case eFormatHexFloat: 1200254721Semaste case eFormatInstruction: 1201254721Semaste case eFormatVoid: 1202254721Semaste result.AppendError("unsupported format for writing memory"); 1203254721Semaste result.SetStatus(eReturnStatusFailed); 1204254721Semaste return false; 1205254721Semaste 1206254721Semaste case eFormatDefault: 1207254721Semaste case eFormatBytes: 1208254721Semaste case eFormatHex: 1209254721Semaste case eFormatHexUppercase: 1210254721Semaste case eFormatPointer: 1211254721Semaste 1212254721Semaste // Decode hex bytes 1213254721Semaste uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success); 1214254721Semaste if (!success) 1215254721Semaste { 1216254721Semaste result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); 1217254721Semaste result.SetStatus(eReturnStatusFailed); 1218254721Semaste return false; 1219254721Semaste } 1220254721Semaste else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1221254721Semaste { 1222254721Semaste result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1223254721Semaste result.SetStatus(eReturnStatusFailed); 1224254721Semaste return false; 1225254721Semaste } 1226254721Semaste buffer.PutMaxHex64 (uval64, item_byte_size); 1227254721Semaste break; 1228254721Semaste 1229254721Semaste case eFormatBoolean: 1230254721Semaste uval64 = Args::StringToBoolean(value_str, false, &success); 1231254721Semaste if (!success) 1232254721Semaste { 1233254721Semaste result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); 1234254721Semaste result.SetStatus(eReturnStatusFailed); 1235254721Semaste return false; 1236254721Semaste } 1237254721Semaste buffer.PutMaxHex64 (uval64, item_byte_size); 1238254721Semaste break; 1239254721Semaste 1240254721Semaste case eFormatBinary: 1241254721Semaste uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success); 1242254721Semaste if (!success) 1243254721Semaste { 1244254721Semaste result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); 1245254721Semaste result.SetStatus(eReturnStatusFailed); 1246254721Semaste return false; 1247254721Semaste } 1248254721Semaste else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1249254721Semaste { 1250254721Semaste result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1251254721Semaste result.SetStatus(eReturnStatusFailed); 1252254721Semaste return false; 1253254721Semaste } 1254254721Semaste buffer.PutMaxHex64 (uval64, item_byte_size); 1255254721Semaste break; 1256254721Semaste 1257254721Semaste case eFormatCharArray: 1258254721Semaste case eFormatChar: 1259254721Semaste case eFormatCString: 1260254721Semaste if (value_str[0]) 1261254721Semaste { 1262254721Semaste size_t len = strlen (value_str); 1263254721Semaste // Include the NULL for C strings... 1264254721Semaste if (m_format_options.GetFormat() == eFormatCString) 1265254721Semaste ++len; 1266254721Semaste Error error; 1267254721Semaste if (process->WriteMemory (addr, value_str, len, error) == len) 1268254721Semaste { 1269254721Semaste addr += len; 1270254721Semaste } 1271254721Semaste else 1272254721Semaste { 1273254721Semaste result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1274254721Semaste result.SetStatus(eReturnStatusFailed); 1275254721Semaste return false; 1276254721Semaste } 1277254721Semaste } 1278254721Semaste break; 1279254721Semaste 1280254721Semaste case eFormatDecimal: 1281254721Semaste sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); 1282254721Semaste if (!success) 1283254721Semaste { 1284254721Semaste result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); 1285254721Semaste result.SetStatus(eReturnStatusFailed); 1286254721Semaste return false; 1287254721Semaste } 1288254721Semaste else if (!SIntValueIsValidForSize (sval64, item_byte_size)) 1289254721Semaste { 1290254721Semaste result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size); 1291254721Semaste result.SetStatus(eReturnStatusFailed); 1292254721Semaste return false; 1293254721Semaste } 1294254721Semaste buffer.PutMaxHex64 (sval64, item_byte_size); 1295254721Semaste break; 1296254721Semaste 1297254721Semaste case eFormatUnsigned: 1298254721Semaste uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); 1299254721Semaste if (!success) 1300254721Semaste { 1301254721Semaste result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); 1302254721Semaste result.SetStatus(eReturnStatusFailed); 1303254721Semaste return false; 1304254721Semaste } 1305254721Semaste else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1306254721Semaste { 1307254721Semaste result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1308254721Semaste result.SetStatus(eReturnStatusFailed); 1309254721Semaste return false; 1310254721Semaste } 1311254721Semaste buffer.PutMaxHex64 (uval64, item_byte_size); 1312254721Semaste break; 1313254721Semaste 1314254721Semaste case eFormatOctal: 1315254721Semaste uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success); 1316254721Semaste if (!success) 1317254721Semaste { 1318254721Semaste result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); 1319254721Semaste result.SetStatus(eReturnStatusFailed); 1320254721Semaste return false; 1321254721Semaste } 1322254721Semaste else if (!UIntValueIsValidForSize (uval64, item_byte_size)) 1323254721Semaste { 1324254721Semaste result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); 1325254721Semaste result.SetStatus(eReturnStatusFailed); 1326254721Semaste return false; 1327254721Semaste } 1328254721Semaste buffer.PutMaxHex64 (uval64, item_byte_size); 1329254721Semaste break; 1330254721Semaste } 1331254721Semaste } 1332254721Semaste 1333254721Semaste if (!buffer.GetString().empty()) 1334254721Semaste { 1335254721Semaste Error error; 1336254721Semaste if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) 1337254721Semaste return true; 1338254721Semaste else 1339254721Semaste { 1340254721Semaste result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); 1341254721Semaste result.SetStatus(eReturnStatusFailed); 1342254721Semaste return false; 1343254721Semaste } 1344254721Semaste } 1345254721Semaste return true; 1346254721Semaste } 1347254721Semaste 1348254721Semaste OptionGroupOptions m_option_group; 1349254721Semaste OptionGroupFormat m_format_options; 1350254721Semaste OptionGroupWriteMemory m_memory_options; 1351254721Semaste}; 1352254721Semaste 1353254721Semaste 1354254721Semaste//------------------------------------------------------------------------- 1355254721Semaste// CommandObjectMemory 1356254721Semaste//------------------------------------------------------------------------- 1357254721Semaste 1358254721SemasteCommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : 1359254721Semaste CommandObjectMultiword (interpreter, 1360254721Semaste "memory", 1361254721Semaste "A set of commands for operating on memory.", 1362254721Semaste "memory <subcommand> [<subcommand-options>]") 1363254721Semaste{ 1364254721Semaste LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); 1365254721Semaste LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); 1366254721Semaste} 1367254721Semaste 1368254721SemasteCommandObjectMemory::~CommandObjectMemory () 1369254721Semaste{ 1370254721Semaste} 1371