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