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