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