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