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