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