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