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