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