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