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