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