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