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