xref: /llvm-project/lldb/source/Commands/CommandObjectMemory.cpp (revision 68e73eaee632b29d36e8b24f62e77ef26084885d)
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       llvm::StringRef str = m_memory_options.m_string.GetStringValue();
1057       if (str.empty()) {
1058         result.AppendError("search string must have non-zero length.");
1059         return false;
1060       }
1061       buffer.CopyData(str);
1062     } else if (m_memory_options.m_expr.OptionWasSet()) {
1063       StackFrame *frame = m_exe_ctx.GetFramePtr();
1064       ValueObjectSP result_sp;
1065       if ((eExpressionCompleted ==
1066            process->GetTarget().EvaluateExpression(
1067                m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
1068           result_sp) {
1069         uint64_t value = result_sp->GetValueAsUnsigned(0);
1070         llvm::Optional<uint64_t> size =
1071             result_sp->GetCompilerType().GetByteSize(nullptr);
1072         if (!size)
1073           return false;
1074         switch (*size) {
1075         case 1: {
1076           uint8_t byte = (uint8_t)value;
1077           buffer.CopyData(&byte, 1);
1078         } break;
1079         case 2: {
1080           uint16_t word = (uint16_t)value;
1081           buffer.CopyData(&word, 2);
1082         } break;
1083         case 4: {
1084           uint32_t lword = (uint32_t)value;
1085           buffer.CopyData(&lword, 4);
1086         } break;
1087         case 8: {
1088           buffer.CopyData(&value, 8);
1089         } break;
1090         case 3:
1091         case 5:
1092         case 6:
1093         case 7:
1094           result.AppendError("unknown type. pass a string instead");
1095           return false;
1096         default:
1097           result.AppendError(
1098               "result size larger than 8 bytes. pass a string instead");
1099           return false;
1100         }
1101       } else {
1102         result.AppendError(
1103             "expression evaluation failed. pass a string instead");
1104         return false;
1105       }
1106     } else {
1107       result.AppendError(
1108           "please pass either a block of text, or an expression to evaluate.");
1109       return false;
1110     }
1111 
1112     size_t count = m_memory_options.m_count.GetCurrentValue();
1113     found_location = low_addr;
1114     bool ever_found = false;
1115     while (count) {
1116       found_location = FastSearch(found_location, high_addr, buffer.GetBytes(),
1117                                   buffer.GetByteSize());
1118       if (found_location == LLDB_INVALID_ADDRESS) {
1119         if (!ever_found) {
1120           result.AppendMessage("data not found within the range.\n");
1121           result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1122         } else
1123           result.AppendMessage("no more matches within the range.\n");
1124         break;
1125       }
1126       result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n",
1127                                      found_location);
1128 
1129       DataBufferHeap dumpbuffer(32, 0);
1130       process->ReadMemory(
1131           found_location + m_memory_options.m_offset.GetCurrentValue(),
1132           dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1133       if (!error.Fail()) {
1134         DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(),
1135                            process->GetByteOrder(),
1136                            process->GetAddressByteSize());
1137         DumpDataExtractor(
1138             data, &result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1,
1139             dumpbuffer.GetByteSize(), 16,
1140             found_location + m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1141         result.GetOutputStream().EOL();
1142       }
1143 
1144       --count;
1145       found_location++;
1146       ever_found = true;
1147     }
1148 
1149     result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1150     return true;
1151   }
1152 
1153   lldb::addr_t FastSearch(lldb::addr_t low, lldb::addr_t high, uint8_t *buffer,
1154                           size_t buffer_size) {
1155     const size_t region_size = high - low;
1156 
1157     if (region_size < buffer_size)
1158       return LLDB_INVALID_ADDRESS;
1159 
1160     std::vector<size_t> bad_char_heuristic(256, buffer_size);
1161     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1162     ProcessMemoryIterator iterator(process_sp, low);
1163 
1164     for (size_t idx = 0; idx < buffer_size - 1; idx++) {
1165       decltype(bad_char_heuristic)::size_type bcu_idx = buffer[idx];
1166       bad_char_heuristic[bcu_idx] = buffer_size - idx - 1;
1167     }
1168     for (size_t s = 0; s <= (region_size - buffer_size);) {
1169       int64_t j = buffer_size - 1;
1170       while (j >= 0 && buffer[j] == iterator[s + j])
1171         j--;
1172       if (j < 0)
1173         return low + s;
1174       else
1175         s += bad_char_heuristic[iterator[s + buffer_size - 1]];
1176     }
1177 
1178     return LLDB_INVALID_ADDRESS;
1179   }
1180 
1181   OptionGroupOptions m_option_group;
1182   OptionGroupFindMemory m_memory_options;
1183 };
1184 
1185 #define LLDB_OPTIONS_memory_write
1186 #include "CommandOptions.inc"
1187 
1188 // Write memory to the inferior process
1189 class CommandObjectMemoryWrite : public CommandObjectParsed {
1190 public:
1191   class OptionGroupWriteMemory : public OptionGroup {
1192   public:
1193     OptionGroupWriteMemory() = default;
1194 
1195     ~OptionGroupWriteMemory() override = default;
1196 
1197     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1198       return llvm::makeArrayRef(g_memory_write_options);
1199     }
1200 
1201     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
1202                           ExecutionContext *execution_context) override {
1203       Status error;
1204       const int short_option = g_memory_write_options[option_idx].short_option;
1205 
1206       switch (short_option) {
1207       case 'i':
1208         m_infile.SetFile(option_value, FileSpec::Style::native);
1209         FileSystem::Instance().Resolve(m_infile);
1210         if (!FileSystem::Instance().Exists(m_infile)) {
1211           m_infile.Clear();
1212           error.SetErrorStringWithFormat("input file does not exist: '%s'",
1213                                          option_value.str().c_str());
1214         }
1215         break;
1216 
1217       case 'o': {
1218         if (option_value.getAsInteger(0, m_infile_offset)) {
1219           m_infile_offset = 0;
1220           error.SetErrorStringWithFormat("invalid offset string '%s'",
1221                                          option_value.str().c_str());
1222         }
1223       } break;
1224 
1225       default:
1226         llvm_unreachable("Unimplemented option");
1227       }
1228       return error;
1229     }
1230 
1231     void OptionParsingStarting(ExecutionContext *execution_context) override {
1232       m_infile.Clear();
1233       m_infile_offset = 0;
1234     }
1235 
1236     FileSpec m_infile;
1237     off_t m_infile_offset;
1238   };
1239 
1240   CommandObjectMemoryWrite(CommandInterpreter &interpreter)
1241       : CommandObjectParsed(
1242             interpreter, "memory write",
1243             "Write to the memory of the current target process.", nullptr,
1244             eCommandRequiresProcess | eCommandProcessMustBeLaunched),
1245         m_format_options(
1246             eFormatBytes, 1, UINT64_MAX,
1247             {std::make_tuple(
1248                  eArgTypeFormat,
1249                  "The format to use for each of the value to be written."),
1250              std::make_tuple(eArgTypeByteSize,
1251                              "The size in bytes to write from input file or "
1252                              "each value.")}) {
1253     CommandArgumentEntry arg1;
1254     CommandArgumentEntry arg2;
1255     CommandArgumentData addr_arg;
1256     CommandArgumentData value_arg;
1257 
1258     // Define the first (and only) variant of this arg.
1259     addr_arg.arg_type = eArgTypeAddress;
1260     addr_arg.arg_repetition = eArgRepeatPlain;
1261 
1262     // There is only one variant this argument could be; put it into the
1263     // argument entry.
1264     arg1.push_back(addr_arg);
1265 
1266     // Define the first (and only) variant of this arg.
1267     value_arg.arg_type = eArgTypeValue;
1268     value_arg.arg_repetition = eArgRepeatPlus;
1269     value_arg.arg_opt_set_association = LLDB_OPT_SET_1;
1270 
1271     // There is only one variant this argument could be; put it into the
1272     // argument entry.
1273     arg2.push_back(value_arg);
1274 
1275     // Push the data for the first argument into the m_arguments vector.
1276     m_arguments.push_back(arg1);
1277     m_arguments.push_back(arg2);
1278 
1279     m_option_group.Append(&m_format_options,
1280                           OptionGroupFormat::OPTION_GROUP_FORMAT,
1281                           LLDB_OPT_SET_1);
1282     m_option_group.Append(&m_format_options,
1283                           OptionGroupFormat::OPTION_GROUP_SIZE,
1284                           LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
1285     m_option_group.Append(&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1286     m_option_group.Finalize();
1287   }
1288 
1289   ~CommandObjectMemoryWrite() override = default;
1290 
1291   Options *GetOptions() override { return &m_option_group; }
1292 
1293 protected:
1294   bool DoExecute(Args &command, CommandReturnObject &result) override {
1295     // No need to check "process" for validity as eCommandRequiresProcess
1296     // ensures it is valid
1297     Process *process = m_exe_ctx.GetProcessPtr();
1298 
1299     const size_t argc = command.GetArgumentCount();
1300 
1301     if (m_memory_options.m_infile) {
1302       if (argc < 1) {
1303         result.AppendErrorWithFormat(
1304             "%s takes a destination address when writing file contents.\n",
1305             m_cmd_name.c_str());
1306         return false;
1307       }
1308       if (argc > 1) {
1309         result.AppendErrorWithFormat(
1310             "%s takes only a destination address when writing file contents.\n",
1311             m_cmd_name.c_str());
1312         return false;
1313       }
1314     } else if (argc < 2) {
1315       result.AppendErrorWithFormat(
1316           "%s takes a destination address and at least one value.\n",
1317           m_cmd_name.c_str());
1318       return false;
1319     }
1320 
1321     StreamString buffer(
1322         Stream::eBinary,
1323         process->GetTarget().GetArchitecture().GetAddressByteSize(),
1324         process->GetTarget().GetArchitecture().GetByteOrder());
1325 
1326     OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1327     size_t item_byte_size = byte_size_value.GetCurrentValue();
1328 
1329     Status error;
1330     lldb::addr_t addr = OptionArgParser::ToAddress(
1331         &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error);
1332 
1333     if (addr == LLDB_INVALID_ADDRESS) {
1334       result.AppendError("invalid address expression\n");
1335       result.AppendError(error.AsCString());
1336       return false;
1337     }
1338 
1339     if (m_memory_options.m_infile) {
1340       size_t length = SIZE_MAX;
1341       if (item_byte_size > 1)
1342         length = item_byte_size;
1343       auto data_sp = FileSystem::Instance().CreateDataBuffer(
1344           m_memory_options.m_infile.GetPath(), length,
1345           m_memory_options.m_infile_offset);
1346       if (data_sp) {
1347         length = data_sp->GetByteSize();
1348         if (length > 0) {
1349           Status error;
1350           size_t bytes_written =
1351               process->WriteMemory(addr, data_sp->GetBytes(), length, error);
1352 
1353           if (bytes_written == length) {
1354             // All bytes written
1355             result.GetOutputStream().Printf(
1356                 "%" PRIu64 " bytes were written to 0x%" PRIx64 "\n",
1357                 (uint64_t)bytes_written, addr);
1358             result.SetStatus(eReturnStatusSuccessFinishResult);
1359           } else if (bytes_written > 0) {
1360             // Some byte written
1361             result.GetOutputStream().Printf(
1362                 "%" PRIu64 " bytes of %" PRIu64
1363                 " requested were written to 0x%" PRIx64 "\n",
1364                 (uint64_t)bytes_written, (uint64_t)length, addr);
1365             result.SetStatus(eReturnStatusSuccessFinishResult);
1366           } else {
1367             result.AppendErrorWithFormat("Memory write to 0x%" PRIx64
1368                                          " failed: %s.\n",
1369                                          addr, error.AsCString());
1370           }
1371         }
1372       } else {
1373         result.AppendErrorWithFormat("Unable to read contents of file.\n");
1374       }
1375       return result.Succeeded();
1376     } else if (item_byte_size == 0) {
1377       if (m_format_options.GetFormat() == eFormatPointer)
1378         item_byte_size = buffer.GetAddressByteSize();
1379       else
1380         item_byte_size = 1;
1381     }
1382 
1383     command.Shift(); // shift off the address argument
1384     uint64_t uval64;
1385     int64_t sval64;
1386     bool success = false;
1387     for (auto &entry : command) {
1388       switch (m_format_options.GetFormat()) {
1389       case kNumFormats:
1390       case eFormatFloat: // TODO: add support for floats soon
1391       case eFormatCharPrintable:
1392       case eFormatBytesWithASCII:
1393       case eFormatComplex:
1394       case eFormatEnum:
1395       case eFormatUnicode8:
1396       case eFormatUnicode16:
1397       case eFormatUnicode32:
1398       case eFormatVectorOfChar:
1399       case eFormatVectorOfSInt8:
1400       case eFormatVectorOfUInt8:
1401       case eFormatVectorOfSInt16:
1402       case eFormatVectorOfUInt16:
1403       case eFormatVectorOfSInt32:
1404       case eFormatVectorOfUInt32:
1405       case eFormatVectorOfSInt64:
1406       case eFormatVectorOfUInt64:
1407       case eFormatVectorOfFloat16:
1408       case eFormatVectorOfFloat32:
1409       case eFormatVectorOfFloat64:
1410       case eFormatVectorOfUInt128:
1411       case eFormatOSType:
1412       case eFormatComplexInteger:
1413       case eFormatAddressInfo:
1414       case eFormatHexFloat:
1415       case eFormatInstruction:
1416       case eFormatVoid:
1417         result.AppendError("unsupported format for writing memory");
1418         return false;
1419 
1420       case eFormatDefault:
1421       case eFormatBytes:
1422       case eFormatHex:
1423       case eFormatHexUppercase:
1424       case eFormatPointer: {
1425         // Decode hex bytes
1426         // Be careful, getAsInteger with a radix of 16 rejects "0xab" so we
1427         // have to special case that:
1428         bool success = false;
1429         if (entry.ref().startswith("0x"))
1430           success = !entry.ref().getAsInteger(0, uval64);
1431         if (!success)
1432           success = !entry.ref().getAsInteger(16, uval64);
1433         if (!success) {
1434           result.AppendErrorWithFormat(
1435               "'%s' is not a valid hex string value.\n", entry.c_str());
1436           return false;
1437         } else if (!llvm::isUIntN(item_byte_size * 8, uval64)) {
1438           result.AppendErrorWithFormat("Value 0x%" PRIx64
1439                                        " is too large to fit in a %" PRIu64
1440                                        " byte unsigned integer value.\n",
1441                                        uval64, (uint64_t)item_byte_size);
1442           return false;
1443         }
1444         buffer.PutMaxHex64(uval64, item_byte_size);
1445         break;
1446       }
1447       case eFormatBoolean:
1448         uval64 = OptionArgParser::ToBoolean(entry.ref(), false, &success);
1449         if (!success) {
1450           result.AppendErrorWithFormat(
1451               "'%s' is not a valid boolean string value.\n", entry.c_str());
1452           return false;
1453         }
1454         buffer.PutMaxHex64(uval64, item_byte_size);
1455         break;
1456 
1457       case eFormatBinary:
1458         if (entry.ref().getAsInteger(2, uval64)) {
1459           result.AppendErrorWithFormat(
1460               "'%s' is not a valid binary string value.\n", entry.c_str());
1461           return false;
1462         } else if (!llvm::isUIntN(item_byte_size * 8, uval64)) {
1463           result.AppendErrorWithFormat("Value 0x%" PRIx64
1464                                        " is too large to fit in a %" PRIu64
1465                                        " byte unsigned integer value.\n",
1466                                        uval64, (uint64_t)item_byte_size);
1467           return false;
1468         }
1469         buffer.PutMaxHex64(uval64, item_byte_size);
1470         break;
1471 
1472       case eFormatCharArray:
1473       case eFormatChar:
1474       case eFormatCString: {
1475         if (entry.ref().empty())
1476           break;
1477 
1478         size_t len = entry.ref().size();
1479         // Include the NULL for C strings...
1480         if (m_format_options.GetFormat() == eFormatCString)
1481           ++len;
1482         Status error;
1483         if (process->WriteMemory(addr, entry.c_str(), len, error) == len) {
1484           addr += len;
1485         } else {
1486           result.AppendErrorWithFormat("Memory write to 0x%" PRIx64
1487                                        " failed: %s.\n",
1488                                        addr, error.AsCString());
1489           return false;
1490         }
1491         break;
1492       }
1493       case eFormatDecimal:
1494         if (entry.ref().getAsInteger(0, sval64)) {
1495           result.AppendErrorWithFormat(
1496               "'%s' is not a valid signed decimal value.\n", entry.c_str());
1497           return false;
1498         } else if (!llvm::isIntN(item_byte_size * 8, sval64)) {
1499           result.AppendErrorWithFormat(
1500               "Value %" PRIi64 " is too large or small to fit in a %" PRIu64
1501               " byte signed integer value.\n",
1502               sval64, (uint64_t)item_byte_size);
1503           return false;
1504         }
1505         buffer.PutMaxHex64(sval64, item_byte_size);
1506         break;
1507 
1508       case eFormatUnsigned:
1509 
1510         if (entry.ref().getAsInteger(0, uval64)) {
1511           result.AppendErrorWithFormat(
1512               "'%s' is not a valid unsigned decimal string value.\n",
1513               entry.c_str());
1514           return false;
1515         } else if (!llvm::isUIntN(item_byte_size * 8, uval64)) {
1516           result.AppendErrorWithFormat("Value %" PRIu64
1517                                        " is too large to fit in a %" PRIu64
1518                                        " byte unsigned integer value.\n",
1519                                        uval64, (uint64_t)item_byte_size);
1520           return false;
1521         }
1522         buffer.PutMaxHex64(uval64, item_byte_size);
1523         break;
1524 
1525       case eFormatOctal:
1526         if (entry.ref().getAsInteger(8, uval64)) {
1527           result.AppendErrorWithFormat(
1528               "'%s' is not a valid octal string value.\n", entry.c_str());
1529           return false;
1530         } else if (!llvm::isUIntN(item_byte_size * 8, uval64)) {
1531           result.AppendErrorWithFormat("Value %" PRIo64
1532                                        " is too large to fit in a %" PRIu64
1533                                        " byte unsigned integer value.\n",
1534                                        uval64, (uint64_t)item_byte_size);
1535           return false;
1536         }
1537         buffer.PutMaxHex64(uval64, item_byte_size);
1538         break;
1539       }
1540     }
1541 
1542     if (!buffer.GetString().empty()) {
1543       Status error;
1544       if (process->WriteMemory(addr, buffer.GetString().data(),
1545                                buffer.GetString().size(),
1546                                error) == buffer.GetString().size())
1547         return true;
1548       else {
1549         result.AppendErrorWithFormat("Memory write to 0x%" PRIx64
1550                                      " failed: %s.\n",
1551                                      addr, error.AsCString());
1552         return false;
1553       }
1554     }
1555     return true;
1556   }
1557 
1558   OptionGroupOptions m_option_group;
1559   OptionGroupFormat m_format_options;
1560   OptionGroupWriteMemory m_memory_options;
1561 };
1562 
1563 // Get malloc/free history of a memory address.
1564 class CommandObjectMemoryHistory : public CommandObjectParsed {
1565 public:
1566   CommandObjectMemoryHistory(CommandInterpreter &interpreter)
1567       : CommandObjectParsed(interpreter, "memory history",
1568                             "Print recorded stack traces for "
1569                             "allocation/deallocation events "
1570                             "associated with an address.",
1571                             nullptr,
1572                             eCommandRequiresTarget | eCommandRequiresProcess |
1573                                 eCommandProcessMustBePaused |
1574                                 eCommandProcessMustBeLaunched) {
1575     CommandArgumentEntry arg1;
1576     CommandArgumentData addr_arg;
1577 
1578     // Define the first (and only) variant of this arg.
1579     addr_arg.arg_type = eArgTypeAddress;
1580     addr_arg.arg_repetition = eArgRepeatPlain;
1581 
1582     // There is only one variant this argument could be; put it into the
1583     // argument entry.
1584     arg1.push_back(addr_arg);
1585 
1586     // Push the data for the first argument into the m_arguments vector.
1587     m_arguments.push_back(arg1);
1588   }
1589 
1590   ~CommandObjectMemoryHistory() override = default;
1591 
1592   llvm::Optional<std::string> GetRepeatCommand(Args &current_command_args,
1593                                                uint32_t index) override {
1594     return m_cmd_name;
1595   }
1596 
1597 protected:
1598   bool DoExecute(Args &command, CommandReturnObject &result) override {
1599     const size_t argc = command.GetArgumentCount();
1600 
1601     if (argc == 0 || argc > 1) {
1602       result.AppendErrorWithFormat("%s takes an address expression",
1603                                    m_cmd_name.c_str());
1604       return false;
1605     }
1606 
1607     Status error;
1608     lldb::addr_t addr = OptionArgParser::ToAddress(
1609         &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error);
1610 
1611     if (addr == LLDB_INVALID_ADDRESS) {
1612       result.AppendError("invalid address expression");
1613       result.AppendError(error.AsCString());
1614       return false;
1615     }
1616 
1617     Stream *output_stream = &result.GetOutputStream();
1618 
1619     const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1620     const MemoryHistorySP &memory_history =
1621         MemoryHistory::FindPlugin(process_sp);
1622 
1623     if (!memory_history) {
1624       result.AppendError("no available memory history provider");
1625       return false;
1626     }
1627 
1628     HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1629 
1630     const bool stop_format = false;
1631     for (auto thread : thread_list) {
1632       thread->GetStatus(*output_stream, 0, UINT32_MAX, 0, stop_format);
1633     }
1634 
1635     result.SetStatus(eReturnStatusSuccessFinishResult);
1636 
1637     return true;
1638   }
1639 };
1640 
1641 // CommandObjectMemoryRegion
1642 #pragma mark CommandObjectMemoryRegion
1643 
1644 class CommandObjectMemoryRegion : public CommandObjectParsed {
1645 public:
1646   CommandObjectMemoryRegion(CommandInterpreter &interpreter)
1647       : CommandObjectParsed(interpreter, "memory region",
1648                             "Get information on the memory region containing "
1649                             "an address in the current target process.",
1650                             "memory region ADDR",
1651                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1652                                 eCommandProcessMustBeLaunched) {}
1653 
1654   ~CommandObjectMemoryRegion() override = default;
1655 
1656 protected:
1657   bool DoExecute(Args &command, CommandReturnObject &result) override {
1658     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1659     if (!process_sp) {
1660       m_prev_end_addr = LLDB_INVALID_ADDRESS;
1661       result.AppendError("invalid process");
1662       return false;
1663     }
1664 
1665     Status error;
1666     lldb::addr_t load_addr = m_prev_end_addr;
1667     m_prev_end_addr = LLDB_INVALID_ADDRESS;
1668 
1669     const size_t argc = command.GetArgumentCount();
1670     const lldb::ABISP &abi = process_sp->GetABI();
1671 
1672     if (argc == 1) {
1673       auto load_addr_str = command[0].ref();
1674       // Non-address bits in this will be handled later by GetMemoryRegion
1675       load_addr = OptionArgParser::ToAddress(&m_exe_ctx, load_addr_str,
1676                                              LLDB_INVALID_ADDRESS, &error);
1677       if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) {
1678         result.AppendErrorWithFormat("invalid address argument \"%s\": %s\n",
1679                                      command[0].c_str(), error.AsCString());
1680         return false;
1681       }
1682     } else if (argc > 1 ||
1683                // When we're repeating the command, the previous end address is
1684                // used for load_addr. If that was 0xF...F then we must have
1685                // reached the end of memory.
1686                (argc == 0 && load_addr == LLDB_INVALID_ADDRESS) ||
1687                // If the target has non-address bits (tags, limited virtual
1688                // address size, etc.), the end of mappable memory will be lower
1689                // than that. So if we find any non-address bit set, we must be
1690                // at the end of the mappable range.
1691                (abi && (abi->FixDataAddress(load_addr) != load_addr))) {
1692       result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n",
1693                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
1694       return false;
1695     }
1696 
1697     lldb_private::MemoryRegionInfo range_info;
1698     error = process_sp->GetMemoryRegionInfo(load_addr, range_info);
1699     if (error.Success()) {
1700       lldb_private::Address addr;
1701       ConstString name = range_info.GetName();
1702       ConstString section_name;
1703       if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr)) {
1704         SectionSP section_sp(addr.GetSection());
1705         if (section_sp) {
1706           // Got the top most section, not the deepest section
1707           while (section_sp->GetParent())
1708             section_sp = section_sp->GetParent();
1709           section_name = section_sp->GetName();
1710         }
1711       }
1712 
1713       result.AppendMessageWithFormatv(
1714           "[{0:x16}-{1:x16}) {2:r}{3:w}{4:x}{5}{6}{7}{8}",
1715           range_info.GetRange().GetRangeBase(),
1716           range_info.GetRange().GetRangeEnd(), range_info.GetReadable(),
1717           range_info.GetWritable(), range_info.GetExecutable(), name ? " " : "",
1718           name, section_name ? " " : "", section_name);
1719       MemoryRegionInfo::OptionalBool memory_tagged =
1720           range_info.GetMemoryTagged();
1721       if (memory_tagged == MemoryRegionInfo::OptionalBool::eYes)
1722         result.AppendMessage("memory tagging: enabled");
1723 
1724       const llvm::Optional<std::vector<addr_t>> &dirty_page_list =
1725           range_info.GetDirtyPageList();
1726       if (dirty_page_list.hasValue()) {
1727         const size_t page_count = dirty_page_list.getValue().size();
1728         result.AppendMessageWithFormat(
1729             "Modified memory (dirty) page list provided, %zu entries.\n",
1730             page_count);
1731         if (page_count > 0) {
1732           bool print_comma = false;
1733           result.AppendMessageWithFormat("Dirty pages: ");
1734           for (size_t i = 0; i < page_count; i++) {
1735             if (print_comma)
1736               result.AppendMessageWithFormat(", ");
1737             else
1738               print_comma = true;
1739             result.AppendMessageWithFormat("0x%" PRIx64,
1740                                            dirty_page_list.getValue()[i]);
1741           }
1742           result.AppendMessageWithFormat(".\n");
1743         }
1744       }
1745 
1746       m_prev_end_addr = range_info.GetRange().GetRangeEnd();
1747       result.SetStatus(eReturnStatusSuccessFinishResult);
1748       return true;
1749     }
1750 
1751     result.AppendErrorWithFormat("%s\n", error.AsCString());
1752     return false;
1753   }
1754 
1755   llvm::Optional<std::string> GetRepeatCommand(Args &current_command_args,
1756                                                uint32_t index) override {
1757     // If we repeat this command, repeat it without any arguments so we can
1758     // show the next memory range
1759     return m_cmd_name;
1760   }
1761 
1762   lldb::addr_t m_prev_end_addr = LLDB_INVALID_ADDRESS;
1763 };
1764 
1765 // CommandObjectMemory
1766 
1767 CommandObjectMemory::CommandObjectMemory(CommandInterpreter &interpreter)
1768     : CommandObjectMultiword(
1769           interpreter, "memory",
1770           "Commands for operating on memory in the current target process.",
1771           "memory <subcommand> [<subcommand-options>]") {
1772   LoadSubCommand("find",
1773                  CommandObjectSP(new CommandObjectMemoryFind(interpreter)));
1774   LoadSubCommand("read",
1775                  CommandObjectSP(new CommandObjectMemoryRead(interpreter)));
1776   LoadSubCommand("write",
1777                  CommandObjectSP(new CommandObjectMemoryWrite(interpreter)));
1778   LoadSubCommand("history",
1779                  CommandObjectSP(new CommandObjectMemoryHistory(interpreter)));
1780   LoadSubCommand("region",
1781                  CommandObjectSP(new CommandObjectMemoryRegion(interpreter)));
1782   LoadSubCommand("tag",
1783                  CommandObjectSP(new CommandObjectMemoryTag(interpreter)));
1784 }
1785 
1786 CommandObjectMemory::~CommandObjectMemory() = default;
1787