]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp
MFV r284234:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Commands / CommandObjectMemory.cpp
1 //===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/lldb-python.h"
11
12 #include "CommandObjectMemory.h"
13
14 // C Includes
15 #include <inttypes.h>
16
17 // C++ Includes
18 // Other libraries and framework includes
19 // Project includes
20 #include "lldb/Core/DataBufferHeap.h"
21 #include "lldb/Core/DataExtractor.h"
22 #include "lldb/Core/Debugger.h"
23 #include "lldb/Core/Module.h"
24 #include "lldb/Core/StreamString.h"
25 #include "lldb/Core/ValueObjectMemory.h"
26 #include "lldb/DataFormatters/ValueObjectPrinter.h"
27 #include "lldb/Interpreter/Args.h"
28 #include "lldb/Interpreter/CommandReturnObject.h"
29 #include "lldb/Interpreter/CommandInterpreter.h"
30 #include "lldb/Interpreter/Options.h"
31 #include "lldb/Interpreter/OptionGroupFormat.h"
32 #include "lldb/Interpreter/OptionGroupOutputFile.h"
33 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
34 #include "lldb/Interpreter/OptionValueString.h"
35 #include "lldb/Symbol/TypeList.h"
36 #include "lldb/Target/MemoryHistory.h"
37 #include "lldb/Target/Process.h"
38 #include "lldb/Target/StackFrame.h"
39 #include "lldb/Target/Thread.h"
40
41 using namespace lldb;
42 using namespace lldb_private;
43
44 static OptionDefinition
45 g_option_table[] =
46 {
47     { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
48     { 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."},
49     { LLDB_OPT_SET_3, true , "type"         ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone          ,"The name of a type to view memory as."},
50     { LLDB_OPT_SET_1|
51       LLDB_OPT_SET_2|
52       LLDB_OPT_SET_3, false, "force"        ,'r', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone          ,"Necessary if reading over target.max-memory-read-size bytes."},
53 };
54
55
56
57 class OptionGroupReadMemory : public OptionGroup
58 {
59 public:
60
61     OptionGroupReadMemory () :
62         m_num_per_line (1,1),
63         m_output_as_binary (false),
64         m_view_as_type()
65     {
66     }
67
68     virtual
69     ~OptionGroupReadMemory ()
70     {
71     }
72     
73     
74     virtual uint32_t
75     GetNumDefinitions ()
76     {
77         return sizeof (g_option_table) / sizeof (OptionDefinition);
78     }
79     
80     virtual const OptionDefinition*
81     GetDefinitions ()
82     {
83         return g_option_table;
84     }
85     
86     virtual Error
87     SetOptionValue (CommandInterpreter &interpreter,
88                     uint32_t option_idx,
89                     const char *option_arg)
90     {
91         Error error;
92         const int short_option = g_option_table[option_idx].short_option;
93         
94         switch (short_option)
95         {
96             case 'l':
97                 error = m_num_per_line.SetValueFromCString (option_arg);
98                 if (m_num_per_line.GetCurrentValue() == 0)
99                     error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
100                 break;
101
102             case 'b':
103                 m_output_as_binary = true;
104                 break;
105                 
106             case 't':
107                 error = m_view_as_type.SetValueFromCString (option_arg);
108                 break;
109             
110             case 'r':
111                 m_force = true;
112                 break;
113                 
114             default:
115                 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
116                 break;
117         }
118         return error;
119     }
120     
121     virtual void
122     OptionParsingStarting (CommandInterpreter &interpreter)
123     {
124         m_num_per_line.Clear();
125         m_output_as_binary = false;
126         m_view_as_type.Clear();
127         m_force = false;
128     }
129     
130     Error
131     FinalizeSettings (Target *target, OptionGroupFormat& format_options)
132     {
133         Error error;
134         OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
135         OptionValueUInt64 &count_value = format_options.GetCountValue();
136         const bool byte_size_option_set = byte_size_value.OptionWasSet();
137         const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
138         const bool count_option_set = format_options.GetCountValue().OptionWasSet();
139         
140         switch (format_options.GetFormat())
141         {
142             default:
143                 break;
144                 
145             case eFormatBoolean:
146                 if (!byte_size_option_set)
147                     byte_size_value = 1;
148                 if (!num_per_line_option_set)
149                     m_num_per_line = 1;
150                 if (!count_option_set)
151                     format_options.GetCountValue() = 8;
152                 break;
153                 
154             case eFormatCString:
155                 break;
156
157             case eFormatInstruction:
158                 if (count_option_set)
159                     byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
160                 m_num_per_line = 1;
161                 break;
162
163             case eFormatAddressInfo:
164                 if (!byte_size_option_set)
165                     byte_size_value = target->GetArchitecture().GetAddressByteSize();
166                 m_num_per_line = 1;
167                 if (!count_option_set)
168                     format_options.GetCountValue() = 8;
169                 break;
170
171             case eFormatPointer:
172                 byte_size_value = target->GetArchitecture().GetAddressByteSize();
173                 if (!num_per_line_option_set)
174                     m_num_per_line = 4;
175                 if (!count_option_set)
176                     format_options.GetCountValue() = 8;
177                 break;
178                 
179             case eFormatBinary:
180             case eFormatFloat:
181             case eFormatOctal:
182             case eFormatDecimal:
183             case eFormatEnum:
184             case eFormatUnicode16:
185             case eFormatUnicode32:
186             case eFormatUnsigned:
187             case eFormatHexFloat:
188                 if (!byte_size_option_set)
189                     byte_size_value = 4;
190                 if (!num_per_line_option_set)
191                     m_num_per_line = 1;
192                 if (!count_option_set)
193                     format_options.GetCountValue() = 8;
194                 break;
195             
196             case eFormatBytes:
197             case eFormatBytesWithASCII:
198                 if (byte_size_option_set)
199                 {
200                     if (byte_size_value > 1)
201                         error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
202                                                         "\tconsider using a different display format or don't specify the byte size",
203                                                         byte_size_value.GetCurrentValue());
204                 }
205                 else
206                     byte_size_value = 1;
207                 if (!num_per_line_option_set)
208                     m_num_per_line = 16;
209                 if (!count_option_set)
210                     format_options.GetCountValue() = 32;
211                 break;
212             case eFormatCharArray:
213             case eFormatChar:
214             case eFormatCharPrintable:
215                 if (!byte_size_option_set)
216                     byte_size_value = 1;
217                 if (!num_per_line_option_set)
218                     m_num_per_line = 32;
219                 if (!count_option_set)
220                     format_options.GetCountValue() = 64;
221                 break;
222             case eFormatComplex:
223                 if (!byte_size_option_set)
224                     byte_size_value = 8;
225                 if (!num_per_line_option_set)
226                     m_num_per_line = 1;
227                 if (!count_option_set)
228                     format_options.GetCountValue() = 8;
229                 break;
230             case eFormatComplexInteger:
231                 if (!byte_size_option_set)
232                     byte_size_value = 8;
233                 if (!num_per_line_option_set)
234                     m_num_per_line = 1;
235                 if (!count_option_set)
236                     format_options.GetCountValue() = 8;
237                 break;
238             case eFormatHex:
239                 if (!byte_size_option_set)
240                     byte_size_value = 4;
241                 if (!num_per_line_option_set)
242                 {
243                     switch (byte_size_value)
244                     {
245                         case 1:
246                         case 2:
247                             m_num_per_line = 8;
248                             break;
249                         case 4:
250                             m_num_per_line = 4;
251                             break;
252                         case 8:
253                             m_num_per_line = 2;
254                             break;
255                         default:
256                             m_num_per_line = 1;
257                             break;
258                     }
259                 }
260                 if (!count_option_set)
261                     count_value = 8;
262                 break;
263                 
264             case eFormatVectorOfChar:
265             case eFormatVectorOfSInt8:
266             case eFormatVectorOfUInt8:
267             case eFormatVectorOfSInt16:
268             case eFormatVectorOfUInt16:
269             case eFormatVectorOfSInt32:
270             case eFormatVectorOfUInt32:
271             case eFormatVectorOfSInt64:
272             case eFormatVectorOfUInt64:
273             case eFormatVectorOfFloat32:
274             case eFormatVectorOfFloat64:
275             case eFormatVectorOfUInt128:
276                 if (!byte_size_option_set)
277                     byte_size_value = 128;
278                 if (!num_per_line_option_set)
279                     m_num_per_line = 1;
280                 if (!count_option_set)
281                     count_value = 4;
282                 break;
283         }
284         return error;
285     }
286
287     bool
288     AnyOptionWasSet () const
289     {
290         return m_num_per_line.OptionWasSet() ||
291                m_output_as_binary ||
292                m_view_as_type.OptionWasSet();
293     }
294     
295     OptionValueUInt64 m_num_per_line;
296     bool m_output_as_binary;
297     OptionValueString m_view_as_type;
298     bool m_force;
299 };
300
301
302
303 //----------------------------------------------------------------------
304 // Read memory from the inferior process
305 //----------------------------------------------------------------------
306 class CommandObjectMemoryRead : public CommandObjectParsed
307 {
308 public:
309
310     CommandObjectMemoryRead (CommandInterpreter &interpreter) :
311         CommandObjectParsed (interpreter,
312                              "memory read",
313                              "Read from the memory of the process being debugged.",
314                              NULL,
315                              eFlagRequiresTarget | eFlagProcessMustBePaused),
316         m_option_group (interpreter),
317         m_format_options (eFormatBytesWithASCII, 1, 8),
318         m_memory_options (),
319         m_outfile_options (),
320         m_varobj_options(),
321         m_next_addr(LLDB_INVALID_ADDRESS),
322         m_prev_byte_size(0),
323         m_prev_format_options (eFormatBytesWithASCII, 1, 8),
324         m_prev_memory_options (),
325         m_prev_outfile_options (),
326         m_prev_varobj_options()
327     {
328         CommandArgumentEntry arg1;
329         CommandArgumentEntry arg2;
330         CommandArgumentData start_addr_arg;
331         CommandArgumentData end_addr_arg;
332         
333         // Define the first (and only) variant of this arg.
334         start_addr_arg.arg_type = eArgTypeAddressOrExpression;
335         start_addr_arg.arg_repetition = eArgRepeatPlain;
336         
337         // There is only one variant this argument could be; put it into the argument entry.
338         arg1.push_back (start_addr_arg);
339         
340         // Define the first (and only) variant of this arg.
341         end_addr_arg.arg_type = eArgTypeAddressOrExpression;
342         end_addr_arg.arg_repetition = eArgRepeatOptional;
343         
344         // There is only one variant this argument could be; put it into the argument entry.
345         arg2.push_back (end_addr_arg);
346         
347         // Push the data for the first argument into the m_arguments vector.
348         m_arguments.push_back (arg1);
349         m_arguments.push_back (arg2);
350         
351         // Add the "--format" and "--count" options to group 1 and 3
352         m_option_group.Append (&m_format_options, 
353                                OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT, 
354                                LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
355         m_option_group.Append (&m_format_options, 
356                                OptionGroupFormat::OPTION_GROUP_GDB_FMT, 
357                                LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
358         // Add the "--size" option to group 1 and 2
359         m_option_group.Append (&m_format_options, 
360                                OptionGroupFormat::OPTION_GROUP_SIZE, 
361                                LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
362         m_option_group.Append (&m_memory_options);
363         m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
364         m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
365         m_option_group.Finalize();
366     }
367
368     virtual
369     ~CommandObjectMemoryRead ()
370     {
371     }
372
373     Options *
374     GetOptions ()
375     {
376         return &m_option_group;
377     }
378
379     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
380     {
381         return m_cmd_name.c_str();
382     }
383
384 protected:
385     virtual bool
386     DoExecute (Args& command, CommandReturnObject &result)
387     {
388         // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
389         Target *target = m_exe_ctx.GetTargetPtr();
390
391         const size_t argc = command.GetArgumentCount();
392
393         if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
394         {
395             result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
396             result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
397             result.SetStatus(eReturnStatusFailed);
398             return false;
399         }
400
401         ClangASTType clang_ast_type;        
402         Error error;
403
404         const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
405         if (view_as_type_cstr && view_as_type_cstr[0])
406         {
407             // We are viewing memory as a type
408             
409             SymbolContext sc;
410             const bool exact_match = false;
411             TypeList type_list;
412             uint32_t reference_count = 0;
413             uint32_t pointer_count = 0;
414             size_t idx;
415             
416 #define ALL_KEYWORDS        \
417     KEYWORD("const")        \
418     KEYWORD("volatile")     \
419     KEYWORD("restrict")     \
420     KEYWORD("struct")       \
421     KEYWORD("class")        \
422     KEYWORD("union")
423             
424 #define KEYWORD(s) s,
425             static const char *g_keywords[] =
426             {
427                 ALL_KEYWORDS
428             };
429 #undef KEYWORD
430
431 #define KEYWORD(s) (sizeof(s) - 1),
432             static const int g_keyword_lengths[] =
433             {
434                 ALL_KEYWORDS
435             };
436 #undef KEYWORD
437             
438 #undef ALL_KEYWORDS
439             
440             static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
441             std::string type_str(view_as_type_cstr);
442             
443             // Remove all instances of g_keywords that are followed by spaces
444             for (size_t i = 0; i < g_num_keywords; ++i)
445             {
446                 const char *keyword = g_keywords[i];
447                 int keyword_len = g_keyword_lengths[i];
448                 
449                 idx = 0;
450                 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
451                 {
452                     if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
453                     {
454                         type_str.erase(idx, keyword_len+1);
455                         idx = 0;
456                     }
457                     else
458                     {
459                         idx += keyword_len;
460                     }
461                 }
462             }
463             bool done = type_str.empty();
464             // 
465             idx = type_str.find_first_not_of (" \t");
466             if (idx > 0 && idx != std::string::npos)
467                 type_str.erase (0, idx);
468             while (!done)
469             {
470                 // Strip trailing spaces
471                 if (type_str.empty())
472                     done = true;
473                 else
474                 {
475                     switch (type_str[type_str.size()-1])
476                     {
477                     case '*':
478                         ++pointer_count;
479                         // fall through...
480                     case ' ':
481                     case '\t':
482                         type_str.erase(type_str.size()-1);
483                         break;
484
485                     case '&':
486                         if (reference_count == 0)
487                         {
488                             reference_count = 1;
489                             type_str.erase(type_str.size()-1);
490                         }
491                         else
492                         {
493                             result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
494                             result.SetStatus(eReturnStatusFailed);
495                             return false;
496                         }
497                         break;
498
499                     default:
500                         done = true;
501                         break;
502                     }
503                 }
504             }
505                     
506             ConstString lookup_type_name(type_str.c_str());
507             StackFrame *frame = m_exe_ctx.GetFramePtr();
508             if (frame)
509             {
510                 sc = frame->GetSymbolContext (eSymbolContextModule);
511                 if (sc.module_sp)
512                 {
513                     sc.module_sp->FindTypes (sc,
514                                              lookup_type_name,
515                                              exact_match,
516                                              1, 
517                                              type_list);
518                 }
519             }
520             if (type_list.GetSize() == 0)
521             {
522                 target->GetImages().FindTypes (sc, 
523                                                lookup_type_name, 
524                                                exact_match, 
525                                                1, 
526                                                type_list);
527             }
528             
529             if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
530             {
531                 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
532                 if (tdecl)
533                 {
534                     clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
535                 }
536             }
537             
538             if (clang_ast_type.IsValid() == false)
539             {
540                 if (type_list.GetSize() == 0)
541                 {
542                     result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
543                                                   lookup_type_name.GetCString(),
544                                                   view_as_type_cstr);
545                     result.SetStatus(eReturnStatusFailed);
546                     return false;
547                 }
548                 else
549                 {
550                     TypeSP type_sp (type_list.GetTypeAtIndex(0));
551                     clang_ast_type = type_sp->GetClangFullType();
552                 }
553             }
554             
555             while (pointer_count > 0)
556             {
557                 ClangASTType pointer_type = clang_ast_type.GetPointerType();
558                 if (pointer_type.IsValid())
559                     clang_ast_type = pointer_type;
560                 else
561                 {
562                     result.AppendError ("unable make a pointer type\n");
563                     result.SetStatus(eReturnStatusFailed);
564                     return false;
565                 }
566                 --pointer_count;
567             }
568
569             m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize();
570             
571             if (m_format_options.GetByteSizeValue() == 0)
572             {
573                 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 
574                                               view_as_type_cstr);
575                 result.SetStatus(eReturnStatusFailed);
576                 return false;
577             }
578             
579             if (!m_format_options.GetCountValue().OptionWasSet())
580                 m_format_options.GetCountValue() = 1;
581         }
582         else
583         {
584             error = m_memory_options.FinalizeSettings (target, m_format_options);
585         }
586
587         // Look for invalid combinations of settings
588         if (error.Fail())
589         {
590             result.AppendError(error.AsCString());
591             result.SetStatus(eReturnStatusFailed);
592             return false;
593         }
594
595         lldb::addr_t addr;
596         size_t total_byte_size = 0;
597         if (argc == 0)
598         {
599             // Use the last address and byte size and all options as they were
600             // if no options have been set
601             addr = m_next_addr;
602             total_byte_size = m_prev_byte_size;
603             clang_ast_type = m_prev_clang_ast_type;
604             if (!m_format_options.AnyOptionWasSet() &&
605                 !m_memory_options.AnyOptionWasSet() &&
606                 !m_outfile_options.AnyOptionWasSet() &&
607                 !m_varobj_options.AnyOptionWasSet())
608             {
609                 m_format_options = m_prev_format_options;
610                 m_memory_options = m_prev_memory_options;
611                 m_outfile_options = m_prev_outfile_options;
612                 m_varobj_options = m_prev_varobj_options;
613             }
614         }
615
616         size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
617
618         // TODO For non-8-bit byte addressable architectures this needs to be
619         // revisited to fully support all lldb's range of formatting options.
620         // Furthermore code memory reads (for those architectures) will not
621         // be correctly formatted even w/o formatting options.
622         size_t item_byte_size =
623             target->GetArchitecture().GetDataByteSize() > 1 ?
624             target->GetArchitecture().GetDataByteSize() :
625             m_format_options.GetByteSizeValue().GetCurrentValue();
626
627         const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
628
629         if (total_byte_size == 0)
630         {
631             total_byte_size = item_count * item_byte_size;
632             if (total_byte_size == 0)
633                 total_byte_size = 32;
634         }
635
636         if (argc > 0)
637             addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
638
639         if (addr == LLDB_INVALID_ADDRESS)
640         {
641             result.AppendError("invalid start address expression.");
642             result.AppendError(error.AsCString());
643             result.SetStatus(eReturnStatusFailed);
644             return false;
645         }
646
647         if (argc == 2)
648         {
649             lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
650             if (end_addr == LLDB_INVALID_ADDRESS)
651             {
652                 result.AppendError("invalid end address expression.");
653                 result.AppendError(error.AsCString());
654                 result.SetStatus(eReturnStatusFailed);
655                 return false;
656             }
657             else if (end_addr <= addr)
658             {
659                 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
660                 result.SetStatus(eReturnStatusFailed);
661                 return false;
662             }
663             else if (m_format_options.GetCountValue().OptionWasSet())
664             {
665                 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count);
666                 result.SetStatus(eReturnStatusFailed);
667                 return false;
668             }
669
670             total_byte_size = end_addr - addr;
671             item_count = total_byte_size / item_byte_size;
672         }
673
674         uint32_t max_unforced_size = target->GetMaximumMemReadSize();
675         
676         if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
677         {
678             result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
679             result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
680             result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
681             return false;
682         }
683         
684         DataBufferSP data_sp;
685         size_t bytes_read = 0;
686         if (clang_ast_type.GetOpaqueQualType())
687         {
688             // Make sure we don't display our type as ASCII bytes like the default memory read
689             if (m_format_options.GetFormatValue().OptionWasSet() == false)
690                 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
691
692             bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue();
693         }
694         else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
695         {
696             data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
697             if (data_sp->GetBytes() == NULL)
698             {
699                 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size);
700                 result.SetStatus(eReturnStatusFailed);
701                 return false;
702             }
703
704             Address address(addr, NULL);
705             bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
706             if (bytes_read == 0)
707             {
708                 const char *error_cstr = error.AsCString();
709                 if (error_cstr && error_cstr[0])
710                 {
711                     result.AppendError(error_cstr);
712                 }
713                 else
714                 {
715                     result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
716                 }
717                 result.SetStatus(eReturnStatusFailed);
718                 return false;
719             }
720             
721             if (bytes_read < total_byte_size)
722                 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);
723         }
724         else
725         {
726             // we treat c-strings as a special case because they do not have a fixed size
727             if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
728                 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
729             else
730                 item_byte_size = target->GetMaximumSizeOfStringSummary();
731             if (!m_format_options.GetCountValue().OptionWasSet())
732                 item_count = 1;
733             data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
734             if (data_sp->GetBytes() == NULL)
735             {
736                 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));
737                 result.SetStatus(eReturnStatusFailed);
738                 return false;
739             }
740             uint8_t *data_ptr = data_sp->GetBytes();
741             auto data_addr = addr;
742             auto count = item_count;
743             item_count = 0;
744             while (item_count < count)
745             {
746                 std::string buffer;
747                 buffer.resize(item_byte_size+1,0);
748                 Error error;
749                 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
750                 if (error.Fail())
751                 {
752                     result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
753                     result.SetStatus(eReturnStatusFailed);
754                     return false;
755                 }
756                 if (item_byte_size == read)
757                 {
758                     result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
759                     break;
760                 }
761                 read+=1; // account for final NULL byte
762                 memcpy(data_ptr, &buffer[0], read);
763                 data_ptr += read;
764                 data_addr += read;
765                 bytes_read += read;
766                 item_count++; // if we break early we know we only read item_count strings
767             }
768             data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
769         }
770
771         m_next_addr = addr + bytes_read;
772         m_prev_byte_size = bytes_read;
773         m_prev_format_options = m_format_options;
774         m_prev_memory_options = m_memory_options;
775         m_prev_outfile_options = m_outfile_options;
776         m_prev_varobj_options = m_varobj_options;
777         m_prev_clang_ast_type = clang_ast_type;
778
779         StreamFile outfile_stream;
780         Stream *output_stream = NULL;
781         const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
782         if (outfile_spec)
783         {
784             char path[PATH_MAX];
785             outfile_spec.GetPath (path, sizeof(path));
786             
787             uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
788             const bool append = m_outfile_options.GetAppend().GetCurrentValue();
789             if (append)
790                 open_options |= File::eOpenOptionAppend;
791             
792             if (outfile_stream.GetFile ().Open (path, open_options).Success())
793             {
794                 if (m_memory_options.m_output_as_binary)
795                 {
796                     const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
797                     if (bytes_written > 0)
798                     {
799                         result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n", 
800                                                          bytes_written, 
801                                                          append ? "appended" : "written", 
802                                                          path);
803                         return true;
804                     }
805                     else 
806                     {
807                         result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
808                         result.SetStatus(eReturnStatusFailed);
809                         return false;
810                     }
811                 }
812                 else
813                 {
814                     // We are going to write ASCII to the file just point the
815                     // output_stream to our outfile_stream...
816                     output_stream = &outfile_stream;
817                 }
818             }
819             else 
820             {
821                 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
822                 result.SetStatus(eReturnStatusFailed);
823                 return false;
824             }
825         }
826         else 
827         {
828             output_stream = &result.GetOutputStream();
829         }
830
831
832         ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
833         if (clang_ast_type.GetOpaqueQualType())
834         {
835             for (uint32_t i = 0; i<item_count; ++i)
836             {
837                 addr_t item_addr = addr + (i * item_byte_size);
838                 Address address (item_addr);
839                 StreamString name_strm;
840                 name_strm.Printf ("0x%" PRIx64, item_addr);
841                 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 
842                                                                     name_strm.GetString().c_str(), 
843                                                                     address, 
844                                                                     clang_ast_type));
845                 if (valobj_sp)
846                 {
847                     Format format = m_format_options.GetFormat();
848                     if (format != eFormatDefault)
849                         valobj_sp->SetFormat (format);
850
851                     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
852                     
853                     valobj_sp->Dump(*output_stream,options);
854                 }
855                 else
856                 {
857                     result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 
858                                                   view_as_type_cstr, 
859                                                   name_strm.GetString().c_str());
860                     result.SetStatus(eReturnStatusFailed);
861                     return false;
862                 }
863             }
864             return true;
865         }
866
867         result.SetStatus(eReturnStatusSuccessFinishResult);
868         DataExtractor data (data_sp, 
869                             target->GetArchitecture().GetByteOrder(), 
870                             target->GetArchitecture().GetAddressByteSize(),
871                             target->GetArchitecture().GetDataByteSize());
872         
873         Format format = m_format_options.GetFormat();
874         if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
875             && (item_byte_size != 1))
876         {
877             // if a count was not passed, or it is 1
878             if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
879             {
880                 // this turns requests such as
881                 // memory read -fc -s10 -c1 *charPtrPtr
882                 // which make no sense (what is a char of size 10?)
883                 // into a request for fetching 10 chars of size 1 from the same memory location
884                 format = eFormatCharArray;
885                 item_count = item_byte_size;
886                 item_byte_size = 1;
887             }
888             else
889             {
890                 // here we passed a count, and it was not 1
891                 // so we have a byte_size and a count
892                 // we could well multiply those, but instead let's just fail
893                 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
894                 result.SetStatus(eReturnStatusFailed);
895                 return false;
896             }
897         }
898
899         assert (output_stream);
900         size_t bytes_dumped = data.Dump (output_stream,
901                                          0,
902                                          format,
903                                          item_byte_size,
904                                          item_count,
905                                          num_per_line / target->GetArchitecture().GetDataByteSize(),
906                                          addr,
907                                          0,
908                                          0,
909                                          exe_scope);
910         m_next_addr = addr + bytes_dumped;
911         output_stream->EOL();
912         return true;
913     }
914
915     OptionGroupOptions m_option_group;
916     OptionGroupFormat m_format_options;
917     OptionGroupReadMemory m_memory_options;
918     OptionGroupOutputFile m_outfile_options;
919     OptionGroupValueObjectDisplay m_varobj_options;
920     lldb::addr_t m_next_addr;
921     lldb::addr_t m_prev_byte_size; 
922     OptionGroupFormat m_prev_format_options;
923     OptionGroupReadMemory m_prev_memory_options;
924     OptionGroupOutputFile m_prev_outfile_options;
925     OptionGroupValueObjectDisplay m_prev_varobj_options;
926     ClangASTType m_prev_clang_ast_type;
927 };
928
929 OptionDefinition
930 g_memory_find_option_table[] =
931 {
932     { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
933     { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,   "Use text to find a byte pattern."},
934     { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount,   "How many times to perform the search."},
935     { 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."},
936 };
937
938 //----------------------------------------------------------------------
939 // Find the specified data in memory
940 //----------------------------------------------------------------------
941 class CommandObjectMemoryFind : public CommandObjectParsed
942 {
943 public:
944   
945   class OptionGroupFindMemory : public OptionGroup
946   {
947   public:
948     OptionGroupFindMemory () :
949       OptionGroup(),
950       m_count(1),
951       m_offset(0)
952     {
953     }
954     
955     virtual
956     ~OptionGroupFindMemory ()
957     {
958     }
959     
960     virtual uint32_t
961     GetNumDefinitions ()
962     {
963       return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
964     }
965     
966     virtual const OptionDefinition*
967     GetDefinitions ()
968     {
969       return g_memory_find_option_table;
970     }
971     
972     virtual Error
973     SetOptionValue (CommandInterpreter &interpreter,
974                     uint32_t option_idx,
975                     const char *option_arg)
976     {
977         Error error;
978         const int short_option = g_memory_find_option_table[option_idx].short_option;
979       
980         switch (short_option)
981         {
982         case 'e':
983               m_expr.SetValueFromCString(option_arg);
984               break;
985           
986         case 's':
987               m_string.SetValueFromCString(option_arg);
988               break;
989           
990         case 'c':
991               if (m_count.SetValueFromCString(option_arg).Fail())
992                   error.SetErrorString("unrecognized value for count");
993               break;
994                 
995         case 'o':
996                if (m_offset.SetValueFromCString(option_arg).Fail())
997                    error.SetErrorString("unrecognized value for dump-offset");
998                 break;
999
1000         default:
1001               error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1002               break;
1003         }
1004         return error;
1005     }
1006     
1007     virtual void
1008     OptionParsingStarting (CommandInterpreter &interpreter)
1009     {
1010         m_expr.Clear();
1011         m_string.Clear();
1012         m_count.Clear();
1013     }
1014     
1015       OptionValueString m_expr;
1016       OptionValueString m_string;
1017       OptionValueUInt64 m_count;
1018       OptionValueUInt64 m_offset;
1019   };
1020   
1021   CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1022   CommandObjectParsed (interpreter,
1023                        "memory find",
1024                        "Find a value in the memory of the process being debugged.",
1025                        NULL,
1026                        eFlagRequiresProcess | eFlagProcessMustBeLaunched),
1027   m_option_group (interpreter),
1028   m_memory_options ()
1029   {
1030     CommandArgumentEntry arg1;
1031     CommandArgumentEntry arg2;
1032     CommandArgumentData addr_arg;
1033     CommandArgumentData value_arg;
1034     
1035     // Define the first (and only) variant of this arg.
1036     addr_arg.arg_type = eArgTypeAddress;
1037     addr_arg.arg_repetition = eArgRepeatPlain;
1038     
1039     // There is only one variant this argument could be; put it into the argument entry.
1040     arg1.push_back (addr_arg);
1041     
1042     // Define the first (and only) variant of this arg.
1043     value_arg.arg_type = eArgTypeValue;
1044     value_arg.arg_repetition = eArgRepeatPlus;
1045     
1046     // There is only one variant this argument could be; put it into the argument entry.
1047     arg2.push_back (value_arg);
1048     
1049     // Push the data for the first argument into the m_arguments vector.
1050     m_arguments.push_back (arg1);
1051     m_arguments.push_back (arg2);
1052     
1053     m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1054     m_option_group.Finalize();
1055   }
1056   
1057   virtual
1058   ~CommandObjectMemoryFind ()
1059   {
1060   }
1061   
1062   Options *
1063   GetOptions ()
1064   {
1065     return &m_option_group;
1066   }
1067   
1068 protected:
1069   virtual bool
1070   DoExecute (Args& command, CommandReturnObject &result)
1071   {
1072       // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1073       Process *process = m_exe_ctx.GetProcessPtr();
1074
1075       const size_t argc = command.GetArgumentCount();
1076
1077       if (argc != 2)
1078       {
1079           result.AppendError("two addresses needed for memory find");
1080           return false;
1081       }
1082
1083       Error error;
1084       lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1085       if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1086       {
1087           result.AppendError("invalid low address");
1088           return false;
1089       }
1090       lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1091       if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1092       {
1093           result.AppendError("invalid high address");
1094           return false;
1095       }
1096
1097       if (high_addr <= low_addr)
1098       {
1099           result.AppendError("starting address must be smaller than ending address");
1100           return false;
1101       }
1102       
1103       lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1104       
1105       DataBufferHeap buffer;
1106       
1107       if (m_memory_options.m_string.OptionWasSet())
1108           buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1109       else if (m_memory_options.m_expr.OptionWasSet())
1110       {
1111           StackFrame* frame = m_exe_ctx.GetFramePtr();
1112           ValueObjectSP result_sp;
1113           if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get())
1114           {
1115               uint64_t value = result_sp->GetValueAsUnsigned(0);
1116               switch (result_sp->GetClangType().GetByteSize())
1117               {
1118                   case 1: {
1119                       uint8_t byte = (uint8_t)value;
1120                       buffer.CopyData(&byte,1);
1121                   }
1122                       break;
1123                   case 2: {
1124                       uint16_t word = (uint16_t)value;
1125                       buffer.CopyData(&word,2);
1126                   }
1127                       break;
1128                   case 4: {
1129                       uint32_t lword = (uint32_t)value;
1130                       buffer.CopyData(&lword,4);
1131                   }
1132                       break;
1133                   case 8: {
1134                       buffer.CopyData(&value, 8);
1135                   }
1136                       break;
1137                   case 3:
1138                   case 5:
1139                   case 6:
1140                   case 7:
1141                       result.AppendError("unknown type. pass a string instead");
1142                       return false;
1143                   default:
1144                       result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead");
1145                       return false;
1146               }
1147           }
1148           else
1149           {
1150               result.AppendError("expression evaluation failed. pass a string instead?");
1151               return false;
1152           }
1153       }
1154       else
1155       {
1156           result.AppendError("please pass either a block of text, or an expression to evaluate.");
1157           return false;
1158       }
1159       
1160       size_t count = m_memory_options.m_count.GetCurrentValue();
1161       found_location = low_addr;
1162       bool ever_found = false;
1163       while (count)
1164       {
1165           found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1166           if (found_location == LLDB_INVALID_ADDRESS)
1167           {
1168               if (!ever_found)
1169               {
1170                   result.AppendMessage("Your data was not found within the range.\n");
1171                   result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1172               }
1173               else
1174                   result.AppendMessage("No more matches found within the range.\n");
1175               break;
1176           }
1177           result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location);
1178
1179           DataBufferHeap dumpbuffer(32,0);
1180           process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1181           if (!error.Fail())
1182           {
1183               DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1184               data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1185               result.GetOutputStream().EOL();
1186           }
1187
1188           --count;
1189           found_location++;
1190           ever_found = true;
1191       }
1192       
1193       result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1194       return true;
1195   }
1196     
1197     lldb::addr_t
1198     Search (lldb::addr_t low,
1199             lldb::addr_t high,
1200             uint8_t* buffer,
1201             size_t buffer_size)
1202     {
1203         Process *process = m_exe_ctx.GetProcessPtr();
1204         DataBufferHeap heap(buffer_size, 0);
1205         lldb::addr_t fictional_ptr = low;
1206         for (auto ptr = low;
1207              low < high;
1208              fictional_ptr++)
1209         {
1210             Error error;
1211             if (ptr == low || buffer_size == 1)
1212                 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
1213             else
1214             {
1215                 memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1);
1216                 process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error);
1217             }
1218             if (error.Fail())
1219                 return LLDB_INVALID_ADDRESS;
1220             if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
1221                 return fictional_ptr;
1222             if (ptr == low)
1223                 ptr += buffer_size;
1224             else
1225                 ptr += 1;
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 = Args::StringToUInt64(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                              eFlagRequiresProcess | eFlagProcessMustBeLaunched),
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 eFlagRequiresProcess 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 > 0)
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 = Args::StringToUInt64(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 = Args::StringToUInt64(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 = Args::StringToSInt64(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 = Args::StringToUInt64(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 = Args::StringToUInt64(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                          eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched)
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 }