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