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