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 // C Includes
11 #include <inttypes.h>
12 
13 // C++ Includes
14 // Other libraries and framework includes
15 #include "clang/AST/Decl.h"
16 
17 // Project includes
18 #include "CommandObjectMemory.h"
19 #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
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/Section.h"
25 #include "lldb/Core/StreamString.h"
26 #include "lldb/Core/ValueObjectMemory.h"
27 #include "lldb/DataFormatters/ValueObjectPrinter.h"
28 #include "lldb/Host/StringConvert.h"
29 #include "lldb/Interpreter/Args.h"
30 #include "lldb/Interpreter/CommandInterpreter.h"
31 #include "lldb/Interpreter/CommandReturnObject.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/Interpreter/Options.h"
37 #include "lldb/Symbol/ClangASTContext.h"
38 #include "lldb/Symbol/SymbolFile.h"
39 #include "lldb/Symbol/TypeList.h"
40 #include "lldb/Target/MemoryHistory.h"
41 #include "lldb/Target/MemoryRegionInfo.h"
42 #include "lldb/Target/Process.h"
43 #include "lldb/Target/StackFrame.h"
44 #include "lldb/Target/Thread.h"
45 
46 #include "lldb/lldb-private.h"
47 
48 using namespace lldb;
49 using namespace lldb_private;
50 
51 static OptionDefinition
52 g_option_table[] =
53 {
54     { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
55     { LLDB_OPT_SET_2, false, "binary"       ,'b', OptionParser::eNoArgument      , nullptr, nullptr, 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."},
56     { LLDB_OPT_SET_3, true , "type"         ,'t', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone          ,"The name of a type to view memory as."},
57     { LLDB_OPT_SET_3, false , "offset"      ,'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount         ,"How many elements of the specified type to skip before starting to display data."},
58     { LLDB_OPT_SET_1|
59       LLDB_OPT_SET_2|
60       LLDB_OPT_SET_3, false, "force"        ,'r', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone          ,"Necessary if reading over target.max-memory-read-size bytes."},
61 };
62 
63 class OptionGroupReadMemory : public OptionGroup
64 {
65 public:
66     OptionGroupReadMemory () :
67         m_num_per_line (1,1),
68         m_output_as_binary (false),
69         m_view_as_type(),
70         m_offset(0,0)
71     {
72     }
73 
74     ~OptionGroupReadMemory() override = default;
75 
76     uint32_t
77     GetNumDefinitions () override
78     {
79         return sizeof (g_option_table) / sizeof (OptionDefinition);
80     }
81 
82     const OptionDefinition*
83     GetDefinitions () override
84     {
85         return g_option_table;
86     }
87 
88     Error
89     SetOptionValue (CommandInterpreter &interpreter,
90                     uint32_t option_idx,
91                     const char *option_arg) override
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             case 'E':
117                 error = m_offset.SetValueFromString(option_arg);
118                 break;
119 
120             default:
121                 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
122                 break;
123         }
124         return error;
125     }
126 
127     void
128     OptionParsingStarting (CommandInterpreter &interpreter) override
129     {
130         m_num_per_line.Clear();
131         m_output_as_binary = false;
132         m_view_as_type.Clear();
133         m_force = false;
134         m_offset.Clear();
135     }
136 
137     Error
138     FinalizeSettings (Target *target, OptionGroupFormat& format_options)
139     {
140         Error error;
141         OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
142         OptionValueUInt64 &count_value = format_options.GetCountValue();
143         const bool byte_size_option_set = byte_size_value.OptionWasSet();
144         const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
145         const bool count_option_set = format_options.GetCountValue().OptionWasSet();
146 
147         switch (format_options.GetFormat())
148         {
149             default:
150                 break;
151 
152             case eFormatBoolean:
153                 if (!byte_size_option_set)
154                     byte_size_value = 1;
155                 if (!num_per_line_option_set)
156                     m_num_per_line = 1;
157                 if (!count_option_set)
158                     format_options.GetCountValue() = 8;
159                 break;
160 
161             case eFormatCString:
162                 break;
163 
164             case eFormatInstruction:
165                 if (count_option_set)
166                     byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
167                 m_num_per_line = 1;
168                 break;
169 
170             case eFormatAddressInfo:
171                 if (!byte_size_option_set)
172                     byte_size_value = target->GetArchitecture().GetAddressByteSize();
173                 m_num_per_line = 1;
174                 if (!count_option_set)
175                     format_options.GetCountValue() = 8;
176                 break;
177 
178             case eFormatPointer:
179                 byte_size_value = target->GetArchitecture().GetAddressByteSize();
180                 if (!num_per_line_option_set)
181                     m_num_per_line = 4;
182                 if (!count_option_set)
183                     format_options.GetCountValue() = 8;
184                 break;
185 
186             case eFormatBinary:
187             case eFormatFloat:
188             case eFormatOctal:
189             case eFormatDecimal:
190             case eFormatEnum:
191             case eFormatUnicode16:
192             case eFormatUnicode32:
193             case eFormatUnsigned:
194             case eFormatHexFloat:
195                 if (!byte_size_option_set)
196                     byte_size_value = 4;
197                 if (!num_per_line_option_set)
198                     m_num_per_line = 1;
199                 if (!count_option_set)
200                     format_options.GetCountValue() = 8;
201                 break;
202 
203             case eFormatBytes:
204             case eFormatBytesWithASCII:
205                 if (byte_size_option_set)
206                 {
207                     if (byte_size_value > 1)
208                         error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
209                                                         "\tconsider using a different display format or don't specify the byte size",
210                                                         byte_size_value.GetCurrentValue());
211                 }
212                 else
213                     byte_size_value = 1;
214                 if (!num_per_line_option_set)
215                     m_num_per_line = 16;
216                 if (!count_option_set)
217                     format_options.GetCountValue() = 32;
218                 break;
219 
220             case eFormatCharArray:
221             case eFormatChar:
222             case eFormatCharPrintable:
223                 if (!byte_size_option_set)
224                     byte_size_value = 1;
225                 if (!num_per_line_option_set)
226                     m_num_per_line = 32;
227                 if (!count_option_set)
228                     format_options.GetCountValue() = 64;
229                 break;
230 
231             case eFormatComplex:
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 
240             case eFormatComplexInteger:
241                 if (!byte_size_option_set)
242                     byte_size_value = 8;
243                 if (!num_per_line_option_set)
244                     m_num_per_line = 1;
245                 if (!count_option_set)
246                     format_options.GetCountValue() = 8;
247                 break;
248 
249             case eFormatHex:
250                 if (!byte_size_option_set)
251                     byte_size_value = 4;
252                 if (!num_per_line_option_set)
253                 {
254                     switch (byte_size_value)
255                     {
256                         case 1:
257                         case 2:
258                             m_num_per_line = 8;
259                             break;
260                         case 4:
261                             m_num_per_line = 4;
262                             break;
263                         case 8:
264                             m_num_per_line = 2;
265                             break;
266                         default:
267                             m_num_per_line = 1;
268                             break;
269                     }
270                 }
271                 if (!count_option_set)
272                     count_value = 8;
273                 break;
274 
275             case eFormatVectorOfChar:
276             case eFormatVectorOfSInt8:
277             case eFormatVectorOfUInt8:
278             case eFormatVectorOfSInt16:
279             case eFormatVectorOfUInt16:
280             case eFormatVectorOfSInt32:
281             case eFormatVectorOfUInt32:
282             case eFormatVectorOfSInt64:
283             case eFormatVectorOfUInt64:
284             case eFormatVectorOfFloat16:
285             case eFormatVectorOfFloat32:
286             case eFormatVectorOfFloat64:
287             case eFormatVectorOfUInt128:
288                 if (!byte_size_option_set)
289                     byte_size_value = 128;
290                 if (!num_per_line_option_set)
291                     m_num_per_line = 1;
292                 if (!count_option_set)
293                     count_value = 4;
294                 break;
295         }
296         return error;
297     }
298 
299     bool
300     AnyOptionWasSet () const
301     {
302         return m_num_per_line.OptionWasSet() ||
303                m_output_as_binary ||
304                m_view_as_type.OptionWasSet() ||
305                m_offset.OptionWasSet();
306     }
307 
308     OptionValueUInt64 m_num_per_line;
309     bool m_output_as_binary;
310     OptionValueString m_view_as_type;
311     bool m_force;
312     OptionValueUInt64 m_offset;
313 };
314 
315 //----------------------------------------------------------------------
316 // Read memory from the inferior process
317 //----------------------------------------------------------------------
318 class CommandObjectMemoryRead : public CommandObjectParsed
319 {
320 public:
321     CommandObjectMemoryRead (CommandInterpreter &interpreter) :
322         CommandObjectParsed(interpreter,
323                             "memory read",
324                             "Read from the memory of the process being debugged.",
325                             nullptr,
326                             eCommandRequiresTarget | eCommandProcessMustBePaused),
327         m_option_group (interpreter),
328         m_format_options (eFormatBytesWithASCII, 1, 8),
329         m_memory_options (),
330         m_outfile_options (),
331         m_varobj_options(),
332         m_next_addr(LLDB_INVALID_ADDRESS),
333         m_prev_byte_size(0),
334         m_prev_format_options (eFormatBytesWithASCII, 1, 8),
335         m_prev_memory_options (),
336         m_prev_outfile_options (),
337         m_prev_varobj_options()
338     {
339         CommandArgumentEntry arg1;
340         CommandArgumentEntry arg2;
341         CommandArgumentData start_addr_arg;
342         CommandArgumentData end_addr_arg;
343 
344         // Define the first (and only) variant of this arg.
345         start_addr_arg.arg_type = eArgTypeAddressOrExpression;
346         start_addr_arg.arg_repetition = eArgRepeatPlain;
347 
348         // There is only one variant this argument could be; put it into the argument entry.
349         arg1.push_back (start_addr_arg);
350 
351         // Define the first (and only) variant of this arg.
352         end_addr_arg.arg_type = eArgTypeAddressOrExpression;
353         end_addr_arg.arg_repetition = eArgRepeatOptional;
354 
355         // There is only one variant this argument could be; put it into the argument entry.
356         arg2.push_back (end_addr_arg);
357 
358         // Push the data for the first argument into the m_arguments vector.
359         m_arguments.push_back (arg1);
360         m_arguments.push_back (arg2);
361 
362         // Add the "--format" and "--count" options to group 1 and 3
363         m_option_group.Append (&m_format_options,
364                                OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
365                                LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
366         m_option_group.Append (&m_format_options,
367                                OptionGroupFormat::OPTION_GROUP_GDB_FMT,
368                                LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
369         // Add the "--size" option to group 1 and 2
370         m_option_group.Append (&m_format_options,
371                                OptionGroupFormat::OPTION_GROUP_SIZE,
372                                LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
373         m_option_group.Append (&m_memory_options);
374         m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
375         m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
376         m_option_group.Finalize();
377     }
378 
379     ~CommandObjectMemoryRead() override = default;
380 
381     Options *
382     GetOptions () override
383     {
384         return &m_option_group;
385     }
386 
387     const char *
388     GetRepeatCommand (Args &current_command_args, uint32_t index) override
389     {
390         return m_cmd_name.c_str();
391     }
392 
393 protected:
394     bool
395     DoExecute (Args& command, CommandReturnObject &result) override
396     {
397         // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid
398         Target *target = m_exe_ctx.GetTargetPtr();
399 
400         const size_t argc = command.GetArgumentCount();
401 
402         if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
403         {
404             result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
405             result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
406             result.SetStatus(eReturnStatusFailed);
407             return false;
408         }
409 
410         CompilerType clang_ast_type;
411         Error error;
412 
413         const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
414         if (view_as_type_cstr && view_as_type_cstr[0])
415         {
416             // We are viewing memory as a type
417 
418             SymbolContext sc;
419             const bool exact_match = false;
420             TypeList type_list;
421             uint32_t reference_count = 0;
422             uint32_t pointer_count = 0;
423             size_t idx;
424 
425 #define ALL_KEYWORDS        \
426     KEYWORD("const")        \
427     KEYWORD("volatile")     \
428     KEYWORD("restrict")     \
429     KEYWORD("struct")       \
430     KEYWORD("class")        \
431     KEYWORD("union")
432 
433 #define KEYWORD(s) s,
434             static const char *g_keywords[] =
435             {
436                 ALL_KEYWORDS
437             };
438 #undef KEYWORD
439 
440 #define KEYWORD(s) (sizeof(s) - 1),
441             static const int g_keyword_lengths[] =
442             {
443                 ALL_KEYWORDS
444             };
445 #undef KEYWORD
446 
447 #undef ALL_KEYWORDS
448 
449             static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
450             std::string type_str(view_as_type_cstr);
451 
452             // Remove all instances of g_keywords that are followed by spaces
453             for (size_t i = 0; i < g_num_keywords; ++i)
454             {
455                 const char *keyword = g_keywords[i];
456                 int keyword_len = g_keyword_lengths[i];
457 
458                 idx = 0;
459                 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
460                 {
461                     if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
462                     {
463                         type_str.erase(idx, keyword_len+1);
464                         idx = 0;
465                     }
466                     else
467                     {
468                         idx += keyword_len;
469                     }
470                 }
471             }
472             bool done = type_str.empty();
473             //
474             idx = type_str.find_first_not_of (" \t");
475             if (idx > 0 && idx != std::string::npos)
476                 type_str.erase (0, idx);
477             while (!done)
478             {
479                 // Strip trailing spaces
480                 if (type_str.empty())
481                     done = true;
482                 else
483                 {
484                     switch (type_str[type_str.size()-1])
485                     {
486                     case '*':
487                         ++pointer_count;
488                         LLVM_FALLTHROUGH;
489                     case ' ':
490                     case '\t':
491                         type_str.erase(type_str.size()-1);
492                         break;
493 
494                     case '&':
495                         if (reference_count == 0)
496                         {
497                             reference_count = 1;
498                             type_str.erase(type_str.size()-1);
499                         }
500                         else
501                         {
502                             result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
503                             result.SetStatus(eReturnStatusFailed);
504                             return false;
505                         }
506                         break;
507 
508                     default:
509                         done = true;
510                         break;
511                     }
512                 }
513             }
514 
515             llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
516             ConstString lookup_type_name(type_str.c_str());
517             StackFrame *frame = m_exe_ctx.GetFramePtr();
518             if (frame)
519             {
520                 sc = frame->GetSymbolContext (eSymbolContextModule);
521                 if (sc.module_sp)
522                 {
523                     sc.module_sp->FindTypes (sc,
524                                              lookup_type_name,
525                                              exact_match,
526                                              1,
527                                              searched_symbol_files,
528                                              type_list);
529                 }
530             }
531             if (type_list.GetSize() == 0)
532             {
533                 target->GetImages().FindTypes (sc,
534                                                lookup_type_name,
535                                                exact_match,
536                                                1,
537                                                searched_symbol_files,
538                                                type_list);
539             }
540 
541             if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
542             {
543                 if (ClangPersistentVariables *persistent_vars = llvm::dyn_cast_or_null<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)))
544                 {
545                     clang::TypeDecl *tdecl = llvm::dyn_cast_or_null<clang::TypeDecl>(persistent_vars->GetPersistentDecl(ConstString(lookup_type_name)));
546 
547                     if (tdecl)
548                     {
549                         clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()),
550                                                        reinterpret_cast<lldb::opaque_compiler_type_t>(const_cast<clang::Type*>(tdecl->getTypeForDecl())));
551                     }
552                 }
553             }
554 
555             if (!clang_ast_type.IsValid())
556             {
557                 if (type_list.GetSize() == 0)
558                 {
559                     result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
560                                                   lookup_type_name.GetCString(),
561                                                   view_as_type_cstr);
562                     result.SetStatus(eReturnStatusFailed);
563                     return false;
564                 }
565                 else
566                 {
567                     TypeSP type_sp (type_list.GetTypeAtIndex(0));
568                     clang_ast_type = type_sp->GetFullCompilerType ();
569                 }
570             }
571 
572             while (pointer_count > 0)
573             {
574                 CompilerType pointer_type = clang_ast_type.GetPointerType();
575                 if (pointer_type.IsValid())
576                     clang_ast_type = pointer_type;
577                 else
578                 {
579                     result.AppendError ("unable make a pointer type\n");
580                     result.SetStatus(eReturnStatusFailed);
581                     return false;
582                 }
583                 --pointer_count;
584             }
585 
586             m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);
587 
588             if (m_format_options.GetByteSizeValue() == 0)
589             {
590                 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
591                                               view_as_type_cstr);
592                 result.SetStatus(eReturnStatusFailed);
593                 return false;
594             }
595 
596             if (!m_format_options.GetCountValue().OptionWasSet())
597                 m_format_options.GetCountValue() = 1;
598         }
599         else
600         {
601             error = m_memory_options.FinalizeSettings (target, m_format_options);
602         }
603 
604         // Look for invalid combinations of settings
605         if (error.Fail())
606         {
607             result.AppendError(error.AsCString());
608             result.SetStatus(eReturnStatusFailed);
609             return false;
610         }
611 
612         lldb::addr_t addr;
613         size_t total_byte_size = 0;
614         if (argc == 0)
615         {
616             // Use the last address and byte size and all options as they were
617             // if no options have been set
618             addr = m_next_addr;
619             total_byte_size = m_prev_byte_size;
620             clang_ast_type = m_prev_clang_ast_type;
621             if (!m_format_options.AnyOptionWasSet() &&
622                 !m_memory_options.AnyOptionWasSet() &&
623                 !m_outfile_options.AnyOptionWasSet() &&
624                 !m_varobj_options.AnyOptionWasSet())
625             {
626                 m_format_options = m_prev_format_options;
627                 m_memory_options = m_prev_memory_options;
628                 m_outfile_options = m_prev_outfile_options;
629                 m_varobj_options = m_prev_varobj_options;
630             }
631         }
632 
633         size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
634 
635         // TODO For non-8-bit byte addressable architectures this needs to be
636         // revisited to fully support all lldb's range of formatting options.
637         // Furthermore code memory reads (for those architectures) will not
638         // be correctly formatted even w/o formatting options.
639         size_t item_byte_size =
640             target->GetArchitecture().GetDataByteSize() > 1 ?
641             target->GetArchitecture().GetDataByteSize() :
642             m_format_options.GetByteSizeValue().GetCurrentValue();
643 
644         const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
645 
646         if (total_byte_size == 0)
647         {
648             total_byte_size = item_count * item_byte_size;
649             if (total_byte_size == 0)
650                 total_byte_size = 32;
651         }
652 
653         if (argc > 0)
654             addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
655 
656         if (addr == LLDB_INVALID_ADDRESS)
657         {
658             result.AppendError("invalid start address expression.");
659             result.AppendError(error.AsCString());
660             result.SetStatus(eReturnStatusFailed);
661             return false;
662         }
663 
664         if (argc == 2)
665         {
666             lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),
667                                                           LLDB_INVALID_ADDRESS, nullptr);
668             if (end_addr == LLDB_INVALID_ADDRESS)
669             {
670                 result.AppendError("invalid end address expression.");
671                 result.AppendError(error.AsCString());
672                 result.SetStatus(eReturnStatusFailed);
673                 return false;
674             }
675             else if (end_addr <= addr)
676             {
677                 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
678                 result.SetStatus(eReturnStatusFailed);
679                 return false;
680             }
681             else if (m_format_options.GetCountValue().OptionWasSet())
682             {
683                 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count);
684                 result.SetStatus(eReturnStatusFailed);
685                 return false;
686             }
687 
688             total_byte_size = end_addr - addr;
689             item_count = total_byte_size / item_byte_size;
690         }
691 
692         uint32_t max_unforced_size = target->GetMaximumMemReadSize();
693 
694         if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
695         {
696             result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
697             result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
698             result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
699             return false;
700         }
701 
702         DataBufferSP data_sp;
703         size_t bytes_read = 0;
704         if (clang_ast_type.GetOpaqueQualType())
705         {
706             // Make sure we don't display our type as ASCII bytes like the default memory read
707             if (!m_format_options.GetFormatValue().OptionWasSet())
708                 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
709 
710             bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue();
711 
712             if (argc > 0)
713                 addr = addr + (clang_ast_type.GetByteSize(nullptr) * m_memory_options.m_offset.GetCurrentValue());
714         }
715         else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
716         {
717             data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
718             if (data_sp->GetBytes() == nullptr)
719             {
720                 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size);
721                 result.SetStatus(eReturnStatusFailed);
722                 return false;
723             }
724 
725             Address address(addr, nullptr);
726             bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
727             if (bytes_read == 0)
728             {
729                 const char *error_cstr = error.AsCString();
730                 if (error_cstr && error_cstr[0])
731                 {
732                     result.AppendError(error_cstr);
733                 }
734                 else
735                 {
736                     result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
737                 }
738                 result.SetStatus(eReturnStatusFailed);
739                 return false;
740             }
741 
742             if (bytes_read < total_byte_size)
743                 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);
744         }
745         else
746         {
747             // we treat c-strings as a special case because they do not have a fixed size
748             if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
749                 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
750             else
751                 item_byte_size = target->GetMaximumSizeOfStringSummary();
752             if (!m_format_options.GetCountValue().OptionWasSet())
753                 item_count = 1;
754             data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
755             if (data_sp->GetBytes() == nullptr)
756             {
757                 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));
758                 result.SetStatus(eReturnStatusFailed);
759                 return false;
760             }
761             uint8_t *data_ptr = data_sp->GetBytes();
762             auto data_addr = addr;
763             auto count = item_count;
764             item_count = 0;
765             bool break_on_no_NULL = false;
766             while (item_count < count)
767             {
768                 std::string buffer;
769                 buffer.resize(item_byte_size+1,0);
770                 Error error;
771                 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
772                 if (error.Fail())
773                 {
774                     result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
775                     result.SetStatus(eReturnStatusFailed);
776                     return false;
777                 }
778 
779                 if (item_byte_size == read)
780                 {
781                     result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
782                     --read;
783                     break_on_no_NULL = true;
784                 }
785                 else
786                     ++read; // account for final NULL byte
787 
788                 memcpy(data_ptr, &buffer[0], read);
789                 data_ptr += read;
790                 data_addr += read;
791                 bytes_read += read;
792                 item_count++; // if we break early we know we only read item_count strings
793 
794                 if (break_on_no_NULL)
795                     break;
796             }
797             data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
798         }
799 
800         m_next_addr = addr + bytes_read;
801         m_prev_byte_size = bytes_read;
802         m_prev_format_options = m_format_options;
803         m_prev_memory_options = m_memory_options;
804         m_prev_outfile_options = m_outfile_options;
805         m_prev_varobj_options = m_varobj_options;
806         m_prev_clang_ast_type = clang_ast_type;
807 
808         StreamFile outfile_stream;
809         Stream *output_stream = nullptr;
810         const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
811         if (outfile_spec)
812         {
813             char path[PATH_MAX];
814             outfile_spec.GetPath (path, sizeof(path));
815 
816             uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
817             const bool append = m_outfile_options.GetAppend().GetCurrentValue();
818             if (append)
819                 open_options |= File::eOpenOptionAppend;
820 
821             if (outfile_stream.GetFile ().Open (path, open_options).Success())
822             {
823                 if (m_memory_options.m_output_as_binary)
824                 {
825                     const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
826                     if (bytes_written > 0)
827                     {
828                         result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
829                                                          bytes_written,
830                                                          append ? "appended" : "written",
831                                                          path);
832                         return true;
833                     }
834                     else
835                     {
836                         result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
837                         result.SetStatus(eReturnStatusFailed);
838                         return false;
839                     }
840                 }
841                 else
842                 {
843                     // We are going to write ASCII to the file just point the
844                     // output_stream to our outfile_stream...
845                     output_stream = &outfile_stream;
846                 }
847             }
848             else
849             {
850                 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
851                 result.SetStatus(eReturnStatusFailed);
852                 return false;
853             }
854         }
855         else
856         {
857             output_stream = &result.GetOutputStream();
858         }
859 
860         ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
861         if (clang_ast_type.GetOpaqueQualType())
862         {
863             for (uint32_t i = 0; i<item_count; ++i)
864             {
865                 addr_t item_addr = addr + (i * item_byte_size);
866                 Address address (item_addr);
867                 StreamString name_strm;
868                 name_strm.Printf ("0x%" PRIx64, item_addr);
869                 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
870                                                                     name_strm.GetString().c_str(),
871                                                                     address,
872                                                                     clang_ast_type));
873                 if (valobj_sp)
874                 {
875                     Format format = m_format_options.GetFormat();
876                     if (format != eFormatDefault)
877                         valobj_sp->SetFormat (format);
878 
879                     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
880 
881                     valobj_sp->Dump(*output_stream,options);
882                 }
883                 else
884                 {
885                     result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
886                                                   view_as_type_cstr,
887                                                   name_strm.GetString().c_str());
888                     result.SetStatus(eReturnStatusFailed);
889                     return false;
890                 }
891             }
892             return true;
893         }
894 
895         result.SetStatus(eReturnStatusSuccessFinishResult);
896         DataExtractor data (data_sp,
897                             target->GetArchitecture().GetByteOrder(),
898                             target->GetArchitecture().GetAddressByteSize(),
899                             target->GetArchitecture().GetDataByteSize());
900 
901         Format format = m_format_options.GetFormat();
902         if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
903             && (item_byte_size != 1))
904         {
905             // if a count was not passed, or it is 1
906             if (!m_format_options.GetCountValue().OptionWasSet() || item_count == 1)
907             {
908                 // this turns requests such as
909                 // memory read -fc -s10 -c1 *charPtrPtr
910                 // which make no sense (what is a char of size 10?)
911                 // into a request for fetching 10 chars of size 1 from the same memory location
912                 format = eFormatCharArray;
913                 item_count = item_byte_size;
914                 item_byte_size = 1;
915             }
916             else
917             {
918                 // here we passed a count, and it was not 1
919                 // so we have a byte_size and a count
920                 // we could well multiply those, but instead let's just fail
921                 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
922                 result.SetStatus(eReturnStatusFailed);
923                 return false;
924             }
925         }
926 
927         assert (output_stream);
928         size_t bytes_dumped = data.Dump (output_stream,
929                                          0,
930                                          format,
931                                          item_byte_size,
932                                          item_count,
933                                          num_per_line / target->GetArchitecture().GetDataByteSize(),
934                                          addr,
935                                          0,
936                                          0,
937                                          exe_scope);
938         m_next_addr = addr + bytes_dumped;
939         output_stream->EOL();
940         return true;
941     }
942 
943     OptionGroupOptions m_option_group;
944     OptionGroupFormat m_format_options;
945     OptionGroupReadMemory m_memory_options;
946     OptionGroupOutputFile m_outfile_options;
947     OptionGroupValueObjectDisplay m_varobj_options;
948     lldb::addr_t m_next_addr;
949     lldb::addr_t m_prev_byte_size;
950     OptionGroupFormat m_prev_format_options;
951     OptionGroupReadMemory m_prev_memory_options;
952     OptionGroupOutputFile m_prev_outfile_options;
953     OptionGroupValueObjectDisplay m_prev_varobj_options;
954     CompilerType m_prev_clang_ast_type;
955 };
956 
957 OptionDefinition
958 g_memory_find_option_table[] =
959 {
960     { LLDB_OPT_SET_1, true, "expression", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
961     { LLDB_OPT_SET_2, true, "string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName,   "Use text to find a byte pattern."},
962     { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount,   "How many times to perform the search."},
963     { LLDB_OPT_SET_ALL, false, "dump-offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset,   "When dumping memory for a match, an offset from the match location to start dumping from."},
964 };
965 
966 //----------------------------------------------------------------------
967 // Find the specified data in memory
968 //----------------------------------------------------------------------
969 class CommandObjectMemoryFind : public CommandObjectParsed
970 {
971 public:
972   class OptionGroupFindMemory : public OptionGroup
973   {
974   public:
975     OptionGroupFindMemory () :
976       OptionGroup(),
977       m_count(1),
978       m_offset(0)
979     {
980     }
981 
982     ~OptionGroupFindMemory() override = default;
983 
984     uint32_t
985     GetNumDefinitions () override
986     {
987       return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
988     }
989 
990     const OptionDefinition*
991     GetDefinitions () override
992     {
993       return g_memory_find_option_table;
994     }
995 
996     Error
997     SetOptionValue (CommandInterpreter &interpreter,
998                     uint32_t option_idx,
999                     const char *option_arg) override
1000     {
1001         Error error;
1002         const int short_option = g_memory_find_option_table[option_idx].short_option;
1003 
1004         switch (short_option)
1005         {
1006         case 'e':
1007               m_expr.SetValueFromString(option_arg);
1008               break;
1009 
1010         case 's':
1011               m_string.SetValueFromString(option_arg);
1012               break;
1013 
1014         case 'c':
1015               if (m_count.SetValueFromString(option_arg).Fail())
1016                   error.SetErrorString("unrecognized value for count");
1017               break;
1018 
1019         case 'o':
1020                if (m_offset.SetValueFromString(option_arg).Fail())
1021                    error.SetErrorString("unrecognized value for dump-offset");
1022                 break;
1023 
1024         default:
1025               error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1026               break;
1027         }
1028         return error;
1029     }
1030 
1031     void
1032     OptionParsingStarting (CommandInterpreter &interpreter) override
1033     {
1034         m_expr.Clear();
1035         m_string.Clear();
1036         m_count.Clear();
1037     }
1038 
1039       OptionValueString m_expr;
1040       OptionValueString m_string;
1041       OptionValueUInt64 m_count;
1042       OptionValueUInt64 m_offset;
1043   };
1044 
1045   CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1046   CommandObjectParsed(interpreter,
1047                       "memory find",
1048                       "Find a value in the memory of the process being debugged.",
1049                       nullptr,
1050                       eCommandRequiresProcess | eCommandProcessMustBeLaunched),
1051   m_option_group (interpreter),
1052   m_memory_options ()
1053   {
1054     CommandArgumentEntry arg1;
1055     CommandArgumentEntry arg2;
1056     CommandArgumentData addr_arg;
1057     CommandArgumentData value_arg;
1058 
1059     // Define the first (and only) variant of this arg.
1060     addr_arg.arg_type = eArgTypeAddressOrExpression;
1061     addr_arg.arg_repetition = eArgRepeatPlain;
1062 
1063     // There is only one variant this argument could be; put it into the argument entry.
1064     arg1.push_back (addr_arg);
1065 
1066     // Define the first (and only) variant of this arg.
1067     value_arg.arg_type = eArgTypeAddressOrExpression;
1068     value_arg.arg_repetition = eArgRepeatPlain;
1069 
1070     // There is only one variant this argument could be; put it into the argument entry.
1071     arg2.push_back (value_arg);
1072 
1073     // Push the data for the first argument into the m_arguments vector.
1074     m_arguments.push_back (arg1);
1075     m_arguments.push_back (arg2);
1076 
1077     m_option_group.Append (&m_memory_options);
1078     m_option_group.Finalize();
1079   }
1080 
1081   ~CommandObjectMemoryFind() override = default;
1082 
1083   Options *
1084   GetOptions () override
1085   {
1086     return &m_option_group;
1087   }
1088 
1089 protected:
1090   bool
1091   DoExecute (Args& command, CommandReturnObject &result) override
1092   {
1093       // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
1094       Process *process = m_exe_ctx.GetProcessPtr();
1095 
1096       const size_t argc = command.GetArgumentCount();
1097 
1098       if (argc != 2)
1099       {
1100           result.AppendError("two addresses needed for memory find");
1101           return false;
1102       }
1103 
1104       Error error;
1105       lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1106       if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1107       {
1108           result.AppendError("invalid low address");
1109           return false;
1110       }
1111       lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1112       if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1113       {
1114           result.AppendError("invalid high address");
1115           return false;
1116       }
1117 
1118       if (high_addr <= low_addr)
1119       {
1120           result.AppendError("starting address must be smaller than ending address");
1121           return false;
1122       }
1123 
1124       lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1125 
1126       DataBufferHeap buffer;
1127 
1128       if (m_memory_options.m_string.OptionWasSet())
1129           buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1130       else if (m_memory_options.m_expr.OptionWasSet())
1131       {
1132           StackFrame* frame = m_exe_ctx.GetFramePtr();
1133           ValueObjectSP result_sp;
1134           if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
1135               result_sp)
1136           {
1137               uint64_t value = result_sp->GetValueAsUnsigned(0);
1138               switch (result_sp->GetCompilerType().GetByteSize(nullptr))
1139               {
1140                   case 1: {
1141                       uint8_t byte = (uint8_t)value;
1142                       buffer.CopyData(&byte,1);
1143                   }
1144                       break;
1145                   case 2: {
1146                       uint16_t word = (uint16_t)value;
1147                       buffer.CopyData(&word,2);
1148                   }
1149                       break;
1150                   case 4: {
1151                       uint32_t lword = (uint32_t)value;
1152                       buffer.CopyData(&lword,4);
1153                   }
1154                       break;
1155                   case 8: {
1156                       buffer.CopyData(&value, 8);
1157                   }
1158                       break;
1159                   case 3:
1160                   case 5:
1161                   case 6:
1162                   case 7:
1163                       result.AppendError("unknown type. pass a string instead");
1164                       return false;
1165                   default:
1166                       result.AppendError("result size larger than 8 bytes. pass a string instead");
1167                       return false;
1168               }
1169           }
1170           else
1171           {
1172               result.AppendError("expression evaluation failed. pass a string instead");
1173               return false;
1174           }
1175       }
1176       else
1177       {
1178           result.AppendError("please pass either a block of text, or an expression to evaluate.");
1179           return false;
1180       }
1181 
1182       size_t count = m_memory_options.m_count.GetCurrentValue();
1183       found_location = low_addr;
1184       bool ever_found = false;
1185       while (count)
1186       {
1187           found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1188           if (found_location == LLDB_INVALID_ADDRESS)
1189           {
1190               if (!ever_found)
1191               {
1192                   result.AppendMessage("data not found within the range.\n");
1193                   result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1194               }
1195               else
1196                   result.AppendMessage("no more matches within the range.\n");
1197               break;
1198           }
1199           result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location);
1200 
1201           DataBufferHeap dumpbuffer(32,0);
1202           process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1203           if (!error.Fail())
1204           {
1205               DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1206               data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1207               result.GetOutputStream().EOL();
1208           }
1209 
1210           --count;
1211           found_location++;
1212           ever_found = true;
1213       }
1214 
1215       result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1216       return true;
1217   }
1218 
1219     lldb::addr_t
1220     Search (lldb::addr_t low,
1221             lldb::addr_t high,
1222             uint8_t* buffer,
1223             size_t buffer_size)
1224     {
1225         Process *process = m_exe_ctx.GetProcessPtr();
1226         DataBufferHeap heap(buffer_size, 0);
1227         for (auto ptr = low;
1228              ptr < high;
1229              ptr++)
1230         {
1231             Error error;
1232             process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
1233             if (error.Fail())
1234                 return LLDB_INVALID_ADDRESS;
1235             if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
1236                 return ptr;
1237         }
1238         return LLDB_INVALID_ADDRESS;
1239     }
1240 
1241     OptionGroupOptions m_option_group;
1242     OptionGroupFindMemory m_memory_options;
1243 };
1244 
1245 OptionDefinition
1246 g_memory_write_option_table[] =
1247 {
1248 { LLDB_OPT_SET_1, true,  "infile", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1249 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset,   "Start writing bytes from an offset within the input file."},
1250 };
1251 
1252 //----------------------------------------------------------------------
1253 // Write memory to the inferior process
1254 //----------------------------------------------------------------------
1255 class CommandObjectMemoryWrite : public CommandObjectParsed
1256 {
1257 public:
1258     class OptionGroupWriteMemory : public OptionGroup
1259     {
1260     public:
1261         OptionGroupWriteMemory () :
1262             OptionGroup()
1263         {
1264         }
1265 
1266         ~OptionGroupWriteMemory() override = default;
1267 
1268         uint32_t
1269         GetNumDefinitions () override
1270         {
1271             return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1272         }
1273 
1274         const OptionDefinition*
1275         GetDefinitions () override
1276         {
1277             return g_memory_write_option_table;
1278         }
1279 
1280         Error
1281         SetOptionValue (CommandInterpreter &interpreter,
1282                         uint32_t option_idx,
1283                         const char *option_arg) override
1284         {
1285             Error error;
1286             const int short_option = g_memory_write_option_table[option_idx].short_option;
1287 
1288             switch (short_option)
1289             {
1290                 case 'i':
1291                     m_infile.SetFile (option_arg, true);
1292                     if (!m_infile.Exists())
1293                     {
1294                         m_infile.Clear();
1295                         error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
1296                     }
1297                     break;
1298 
1299                 case 'o':
1300                     {
1301                         bool success;
1302                         m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success);
1303                         if (!success)
1304                         {
1305                             error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
1306                         }
1307                     }
1308                     break;
1309 
1310                 default:
1311                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1312                     break;
1313             }
1314             return error;
1315         }
1316 
1317         void
1318         OptionParsingStarting (CommandInterpreter &interpreter) override
1319         {
1320             m_infile.Clear();
1321             m_infile_offset = 0;
1322         }
1323 
1324         FileSpec m_infile;
1325         off_t m_infile_offset;
1326     };
1327 
1328     CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
1329         CommandObjectParsed(interpreter,
1330                             "memory write",
1331                             "Write to the memory of the process being debugged.",
1332                             nullptr,
1333                             eCommandRequiresProcess | eCommandProcessMustBeLaunched),
1334         m_option_group (interpreter),
1335         m_format_options (eFormatBytes, 1, UINT64_MAX),
1336         m_memory_options ()
1337     {
1338         CommandArgumentEntry arg1;
1339         CommandArgumentEntry arg2;
1340         CommandArgumentData addr_arg;
1341         CommandArgumentData value_arg;
1342 
1343         // Define the first (and only) variant of this arg.
1344         addr_arg.arg_type = eArgTypeAddress;
1345         addr_arg.arg_repetition = eArgRepeatPlain;
1346 
1347         // There is only one variant this argument could be; put it into the argument entry.
1348         arg1.push_back (addr_arg);
1349 
1350         // Define the first (and only) variant of this arg.
1351         value_arg.arg_type = eArgTypeValue;
1352         value_arg.arg_repetition = eArgRepeatPlus;
1353 
1354         // There is only one variant this argument could be; put it into the argument entry.
1355         arg2.push_back (value_arg);
1356 
1357         // Push the data for the first argument into the m_arguments vector.
1358         m_arguments.push_back (arg1);
1359         m_arguments.push_back (arg2);
1360 
1361         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1362         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE  , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1363         m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1364         m_option_group.Finalize();
1365     }
1366 
1367     ~CommandObjectMemoryWrite() override = default;
1368 
1369     Options *
1370     GetOptions () override
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     bool
1404     DoExecute (Args& command, CommandReturnObject &result) override
1405     {
1406         // No need to check "process" for validity as eCommandRequiresProcess 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 eFormatVectorOfFloat16:
1525             case eFormatVectorOfFloat32:
1526             case eFormatVectorOfFloat64:
1527             case eFormatVectorOfUInt128:
1528             case eFormatOSType:
1529             case eFormatComplexInteger:
1530             case eFormatAddressInfo:
1531             case eFormatHexFloat:
1532             case eFormatInstruction:
1533             case eFormatVoid:
1534                 result.AppendError("unsupported format for writing memory");
1535                 result.SetStatus(eReturnStatusFailed);
1536                 return false;
1537 
1538             case eFormatDefault:
1539             case eFormatBytes:
1540             case eFormatHex:
1541             case eFormatHexUppercase:
1542             case eFormatPointer:
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     CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
1691         CommandObjectParsed(interpreter,
1692                             "memory history",
1693                             "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
1694                             nullptr,
1695                             eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused |
1696                             eCommandProcessMustBeLaunched)
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     ~CommandObjectMemoryHistory() override = default;
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)
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 // CommandObjectMemoryRegion
1773 //-------------------------------------------------------------------------
1774 #pragma mark CommandObjectMemoryRegion
1775 
1776 class CommandObjectMemoryRegion : public CommandObjectParsed
1777 {
1778 public:
1779     CommandObjectMemoryRegion(CommandInterpreter &interpreter)
1780         : CommandObjectParsed(interpreter, "memory region",
1781                               "Get information on a memory region that contains an address in the current process.",
1782                               "memory region ADDR",
1783                               eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched),
1784           m_prev_end_addr(LLDB_INVALID_ADDRESS)
1785     {
1786     }
1787 
1788     ~CommandObjectMemoryRegion() override = default;
1789 
1790 protected:
1791     bool
1792     DoExecute(Args &command, CommandReturnObject &result) override
1793     {
1794         ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1795         if (process_sp)
1796         {
1797             Error error;
1798             lldb::addr_t load_addr = m_prev_end_addr;
1799             m_prev_end_addr = LLDB_INVALID_ADDRESS;
1800 
1801             const size_t argc = command.GetArgumentCount();
1802             if (argc > 1 || (argc == 0 && load_addr == LLDB_INVALID_ADDRESS))
1803             {
1804                 result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n", m_cmd_name.c_str(),
1805                                              m_cmd_syntax.c_str());
1806                 result.SetStatus(eReturnStatusFailed);
1807             }
1808             else
1809             {
1810                 const char *load_addr_cstr = command.GetArgumentAtIndex(0);
1811                 if (command.GetArgumentCount() == 1)
1812                 {
1813                     load_addr = Args::StringToAddress(&m_exe_ctx, load_addr_cstr, LLDB_INVALID_ADDRESS, &error);
1814                     if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS)
1815                     {
1816                         result.AppendErrorWithFormat("invalid address argument \"%s\": %s\n", load_addr_cstr,
1817                                                      error.AsCString());
1818                         result.SetStatus(eReturnStatusFailed);
1819                     }
1820                 }
1821 
1822                 lldb_private::MemoryRegionInfo range_info;
1823                 error = process_sp->GetMemoryRegionInfo(load_addr, range_info);
1824                 if (error.Success())
1825                 {
1826                     lldb_private::Address addr;
1827                     ConstString section_name;
1828                     if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr))
1829                     {
1830                         SectionSP section_sp(addr.GetSection());
1831                         if (section_sp)
1832                         {
1833                             // Got the top most section, not the deepest section
1834                             while (section_sp->GetParent())
1835                                 section_sp = section_sp->GetParent();
1836                             section_name = section_sp->GetName();
1837                         }
1838                     }
1839                     result.AppendMessageWithFormat(
1840                         "[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s\n", range_info.GetRange().GetRangeBase(),
1841                         range_info.GetRange().GetRangeEnd(), range_info.GetReadable() ? 'r' : '-',
1842                         range_info.GetWritable() ? 'w' : '-', range_info.GetExecutable() ? 'x' : '-',
1843                         section_name ? " " : "", section_name ? section_name.AsCString() : "");
1844                     m_prev_end_addr = range_info.GetRange().GetRangeEnd();
1845                     result.SetStatus(eReturnStatusSuccessFinishResult);
1846                 }
1847                 else
1848                 {
1849                     result.SetStatus(eReturnStatusFailed);
1850                     result.AppendErrorWithFormat("%s\n", error.AsCString());
1851                 }
1852             }
1853         }
1854         else
1855         {
1856             m_prev_end_addr = LLDB_INVALID_ADDRESS;
1857             result.AppendError("invalid process");
1858             result.SetStatus(eReturnStatusFailed);
1859         }
1860         return result.Succeeded();
1861     }
1862 
1863     const char *
1864     GetRepeatCommand(Args &current_command_args, uint32_t index) override
1865     {
1866         // If we repeat this command, repeat it without any arguments so we can
1867         // show the next memory range
1868         return m_cmd_name.c_str();
1869     }
1870 
1871     lldb::addr_t m_prev_end_addr;
1872 };
1873 
1874 //-------------------------------------------------------------------------
1875 // CommandObjectMemory
1876 //-------------------------------------------------------------------------
1877 
1878 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
1879     CommandObjectMultiword (interpreter,
1880                             "memory",
1881                             "A set of commands for operating on memory.",
1882                             "memory <subcommand> [<subcommand-options>]")
1883 {
1884     LoadSubCommand("find", CommandObjectSP(new CommandObjectMemoryFind(interpreter)));
1885     LoadSubCommand("read", CommandObjectSP(new CommandObjectMemoryRead(interpreter)));
1886     LoadSubCommand("write", CommandObjectSP(new CommandObjectMemoryWrite(interpreter)));
1887     LoadSubCommand("history", CommandObjectSP(new CommandObjectMemoryHistory(interpreter)));
1888     LoadSubCommand("region", CommandObjectSP(new CommandObjectMemoryRegion(interpreter)));
1889 }
1890 
1891 CommandObjectMemory::~CommandObjectMemory() = default;
1892