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