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