xref: /llvm-project/lldb/source/Commands/CommandObjectMemory.cpp (revision ac9c3a62a1e76df587fb14eb83be2229157962b1)
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   bool
1092   DoExecute (Args& command, CommandReturnObject &result) override
1093   {
1094       // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
1095       Process *process = m_exe_ctx.GetProcessPtr();
1096 
1097       const size_t argc = command.GetArgumentCount();
1098 
1099       if (argc != 2)
1100       {
1101           result.AppendError("two addresses needed for memory find");
1102           return false;
1103       }
1104 
1105       Error error;
1106       lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1107       if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1108       {
1109           result.AppendError("invalid low address");
1110           return false;
1111       }
1112       lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1113       if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1114       {
1115           result.AppendError("invalid high address");
1116           return false;
1117       }
1118 
1119       if (high_addr <= low_addr)
1120       {
1121           result.AppendError("starting address must be smaller than ending address");
1122           return false;
1123       }
1124 
1125       lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1126 
1127       DataBufferHeap buffer;
1128 
1129       if (m_memory_options.m_string.OptionWasSet())
1130           buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1131       else if (m_memory_options.m_expr.OptionWasSet())
1132       {
1133           StackFrame* frame = m_exe_ctx.GetFramePtr();
1134           ValueObjectSP result_sp;
1135           if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
1136               result_sp)
1137           {
1138               uint64_t value = result_sp->GetValueAsUnsigned(0);
1139               switch (result_sp->GetCompilerType().GetByteSize(nullptr))
1140               {
1141                   case 1: {
1142                       uint8_t byte = (uint8_t)value;
1143                       buffer.CopyData(&byte,1);
1144                   }
1145                       break;
1146                   case 2: {
1147                       uint16_t word = (uint16_t)value;
1148                       buffer.CopyData(&word,2);
1149                   }
1150                       break;
1151                   case 4: {
1152                       uint32_t lword = (uint32_t)value;
1153                       buffer.CopyData(&lword,4);
1154                   }
1155                       break;
1156                   case 8: {
1157                       buffer.CopyData(&value, 8);
1158                   }
1159                       break;
1160                   case 3:
1161                   case 5:
1162                   case 6:
1163                   case 7:
1164                       result.AppendError("unknown type. pass a string instead");
1165                       return false;
1166                   default:
1167                       result.AppendError("result size larger than 8 bytes. pass a string instead");
1168                       return false;
1169               }
1170           }
1171           else
1172           {
1173               result.AppendError("expression evaluation failed. pass a string instead");
1174               return false;
1175           }
1176       }
1177       else
1178       {
1179           result.AppendError("please pass either a block of text, or an expression to evaluate.");
1180           return false;
1181       }
1182 
1183       size_t count = m_memory_options.m_count.GetCurrentValue();
1184       found_location = low_addr;
1185       bool ever_found = false;
1186       while (count)
1187       {
1188           found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1189           if (found_location == LLDB_INVALID_ADDRESS)
1190           {
1191               if (!ever_found)
1192               {
1193                   result.AppendMessage("data not found within the range.\n");
1194                   result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1195               }
1196               else
1197                   result.AppendMessage("no more matches within the range.\n");
1198               break;
1199           }
1200           result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location);
1201 
1202           DataBufferHeap dumpbuffer(32,0);
1203           process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1204           if (!error.Fail())
1205           {
1206               DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1207               data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1208               result.GetOutputStream().EOL();
1209           }
1210 
1211           --count;
1212           found_location++;
1213           ever_found = true;
1214       }
1215 
1216       result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1217       return true;
1218   }
1219 
1220     lldb::addr_t
1221     Search (lldb::addr_t low,
1222             lldb::addr_t high,
1223             uint8_t* buffer,
1224             size_t buffer_size)
1225     {
1226         Process *process = m_exe_ctx.GetProcessPtr();
1227         DataBufferHeap heap(buffer_size, 0);
1228         for (auto ptr = low;
1229              ptr < high;
1230              ptr++)
1231         {
1232             Error error;
1233             process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
1234             if (error.Fail())
1235                 return LLDB_INVALID_ADDRESS;
1236             if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
1237                 return ptr;
1238         }
1239         return LLDB_INVALID_ADDRESS;
1240     }
1241 
1242     OptionGroupOptions m_option_group;
1243     OptionGroupFindMemory m_memory_options;
1244 };
1245 
1246 OptionDefinition
1247 g_memory_write_option_table[] =
1248 {
1249   // clang-format off
1250   {LLDB_OPT_SET_1, true,  "infile", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1251   {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset,   "Start writing bytes from an offset within the input file."},
1252   // clang-format on
1253 };
1254 
1255 //----------------------------------------------------------------------
1256 // Write memory to the inferior process
1257 //----------------------------------------------------------------------
1258 class CommandObjectMemoryWrite : public CommandObjectParsed
1259 {
1260 public:
1261     class OptionGroupWriteMemory : public OptionGroup
1262     {
1263     public:
1264         OptionGroupWriteMemory () :
1265             OptionGroup()
1266         {
1267         }
1268 
1269         ~OptionGroupWriteMemory() override = default;
1270 
1271         uint32_t
1272         GetNumDefinitions () override
1273         {
1274             return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1275         }
1276 
1277         const OptionDefinition*
1278         GetDefinitions () override
1279         {
1280             return g_memory_write_option_table;
1281         }
1282 
1283         Error
1284         SetOptionValue (uint32_t option_idx,
1285                         const char *option_arg,
1286                         ExecutionContext *execution_context) override
1287         {
1288             Error error;
1289             const int short_option = g_memory_write_option_table[option_idx].short_option;
1290 
1291             switch (short_option)
1292             {
1293                 case 'i':
1294                     m_infile.SetFile (option_arg, true);
1295                     if (!m_infile.Exists())
1296                     {
1297                         m_infile.Clear();
1298                         error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
1299                     }
1300                     break;
1301 
1302                 case 'o':
1303                     {
1304                         bool success;
1305                         m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success);
1306                         if (!success)
1307                         {
1308                             error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
1309                         }
1310                     }
1311                     break;
1312 
1313                 default:
1314                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1315                     break;
1316             }
1317             return error;
1318         }
1319 
1320         void
1321         OptionParsingStarting(ExecutionContext *execution_context) override
1322         {
1323             m_infile.Clear();
1324             m_infile_offset = 0;
1325         }
1326 
1327         FileSpec m_infile;
1328         off_t m_infile_offset;
1329     };
1330 
1331     CommandObjectMemoryWrite(CommandInterpreter &interpreter)
1332         : CommandObjectParsed(interpreter, "memory write", "Write to the memory of the current target process.",
1333                               nullptr, eCommandRequiresProcess | eCommandProcessMustBeLaunched),
1334           m_option_group(),
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(
1692               interpreter, "memory history",
1693               "Print recorded stack traces for allocation/deallocation events associated with an address.", nullptr,
1694               eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused |
1695                   eCommandProcessMustBeLaunched)
1696     {
1697         CommandArgumentEntry arg1;
1698         CommandArgumentData addr_arg;
1699 
1700         // Define the first (and only) variant of this arg.
1701         addr_arg.arg_type = eArgTypeAddress;
1702         addr_arg.arg_repetition = eArgRepeatPlain;
1703 
1704         // There is only one variant this argument could be; put it into the argument entry.
1705         arg1.push_back (addr_arg);
1706 
1707         // Push the data for the first argument into the m_arguments vector.
1708         m_arguments.push_back (arg1);
1709     }
1710 
1711     ~CommandObjectMemoryHistory() override = default;
1712 
1713     const char *
1714     GetRepeatCommand (Args &current_command_args, uint32_t index) override
1715     {
1716         return m_cmd_name.c_str();
1717     }
1718 
1719 protected:
1720     bool
1721     DoExecute (Args& command, CommandReturnObject &result) override
1722     {
1723         const size_t argc = command.GetArgumentCount();
1724 
1725         if (argc == 0 || argc > 1)
1726         {
1727             result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
1728             result.SetStatus(eReturnStatusFailed);
1729             return false;
1730         }
1731 
1732         Error error;
1733         lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1734                                                    command.GetArgumentAtIndex(0),
1735                                                    LLDB_INVALID_ADDRESS,
1736                                                    &error);
1737 
1738         if (addr == LLDB_INVALID_ADDRESS)
1739         {
1740             result.AppendError("invalid address expression");
1741             result.AppendError(error.AsCString());
1742             result.SetStatus(eReturnStatusFailed);
1743             return false;
1744         }
1745 
1746         Stream *output_stream = &result.GetOutputStream();
1747 
1748         const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1749         const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
1750 
1751         if (!memory_history)
1752         {
1753             result.AppendError("no available memory history provider");
1754             result.SetStatus(eReturnStatusFailed);
1755             return false;
1756         }
1757 
1758         HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1759 
1760         for (auto thread : thread_list) {
1761             thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
1762         }
1763 
1764         result.SetStatus(eReturnStatusSuccessFinishResult);
1765 
1766         return true;
1767     }
1768 };
1769 
1770 //-------------------------------------------------------------------------
1771 // CommandObjectMemoryRegion
1772 //-------------------------------------------------------------------------
1773 #pragma mark CommandObjectMemoryRegion
1774 
1775 class CommandObjectMemoryRegion : public CommandObjectParsed
1776 {
1777 public:
1778     CommandObjectMemoryRegion(CommandInterpreter &interpreter)
1779         : CommandObjectParsed(
1780               interpreter, "memory region",
1781               "Get information on the memory region containing an address in the current target process.",
1782               "memory region ADDR", eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched),
1783           m_prev_end_addr(LLDB_INVALID_ADDRESS)
1784     {
1785     }
1786 
1787     ~CommandObjectMemoryRegion() override = default;
1788 
1789 protected:
1790     bool
1791     DoExecute(Args &command, CommandReturnObject &result) override
1792     {
1793         ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1794         if (process_sp)
1795         {
1796             Error error;
1797             lldb::addr_t load_addr = m_prev_end_addr;
1798             m_prev_end_addr = LLDB_INVALID_ADDRESS;
1799 
1800             const size_t argc = command.GetArgumentCount();
1801             if (argc > 1 || (argc == 0 && load_addr == LLDB_INVALID_ADDRESS))
1802             {
1803                 result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n", m_cmd_name.c_str(),
1804                                              m_cmd_syntax.c_str());
1805                 result.SetStatus(eReturnStatusFailed);
1806             }
1807             else
1808             {
1809                 const char *load_addr_cstr = command.GetArgumentAtIndex(0);
1810                 if (command.GetArgumentCount() == 1)
1811                 {
1812                     load_addr = Args::StringToAddress(&m_exe_ctx, load_addr_cstr, LLDB_INVALID_ADDRESS, &error);
1813                     if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS)
1814                     {
1815                         result.AppendErrorWithFormat("invalid address argument \"%s\": %s\n", load_addr_cstr,
1816                                                      error.AsCString());
1817                         result.SetStatus(eReturnStatusFailed);
1818                     }
1819                 }
1820 
1821                 lldb_private::MemoryRegionInfo range_info;
1822                 error = process_sp->GetMemoryRegionInfo(load_addr, range_info);
1823                 if (error.Success())
1824                 {
1825                     lldb_private::Address addr;
1826                     ConstString section_name;
1827                     if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr))
1828                     {
1829                         SectionSP section_sp(addr.GetSection());
1830                         if (section_sp)
1831                         {
1832                             // Got the top most section, not the deepest section
1833                             while (section_sp->GetParent())
1834                                 section_sp = section_sp->GetParent();
1835                             section_name = section_sp->GetName();
1836                         }
1837                     }
1838                     result.AppendMessageWithFormat(
1839                         "[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s\n", range_info.GetRange().GetRangeBase(),
1840                         range_info.GetRange().GetRangeEnd(), range_info.GetReadable() ? 'r' : '-',
1841                         range_info.GetWritable() ? 'w' : '-', range_info.GetExecutable() ? 'x' : '-',
1842                         section_name ? " " : "", section_name ? section_name.AsCString() : "");
1843                     m_prev_end_addr = range_info.GetRange().GetRangeEnd();
1844                     result.SetStatus(eReturnStatusSuccessFinishResult);
1845                 }
1846                 else
1847                 {
1848                     result.SetStatus(eReturnStatusFailed);
1849                     result.AppendErrorWithFormat("%s\n", error.AsCString());
1850                 }
1851             }
1852         }
1853         else
1854         {
1855             m_prev_end_addr = LLDB_INVALID_ADDRESS;
1856             result.AppendError("invalid process");
1857             result.SetStatus(eReturnStatusFailed);
1858         }
1859         return result.Succeeded();
1860     }
1861 
1862     const char *
1863     GetRepeatCommand(Args &current_command_args, uint32_t index) override
1864     {
1865         // If we repeat this command, repeat it without any arguments so we can
1866         // show the next memory range
1867         return m_cmd_name.c_str();
1868     }
1869 
1870     lldb::addr_t m_prev_end_addr;
1871 };
1872 
1873 //-------------------------------------------------------------------------
1874 // CommandObjectMemory
1875 //-------------------------------------------------------------------------
1876 
1877 CommandObjectMemory::CommandObjectMemory(CommandInterpreter &interpreter)
1878     : CommandObjectMultiword(interpreter, "memory", "Commands for operating on memory in the current target process.",
1879                              "memory <subcommand> [<subcommand-options>]")
1880 {
1881     LoadSubCommand("find", CommandObjectSP(new CommandObjectMemoryFind(interpreter)));
1882     LoadSubCommand("read", CommandObjectSP(new CommandObjectMemoryRead(interpreter)));
1883     LoadSubCommand("write", CommandObjectSP(new CommandObjectMemoryWrite(interpreter)));
1884     LoadSubCommand("history", CommandObjectSP(new CommandObjectMemoryHistory(interpreter)));
1885     LoadSubCommand("region", CommandObjectSP(new CommandObjectMemoryRegion(interpreter)));
1886 }
1887 
1888 CommandObjectMemory::~CommandObjectMemory() = default;
1889