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 #include <inttypes.h>
16 
17 // C++ Includes
18 // Other libraries and framework includes
19 // Project includes
20 #include "lldb/Core/DataBufferHeap.h"
21 #include "lldb/Core/DataExtractor.h"
22 #include "lldb/Core/Debugger.h"
23 #include "lldb/Core/Module.h"
24 #include "lldb/Core/StreamString.h"
25 #include "lldb/Core/ValueObjectMemory.h"
26 #include "lldb/DataFormatters/ValueObjectPrinter.h"
27 #include "lldb/Expression/ClangPersistentVariables.h"
28 #include "lldb/Host/StringConvert.h"
29 #include "lldb/Interpreter/Args.h"
30 #include "lldb/Interpreter/CommandReturnObject.h"
31 #include "lldb/Interpreter/CommandInterpreter.h"
32 #include "lldb/Interpreter/Options.h"
33 #include "lldb/Interpreter/OptionGroupFormat.h"
34 #include "lldb/Interpreter/OptionGroupOutputFile.h"
35 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
36 #include "lldb/Interpreter/OptionValueString.h"
37 #include "lldb/Symbol/TypeList.h"
38 #include "lldb/Target/MemoryHistory.h"
39 #include "lldb/Target/Process.h"
40 #include "lldb/Target/StackFrame.h"
41 #include "lldb/Target/Thread.h"
42 
43 using namespace lldb;
44 using namespace lldb_private;
45 
46 static OptionDefinition
47 g_option_table[] =
48 {
49     { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
50     { LLDB_OPT_SET_2, false, "binary"       ,'b', OptionParser::eNoArgument      , NULL, 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."},
51     { LLDB_OPT_SET_3, true , "type"         ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone          ,"The name of a type to view memory as."},
52     { LLDB_OPT_SET_1|
53       LLDB_OPT_SET_2|
54       LLDB_OPT_SET_3, false, "force"        ,'r', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone          ,"Necessary if reading over target.max-memory-read-size bytes."},
55 };
56 
57 
58 
59 class OptionGroupReadMemory : public OptionGroup
60 {
61 public:
62 
63     OptionGroupReadMemory () :
64         m_num_per_line (1,1),
65         m_output_as_binary (false),
66         m_view_as_type()
67     {
68     }
69 
70     virtual
71     ~OptionGroupReadMemory ()
72     {
73     }
74 
75 
76     virtual uint32_t
77     GetNumDefinitions ()
78     {
79         return sizeof (g_option_table) / sizeof (OptionDefinition);
80     }
81 
82     virtual const OptionDefinition*
83     GetDefinitions ()
84     {
85         return g_option_table;
86     }
87 
88     virtual Error
89     SetOptionValue (CommandInterpreter &interpreter,
90                     uint32_t option_idx,
91                     const char *option_arg)
92     {
93         Error error;
94         const int short_option = g_option_table[option_idx].short_option;
95 
96         switch (short_option)
97         {
98             case 'l':
99                 error = m_num_per_line.SetValueFromString (option_arg);
100                 if (m_num_per_line.GetCurrentValue() == 0)
101                     error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
102                 break;
103 
104             case 'b':
105                 m_output_as_binary = true;
106                 break;
107 
108             case 't':
109                 error = m_view_as_type.SetValueFromString (option_arg);
110                 break;
111 
112             case 'r':
113                 m_force = true;
114                 break;
115 
116             default:
117                 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
118                 break;
119         }
120         return error;
121     }
122 
123     virtual void
124     OptionParsingStarting (CommandInterpreter &interpreter)
125     {
126         m_num_per_line.Clear();
127         m_output_as_binary = false;
128         m_view_as_type.Clear();
129         m_force = false;
130     }
131 
132     Error
133     FinalizeSettings (Target *target, OptionGroupFormat& format_options)
134     {
135         Error error;
136         OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
137         OptionValueUInt64 &count_value = format_options.GetCountValue();
138         const bool byte_size_option_set = byte_size_value.OptionWasSet();
139         const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
140         const bool count_option_set = format_options.GetCountValue().OptionWasSet();
141 
142         switch (format_options.GetFormat())
143         {
144             default:
145                 break;
146 
147             case eFormatBoolean:
148                 if (!byte_size_option_set)
149                     byte_size_value = 1;
150                 if (!num_per_line_option_set)
151                     m_num_per_line = 1;
152                 if (!count_option_set)
153                     format_options.GetCountValue() = 8;
154                 break;
155 
156             case eFormatCString:
157                 break;
158 
159             case eFormatInstruction:
160                 if (count_option_set)
161                     byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
162                 m_num_per_line = 1;
163                 break;
164 
165             case eFormatAddressInfo:
166                 if (!byte_size_option_set)
167                     byte_size_value = target->GetArchitecture().GetAddressByteSize();
168                 m_num_per_line = 1;
169                 if (!count_option_set)
170                     format_options.GetCountValue() = 8;
171                 break;
172 
173             case eFormatPointer:
174                 byte_size_value = target->GetArchitecture().GetAddressByteSize();
175                 if (!num_per_line_option_set)
176                     m_num_per_line = 4;
177                 if (!count_option_set)
178                     format_options.GetCountValue() = 8;
179                 break;
180 
181             case eFormatBinary:
182             case eFormatFloat:
183             case eFormatOctal:
184             case eFormatDecimal:
185             case eFormatEnum:
186             case eFormatUnicode16:
187             case eFormatUnicode32:
188             case eFormatUnsigned:
189             case eFormatHexFloat:
190                 if (!byte_size_option_set)
191                     byte_size_value = 4;
192                 if (!num_per_line_option_set)
193                     m_num_per_line = 1;
194                 if (!count_option_set)
195                     format_options.GetCountValue() = 8;
196                 break;
197 
198             case eFormatBytes:
199             case eFormatBytesWithASCII:
200                 if (byte_size_option_set)
201                 {
202                     if (byte_size_value > 1)
203                         error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
204                                                         "\tconsider using a different display format or don't specify the byte size",
205                                                         byte_size_value.GetCurrentValue());
206                 }
207                 else
208                     byte_size_value = 1;
209                 if (!num_per_line_option_set)
210                     m_num_per_line = 16;
211                 if (!count_option_set)
212                     format_options.GetCountValue() = 32;
213                 break;
214             case eFormatCharArray:
215             case eFormatChar:
216             case eFormatCharPrintable:
217                 if (!byte_size_option_set)
218                     byte_size_value = 1;
219                 if (!num_per_line_option_set)
220                     m_num_per_line = 32;
221                 if (!count_option_set)
222                     format_options.GetCountValue() = 64;
223                 break;
224             case eFormatComplex:
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 eFormatComplexInteger:
233                 if (!byte_size_option_set)
234                     byte_size_value = 8;
235                 if (!num_per_line_option_set)
236                     m_num_per_line = 1;
237                 if (!count_option_set)
238                     format_options.GetCountValue() = 8;
239                 break;
240             case eFormatHex:
241                 if (!byte_size_option_set)
242                     byte_size_value = 4;
243                 if (!num_per_line_option_set)
244                 {
245                     switch (byte_size_value)
246                     {
247                         case 1:
248                         case 2:
249                             m_num_per_line = 8;
250                             break;
251                         case 4:
252                             m_num_per_line = 4;
253                             break;
254                         case 8:
255                             m_num_per_line = 2;
256                             break;
257                         default:
258                             m_num_per_line = 1;
259                             break;
260                     }
261                 }
262                 if (!count_option_set)
263                     count_value = 8;
264                 break;
265 
266             case eFormatVectorOfChar:
267             case eFormatVectorOfSInt8:
268             case eFormatVectorOfUInt8:
269             case eFormatVectorOfSInt16:
270             case eFormatVectorOfUInt16:
271             case eFormatVectorOfSInt32:
272             case eFormatVectorOfUInt32:
273             case eFormatVectorOfSInt64:
274             case eFormatVectorOfUInt64:
275             case eFormatVectorOfFloat32:
276             case eFormatVectorOfFloat64:
277             case eFormatVectorOfUInt128:
278                 if (!byte_size_option_set)
279                     byte_size_value = 128;
280                 if (!num_per_line_option_set)
281                     m_num_per_line = 1;
282                 if (!count_option_set)
283                     count_value = 4;
284                 break;
285         }
286         return error;
287     }
288 
289     bool
290     AnyOptionWasSet () const
291     {
292         return m_num_per_line.OptionWasSet() ||
293                m_output_as_binary ||
294                m_view_as_type.OptionWasSet();
295     }
296 
297     OptionValueUInt64 m_num_per_line;
298     bool m_output_as_binary;
299     OptionValueString m_view_as_type;
300     bool m_force;
301 };
302 
303 
304 
305 //----------------------------------------------------------------------
306 // Read memory from the inferior process
307 //----------------------------------------------------------------------
308 class CommandObjectMemoryRead : public CommandObjectParsed
309 {
310 public:
311 
312     CommandObjectMemoryRead (CommandInterpreter &interpreter) :
313         CommandObjectParsed (interpreter,
314                              "memory read",
315                              "Read from the memory of the process being debugged.",
316                              NULL,
317                              eFlagRequiresTarget | eFlagProcessMustBePaused),
318         m_option_group (interpreter),
319         m_format_options (eFormatBytesWithASCII, 1, 8),
320         m_memory_options (),
321         m_outfile_options (),
322         m_varobj_options(),
323         m_next_addr(LLDB_INVALID_ADDRESS),
324         m_prev_byte_size(0),
325         m_prev_format_options (eFormatBytesWithASCII, 1, 8),
326         m_prev_memory_options (),
327         m_prev_outfile_options (),
328         m_prev_varobj_options()
329     {
330         CommandArgumentEntry arg1;
331         CommandArgumentEntry arg2;
332         CommandArgumentData start_addr_arg;
333         CommandArgumentData end_addr_arg;
334 
335         // Define the first (and only) variant of this arg.
336         start_addr_arg.arg_type = eArgTypeAddressOrExpression;
337         start_addr_arg.arg_repetition = eArgRepeatPlain;
338 
339         // There is only one variant this argument could be; put it into the argument entry.
340         arg1.push_back (start_addr_arg);
341 
342         // Define the first (and only) variant of this arg.
343         end_addr_arg.arg_type = eArgTypeAddressOrExpression;
344         end_addr_arg.arg_repetition = eArgRepeatOptional;
345 
346         // There is only one variant this argument could be; put it into the argument entry.
347         arg2.push_back (end_addr_arg);
348 
349         // Push the data for the first argument into the m_arguments vector.
350         m_arguments.push_back (arg1);
351         m_arguments.push_back (arg2);
352 
353         // Add the "--format" and "--count" options to group 1 and 3
354         m_option_group.Append (&m_format_options,
355                                OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
356                                LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
357         m_option_group.Append (&m_format_options,
358                                OptionGroupFormat::OPTION_GROUP_GDB_FMT,
359                                LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
360         // Add the "--size" option to group 1 and 2
361         m_option_group.Append (&m_format_options,
362                                OptionGroupFormat::OPTION_GROUP_SIZE,
363                                LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
364         m_option_group.Append (&m_memory_options);
365         m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
366         m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
367         m_option_group.Finalize();
368     }
369 
370     virtual
371     ~CommandObjectMemoryRead ()
372     {
373     }
374 
375     Options *
376     GetOptions ()
377     {
378         return &m_option_group;
379     }
380 
381     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
382     {
383         return m_cmd_name.c_str();
384     }
385 
386 protected:
387     virtual bool
388     DoExecute (Args& command, CommandReturnObject &result)
389     {
390         // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
391         Target *target = m_exe_ctx.GetTargetPtr();
392 
393         const size_t argc = command.GetArgumentCount();
394 
395         if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
396         {
397             result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
398             result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
399             result.SetStatus(eReturnStatusFailed);
400             return false;
401         }
402 
403         ClangASTType clang_ast_type;
404         Error error;
405 
406         const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
407         if (view_as_type_cstr && view_as_type_cstr[0])
408         {
409             // We are viewing memory as a type
410 
411             SymbolContext sc;
412             const bool exact_match = false;
413             TypeList type_list;
414             uint32_t reference_count = 0;
415             uint32_t pointer_count = 0;
416             size_t idx;
417 
418 #define ALL_KEYWORDS        \
419     KEYWORD("const")        \
420     KEYWORD("volatile")     \
421     KEYWORD("restrict")     \
422     KEYWORD("struct")       \
423     KEYWORD("class")        \
424     KEYWORD("union")
425 
426 #define KEYWORD(s) s,
427             static const char *g_keywords[] =
428             {
429                 ALL_KEYWORDS
430             };
431 #undef KEYWORD
432 
433 #define KEYWORD(s) (sizeof(s) - 1),
434             static const int g_keyword_lengths[] =
435             {
436                 ALL_KEYWORDS
437             };
438 #undef KEYWORD
439 
440 #undef ALL_KEYWORDS
441 
442             static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
443             std::string type_str(view_as_type_cstr);
444 
445             // Remove all instances of g_keywords that are followed by spaces
446             for (size_t i = 0; i < g_num_keywords; ++i)
447             {
448                 const char *keyword = g_keywords[i];
449                 int keyword_len = g_keyword_lengths[i];
450 
451                 idx = 0;
452                 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
453                 {
454                     if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
455                     {
456                         type_str.erase(idx, keyword_len+1);
457                         idx = 0;
458                     }
459                     else
460                     {
461                         idx += keyword_len;
462                     }
463                 }
464             }
465             bool done = type_str.empty();
466             //
467             idx = type_str.find_first_not_of (" \t");
468             if (idx > 0 && idx != std::string::npos)
469                 type_str.erase (0, idx);
470             while (!done)
471             {
472                 // Strip trailing spaces
473                 if (type_str.empty())
474                     done = true;
475                 else
476                 {
477                     switch (type_str[type_str.size()-1])
478                     {
479                     case '*':
480                         ++pointer_count;
481                         // fall through...
482                     case ' ':
483                     case '\t':
484                         type_str.erase(type_str.size()-1);
485                         break;
486 
487                     case '&':
488                         if (reference_count == 0)
489                         {
490                             reference_count = 1;
491                             type_str.erase(type_str.size()-1);
492                         }
493                         else
494                         {
495                             result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
496                             result.SetStatus(eReturnStatusFailed);
497                             return false;
498                         }
499                         break;
500 
501                     default:
502                         done = true;
503                         break;
504                     }
505                 }
506             }
507 
508             ConstString lookup_type_name(type_str.c_str());
509             StackFrame *frame = m_exe_ctx.GetFramePtr();
510             if (frame)
511             {
512                 sc = frame->GetSymbolContext (eSymbolContextModule);
513                 if (sc.module_sp)
514                 {
515                     sc.module_sp->FindTypes (sc,
516                                              lookup_type_name,
517                                              exact_match,
518                                              1,
519                                              type_list);
520                 }
521             }
522             if (type_list.GetSize() == 0)
523             {
524                 target->GetImages().FindTypes (sc,
525                                                lookup_type_name,
526                                                exact_match,
527                                                1,
528                                                type_list);
529             }
530 
531             if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
532             {
533                 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
534                 if (tdecl)
535                 {
536                     clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
537                 }
538             }
539 
540             if (clang_ast_type.IsValid() == false)
541             {
542                 if (type_list.GetSize() == 0)
543                 {
544                     result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
545                                                   lookup_type_name.GetCString(),
546                                                   view_as_type_cstr);
547                     result.SetStatus(eReturnStatusFailed);
548                     return false;
549                 }
550                 else
551                 {
552                     TypeSP type_sp (type_list.GetTypeAtIndex(0));
553                     clang_ast_type = type_sp->GetClangFullType();
554                 }
555             }
556 
557             while (pointer_count > 0)
558             {
559                 ClangASTType pointer_type = clang_ast_type.GetPointerType();
560                 if (pointer_type.IsValid())
561                     clang_ast_type = pointer_type;
562                 else
563                 {
564                     result.AppendError ("unable make a pointer type\n");
565                     result.SetStatus(eReturnStatusFailed);
566                     return false;
567                 }
568                 --pointer_count;
569             }
570 
571             m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);
572 
573             if (m_format_options.GetByteSizeValue() == 0)
574             {
575                 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
576                                               view_as_type_cstr);
577                 result.SetStatus(eReturnStatusFailed);
578                 return false;
579             }
580 
581             if (!m_format_options.GetCountValue().OptionWasSet())
582                 m_format_options.GetCountValue() = 1;
583         }
584         else
585         {
586             error = m_memory_options.FinalizeSettings (target, m_format_options);
587         }
588 
589         // Look for invalid combinations of settings
590         if (error.Fail())
591         {
592             result.AppendError(error.AsCString());
593             result.SetStatus(eReturnStatusFailed);
594             return false;
595         }
596 
597         lldb::addr_t addr;
598         size_t total_byte_size = 0;
599         if (argc == 0)
600         {
601             // Use the last address and byte size and all options as they were
602             // if no options have been set
603             addr = m_next_addr;
604             total_byte_size = m_prev_byte_size;
605             clang_ast_type = m_prev_clang_ast_type;
606             if (!m_format_options.AnyOptionWasSet() &&
607                 !m_memory_options.AnyOptionWasSet() &&
608                 !m_outfile_options.AnyOptionWasSet() &&
609                 !m_varobj_options.AnyOptionWasSet())
610             {
611                 m_format_options = m_prev_format_options;
612                 m_memory_options = m_prev_memory_options;
613                 m_outfile_options = m_prev_outfile_options;
614                 m_varobj_options = m_prev_varobj_options;
615             }
616         }
617 
618         size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
619 
620         // TODO For non-8-bit byte addressable architectures this needs to be
621         // revisited to fully support all lldb's range of formatting options.
622         // Furthermore code memory reads (for those architectures) will not
623         // be correctly formatted even w/o formatting options.
624         size_t item_byte_size =
625             target->GetArchitecture().GetDataByteSize() > 1 ?
626             target->GetArchitecture().GetDataByteSize() :
627             m_format_options.GetByteSizeValue().GetCurrentValue();
628 
629         const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
630 
631         if (total_byte_size == 0)
632         {
633             total_byte_size = item_count * item_byte_size;
634             if (total_byte_size == 0)
635                 total_byte_size = 32;
636         }
637 
638         if (argc > 0)
639             addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
640 
641         if (addr == LLDB_INVALID_ADDRESS)
642         {
643             result.AppendError("invalid start address expression.");
644             result.AppendError(error.AsCString());
645             result.SetStatus(eReturnStatusFailed);
646             return false;
647         }
648 
649         if (argc == 2)
650         {
651             lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
652             if (end_addr == LLDB_INVALID_ADDRESS)
653             {
654                 result.AppendError("invalid end address expression.");
655                 result.AppendError(error.AsCString());
656                 result.SetStatus(eReturnStatusFailed);
657                 return false;
658             }
659             else if (end_addr <= addr)
660             {
661                 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
662                 result.SetStatus(eReturnStatusFailed);
663                 return false;
664             }
665             else if (m_format_options.GetCountValue().OptionWasSet())
666             {
667                 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count);
668                 result.SetStatus(eReturnStatusFailed);
669                 return false;
670             }
671 
672             total_byte_size = end_addr - addr;
673             item_count = total_byte_size / item_byte_size;
674         }
675 
676         uint32_t max_unforced_size = target->GetMaximumMemReadSize();
677 
678         if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
679         {
680             result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
681             result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
682             result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
683             return false;
684         }
685 
686         DataBufferSP data_sp;
687         size_t bytes_read = 0;
688         if (clang_ast_type.GetOpaqueQualType())
689         {
690             // Make sure we don't display our type as ASCII bytes like the default memory read
691             if (m_format_options.GetFormatValue().OptionWasSet() == false)
692                 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
693 
694             bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue();
695         }
696         else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
697         {
698             data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
699             if (data_sp->GetBytes() == NULL)
700             {
701                 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size);
702                 result.SetStatus(eReturnStatusFailed);
703                 return false;
704             }
705 
706             Address address(addr, NULL);
707             bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
708             if (bytes_read == 0)
709             {
710                 const char *error_cstr = error.AsCString();
711                 if (error_cstr && error_cstr[0])
712                 {
713                     result.AppendError(error_cstr);
714                 }
715                 else
716                 {
717                     result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
718                 }
719                 result.SetStatus(eReturnStatusFailed);
720                 return false;
721             }
722 
723             if (bytes_read < total_byte_size)
724                 result.AppendWarningWithFormat("Not all bytes (%" PRIu64 "/%" PRIu64 ") were able to be read from 0x%" PRIx64 ".\n", (uint64_t)bytes_read, (uint64_t)total_byte_size, addr);
725         }
726         else
727         {
728             // we treat c-strings as a special case because they do not have a fixed size
729             if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
730                 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
731             else
732                 item_byte_size = target->GetMaximumSizeOfStringSummary();
733             if (!m_format_options.GetCountValue().OptionWasSet())
734                 item_count = 1;
735             data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
736             if (data_sp->GetBytes() == NULL)
737             {
738                 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx64 " bytes for the memory read buffer, specify a smaller size to read", (uint64_t)((item_byte_size+1) * item_count));
739                 result.SetStatus(eReturnStatusFailed);
740                 return false;
741             }
742             uint8_t *data_ptr = data_sp->GetBytes();
743             auto data_addr = addr;
744             auto count = item_count;
745             item_count = 0;
746             while (item_count < count)
747             {
748                 std::string buffer;
749                 buffer.resize(item_byte_size+1,0);
750                 Error error;
751                 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
752                 if (error.Fail())
753                 {
754                     result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
755                     result.SetStatus(eReturnStatusFailed);
756                     return false;
757                 }
758                 if (item_byte_size == read)
759                 {
760                     result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
761                     break;
762                 }
763                 read+=1; // account for final NULL byte
764                 memcpy(data_ptr, &buffer[0], read);
765                 data_ptr += read;
766                 data_addr += read;
767                 bytes_read += read;
768                 item_count++; // if we break early we know we only read item_count strings
769             }
770             data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
771         }
772 
773         m_next_addr = addr + bytes_read;
774         m_prev_byte_size = bytes_read;
775         m_prev_format_options = m_format_options;
776         m_prev_memory_options = m_memory_options;
777         m_prev_outfile_options = m_outfile_options;
778         m_prev_varobj_options = m_varobj_options;
779         m_prev_clang_ast_type = clang_ast_type;
780 
781         StreamFile outfile_stream;
782         Stream *output_stream = NULL;
783         const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
784         if (outfile_spec)
785         {
786             char path[PATH_MAX];
787             outfile_spec.GetPath (path, sizeof(path));
788 
789             uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
790             const bool append = m_outfile_options.GetAppend().GetCurrentValue();
791             if (append)
792                 open_options |= File::eOpenOptionAppend;
793 
794             if (outfile_stream.GetFile ().Open (path, open_options).Success())
795             {
796                 if (m_memory_options.m_output_as_binary)
797                 {
798                     const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
799                     if (bytes_written > 0)
800                     {
801                         result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
802                                                          bytes_written,
803                                                          append ? "appended" : "written",
804                                                          path);
805                         return true;
806                     }
807                     else
808                     {
809                         result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
810                         result.SetStatus(eReturnStatusFailed);
811                         return false;
812                     }
813                 }
814                 else
815                 {
816                     // We are going to write ASCII to the file just point the
817                     // output_stream to our outfile_stream...
818                     output_stream = &outfile_stream;
819                 }
820             }
821             else
822             {
823                 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
824                 result.SetStatus(eReturnStatusFailed);
825                 return false;
826             }
827         }
828         else
829         {
830             output_stream = &result.GetOutputStream();
831         }
832 
833 
834         ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
835         if (clang_ast_type.GetOpaqueQualType())
836         {
837             for (uint32_t i = 0; i<item_count; ++i)
838             {
839                 addr_t item_addr = addr + (i * item_byte_size);
840                 Address address (item_addr);
841                 StreamString name_strm;
842                 name_strm.Printf ("0x%" PRIx64, item_addr);
843                 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
844                                                                     name_strm.GetString().c_str(),
845                                                                     address,
846                                                                     clang_ast_type));
847                 if (valobj_sp)
848                 {
849                     Format format = m_format_options.GetFormat();
850                     if (format != eFormatDefault)
851                         valobj_sp->SetFormat (format);
852 
853                     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
854 
855                     valobj_sp->Dump(*output_stream,options);
856                 }
857                 else
858                 {
859                     result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
860                                                   view_as_type_cstr,
861                                                   name_strm.GetString().c_str());
862                     result.SetStatus(eReturnStatusFailed);
863                     return false;
864                 }
865             }
866             return true;
867         }
868 
869         result.SetStatus(eReturnStatusSuccessFinishResult);
870         DataExtractor data (data_sp,
871                             target->GetArchitecture().GetByteOrder(),
872                             target->GetArchitecture().GetAddressByteSize(),
873                             target->GetArchitecture().GetDataByteSize());
874 
875         Format format = m_format_options.GetFormat();
876         if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
877             && (item_byte_size != 1))
878         {
879             // if a count was not passed, or it is 1
880             if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
881             {
882                 // this turns requests such as
883                 // memory read -fc -s10 -c1 *charPtrPtr
884                 // which make no sense (what is a char of size 10?)
885                 // into a request for fetching 10 chars of size 1 from the same memory location
886                 format = eFormatCharArray;
887                 item_count = item_byte_size;
888                 item_byte_size = 1;
889             }
890             else
891             {
892                 // here we passed a count, and it was not 1
893                 // so we have a byte_size and a count
894                 // we could well multiply those, but instead let's just fail
895                 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
896                 result.SetStatus(eReturnStatusFailed);
897                 return false;
898             }
899         }
900 
901         assert (output_stream);
902         size_t bytes_dumped = data.Dump (output_stream,
903                                          0,
904                                          format,
905                                          item_byte_size,
906                                          item_count,
907                                          num_per_line / target->GetArchitecture().GetDataByteSize(),
908                                          addr,
909                                          0,
910                                          0,
911                                          exe_scope);
912         m_next_addr = addr + bytes_dumped;
913         output_stream->EOL();
914         return true;
915     }
916 
917     OptionGroupOptions m_option_group;
918     OptionGroupFormat m_format_options;
919     OptionGroupReadMemory m_memory_options;
920     OptionGroupOutputFile m_outfile_options;
921     OptionGroupValueObjectDisplay m_varobj_options;
922     lldb::addr_t m_next_addr;
923     lldb::addr_t m_prev_byte_size;
924     OptionGroupFormat m_prev_format_options;
925     OptionGroupReadMemory m_prev_memory_options;
926     OptionGroupOutputFile m_prev_outfile_options;
927     OptionGroupValueObjectDisplay m_prev_varobj_options;
928     ClangASTType m_prev_clang_ast_type;
929 };
930 
931 OptionDefinition
932 g_memory_find_option_table[] =
933 {
934     { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
935     { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,   "Use text to find a byte pattern."},
936     { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount,   "How many times to perform the search."},
937     { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset,   "When dumping memory for a match, an offset from the match location to start dumping from."},
938 };
939 
940 //----------------------------------------------------------------------
941 // Find the specified data in memory
942 //----------------------------------------------------------------------
943 class CommandObjectMemoryFind : public CommandObjectParsed
944 {
945 public:
946 
947   class OptionGroupFindMemory : public OptionGroup
948   {
949   public:
950     OptionGroupFindMemory () :
951       OptionGroup(),
952       m_count(1),
953       m_offset(0)
954     {
955     }
956 
957     virtual
958     ~OptionGroupFindMemory ()
959     {
960     }
961 
962     virtual uint32_t
963     GetNumDefinitions ()
964     {
965       return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
966     }
967 
968     virtual const OptionDefinition*
969     GetDefinitions ()
970     {
971       return g_memory_find_option_table;
972     }
973 
974     virtual Error
975     SetOptionValue (CommandInterpreter &interpreter,
976                     uint32_t option_idx,
977                     const char *option_arg)
978     {
979         Error error;
980         const int short_option = g_memory_find_option_table[option_idx].short_option;
981 
982         switch (short_option)
983         {
984         case 'e':
985               m_expr.SetValueFromString(option_arg);
986               break;
987 
988         case 's':
989               m_string.SetValueFromString(option_arg);
990               break;
991 
992         case 'c':
993               if (m_count.SetValueFromString(option_arg).Fail())
994                   error.SetErrorString("unrecognized value for count");
995               break;
996 
997         case 'o':
998                if (m_offset.SetValueFromString(option_arg).Fail())
999                    error.SetErrorString("unrecognized value for dump-offset");
1000                 break;
1001 
1002         default:
1003               error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1004               break;
1005         }
1006         return error;
1007     }
1008 
1009     virtual void
1010     OptionParsingStarting (CommandInterpreter &interpreter)
1011     {
1012         m_expr.Clear();
1013         m_string.Clear();
1014         m_count.Clear();
1015     }
1016 
1017       OptionValueString m_expr;
1018       OptionValueString m_string;
1019       OptionValueUInt64 m_count;
1020       OptionValueUInt64 m_offset;
1021   };
1022 
1023   CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1024   CommandObjectParsed (interpreter,
1025                        "memory find",
1026                        "Find a value in the memory of the process being debugged.",
1027                        NULL,
1028                        eFlagRequiresProcess | eFlagProcessMustBeLaunched),
1029   m_option_group (interpreter),
1030   m_memory_options ()
1031   {
1032     CommandArgumentEntry arg1;
1033     CommandArgumentEntry arg2;
1034     CommandArgumentData addr_arg;
1035     CommandArgumentData value_arg;
1036 
1037     // Define the first (and only) variant of this arg.
1038     addr_arg.arg_type = eArgTypeAddress;
1039     addr_arg.arg_repetition = eArgRepeatPlain;
1040 
1041     // There is only one variant this argument could be; put it into the argument entry.
1042     arg1.push_back (addr_arg);
1043 
1044     // Define the first (and only) variant of this arg.
1045     value_arg.arg_type = eArgTypeValue;
1046     value_arg.arg_repetition = eArgRepeatPlus;
1047 
1048     // There is only one variant this argument could be; put it into the argument entry.
1049     arg2.push_back (value_arg);
1050 
1051     // Push the data for the first argument into the m_arguments vector.
1052     m_arguments.push_back (arg1);
1053     m_arguments.push_back (arg2);
1054 
1055     m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1056     m_option_group.Finalize();
1057   }
1058 
1059   virtual
1060   ~CommandObjectMemoryFind ()
1061   {
1062   }
1063 
1064   Options *
1065   GetOptions ()
1066   {
1067     return &m_option_group;
1068   }
1069 
1070 protected:
1071   virtual bool
1072   DoExecute (Args& command, CommandReturnObject &result)
1073   {
1074       // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1075       Process *process = m_exe_ctx.GetProcessPtr();
1076 
1077       const size_t argc = command.GetArgumentCount();
1078 
1079       if (argc != 2)
1080       {
1081           result.AppendError("two addresses needed for memory find");
1082           return false;
1083       }
1084 
1085       Error error;
1086       lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1087       if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1088       {
1089           result.AppendError("invalid low address");
1090           return false;
1091       }
1092       lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1093       if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1094       {
1095           result.AppendError("invalid high address");
1096           return false;
1097       }
1098 
1099       if (high_addr <= low_addr)
1100       {
1101           result.AppendError("starting address must be smaller than ending address");
1102           return false;
1103       }
1104 
1105       lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1106 
1107       DataBufferHeap buffer;
1108 
1109       if (m_memory_options.m_string.OptionWasSet())
1110           buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1111       else if (m_memory_options.m_expr.OptionWasSet())
1112       {
1113           StackFrame* frame = m_exe_ctx.GetFramePtr();
1114           ValueObjectSP result_sp;
1115           if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get())
1116           {
1117               uint64_t value = result_sp->GetValueAsUnsigned(0);
1118               switch (result_sp->GetClangType().GetByteSize(nullptr))
1119               {
1120                   case 1: {
1121                       uint8_t byte = (uint8_t)value;
1122                       buffer.CopyData(&byte,1);
1123                   }
1124                       break;
1125                   case 2: {
1126                       uint16_t word = (uint16_t)value;
1127                       buffer.CopyData(&word,2);
1128                   }
1129                       break;
1130                   case 4: {
1131                       uint32_t lword = (uint32_t)value;
1132                       buffer.CopyData(&lword,4);
1133                   }
1134                       break;
1135                   case 8: {
1136                       buffer.CopyData(&value, 8);
1137                   }
1138                       break;
1139                   case 3:
1140                   case 5:
1141                   case 6:
1142                   case 7:
1143                       result.AppendError("unknown type. pass a string instead");
1144                       return false;
1145                   default:
1146                       result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead");
1147                       return false;
1148               }
1149           }
1150           else
1151           {
1152               result.AppendError("expression evaluation failed. pass a string instead?");
1153               return false;
1154           }
1155       }
1156       else
1157       {
1158           result.AppendError("please pass either a block of text, or an expression to evaluate.");
1159           return false;
1160       }
1161 
1162       size_t count = m_memory_options.m_count.GetCurrentValue();
1163       found_location = low_addr;
1164       bool ever_found = false;
1165       while (count)
1166       {
1167           found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1168           if (found_location == LLDB_INVALID_ADDRESS)
1169           {
1170               if (!ever_found)
1171               {
1172                   result.AppendMessage("Your data was not found within the range.\n");
1173                   result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1174               }
1175               else
1176                   result.AppendMessage("No more matches found within the range.\n");
1177               break;
1178           }
1179           result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location);
1180 
1181           DataBufferHeap dumpbuffer(32,0);
1182           process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1183           if (!error.Fail())
1184           {
1185               DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1186               data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1187               result.GetOutputStream().EOL();
1188           }
1189 
1190           --count;
1191           found_location++;
1192           ever_found = true;
1193       }
1194 
1195       result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1196       return true;
1197   }
1198 
1199     lldb::addr_t
1200     Search (lldb::addr_t low,
1201             lldb::addr_t high,
1202             uint8_t* buffer,
1203             size_t buffer_size)
1204     {
1205         Process *process = m_exe_ctx.GetProcessPtr();
1206         DataBufferHeap heap(buffer_size, 0);
1207         lldb::addr_t fictional_ptr = low;
1208         for (auto ptr = low;
1209              low < high;
1210              fictional_ptr++)
1211         {
1212             Error error;
1213             if (ptr == low || buffer_size == 1)
1214                 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
1215             else
1216             {
1217                 memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1);
1218                 process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error);
1219             }
1220             if (error.Fail())
1221                 return LLDB_INVALID_ADDRESS;
1222             if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
1223                 return fictional_ptr;
1224             if (ptr == low)
1225                 ptr += buffer_size;
1226             else
1227                 ptr += 1;
1228         }
1229         return LLDB_INVALID_ADDRESS;
1230     }
1231 
1232     OptionGroupOptions m_option_group;
1233     OptionGroupFindMemory m_memory_options;
1234 };
1235 
1236 
1237 OptionDefinition
1238 g_memory_write_option_table[] =
1239 {
1240 { LLDB_OPT_SET_1, true,  "infile", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1241 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset,   "Start writing bytes from an offset within the input file."},
1242 };
1243 
1244 //----------------------------------------------------------------------
1245 // Write memory to the inferior process
1246 //----------------------------------------------------------------------
1247 class CommandObjectMemoryWrite : public CommandObjectParsed
1248 {
1249 public:
1250 
1251     class OptionGroupWriteMemory : public OptionGroup
1252     {
1253     public:
1254         OptionGroupWriteMemory () :
1255             OptionGroup()
1256         {
1257         }
1258 
1259         virtual
1260         ~OptionGroupWriteMemory ()
1261         {
1262         }
1263 
1264         virtual uint32_t
1265         GetNumDefinitions ()
1266         {
1267             return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1268         }
1269 
1270         virtual const OptionDefinition*
1271         GetDefinitions ()
1272         {
1273             return g_memory_write_option_table;
1274         }
1275 
1276         virtual Error
1277         SetOptionValue (CommandInterpreter &interpreter,
1278                         uint32_t option_idx,
1279                         const char *option_arg)
1280         {
1281             Error error;
1282             const int short_option = g_memory_write_option_table[option_idx].short_option;
1283 
1284             switch (short_option)
1285             {
1286                 case 'i':
1287                     m_infile.SetFile (option_arg, true);
1288                     if (!m_infile.Exists())
1289                     {
1290                         m_infile.Clear();
1291                         error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
1292                     }
1293                     break;
1294 
1295                 case 'o':
1296                     {
1297                         bool success;
1298                         m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success);
1299                         if (!success)
1300                         {
1301                             error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
1302                         }
1303                     }
1304                     break;
1305 
1306                 default:
1307                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1308                     break;
1309             }
1310             return error;
1311         }
1312 
1313         virtual void
1314         OptionParsingStarting (CommandInterpreter &interpreter)
1315         {
1316             m_infile.Clear();
1317             m_infile_offset = 0;
1318         }
1319 
1320         FileSpec m_infile;
1321         off_t m_infile_offset;
1322     };
1323 
1324     CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
1325         CommandObjectParsed (interpreter,
1326                              "memory write",
1327                              "Write to the memory of the process being debugged.",
1328                              NULL,
1329                              eFlagRequiresProcess | eFlagProcessMustBeLaunched),
1330         m_option_group (interpreter),
1331         m_format_options (eFormatBytes, 1, UINT64_MAX),
1332         m_memory_options ()
1333     {
1334         CommandArgumentEntry arg1;
1335         CommandArgumentEntry arg2;
1336         CommandArgumentData addr_arg;
1337         CommandArgumentData value_arg;
1338 
1339         // Define the first (and only) variant of this arg.
1340         addr_arg.arg_type = eArgTypeAddress;
1341         addr_arg.arg_repetition = eArgRepeatPlain;
1342 
1343         // There is only one variant this argument could be; put it into the argument entry.
1344         arg1.push_back (addr_arg);
1345 
1346         // Define the first (and only) variant of this arg.
1347         value_arg.arg_type = eArgTypeValue;
1348         value_arg.arg_repetition = eArgRepeatPlus;
1349 
1350         // There is only one variant this argument could be; put it into the argument entry.
1351         arg2.push_back (value_arg);
1352 
1353         // Push the data for the first argument into the m_arguments vector.
1354         m_arguments.push_back (arg1);
1355         m_arguments.push_back (arg2);
1356 
1357         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1358         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE  , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1359         m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1360         m_option_group.Finalize();
1361 
1362     }
1363 
1364     virtual
1365     ~CommandObjectMemoryWrite ()
1366     {
1367     }
1368 
1369     Options *
1370     GetOptions ()
1371     {
1372         return &m_option_group;
1373     }
1374 
1375     bool
1376     UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1377     {
1378         if (total_byte_size > 8)
1379             return false;
1380 
1381         if (total_byte_size == 8)
1382             return true;
1383 
1384         const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1385         return uval64 <= max;
1386     }
1387 
1388     bool
1389     SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1390     {
1391         if (total_byte_size > 8)
1392             return false;
1393 
1394         if (total_byte_size == 8)
1395             return true;
1396 
1397         const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1398         const int64_t min = ~(max);
1399         return min <= sval64 && sval64 <= max;
1400     }
1401 
1402 protected:
1403     virtual bool
1404     DoExecute (Args& command, CommandReturnObject &result)
1405     {
1406         // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1407         Process *process = m_exe_ctx.GetProcessPtr();
1408 
1409         const size_t argc = command.GetArgumentCount();
1410 
1411         if (m_memory_options.m_infile)
1412         {
1413             if (argc < 1)
1414             {
1415                 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1416                 result.SetStatus(eReturnStatusFailed);
1417                 return false;
1418             }
1419         }
1420         else if (argc < 2)
1421         {
1422             result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
1423             result.SetStatus(eReturnStatusFailed);
1424             return false;
1425         }
1426 
1427         StreamString buffer (Stream::eBinary,
1428                              process->GetTarget().GetArchitecture().GetAddressByteSize(),
1429                              process->GetTarget().GetArchitecture().GetByteOrder());
1430 
1431         OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1432         size_t item_byte_size = byte_size_value.GetCurrentValue();
1433 
1434         Error error;
1435         lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1436                                                    command.GetArgumentAtIndex(0),
1437                                                    LLDB_INVALID_ADDRESS,
1438                                                    &error);
1439 
1440         if (addr == LLDB_INVALID_ADDRESS)
1441         {
1442             result.AppendError("invalid address expression\n");
1443             result.AppendError(error.AsCString());
1444             result.SetStatus(eReturnStatusFailed);
1445             return false;
1446         }
1447 
1448         if (m_memory_options.m_infile)
1449         {
1450             size_t length = SIZE_MAX;
1451             if (item_byte_size > 1)
1452                 length = item_byte_size;
1453             lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
1454             if (data_sp)
1455             {
1456                 length = data_sp->GetByteSize();
1457                 if (length > 0)
1458                 {
1459                     Error error;
1460                     size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1461 
1462                     if (bytes_written == length)
1463                     {
1464                         // All bytes written
1465                         result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
1466                         result.SetStatus(eReturnStatusSuccessFinishResult);
1467                     }
1468                     else if (bytes_written > 0)
1469                     {
1470                         // Some byte written
1471                         result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr);
1472                         result.SetStatus(eReturnStatusSuccessFinishResult);
1473                     }
1474                     else
1475                     {
1476                         result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1477                         result.SetStatus(eReturnStatusFailed);
1478                     }
1479                 }
1480             }
1481             else
1482             {
1483                 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1484                 result.SetStatus(eReturnStatusFailed);
1485             }
1486             return result.Succeeded();
1487         }
1488         else if (item_byte_size == 0)
1489         {
1490             if (m_format_options.GetFormat() == eFormatPointer)
1491                 item_byte_size = buffer.GetAddressByteSize();
1492             else
1493                 item_byte_size = 1;
1494         }
1495 
1496         command.Shift(); // shift off the address argument
1497         uint64_t uval64;
1498         int64_t sval64;
1499         bool success = false;
1500         const size_t num_value_args = command.GetArgumentCount();
1501         for (size_t i=0; i<num_value_args; ++i)
1502         {
1503             const char *value_str = command.GetArgumentAtIndex(i);
1504 
1505             switch (m_format_options.GetFormat())
1506             {
1507             case kNumFormats:
1508             case eFormatFloat:  // TODO: add support for floats soon
1509             case eFormatCharPrintable:
1510             case eFormatBytesWithASCII:
1511             case eFormatComplex:
1512             case eFormatEnum:
1513             case eFormatUnicode16:
1514             case eFormatUnicode32:
1515             case eFormatVectorOfChar:
1516             case eFormatVectorOfSInt8:
1517             case eFormatVectorOfUInt8:
1518             case eFormatVectorOfSInt16:
1519             case eFormatVectorOfUInt16:
1520             case eFormatVectorOfSInt32:
1521             case eFormatVectorOfUInt32:
1522             case eFormatVectorOfSInt64:
1523             case eFormatVectorOfUInt64:
1524             case eFormatVectorOfFloat32:
1525             case eFormatVectorOfFloat64:
1526             case eFormatVectorOfUInt128:
1527             case eFormatOSType:
1528             case eFormatComplexInteger:
1529             case eFormatAddressInfo:
1530             case eFormatHexFloat:
1531             case eFormatInstruction:
1532             case eFormatVoid:
1533                 result.AppendError("unsupported format for writing memory");
1534                 result.SetStatus(eReturnStatusFailed);
1535                 return false;
1536 
1537             case eFormatDefault:
1538             case eFormatBytes:
1539             case eFormatHex:
1540             case eFormatHexUppercase:
1541             case eFormatPointer:
1542 
1543                 // Decode hex bytes
1544                 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success);
1545                 if (!success)
1546                 {
1547                     result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1548                     result.SetStatus(eReturnStatusFailed);
1549                     return false;
1550                 }
1551                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1552                 {
1553                     result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
1554                     result.SetStatus(eReturnStatusFailed);
1555                     return false;
1556                 }
1557                 buffer.PutMaxHex64 (uval64, item_byte_size);
1558                 break;
1559 
1560             case eFormatBoolean:
1561                 uval64 = Args::StringToBoolean(value_str, false, &success);
1562                 if (!success)
1563                 {
1564                     result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1565                     result.SetStatus(eReturnStatusFailed);
1566                     return false;
1567                 }
1568                 buffer.PutMaxHex64 (uval64, item_byte_size);
1569                 break;
1570 
1571             case eFormatBinary:
1572                 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success);
1573                 if (!success)
1574                 {
1575                     result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1576                     result.SetStatus(eReturnStatusFailed);
1577                     return false;
1578                 }
1579                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1580                 {
1581                     result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
1582                     result.SetStatus(eReturnStatusFailed);
1583                     return false;
1584                 }
1585                 buffer.PutMaxHex64 (uval64, item_byte_size);
1586                 break;
1587 
1588             case eFormatCharArray:
1589             case eFormatChar:
1590             case eFormatCString:
1591                 if (value_str[0])
1592                 {
1593                     size_t len = strlen (value_str);
1594                     // Include the NULL for C strings...
1595                     if (m_format_options.GetFormat() == eFormatCString)
1596                         ++len;
1597                     Error error;
1598                     if (process->WriteMemory (addr, value_str, len, error) == len)
1599                     {
1600                         addr += len;
1601                     }
1602                     else
1603                     {
1604                         result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1605                         result.SetStatus(eReturnStatusFailed);
1606                         return false;
1607                     }
1608                 }
1609                 break;
1610 
1611             case eFormatDecimal:
1612                 sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success);
1613                 if (!success)
1614                 {
1615                     result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1616                     result.SetStatus(eReturnStatusFailed);
1617                     return false;
1618                 }
1619                 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1620                 {
1621                     result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %" PRIu64 " byte signed integer value.\n", sval64, (uint64_t)item_byte_size);
1622                     result.SetStatus(eReturnStatusFailed);
1623                     return false;
1624                 }
1625                 buffer.PutMaxHex64 (sval64, item_byte_size);
1626                 break;
1627 
1628             case eFormatUnsigned:
1629                 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success);
1630                 if (!success)
1631                 {
1632                     result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1633                     result.SetStatus(eReturnStatusFailed);
1634                     return false;
1635                 }
1636                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1637                 {
1638                     result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
1639                     result.SetStatus(eReturnStatusFailed);
1640                     return false;
1641                 }
1642                 buffer.PutMaxHex64 (uval64, item_byte_size);
1643                 break;
1644 
1645             case eFormatOctal:
1646                 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success);
1647                 if (!success)
1648                 {
1649                     result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1650                     result.SetStatus(eReturnStatusFailed);
1651                     return false;
1652                 }
1653                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1654                 {
1655                     result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
1656                     result.SetStatus(eReturnStatusFailed);
1657                     return false;
1658                 }
1659                 buffer.PutMaxHex64 (uval64, item_byte_size);
1660                 break;
1661             }
1662         }
1663 
1664         if (!buffer.GetString().empty())
1665         {
1666             Error error;
1667             if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
1668                 return true;
1669             else
1670             {
1671                 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1672                 result.SetStatus(eReturnStatusFailed);
1673                 return false;
1674             }
1675         }
1676         return true;
1677     }
1678 
1679     OptionGroupOptions m_option_group;
1680     OptionGroupFormat m_format_options;
1681     OptionGroupWriteMemory m_memory_options;
1682 };
1683 
1684 //----------------------------------------------------------------------
1685 // Get malloc/free history of a memory address.
1686 //----------------------------------------------------------------------
1687 class CommandObjectMemoryHistory : public CommandObjectParsed
1688 {
1689 public:
1690 
1691     CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
1692     CommandObjectParsed (interpreter,
1693                          "memory history",
1694                          "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
1695                          NULL,
1696                          eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched)
1697     {
1698         CommandArgumentEntry arg1;
1699         CommandArgumentData addr_arg;
1700 
1701         // Define the first (and only) variant of this arg.
1702         addr_arg.arg_type = eArgTypeAddress;
1703         addr_arg.arg_repetition = eArgRepeatPlain;
1704 
1705         // There is only one variant this argument could be; put it into the argument entry.
1706         arg1.push_back (addr_arg);
1707 
1708         // Push the data for the first argument into the m_arguments vector.
1709         m_arguments.push_back (arg1);
1710     }
1711 
1712     virtual
1713     ~CommandObjectMemoryHistory ()
1714     {
1715     }
1716 
1717     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
1718     {
1719         return m_cmd_name.c_str();
1720     }
1721 
1722 protected:
1723     virtual bool
1724     DoExecute (Args& command, CommandReturnObject &result)
1725     {
1726         const size_t argc = command.GetArgumentCount();
1727 
1728         if (argc == 0 || argc > 1)
1729         {
1730             result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
1731             result.SetStatus(eReturnStatusFailed);
1732             return false;
1733         }
1734 
1735         Error error;
1736         lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1737                                                    command.GetArgumentAtIndex(0),
1738                                                    LLDB_INVALID_ADDRESS,
1739                                                    &error);
1740 
1741         if (addr == LLDB_INVALID_ADDRESS)
1742         {
1743             result.AppendError("invalid address expression");
1744             result.AppendError(error.AsCString());
1745             result.SetStatus(eReturnStatusFailed);
1746             return false;
1747         }
1748 
1749         Stream *output_stream = &result.GetOutputStream();
1750 
1751         const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1752         const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
1753 
1754         if (! memory_history.get())
1755         {
1756             result.AppendError("no available memory history provider");
1757             result.SetStatus(eReturnStatusFailed);
1758             return false;
1759         }
1760 
1761         HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1762 
1763         for (auto thread : thread_list) {
1764             thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
1765         }
1766 
1767         result.SetStatus(eReturnStatusSuccessFinishResult);
1768 
1769         return true;
1770     }
1771 
1772 };
1773 
1774 
1775 //-------------------------------------------------------------------------
1776 // CommandObjectMemory
1777 //-------------------------------------------------------------------------
1778 
1779 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
1780     CommandObjectMultiword (interpreter,
1781                             "memory",
1782                             "A set of commands for operating on memory.",
1783                             "memory <subcommand> [<subcommand-options>]")
1784 {
1785     LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
1786     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1787     LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
1788     LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
1789 }
1790 
1791 CommandObjectMemory::~CommandObjectMemory ()
1792 {
1793 }
1794