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