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