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