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