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