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