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