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