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