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