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