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