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 "lldb/Expression/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                 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
534                 if (tdecl)
535                 {
536                     clang_ast_type.SetClangType(ClangASTContext::GetASTContext(&tdecl->getASTContext()),(const lldb::clang_type_t)tdecl->getTypeForDecl());
537                 }
538             }
539 
540             if (clang_ast_type.IsValid() == false)
541             {
542                 if (type_list.GetSize() == 0)
543                 {
544                     result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
545                                                   lookup_type_name.GetCString(),
546                                                   view_as_type_cstr);
547                     result.SetStatus(eReturnStatusFailed);
548                     return false;
549                 }
550                 else
551                 {
552                     TypeSP type_sp (type_list.GetTypeAtIndex(0));
553                     clang_ast_type = type_sp->GetClangFullType();
554                 }
555             }
556 
557             while (pointer_count > 0)
558             {
559                 CompilerType pointer_type = clang_ast_type.GetPointerType();
560                 if (pointer_type.IsValid())
561                     clang_ast_type = pointer_type;
562                 else
563                 {
564                     result.AppendError ("unable make a pointer type\n");
565                     result.SetStatus(eReturnStatusFailed);
566                     return false;
567                 }
568                 --pointer_count;
569             }
570 
571             m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);
572 
573             if (m_format_options.GetByteSizeValue() == 0)
574             {
575                 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
576                                               view_as_type_cstr);
577                 result.SetStatus(eReturnStatusFailed);
578                 return false;
579             }
580 
581             if (!m_format_options.GetCountValue().OptionWasSet())
582                 m_format_options.GetCountValue() = 1;
583         }
584         else
585         {
586             error = m_memory_options.FinalizeSettings (target, m_format_options);
587         }
588 
589         // Look for invalid combinations of settings
590         if (error.Fail())
591         {
592             result.AppendError(error.AsCString());
593             result.SetStatus(eReturnStatusFailed);
594             return false;
595         }
596 
597         lldb::addr_t addr;
598         size_t total_byte_size = 0;
599         if (argc == 0)
600         {
601             // Use the last address and byte size and all options as they were
602             // if no options have been set
603             addr = m_next_addr;
604             total_byte_size = m_prev_byte_size;
605             clang_ast_type = m_prev_clang_ast_type;
606             if (!m_format_options.AnyOptionWasSet() &&
607                 !m_memory_options.AnyOptionWasSet() &&
608                 !m_outfile_options.AnyOptionWasSet() &&
609                 !m_varobj_options.AnyOptionWasSet())
610             {
611                 m_format_options = m_prev_format_options;
612                 m_memory_options = m_prev_memory_options;
613                 m_outfile_options = m_prev_outfile_options;
614                 m_varobj_options = m_prev_varobj_options;
615             }
616         }
617 
618         size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
619 
620         // TODO For non-8-bit byte addressable architectures this needs to be
621         // revisited to fully support all lldb's range of formatting options.
622         // Furthermore code memory reads (for those architectures) will not
623         // be correctly formatted even w/o formatting options.
624         size_t item_byte_size =
625             target->GetArchitecture().GetDataByteSize() > 1 ?
626             target->GetArchitecture().GetDataByteSize() :
627             m_format_options.GetByteSizeValue().GetCurrentValue();
628 
629         const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
630 
631         if (total_byte_size == 0)
632         {
633             total_byte_size = item_count * item_byte_size;
634             if (total_byte_size == 0)
635                 total_byte_size = 32;
636         }
637 
638         if (argc > 0)
639             addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
640 
641         if (addr == LLDB_INVALID_ADDRESS)
642         {
643             result.AppendError("invalid start address expression.");
644             result.AppendError(error.AsCString());
645             result.SetStatus(eReturnStatusFailed);
646             return false;
647         }
648 
649         if (argc == 2)
650         {
651             lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
652             if (end_addr == LLDB_INVALID_ADDRESS)
653             {
654                 result.AppendError("invalid end address expression.");
655                 result.AppendError(error.AsCString());
656                 result.SetStatus(eReturnStatusFailed);
657                 return false;
658             }
659             else if (end_addr <= addr)
660             {
661                 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
662                 result.SetStatus(eReturnStatusFailed);
663                 return false;
664             }
665             else if (m_format_options.GetCountValue().OptionWasSet())
666             {
667                 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count);
668                 result.SetStatus(eReturnStatusFailed);
669                 return false;
670             }
671 
672             total_byte_size = end_addr - addr;
673             item_count = total_byte_size / item_byte_size;
674         }
675 
676         uint32_t max_unforced_size = target->GetMaximumMemReadSize();
677 
678         if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
679         {
680             result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
681             result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
682             result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
683             return false;
684         }
685 
686         DataBufferSP data_sp;
687         size_t bytes_read = 0;
688         if (clang_ast_type.GetOpaqueQualType())
689         {
690             // Make sure we don't display our type as ASCII bytes like the default memory read
691             if (m_format_options.GetFormatValue().OptionWasSet() == false)
692                 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
693 
694             bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue();
695         }
696         else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
697         {
698             data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
699             if (data_sp->GetBytes() == NULL)
700             {
701                 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size);
702                 result.SetStatus(eReturnStatusFailed);
703                 return false;
704             }
705 
706             Address address(addr, NULL);
707             bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
708             if (bytes_read == 0)
709             {
710                 const char *error_cstr = error.AsCString();
711                 if (error_cstr && error_cstr[0])
712                 {
713                     result.AppendError(error_cstr);
714                 }
715                 else
716                 {
717                     result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
718                 }
719                 result.SetStatus(eReturnStatusFailed);
720                 return false;
721             }
722 
723             if (bytes_read < total_byte_size)
724                 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);
725         }
726         else
727         {
728             // we treat c-strings as a special case because they do not have a fixed size
729             if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
730                 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
731             else
732                 item_byte_size = target->GetMaximumSizeOfStringSummary();
733             if (!m_format_options.GetCountValue().OptionWasSet())
734                 item_count = 1;
735             data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
736             if (data_sp->GetBytes() == NULL)
737             {
738                 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));
739                 result.SetStatus(eReturnStatusFailed);
740                 return false;
741             }
742             uint8_t *data_ptr = data_sp->GetBytes();
743             auto data_addr = addr;
744             auto count = item_count;
745             item_count = 0;
746             bool break_on_no_NULL = false;
747             while (item_count < count)
748             {
749                 std::string buffer;
750                 buffer.resize(item_byte_size+1,0);
751                 Error error;
752                 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
753                 if (error.Fail())
754                 {
755                     result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
756                     result.SetStatus(eReturnStatusFailed);
757                     return false;
758                 }
759 
760                 if (item_byte_size == read)
761                 {
762                     result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
763                     --read;
764                     break_on_no_NULL = true;
765                 }
766                 else
767                     ++read; // account for final NULL byte
768 
769                 memcpy(data_ptr, &buffer[0], read);
770                 data_ptr += read;
771                 data_addr += read;
772                 bytes_read += read;
773                 item_count++; // if we break early we know we only read item_count strings
774 
775                 if (break_on_no_NULL)
776                     break;
777             }
778             data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
779         }
780 
781         m_next_addr = addr + bytes_read;
782         m_prev_byte_size = bytes_read;
783         m_prev_format_options = m_format_options;
784         m_prev_memory_options = m_memory_options;
785         m_prev_outfile_options = m_outfile_options;
786         m_prev_varobj_options = m_varobj_options;
787         m_prev_clang_ast_type = clang_ast_type;
788 
789         StreamFile outfile_stream;
790         Stream *output_stream = NULL;
791         const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
792         if (outfile_spec)
793         {
794             char path[PATH_MAX];
795             outfile_spec.GetPath (path, sizeof(path));
796 
797             uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
798             const bool append = m_outfile_options.GetAppend().GetCurrentValue();
799             if (append)
800                 open_options |= File::eOpenOptionAppend;
801 
802             if (outfile_stream.GetFile ().Open (path, open_options).Success())
803             {
804                 if (m_memory_options.m_output_as_binary)
805                 {
806                     const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
807                     if (bytes_written > 0)
808                     {
809                         result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
810                                                          bytes_written,
811                                                          append ? "appended" : "written",
812                                                          path);
813                         return true;
814                     }
815                     else
816                     {
817                         result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
818                         result.SetStatus(eReturnStatusFailed);
819                         return false;
820                     }
821                 }
822                 else
823                 {
824                     // We are going to write ASCII to the file just point the
825                     // output_stream to our outfile_stream...
826                     output_stream = &outfile_stream;
827                 }
828             }
829             else
830             {
831                 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
832                 result.SetStatus(eReturnStatusFailed);
833                 return false;
834             }
835         }
836         else
837         {
838             output_stream = &result.GetOutputStream();
839         }
840 
841 
842         ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
843         if (clang_ast_type.GetOpaqueQualType())
844         {
845             for (uint32_t i = 0; i<item_count; ++i)
846             {
847                 addr_t item_addr = addr + (i * item_byte_size);
848                 Address address (item_addr);
849                 StreamString name_strm;
850                 name_strm.Printf ("0x%" PRIx64, item_addr);
851                 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
852                                                                     name_strm.GetString().c_str(),
853                                                                     address,
854                                                                     clang_ast_type));
855                 if (valobj_sp)
856                 {
857                     Format format = m_format_options.GetFormat();
858                     if (format != eFormatDefault)
859                         valobj_sp->SetFormat (format);
860 
861                     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
862 
863                     valobj_sp->Dump(*output_stream,options);
864                 }
865                 else
866                 {
867                     result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
868                                                   view_as_type_cstr,
869                                                   name_strm.GetString().c_str());
870                     result.SetStatus(eReturnStatusFailed);
871                     return false;
872                 }
873             }
874             return true;
875         }
876 
877         result.SetStatus(eReturnStatusSuccessFinishResult);
878         DataExtractor data (data_sp,
879                             target->GetArchitecture().GetByteOrder(),
880                             target->GetArchitecture().GetAddressByteSize(),
881                             target->GetArchitecture().GetDataByteSize());
882 
883         Format format = m_format_options.GetFormat();
884         if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
885             && (item_byte_size != 1))
886         {
887             // if a count was not passed, or it is 1
888             if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
889             {
890                 // this turns requests such as
891                 // memory read -fc -s10 -c1 *charPtrPtr
892                 // which make no sense (what is a char of size 10?)
893                 // into a request for fetching 10 chars of size 1 from the same memory location
894                 format = eFormatCharArray;
895                 item_count = item_byte_size;
896                 item_byte_size = 1;
897             }
898             else
899             {
900                 // here we passed a count, and it was not 1
901                 // so we have a byte_size and a count
902                 // we could well multiply those, but instead let's just fail
903                 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
904                 result.SetStatus(eReturnStatusFailed);
905                 return false;
906             }
907         }
908 
909         assert (output_stream);
910         size_t bytes_dumped = data.Dump (output_stream,
911                                          0,
912                                          format,
913                                          item_byte_size,
914                                          item_count,
915                                          num_per_line / target->GetArchitecture().GetDataByteSize(),
916                                          addr,
917                                          0,
918                                          0,
919                                          exe_scope);
920         m_next_addr = addr + bytes_dumped;
921         output_stream->EOL();
922         return true;
923     }
924 
925     OptionGroupOptions m_option_group;
926     OptionGroupFormat m_format_options;
927     OptionGroupReadMemory m_memory_options;
928     OptionGroupOutputFile m_outfile_options;
929     OptionGroupValueObjectDisplay m_varobj_options;
930     lldb::addr_t m_next_addr;
931     lldb::addr_t m_prev_byte_size;
932     OptionGroupFormat m_prev_format_options;
933     OptionGroupReadMemory m_prev_memory_options;
934     OptionGroupOutputFile m_prev_outfile_options;
935     OptionGroupValueObjectDisplay m_prev_varobj_options;
936     CompilerType m_prev_clang_ast_type;
937 };
938 
939 OptionDefinition
940 g_memory_find_option_table[] =
941 {
942     { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
943     { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,   "Use text to find a byte pattern."},
944     { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount,   "How many times to perform the search."},
945     { 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."},
946 };
947 
948 //----------------------------------------------------------------------
949 // Find the specified data in memory
950 //----------------------------------------------------------------------
951 class CommandObjectMemoryFind : public CommandObjectParsed
952 {
953 public:
954 
955   class OptionGroupFindMemory : public OptionGroup
956   {
957   public:
958     OptionGroupFindMemory () :
959       OptionGroup(),
960       m_count(1),
961       m_offset(0)
962     {
963     }
964 
965     virtual
966     ~OptionGroupFindMemory ()
967     {
968     }
969 
970     virtual uint32_t
971     GetNumDefinitions ()
972     {
973       return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
974     }
975 
976     virtual const OptionDefinition*
977     GetDefinitions ()
978     {
979       return g_memory_find_option_table;
980     }
981 
982     virtual Error
983     SetOptionValue (CommandInterpreter &interpreter,
984                     uint32_t option_idx,
985                     const char *option_arg)
986     {
987         Error error;
988         const int short_option = g_memory_find_option_table[option_idx].short_option;
989 
990         switch (short_option)
991         {
992         case 'e':
993               m_expr.SetValueFromString(option_arg);
994               break;
995 
996         case 's':
997               m_string.SetValueFromString(option_arg);
998               break;
999 
1000         case 'c':
1001               if (m_count.SetValueFromString(option_arg).Fail())
1002                   error.SetErrorString("unrecognized value for count");
1003               break;
1004 
1005         case 'o':
1006                if (m_offset.SetValueFromString(option_arg).Fail())
1007                    error.SetErrorString("unrecognized value for dump-offset");
1008                 break;
1009 
1010         default:
1011               error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1012               break;
1013         }
1014         return error;
1015     }
1016 
1017     virtual void
1018     OptionParsingStarting (CommandInterpreter &interpreter)
1019     {
1020         m_expr.Clear();
1021         m_string.Clear();
1022         m_count.Clear();
1023     }
1024 
1025       OptionValueString m_expr;
1026       OptionValueString m_string;
1027       OptionValueUInt64 m_count;
1028       OptionValueUInt64 m_offset;
1029   };
1030 
1031   CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1032   CommandObjectParsed (interpreter,
1033                        "memory find",
1034                        "Find a value in the memory of the process being debugged.",
1035                        NULL,
1036                        eCommandRequiresProcess | eCommandProcessMustBeLaunched),
1037   m_option_group (interpreter),
1038   m_memory_options ()
1039   {
1040     CommandArgumentEntry arg1;
1041     CommandArgumentEntry arg2;
1042     CommandArgumentData addr_arg;
1043     CommandArgumentData value_arg;
1044 
1045     // Define the first (and only) variant of this arg.
1046     addr_arg.arg_type = eArgTypeAddressOrExpression;
1047     addr_arg.arg_repetition = eArgRepeatPlain;
1048 
1049     // There is only one variant this argument could be; put it into the argument entry.
1050     arg1.push_back (addr_arg);
1051 
1052     // Define the first (and only) variant of this arg.
1053     value_arg.arg_type = eArgTypeAddressOrExpression;
1054     value_arg.arg_repetition = eArgRepeatPlain;
1055 
1056     // There is only one variant this argument could be; put it into the argument entry.
1057     arg2.push_back (value_arg);
1058 
1059     // Push the data for the first argument into the m_arguments vector.
1060     m_arguments.push_back (arg1);
1061     m_arguments.push_back (arg2);
1062 
1063     m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1064     m_option_group.Finalize();
1065   }
1066 
1067   virtual
1068   ~CommandObjectMemoryFind ()
1069   {
1070   }
1071 
1072   Options *
1073   GetOptions ()
1074   {
1075     return &m_option_group;
1076   }
1077 
1078 protected:
1079   virtual bool
1080   DoExecute (Args& command, CommandReturnObject &result)
1081   {
1082       // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
1083       Process *process = m_exe_ctx.GetProcessPtr();
1084 
1085       const size_t argc = command.GetArgumentCount();
1086 
1087       if (argc != 2)
1088       {
1089           result.AppendError("two addresses needed for memory find");
1090           return false;
1091       }
1092 
1093       Error error;
1094       lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1095       if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1096       {
1097           result.AppendError("invalid low address");
1098           return false;
1099       }
1100       lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1101       if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1102       {
1103           result.AppendError("invalid high address");
1104           return false;
1105       }
1106 
1107       if (high_addr <= low_addr)
1108       {
1109           result.AppendError("starting address must be smaller than ending address");
1110           return false;
1111       }
1112 
1113       lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1114 
1115       DataBufferHeap buffer;
1116 
1117       if (m_memory_options.m_string.OptionWasSet())
1118           buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1119       else if (m_memory_options.m_expr.OptionWasSet())
1120       {
1121           StackFrame* frame = m_exe_ctx.GetFramePtr();
1122           ValueObjectSP result_sp;
1123           if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
1124               result_sp.get())
1125           {
1126               uint64_t value = result_sp->GetValueAsUnsigned(0);
1127               switch (result_sp->GetClangType().GetByteSize(nullptr))
1128               {
1129                   case 1: {
1130                       uint8_t byte = (uint8_t)value;
1131                       buffer.CopyData(&byte,1);
1132                   }
1133                       break;
1134                   case 2: {
1135                       uint16_t word = (uint16_t)value;
1136                       buffer.CopyData(&word,2);
1137                   }
1138                       break;
1139                   case 4: {
1140                       uint32_t lword = (uint32_t)value;
1141                       buffer.CopyData(&lword,4);
1142                   }
1143                       break;
1144                   case 8: {
1145                       buffer.CopyData(&value, 8);
1146                   }
1147                       break;
1148                   case 3:
1149                   case 5:
1150                   case 6:
1151                   case 7:
1152                       result.AppendError("unknown type. pass a string instead");
1153                       return false;
1154                   default:
1155                       result.AppendError("result size larger than 8 bytes. pass a string instead");
1156                       return false;
1157               }
1158           }
1159           else
1160           {
1161               result.AppendError("expression evaluation failed. pass a string instead");
1162               return false;
1163           }
1164       }
1165       else
1166       {
1167           result.AppendError("please pass either a block of text, or an expression to evaluate.");
1168           return false;
1169       }
1170 
1171       size_t count = m_memory_options.m_count.GetCurrentValue();
1172       found_location = low_addr;
1173       bool ever_found = false;
1174       while (count)
1175       {
1176           found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1177           if (found_location == LLDB_INVALID_ADDRESS)
1178           {
1179               if (!ever_found)
1180               {
1181                   result.AppendMessage("data not found within the range.\n");
1182                   result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1183               }
1184               else
1185                   result.AppendMessage("no more matches within the range.\n");
1186               break;
1187           }
1188           result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location);
1189 
1190           DataBufferHeap dumpbuffer(32,0);
1191           process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1192           if (!error.Fail())
1193           {
1194               DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1195               data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1196               result.GetOutputStream().EOL();
1197           }
1198 
1199           --count;
1200           found_location++;
1201           ever_found = true;
1202       }
1203 
1204       result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1205       return true;
1206   }
1207 
1208     lldb::addr_t
1209     Search (lldb::addr_t low,
1210             lldb::addr_t high,
1211             uint8_t* buffer,
1212             size_t buffer_size)
1213     {
1214         Process *process = m_exe_ctx.GetProcessPtr();
1215         DataBufferHeap heap(buffer_size, 0);
1216         for (auto ptr = low;
1217              ptr < high;
1218              ptr++)
1219         {
1220             Error error;
1221             process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
1222             if (error.Fail())
1223                 return LLDB_INVALID_ADDRESS;
1224             if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
1225                 return ptr;
1226         }
1227         return LLDB_INVALID_ADDRESS;
1228     }
1229 
1230     OptionGroupOptions m_option_group;
1231     OptionGroupFindMemory m_memory_options;
1232 };
1233 
1234 
1235 OptionDefinition
1236 g_memory_write_option_table[] =
1237 {
1238 { LLDB_OPT_SET_1, true,  "infile", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1239 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset,   "Start writing bytes from an offset within the input file."},
1240 };
1241 
1242 //----------------------------------------------------------------------
1243 // Write memory to the inferior process
1244 //----------------------------------------------------------------------
1245 class CommandObjectMemoryWrite : public CommandObjectParsed
1246 {
1247 public:
1248 
1249     class OptionGroupWriteMemory : public OptionGroup
1250     {
1251     public:
1252         OptionGroupWriteMemory () :
1253             OptionGroup()
1254         {
1255         }
1256 
1257         virtual
1258         ~OptionGroupWriteMemory ()
1259         {
1260         }
1261 
1262         virtual uint32_t
1263         GetNumDefinitions ()
1264         {
1265             return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1266         }
1267 
1268         virtual const OptionDefinition*
1269         GetDefinitions ()
1270         {
1271             return g_memory_write_option_table;
1272         }
1273 
1274         virtual Error
1275         SetOptionValue (CommandInterpreter &interpreter,
1276                         uint32_t option_idx,
1277                         const char *option_arg)
1278         {
1279             Error error;
1280             const int short_option = g_memory_write_option_table[option_idx].short_option;
1281 
1282             switch (short_option)
1283             {
1284                 case 'i':
1285                     m_infile.SetFile (option_arg, true);
1286                     if (!m_infile.Exists())
1287                     {
1288                         m_infile.Clear();
1289                         error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
1290                     }
1291                     break;
1292 
1293                 case 'o':
1294                     {
1295                         bool success;
1296                         m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success);
1297                         if (!success)
1298                         {
1299                             error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
1300                         }
1301                     }
1302                     break;
1303 
1304                 default:
1305                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1306                     break;
1307             }
1308             return error;
1309         }
1310 
1311         virtual void
1312         OptionParsingStarting (CommandInterpreter &interpreter)
1313         {
1314             m_infile.Clear();
1315             m_infile_offset = 0;
1316         }
1317 
1318         FileSpec m_infile;
1319         off_t m_infile_offset;
1320     };
1321 
1322     CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
1323         CommandObjectParsed (interpreter,
1324                              "memory write",
1325                              "Write to the memory of the process being debugged.",
1326                              NULL,
1327                              eCommandRequiresProcess | eCommandProcessMustBeLaunched),
1328         m_option_group (interpreter),
1329         m_format_options (eFormatBytes, 1, UINT64_MAX),
1330         m_memory_options ()
1331     {
1332         CommandArgumentEntry arg1;
1333         CommandArgumentEntry arg2;
1334         CommandArgumentData addr_arg;
1335         CommandArgumentData value_arg;
1336 
1337         // Define the first (and only) variant of this arg.
1338         addr_arg.arg_type = eArgTypeAddress;
1339         addr_arg.arg_repetition = eArgRepeatPlain;
1340 
1341         // There is only one variant this argument could be; put it into the argument entry.
1342         arg1.push_back (addr_arg);
1343 
1344         // Define the first (and only) variant of this arg.
1345         value_arg.arg_type = eArgTypeValue;
1346         value_arg.arg_repetition = eArgRepeatPlus;
1347 
1348         // There is only one variant this argument could be; put it into the argument entry.
1349         arg2.push_back (value_arg);
1350 
1351         // Push the data for the first argument into the m_arguments vector.
1352         m_arguments.push_back (arg1);
1353         m_arguments.push_back (arg2);
1354 
1355         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1356         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE  , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1357         m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1358         m_option_group.Finalize();
1359 
1360     }
1361 
1362     virtual
1363     ~CommandObjectMemoryWrite ()
1364     {
1365     }
1366 
1367     Options *
1368     GetOptions ()
1369     {
1370         return &m_option_group;
1371     }
1372 
1373     bool
1374     UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1375     {
1376         if (total_byte_size > 8)
1377             return false;
1378 
1379         if (total_byte_size == 8)
1380             return true;
1381 
1382         const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1383         return uval64 <= max;
1384     }
1385 
1386     bool
1387     SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1388     {
1389         if (total_byte_size > 8)
1390             return false;
1391 
1392         if (total_byte_size == 8)
1393             return true;
1394 
1395         const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1396         const int64_t min = ~(max);
1397         return min <= sval64 && sval64 <= max;
1398     }
1399 
1400 protected:
1401     virtual bool
1402     DoExecute (Args& command, CommandReturnObject &result)
1403     {
1404         // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
1405         Process *process = m_exe_ctx.GetProcessPtr();
1406 
1407         const size_t argc = command.GetArgumentCount();
1408 
1409         if (m_memory_options.m_infile)
1410         {
1411             if (argc < 1)
1412             {
1413                 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1414                 result.SetStatus(eReturnStatusFailed);
1415                 return false;
1416             }
1417         }
1418         else if (argc < 2)
1419         {
1420             result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
1421             result.SetStatus(eReturnStatusFailed);
1422             return false;
1423         }
1424 
1425         StreamString buffer (Stream::eBinary,
1426                              process->GetTarget().GetArchitecture().GetAddressByteSize(),
1427                              process->GetTarget().GetArchitecture().GetByteOrder());
1428 
1429         OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1430         size_t item_byte_size = byte_size_value.GetCurrentValue();
1431 
1432         Error error;
1433         lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1434                                                    command.GetArgumentAtIndex(0),
1435                                                    LLDB_INVALID_ADDRESS,
1436                                                    &error);
1437 
1438         if (addr == LLDB_INVALID_ADDRESS)
1439         {
1440             result.AppendError("invalid address expression\n");
1441             result.AppendError(error.AsCString());
1442             result.SetStatus(eReturnStatusFailed);
1443             return false;
1444         }
1445 
1446         if (m_memory_options.m_infile)
1447         {
1448             size_t length = SIZE_MAX;
1449             if (item_byte_size > 1)
1450                 length = item_byte_size;
1451             lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
1452             if (data_sp)
1453             {
1454                 length = data_sp->GetByteSize();
1455                 if (length > 0)
1456                 {
1457                     Error error;
1458                     size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1459 
1460                     if (bytes_written == length)
1461                     {
1462                         // All bytes written
1463                         result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
1464                         result.SetStatus(eReturnStatusSuccessFinishResult);
1465                     }
1466                     else if (bytes_written > 0)
1467                     {
1468                         // Some byte written
1469                         result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr);
1470                         result.SetStatus(eReturnStatusSuccessFinishResult);
1471                     }
1472                     else
1473                     {
1474                         result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1475                         result.SetStatus(eReturnStatusFailed);
1476                     }
1477                 }
1478             }
1479             else
1480             {
1481                 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1482                 result.SetStatus(eReturnStatusFailed);
1483             }
1484             return result.Succeeded();
1485         }
1486         else if (item_byte_size == 0)
1487         {
1488             if (m_format_options.GetFormat() == eFormatPointer)
1489                 item_byte_size = buffer.GetAddressByteSize();
1490             else
1491                 item_byte_size = 1;
1492         }
1493 
1494         command.Shift(); // shift off the address argument
1495         uint64_t uval64;
1496         int64_t sval64;
1497         bool success = false;
1498         const size_t num_value_args = command.GetArgumentCount();
1499         for (size_t i=0; i<num_value_args; ++i)
1500         {
1501             const char *value_str = command.GetArgumentAtIndex(i);
1502 
1503             switch (m_format_options.GetFormat())
1504             {
1505             case kNumFormats:
1506             case eFormatFloat:  // TODO: add support for floats soon
1507             case eFormatCharPrintable:
1508             case eFormatBytesWithASCII:
1509             case eFormatComplex:
1510             case eFormatEnum:
1511             case eFormatUnicode16:
1512             case eFormatUnicode32:
1513             case eFormatVectorOfChar:
1514             case eFormatVectorOfSInt8:
1515             case eFormatVectorOfUInt8:
1516             case eFormatVectorOfSInt16:
1517             case eFormatVectorOfUInt16:
1518             case eFormatVectorOfSInt32:
1519             case eFormatVectorOfUInt32:
1520             case eFormatVectorOfSInt64:
1521             case eFormatVectorOfUInt64:
1522             case eFormatVectorOfFloat32:
1523             case eFormatVectorOfFloat64:
1524             case eFormatVectorOfUInt128:
1525             case eFormatOSType:
1526             case eFormatComplexInteger:
1527             case eFormatAddressInfo:
1528             case eFormatHexFloat:
1529             case eFormatInstruction:
1530             case eFormatVoid:
1531                 result.AppendError("unsupported format for writing memory");
1532                 result.SetStatus(eReturnStatusFailed);
1533                 return false;
1534 
1535             case eFormatDefault:
1536             case eFormatBytes:
1537             case eFormatHex:
1538             case eFormatHexUppercase:
1539             case eFormatPointer:
1540 
1541                 // Decode hex bytes
1542                 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success);
1543                 if (!success)
1544                 {
1545                     result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1546                     result.SetStatus(eReturnStatusFailed);
1547                     return false;
1548                 }
1549                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1550                 {
1551                     result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
1552                     result.SetStatus(eReturnStatusFailed);
1553                     return false;
1554                 }
1555                 buffer.PutMaxHex64 (uval64, item_byte_size);
1556                 break;
1557 
1558             case eFormatBoolean:
1559                 uval64 = Args::StringToBoolean(value_str, false, &success);
1560                 if (!success)
1561                 {
1562                     result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1563                     result.SetStatus(eReturnStatusFailed);
1564                     return false;
1565                 }
1566                 buffer.PutMaxHex64 (uval64, item_byte_size);
1567                 break;
1568 
1569             case eFormatBinary:
1570                 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success);
1571                 if (!success)
1572                 {
1573                     result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1574                     result.SetStatus(eReturnStatusFailed);
1575                     return false;
1576                 }
1577                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1578                 {
1579                     result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
1580                     result.SetStatus(eReturnStatusFailed);
1581                     return false;
1582                 }
1583                 buffer.PutMaxHex64 (uval64, item_byte_size);
1584                 break;
1585 
1586             case eFormatCharArray:
1587             case eFormatChar:
1588             case eFormatCString:
1589                 if (value_str[0])
1590                 {
1591                     size_t len = strlen (value_str);
1592                     // Include the NULL for C strings...
1593                     if (m_format_options.GetFormat() == eFormatCString)
1594                         ++len;
1595                     Error error;
1596                     if (process->WriteMemory (addr, value_str, len, error) == len)
1597                     {
1598                         addr += len;
1599                     }
1600                     else
1601                     {
1602                         result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1603                         result.SetStatus(eReturnStatusFailed);
1604                         return false;
1605                     }
1606                 }
1607                 break;
1608 
1609             case eFormatDecimal:
1610                 sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success);
1611                 if (!success)
1612                 {
1613                     result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1614                     result.SetStatus(eReturnStatusFailed);
1615                     return false;
1616                 }
1617                 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1618                 {
1619                     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);
1620                     result.SetStatus(eReturnStatusFailed);
1621                     return false;
1622                 }
1623                 buffer.PutMaxHex64 (sval64, item_byte_size);
1624                 break;
1625 
1626             case eFormatUnsigned:
1627                 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success);
1628                 if (!success)
1629                 {
1630                     result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1631                     result.SetStatus(eReturnStatusFailed);
1632                     return false;
1633                 }
1634                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1635                 {
1636                     result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
1637                     result.SetStatus(eReturnStatusFailed);
1638                     return false;
1639                 }
1640                 buffer.PutMaxHex64 (uval64, item_byte_size);
1641                 break;
1642 
1643             case eFormatOctal:
1644                 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success);
1645                 if (!success)
1646                 {
1647                     result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1648                     result.SetStatus(eReturnStatusFailed);
1649                     return false;
1650                 }
1651                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1652                 {
1653                     result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
1654                     result.SetStatus(eReturnStatusFailed);
1655                     return false;
1656                 }
1657                 buffer.PutMaxHex64 (uval64, item_byte_size);
1658                 break;
1659             }
1660         }
1661 
1662         if (!buffer.GetString().empty())
1663         {
1664             Error error;
1665             if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
1666                 return true;
1667             else
1668             {
1669                 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1670                 result.SetStatus(eReturnStatusFailed);
1671                 return false;
1672             }
1673         }
1674         return true;
1675     }
1676 
1677     OptionGroupOptions m_option_group;
1678     OptionGroupFormat m_format_options;
1679     OptionGroupWriteMemory m_memory_options;
1680 };
1681 
1682 //----------------------------------------------------------------------
1683 // Get malloc/free history of a memory address.
1684 //----------------------------------------------------------------------
1685 class CommandObjectMemoryHistory : public CommandObjectParsed
1686 {
1687 public:
1688 
1689     CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
1690     CommandObjectParsed (interpreter,
1691                          "memory history",
1692                          "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
1693                          NULL,
1694                          eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | eCommandProcessMustBeLaunched)
1695     {
1696         CommandArgumentEntry arg1;
1697         CommandArgumentData addr_arg;
1698 
1699         // Define the first (and only) variant of this arg.
1700         addr_arg.arg_type = eArgTypeAddress;
1701         addr_arg.arg_repetition = eArgRepeatPlain;
1702 
1703         // There is only one variant this argument could be; put it into the argument entry.
1704         arg1.push_back (addr_arg);
1705 
1706         // Push the data for the first argument into the m_arguments vector.
1707         m_arguments.push_back (arg1);
1708     }
1709 
1710     virtual
1711     ~CommandObjectMemoryHistory ()
1712     {
1713     }
1714 
1715     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
1716     {
1717         return m_cmd_name.c_str();
1718     }
1719 
1720 protected:
1721     virtual bool
1722     DoExecute (Args& command, CommandReturnObject &result)
1723     {
1724         const size_t argc = command.GetArgumentCount();
1725 
1726         if (argc == 0 || argc > 1)
1727         {
1728             result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
1729             result.SetStatus(eReturnStatusFailed);
1730             return false;
1731         }
1732 
1733         Error error;
1734         lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1735                                                    command.GetArgumentAtIndex(0),
1736                                                    LLDB_INVALID_ADDRESS,
1737                                                    &error);
1738 
1739         if (addr == LLDB_INVALID_ADDRESS)
1740         {
1741             result.AppendError("invalid address expression");
1742             result.AppendError(error.AsCString());
1743             result.SetStatus(eReturnStatusFailed);
1744             return false;
1745         }
1746 
1747         Stream *output_stream = &result.GetOutputStream();
1748 
1749         const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1750         const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
1751 
1752         if (! memory_history.get())
1753         {
1754             result.AppendError("no available memory history provider");
1755             result.SetStatus(eReturnStatusFailed);
1756             return false;
1757         }
1758 
1759         HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1760 
1761         for (auto thread : thread_list) {
1762             thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
1763         }
1764 
1765         result.SetStatus(eReturnStatusSuccessFinishResult);
1766 
1767         return true;
1768     }
1769 
1770 };
1771 
1772 
1773 //-------------------------------------------------------------------------
1774 // CommandObjectMemory
1775 //-------------------------------------------------------------------------
1776 
1777 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
1778     CommandObjectMultiword (interpreter,
1779                             "memory",
1780                             "A set of commands for operating on memory.",
1781                             "memory <subcommand> [<subcommand-options>]")
1782 {
1783     LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
1784     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1785     LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
1786     LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
1787 }
1788 
1789 CommandObjectMemory::~CommandObjectMemory ()
1790 {
1791 }
1792