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