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 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/DataBufferHeap.h"
17 #include "lldb/Core/DataExtractor.h"
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Core/StreamString.h"
20 #include "lldb/Core/ValueObjectMemory.h"
21 #include "lldb/Interpreter/Args.h"
22 #include "lldb/Interpreter/CommandReturnObject.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/Options.h"
25 #include "lldb/Interpreter/OptionGroupFormat.h"
26 #include "lldb/Interpreter/OptionGroupOutputFile.h"
27 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
28 #include "lldb/Symbol/ClangNamespaceDecl.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/StackFrame.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 static OptionDefinition
36 g_option_table[] =
37 {
38     { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
39     { LLDB_OPT_SET_2, false, "binary"       ,'b', no_argument      , 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."},
40     { LLDB_OPT_SET_3, true , "view-as"      ,'t', required_argument, NULL, 0, eArgTypeNone          ,"The name of a type to view memory as."},
41     { LLDB_OPT_SET_4, false, "force"        ,'r', no_argument,       NULL, 0, eArgTypeNone          ,"Necessary if reading over 1024 bytes of memory."},
42 };
43 
44 
45 
46 class OptionGroupReadMemory : public OptionGroup
47 {
48 public:
49 
50     OptionGroupReadMemory () :
51         m_num_per_line (1,1),
52         m_output_as_binary (false),
53         m_view_as_type()
54     {
55     }
56 
57     virtual
58     ~OptionGroupReadMemory ()
59     {
60     }
61 
62 
63     virtual uint32_t
64     GetNumDefinitions ()
65     {
66         return sizeof (g_option_table) / sizeof (OptionDefinition);
67     }
68 
69     virtual const OptionDefinition*
70     GetDefinitions ()
71     {
72         return g_option_table;
73     }
74 
75     virtual Error
76     SetOptionValue (CommandInterpreter &interpreter,
77                     uint32_t option_idx,
78                     const char *option_arg)
79     {
80         Error error;
81         char short_option = (char) g_option_table[option_idx].short_option;
82 
83         switch (short_option)
84         {
85             case 'l':
86                 error = m_num_per_line.SetValueFromCString (option_arg);
87                 if (m_num_per_line.GetCurrentValue() == 0)
88                     error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
89                 break;
90 
91             case 'b':
92                 m_output_as_binary = true;
93                 break;
94 
95             case 't':
96                 error = m_view_as_type.SetValueFromCString (option_arg);
97                 break;
98 
99             case 'r':
100                 m_force = true;
101                 break;
102 
103             default:
104                 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
105                 break;
106         }
107         return error;
108     }
109 
110     virtual void
111     OptionParsingStarting (CommandInterpreter &interpreter)
112     {
113         m_num_per_line.Clear();
114         m_output_as_binary = false;
115         m_view_as_type.Clear();
116     }
117 
118     Error
119     FinalizeSettings (Target *target, OptionGroupFormat& format_options)
120     {
121         Error error;
122         OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
123         OptionValueUInt64 &count_value = format_options.GetCountValue();
124         const bool byte_size_option_set = byte_size_value.OptionWasSet();
125         const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
126         const bool count_option_set = format_options.GetCountValue().OptionWasSet();
127 
128         switch (format_options.GetFormat())
129         {
130             default:
131                 break;
132 
133             case eFormatBoolean:
134                 if (!byte_size_option_set)
135                     byte_size_value = 1;
136                 if (!num_per_line_option_set)
137                     m_num_per_line = 1;
138                 if (!count_option_set)
139                     format_options.GetCountValue() = 8;
140                 break;
141 
142             case eFormatCString:
143                 break;
144 
145             case eFormatInstruction:
146                 if (count_option_set)
147                     byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize() * format_options.GetCountValue().GetCurrentValue();
148                 m_num_per_line = 1;
149                 break;
150 
151             case eFormatAddressInfo:
152                 if (!byte_size_option_set)
153                     byte_size_value = target->GetArchitecture().GetAddressByteSize();
154                 m_num_per_line = 1;
155                 if (!count_option_set)
156                     format_options.GetCountValue() = 8;
157                 break;
158 
159             case eFormatPointer:
160                 byte_size_value = target->GetArchitecture().GetAddressByteSize();
161                 if (!num_per_line_option_set)
162                     m_num_per_line = 4;
163                 if (!count_option_set)
164                     format_options.GetCountValue() = 8;
165                 break;
166 
167             case eFormatBinary:
168             case eFormatFloat:
169             case eFormatOctal:
170             case eFormatDecimal:
171             case eFormatEnum:
172             case eFormatUnicode16:
173             case eFormatUnicode32:
174             case eFormatUnsigned:
175             case eFormatHexFloat:
176                 if (!byte_size_option_set)
177                     byte_size_value = 4;
178                 if (!num_per_line_option_set)
179                     m_num_per_line = 1;
180                 if (!count_option_set)
181                     format_options.GetCountValue() = 8;
182                 break;
183 
184             case eFormatBytes:
185             case eFormatBytesWithASCII:
186                 if (byte_size_option_set)
187                 {
188                     if (byte_size_value > 1)
189                         error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %llu\n"
190                                                         "\tconsider using a different display format or don't specify the byte size",
191                                                         byte_size_value.GetCurrentValue());
192                 }
193                 else
194                     byte_size_value = 1;
195                 if (!num_per_line_option_set)
196                     m_num_per_line = 16;
197                 if (!count_option_set)
198                     format_options.GetCountValue() = 32;
199                 break;
200             case eFormatCharArray:
201             case eFormatChar:
202             case eFormatCharPrintable:
203                 if (!byte_size_option_set)
204                     byte_size_value = 1;
205                 if (!num_per_line_option_set)
206                     m_num_per_line = 32;
207                 if (!count_option_set)
208                     format_options.GetCountValue() = 64;
209                 break;
210             case eFormatComplex:
211                 if (!byte_size_option_set)
212                     byte_size_value = 8;
213                 if (!num_per_line_option_set)
214                     m_num_per_line = 1;
215                 if (!count_option_set)
216                     format_options.GetCountValue() = 8;
217                 break;
218             case eFormatHex:
219                 if (!byte_size_option_set)
220                     byte_size_value = 4;
221                 if (!num_per_line_option_set)
222                 {
223                     switch (byte_size_value)
224                     {
225                         case 1:
226                         case 2:
227                             m_num_per_line = 8;
228                             break;
229                         case 4:
230                             m_num_per_line = 4;
231                             break;
232                         case 8:
233                             m_num_per_line = 2;
234                             break;
235                         default:
236                             m_num_per_line = 1;
237                             break;
238                     }
239                 }
240                 if (!count_option_set)
241                     count_value = 8;
242                 break;
243 
244             case eFormatVectorOfChar:
245             case eFormatVectorOfSInt8:
246             case eFormatVectorOfUInt8:
247             case eFormatVectorOfSInt16:
248             case eFormatVectorOfUInt16:
249             case eFormatVectorOfSInt32:
250             case eFormatVectorOfUInt32:
251             case eFormatVectorOfSInt64:
252             case eFormatVectorOfUInt64:
253             case eFormatVectorOfFloat32:
254             case eFormatVectorOfFloat64:
255             case eFormatVectorOfUInt128:
256                 if (!byte_size_option_set)
257                     byte_size_value = 128;
258                 if (!num_per_line_option_set)
259                     m_num_per_line = 1;
260                 if (!count_option_set)
261                     count_value = 4;
262                 break;
263         }
264         return error;
265     }
266 
267     bool
268     AnyOptionWasSet () const
269     {
270         return m_num_per_line.OptionWasSet() ||
271                m_output_as_binary ||
272                m_view_as_type.OptionWasSet();
273     }
274 
275     OptionValueUInt64 m_num_per_line;
276     bool m_output_as_binary;
277     OptionValueString m_view_as_type;
278     bool m_force;
279 };
280 
281 
282 
283 //----------------------------------------------------------------------
284 // Read memory from the inferior process
285 //----------------------------------------------------------------------
286 class CommandObjectMemoryRead : public CommandObjectParsed
287 {
288 public:
289 
290     CommandObjectMemoryRead (CommandInterpreter &interpreter) :
291         CommandObjectParsed (interpreter,
292                              "memory read",
293                              "Read from the memory of the process being debugged.",
294                              NULL,
295                              eFlagProcessMustBePaused),
296         m_option_group (interpreter),
297         m_format_options (eFormatBytesWithASCII, 1, 8),
298         m_memory_options (),
299         m_outfile_options (),
300         m_varobj_options(),
301         m_next_addr(LLDB_INVALID_ADDRESS),
302         m_prev_byte_size(0),
303         m_prev_format_options (eFormatBytesWithASCII, 1, 8),
304         m_prev_memory_options (),
305         m_prev_outfile_options (),
306         m_prev_varobj_options()
307     {
308         CommandArgumentEntry arg1;
309         CommandArgumentEntry arg2;
310         CommandArgumentData start_addr_arg;
311         CommandArgumentData end_addr_arg;
312 
313         // Define the first (and only) variant of this arg.
314         start_addr_arg.arg_type = eArgTypeStartAddress;
315         start_addr_arg.arg_repetition = eArgRepeatPlain;
316 
317         // There is only one variant this argument could be; put it into the argument entry.
318         arg1.push_back (start_addr_arg);
319 
320         // Define the first (and only) variant of this arg.
321         end_addr_arg.arg_type = eArgTypeEndAddress;
322         end_addr_arg.arg_repetition = eArgRepeatOptional;
323 
324         // There is only one variant this argument could be; put it into the argument entry.
325         arg2.push_back (end_addr_arg);
326 
327         // Push the data for the first argument into the m_arguments vector.
328         m_arguments.push_back (arg1);
329         m_arguments.push_back (arg2);
330 
331         // Add the "--format" and "--count" options to group 1 and 3
332         m_option_group.Append (&m_format_options,
333                                OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
334                                LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
335         m_option_group.Append (&m_format_options,
336                                OptionGroupFormat::OPTION_GROUP_GDB_FMT,
337                                LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
338         // Add the "--size" option to group 1 and 2
339         m_option_group.Append (&m_format_options,
340                                OptionGroupFormat::OPTION_GROUP_SIZE,
341                                LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
342         m_option_group.Append (&m_memory_options);
343         m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
344         m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
345         m_option_group.Finalize();
346     }
347 
348     virtual
349     ~CommandObjectMemoryRead ()
350     {
351     }
352 
353     Options *
354     GetOptions ()
355     {
356         return &m_option_group;
357     }
358 
359     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
360     {
361         return m_cmd_name.c_str();
362     }
363 
364 protected:
365     virtual bool
366     DoExecute (Args& command,
367              CommandReturnObject &result)
368     {
369         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
370         Target *target = exe_ctx.GetTargetPtr();
371         if (target == NULL)
372         {
373             result.AppendError("need at least a target to read memory");
374             result.SetStatus(eReturnStatusFailed);
375             return false;
376         }
377         const size_t argc = command.GetArgumentCount();
378 
379 
380         if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
381         {
382             result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
383             result.SetStatus(eReturnStatusFailed);
384             return false;
385         }
386 
387         ClangASTType clang_ast_type;
388         Error error;
389 
390         Format format = m_format_options.GetFormat();
391         const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
392         if (view_as_type_cstr && view_as_type_cstr[0])
393         {
394             // We are viewing memory as a type
395             SymbolContext sc;
396             const bool exact_match = false;
397             TypeList type_list;
398             uint32_t reference_count = 0;
399             uint32_t pointer_count = 0;
400             size_t idx;
401 
402 #define ALL_KEYWORDS        \
403     KEYWORD("const")        \
404     KEYWORD("volatile")     \
405     KEYWORD("restrict")     \
406     KEYWORD("struct")       \
407     KEYWORD("class")        \
408     KEYWORD("union")
409 
410 #define KEYWORD(s) s,
411             static const char *g_keywords[] =
412             {
413                 ALL_KEYWORDS
414             };
415 #undef KEYWORD
416 
417 #define KEYWORD(s) (sizeof(s) - 1),
418             static const int g_keyword_lengths[] =
419             {
420                 ALL_KEYWORDS
421             };
422 #undef KEYWORD
423 
424 #undef ALL_KEYWORDS
425 
426             static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
427             std::string type_str(view_as_type_cstr);
428 
429             // Remove all instances of g_keywords that are followed by spaces
430             for (size_t i = 0; i < g_num_keywords; ++i)
431             {
432                 const char *keyword = g_keywords[i];
433                 int keyword_len = g_keyword_lengths[i];
434 
435                 idx = 0;
436                 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
437                 {
438                     if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
439                     {
440                         type_str.erase(idx, keyword_len+1);
441                         idx = 0;
442                     }
443                     else
444                     {
445                         idx += keyword_len;
446                     }
447                 }
448             }
449             bool done = type_str.empty();
450             //
451             idx = type_str.find_first_not_of (" \t");
452             if (idx > 0 && idx != std::string::npos)
453                 type_str.erase (0, idx);
454             while (!done)
455             {
456                 // Strip trailing spaces
457                 if (type_str.empty())
458                     done = true;
459                 else
460                 {
461                     switch (type_str[type_str.size()-1])
462                     {
463                     case '*':
464                         ++pointer_count;
465                         // fall through...
466                     case ' ':
467                     case '\t':
468                         type_str.erase(type_str.size()-1);
469                         break;
470 
471                     case '&':
472                         if (reference_count == 0)
473                         {
474                             reference_count = 1;
475                             type_str.erase(type_str.size()-1);
476                         }
477                         else
478                         {
479                             result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
480                             result.SetStatus(eReturnStatusFailed);
481                             return false;
482                         }
483                         break;
484 
485                     default:
486                         done = true;
487                         break;
488                     }
489                 }
490             }
491 
492             ConstString lookup_type_name(type_str.c_str());
493             StackFrame *frame = exe_ctx.GetFramePtr();
494             if (frame)
495             {
496                 sc = frame->GetSymbolContext (eSymbolContextModule);
497                 if (sc.module_sp)
498                 {
499                     sc.module_sp->FindTypes (sc,
500                                              lookup_type_name,
501                                              exact_match,
502                                              1,
503                                              type_list);
504                 }
505             }
506             if (type_list.GetSize() == 0)
507             {
508                 target->GetImages().FindTypes (sc,
509                                                lookup_type_name,
510                                                exact_match,
511                                                1,
512                                                type_list);
513             }
514 
515             if (type_list.GetSize() == 0)
516             {
517                 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
518                                               lookup_type_name.GetCString(),
519                                               view_as_type_cstr);
520                 result.SetStatus(eReturnStatusFailed);
521                 return false;
522             }
523 
524             TypeSP type_sp (type_list.GetTypeAtIndex(0));
525             clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
526 
527             while (pointer_count > 0)
528             {
529                 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
530                 if (pointer_type)
531                     clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
532                 else
533                 {
534                     result.AppendError ("unable make a pointer type\n");
535                     result.SetStatus(eReturnStatusFailed);
536                     return false;
537                 }
538                 --pointer_count;
539             }
540 
541             m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
542 
543             if (m_format_options.GetByteSizeValue() == 0)
544             {
545                 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
546                                               view_as_type_cstr);
547                 result.SetStatus(eReturnStatusFailed);
548                 return false;
549             }
550 
551             if (!m_format_options.GetCountValue().OptionWasSet())
552                 m_format_options.GetCountValue() = 1;
553         }
554         else
555         {
556             error = m_memory_options.FinalizeSettings (target, m_format_options);
557         }
558 
559         // Look for invalid combinations of settings
560         if (error.Fail())
561         {
562             result.AppendErrorWithFormat("%s", error.AsCString());
563             result.SetStatus(eReturnStatusFailed);
564             return false;
565         }
566 
567         lldb::addr_t addr;
568         size_t total_byte_size = 0;
569         if (argc == 0)
570         {
571             // Use the last address and byte size and all options as they were
572             // if no options have been set
573             addr = m_next_addr;
574             total_byte_size = m_prev_byte_size;
575             if (!m_format_options.AnyOptionWasSet() &&
576                 !m_memory_options.AnyOptionWasSet() &&
577                 !m_outfile_options.AnyOptionWasSet() &&
578                 !m_varobj_options.AnyOptionWasSet())
579             {
580                 m_format_options = m_prev_format_options;
581                 m_memory_options = m_prev_memory_options;
582                 m_outfile_options = m_prev_outfile_options;
583                 m_varobj_options = m_prev_varobj_options;
584             }
585         }
586 
587         size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
588         const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
589         const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
590 
591         if (total_byte_size == 0)
592         {
593             total_byte_size = item_count * item_byte_size;
594             if (total_byte_size == 0)
595                 total_byte_size = 32;
596         }
597 
598         if (argc > 0)
599             addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
600 
601         if (addr == LLDB_INVALID_ADDRESS)
602         {
603             result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
604             result.SetStatus(eReturnStatusFailed);
605             return false;
606         }
607 
608         if (argc == 2)
609         {
610             lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
611             if (end_addr == LLDB_INVALID_ADDRESS)
612             {
613                 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
614                 result.SetStatus(eReturnStatusFailed);
615                 return false;
616             }
617             else if (end_addr <= addr)
618             {
619                 result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
620                 result.SetStatus(eReturnStatusFailed);
621                 return false;
622             }
623             else if (m_format_options.GetCountValue().OptionWasSet())
624             {
625                 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count);
626                 result.SetStatus(eReturnStatusFailed);
627                 return false;
628             }
629 
630             total_byte_size = end_addr - addr;
631             item_count = total_byte_size / item_byte_size;
632         }
633 
634         if (total_byte_size > 1024 && !m_memory_options.m_force)
635         {
636             result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
637             result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
638             return false;
639         }
640 
641         DataBufferSP data_sp;
642         size_t bytes_read = 0;
643         if (!clang_ast_type.GetOpaqueQualType())
644         {
645             data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
646             Address address(addr, NULL);
647             bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
648             if (bytes_read == 0)
649             {
650                 const char *error_cstr = error.AsCString();
651                 if (error_cstr && error_cstr[0])
652                 {
653                     result.AppendError(error_cstr);
654                 }
655                 else
656                 {
657                     result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr);
658                 }
659                 result.SetStatus(eReturnStatusFailed);
660                 return false;
661             }
662 
663             if (bytes_read < total_byte_size)
664                 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
665             else
666             {
667                 m_next_addr = addr + bytes_read;
668                 m_prev_byte_size = bytes_read;
669                 m_prev_format_options = m_format_options;
670                 m_prev_memory_options = m_memory_options;
671                 m_prev_outfile_options = m_outfile_options;
672                 m_prev_varobj_options = m_varobj_options;
673             }
674         }
675 
676         StreamFile outfile_stream;
677         Stream *output_stream = NULL;
678         const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
679         if (outfile_spec)
680         {
681             char path[PATH_MAX];
682             outfile_spec.GetPath (path, sizeof(path));
683 
684             uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
685             const bool append = m_outfile_options.GetAppend().GetCurrentValue();
686             if (append)
687                 open_options |= File::eOpenOptionAppend;
688 
689             if (outfile_stream.GetFile ().Open (path, open_options).Success())
690             {
691                 if (m_memory_options.m_output_as_binary)
692                 {
693                     int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
694                     if (bytes_written > 0)
695                     {
696                         result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
697                                                          bytes_written,
698                                                          append ? "appended" : "written",
699                                                          path);
700                         return true;
701                     }
702                     else
703                     {
704                         result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
705                         result.SetStatus(eReturnStatusFailed);
706                         return false;
707                     }
708                 }
709                 else
710                 {
711                     // We are going to write ASCII to the file just point the
712                     // output_stream to our outfile_stream...
713                     output_stream = &outfile_stream;
714                 }
715             }
716             else
717             {
718                 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
719                 result.SetStatus(eReturnStatusFailed);
720                 return false;
721             }
722         }
723         else
724         {
725             output_stream = &result.GetOutputStream();
726         }
727 
728 
729         ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
730         if (clang_ast_type.GetOpaqueQualType())
731         {
732             for (uint32_t i = 0; i<item_count; ++i)
733             {
734                 addr_t item_addr = addr + (i * item_byte_size);
735                 Address address (item_addr);
736                 StreamString name_strm;
737                 name_strm.Printf ("0x%llx", item_addr);
738                 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
739                                                                     name_strm.GetString().c_str(),
740                                                                     address,
741                                                                     clang_ast_type));
742                 if (valobj_sp)
743                 {
744                     if (format != eFormatDefault)
745                         valobj_sp->SetFormat (format);
746 
747                     bool scope_already_checked = true;
748 
749                     ValueObject::DumpValueObjectOptions options;
750                     options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
751                     .SetMaximumDepth(m_varobj_options.max_depth)
752                     .SetShowLocation(m_varobj_options.show_location)
753                     .SetShowTypes(m_varobj_options.show_types)
754                     .SetUseObjectiveC(m_varobj_options.use_objc)
755                     .SetScopeChecked(scope_already_checked)
756                     .SetFlatOutput(m_varobj_options.flat_output)
757                     .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
758                     .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
759                     .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
760                     .SetFormat(format)
761                     .SetSummary();
762                     ValueObject::DumpValueObject (*output_stream,
763                                                   valobj_sp.get(),
764                                                   options);
765                 }
766                 else
767                 {
768                     result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
769                                                   view_as_type_cstr,
770                                                   name_strm.GetString().c_str());
771                     result.SetStatus(eReturnStatusFailed);
772                     return false;
773                 }
774             }
775             return true;
776         }
777 
778         result.SetStatus(eReturnStatusSuccessFinishResult);
779         DataExtractor data (data_sp,
780                             target->GetArchitecture().GetByteOrder(),
781                             target->GetArchitecture().GetAddressByteSize());
782 
783 
784         assert (output_stream);
785         uint32_t bytes_dumped = data.Dump (output_stream,
786                                            0,
787                                            m_format_options.GetFormat(),
788                                            item_byte_size,
789                                            item_count,
790                                            num_per_line,
791                                            addr,
792                                            0,
793                                            0,
794                                            exe_scope);
795         m_next_addr = addr + bytes_dumped;
796         output_stream->EOL();
797         return true;
798     }
799 
800     OptionGroupOptions m_option_group;
801     OptionGroupFormat m_format_options;
802     OptionGroupReadMemory m_memory_options;
803     OptionGroupOutputFile m_outfile_options;
804     OptionGroupValueObjectDisplay m_varobj_options;
805     lldb::addr_t m_next_addr;
806     lldb::addr_t m_prev_byte_size;
807     OptionGroupFormat m_prev_format_options;
808     OptionGroupReadMemory m_prev_memory_options;
809     OptionGroupOutputFile m_prev_outfile_options;
810     OptionGroupValueObjectDisplay m_prev_varobj_options;
811 };
812 
813 
814 OptionDefinition
815 g_memory_write_option_table[] =
816 {
817 { LLDB_OPT_SET_1, true,  "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
818 { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset,   "Start writng bytes from an offset within the input file."},
819 };
820 
821 
822 //----------------------------------------------------------------------
823 // Write memory to the inferior process
824 //----------------------------------------------------------------------
825 class CommandObjectMemoryWrite : public CommandObjectParsed
826 {
827 public:
828 
829     class OptionGroupWriteMemory : public OptionGroup
830     {
831     public:
832         OptionGroupWriteMemory () :
833             OptionGroup()
834         {
835         }
836 
837         virtual
838         ~OptionGroupWriteMemory ()
839         {
840         }
841 
842         virtual uint32_t
843         GetNumDefinitions ()
844         {
845             return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
846         }
847 
848         virtual const OptionDefinition*
849         GetDefinitions ()
850         {
851             return g_memory_write_option_table;
852         }
853 
854         virtual Error
855         SetOptionValue (CommandInterpreter &interpreter,
856                         uint32_t option_idx,
857                         const char *option_arg)
858         {
859             Error error;
860             char short_option = (char) g_memory_write_option_table[option_idx].short_option;
861 
862             switch (short_option)
863             {
864                 case 'i':
865                     m_infile.SetFile (option_arg, true);
866                     if (!m_infile.Exists())
867                     {
868                         m_infile.Clear();
869                         error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
870                     }
871                     break;
872 
873                 case 'o':
874                     {
875                         bool success;
876                         m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
877                         if (!success)
878                         {
879                             error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
880                         }
881                     }
882                     break;
883 
884                 default:
885                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
886                     break;
887             }
888             return error;
889         }
890 
891         virtual void
892         OptionParsingStarting (CommandInterpreter &interpreter)
893         {
894             m_infile.Clear();
895             m_infile_offset = 0;
896         }
897 
898         FileSpec m_infile;
899         off_t m_infile_offset;
900     };
901 
902     CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
903         CommandObjectParsed (interpreter,
904                              "memory write",
905                              "Write to the memory of the process being debugged.",
906                              NULL,
907                              eFlagProcessMustBeLaunched),
908         m_option_group (interpreter),
909         m_format_options (eFormatBytes, 1, UINT64_MAX),
910         m_memory_options ()
911     {
912         CommandArgumentEntry arg1;
913         CommandArgumentEntry arg2;
914         CommandArgumentData addr_arg;
915         CommandArgumentData value_arg;
916 
917         // Define the first (and only) variant of this arg.
918         addr_arg.arg_type = eArgTypeAddress;
919         addr_arg.arg_repetition = eArgRepeatPlain;
920 
921         // There is only one variant this argument could be; put it into the argument entry.
922         arg1.push_back (addr_arg);
923 
924         // Define the first (and only) variant of this arg.
925         value_arg.arg_type = eArgTypeValue;
926         value_arg.arg_repetition = eArgRepeatPlus;
927 
928         // There is only one variant this argument could be; put it into the argument entry.
929         arg2.push_back (value_arg);
930 
931         // Push the data for the first argument into the m_arguments vector.
932         m_arguments.push_back (arg1);
933         m_arguments.push_back (arg2);
934 
935         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
936         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE  , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
937         m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
938         m_option_group.Finalize();
939 
940     }
941 
942     virtual
943     ~CommandObjectMemoryWrite ()
944     {
945     }
946 
947     Options *
948     GetOptions ()
949     {
950         return &m_option_group;
951     }
952 
953     bool
954     UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
955     {
956         if (total_byte_size > 8)
957             return false;
958 
959         if (total_byte_size == 8)
960             return true;
961 
962         const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
963         return uval64 <= max;
964     }
965 
966     bool
967     SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
968     {
969         if (total_byte_size > 8)
970             return false;
971 
972         if (total_byte_size == 8)
973             return true;
974 
975         const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
976         const int64_t min = ~(max);
977         return min <= sval64 && sval64 <= max;
978     }
979 
980 protected:
981     virtual bool
982     DoExecute (Args& command, CommandReturnObject &result)
983     {
984         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
985         if (process == NULL)
986         {
987             result.AppendError("need a process to read memory");
988             result.SetStatus(eReturnStatusFailed);
989             return false;
990         }
991 
992         const size_t argc = command.GetArgumentCount();
993 
994         if (m_memory_options.m_infile)
995         {
996             if (argc < 1)
997             {
998                 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
999                 result.SetStatus(eReturnStatusFailed);
1000                 return false;
1001             }
1002         }
1003         else if (argc < 2)
1004         {
1005             result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
1006             result.SetStatus(eReturnStatusFailed);
1007             return false;
1008         }
1009 
1010         StreamString buffer (Stream::eBinary,
1011                              process->GetTarget().GetArchitecture().GetAddressByteSize(),
1012                              process->GetTarget().GetArchitecture().GetByteOrder());
1013 
1014         OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1015         size_t item_byte_size = byte_size_value.GetCurrentValue();
1016 
1017         lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
1018 
1019         if (addr == LLDB_INVALID_ADDRESS)
1020         {
1021             result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
1022             result.SetStatus(eReturnStatusFailed);
1023             return false;
1024         }
1025 
1026         if (m_memory_options.m_infile)
1027         {
1028             size_t length = SIZE_MAX;
1029             if (item_byte_size > 0)
1030                 length = item_byte_size;
1031             lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
1032             if (data_sp)
1033             {
1034                 length = data_sp->GetByteSize();
1035                 if (length > 0)
1036                 {
1037                     Error error;
1038                     size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1039 
1040                     if (bytes_written == length)
1041                     {
1042                         // All bytes written
1043                         result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
1044                         result.SetStatus(eReturnStatusSuccessFinishResult);
1045                     }
1046                     else if (bytes_written > 0)
1047                     {
1048                         // Some byte written
1049                         result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
1050                         result.SetStatus(eReturnStatusSuccessFinishResult);
1051                     }
1052                     else
1053                     {
1054                         result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1055                         result.SetStatus(eReturnStatusFailed);
1056                     }
1057                 }
1058             }
1059             else
1060             {
1061                 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1062                 result.SetStatus(eReturnStatusFailed);
1063             }
1064             return result.Succeeded();
1065         }
1066         else if (item_byte_size == 0)
1067         {
1068             if (m_format_options.GetFormat() == eFormatPointer)
1069                 item_byte_size = buffer.GetAddressByteSize();
1070             else
1071                 item_byte_size = 1;
1072         }
1073 
1074         command.Shift(); // shift off the address argument
1075         uint64_t uval64;
1076         int64_t sval64;
1077         bool success = false;
1078         const uint32_t num_value_args = command.GetArgumentCount();
1079         uint32_t i;
1080         for (i=0; i<num_value_args; ++i)
1081         {
1082             const char *value_str = command.GetArgumentAtIndex(i);
1083 
1084             switch (m_format_options.GetFormat())
1085             {
1086             case kNumFormats:
1087             case eFormatFloat:  // TODO: add support for floats soon
1088             case eFormatCharPrintable:
1089             case eFormatBytesWithASCII:
1090             case eFormatComplex:
1091             case eFormatEnum:
1092             case eFormatUnicode16:
1093             case eFormatUnicode32:
1094             case eFormatVectorOfChar:
1095             case eFormatVectorOfSInt8:
1096             case eFormatVectorOfUInt8:
1097             case eFormatVectorOfSInt16:
1098             case eFormatVectorOfUInt16:
1099             case eFormatVectorOfSInt32:
1100             case eFormatVectorOfUInt32:
1101             case eFormatVectorOfSInt64:
1102             case eFormatVectorOfUInt64:
1103             case eFormatVectorOfFloat32:
1104             case eFormatVectorOfFloat64:
1105             case eFormatVectorOfUInt128:
1106             case eFormatOSType:
1107             case eFormatComplexInteger:
1108             case eFormatAddressInfo:
1109             case eFormatHexFloat:
1110             case eFormatInstruction:
1111                 result.AppendError("unsupported format for writing memory");
1112                 result.SetStatus(eReturnStatusFailed);
1113                 return false;
1114 
1115             case eFormatDefault:
1116             case eFormatBytes:
1117             case eFormatHex:
1118             case eFormatPointer:
1119 
1120                 // Decode hex bytes
1121                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1122                 if (!success)
1123                 {
1124                     result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1125                     result.SetStatus(eReturnStatusFailed);
1126                     return false;
1127                 }
1128                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1129                 {
1130                     result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1131                     result.SetStatus(eReturnStatusFailed);
1132                     return false;
1133                 }
1134                 buffer.PutMaxHex64 (uval64, item_byte_size);
1135                 break;
1136 
1137             case eFormatBoolean:
1138                 uval64 = Args::StringToBoolean(value_str, false, &success);
1139                 if (!success)
1140                 {
1141                     result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1142                     result.SetStatus(eReturnStatusFailed);
1143                     return false;
1144                 }
1145                 buffer.PutMaxHex64 (uval64, item_byte_size);
1146                 break;
1147 
1148             case eFormatBinary:
1149                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1150                 if (!success)
1151                 {
1152                     result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1153                     result.SetStatus(eReturnStatusFailed);
1154                     return false;
1155                 }
1156                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1157                 {
1158                     result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1159                     result.SetStatus(eReturnStatusFailed);
1160                     return false;
1161                 }
1162                 buffer.PutMaxHex64 (uval64, item_byte_size);
1163                 break;
1164 
1165             case eFormatCharArray:
1166             case eFormatChar:
1167             case eFormatCString:
1168                 if (value_str[0])
1169                 {
1170                     size_t len = strlen (value_str);
1171                     // Include the NULL for C strings...
1172                     if (m_format_options.GetFormat() == eFormatCString)
1173                         ++len;
1174                     Error error;
1175                     if (process->WriteMemory (addr, value_str, len, error) == len)
1176                     {
1177                         addr += len;
1178                     }
1179                     else
1180                     {
1181                         result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1182                         result.SetStatus(eReturnStatusFailed);
1183                         return false;
1184                     }
1185                 }
1186                 break;
1187 
1188             case eFormatDecimal:
1189                 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1190                 if (!success)
1191                 {
1192                     result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1193                     result.SetStatus(eReturnStatusFailed);
1194                     return false;
1195                 }
1196                 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1197                 {
1198                     result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
1199                     result.SetStatus(eReturnStatusFailed);
1200                     return false;
1201                 }
1202                 buffer.PutMaxHex64 (sval64, item_byte_size);
1203                 break;
1204 
1205             case eFormatUnsigned:
1206                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1207                 if (!success)
1208                 {
1209                     result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1210                     result.SetStatus(eReturnStatusFailed);
1211                     return false;
1212                 }
1213                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1214                 {
1215                     result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1216                     result.SetStatus(eReturnStatusFailed);
1217                     return false;
1218                 }
1219                 buffer.PutMaxHex64 (uval64, item_byte_size);
1220                 break;
1221 
1222             case eFormatOctal:
1223                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1224                 if (!success)
1225                 {
1226                     result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1227                     result.SetStatus(eReturnStatusFailed);
1228                     return false;
1229                 }
1230                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1231                 {
1232                     result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1233                     result.SetStatus(eReturnStatusFailed);
1234                     return false;
1235                 }
1236                 buffer.PutMaxHex64 (uval64, item_byte_size);
1237                 break;
1238             }
1239         }
1240 
1241         if (!buffer.GetString().empty())
1242         {
1243             Error error;
1244             if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
1245                 return true;
1246             else
1247             {
1248                 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1249                 result.SetStatus(eReturnStatusFailed);
1250                 return false;
1251             }
1252         }
1253         return true;
1254     }
1255 
1256     OptionGroupOptions m_option_group;
1257     OptionGroupFormat m_format_options;
1258     OptionGroupWriteMemory m_memory_options;
1259 };
1260 
1261 
1262 //-------------------------------------------------------------------------
1263 // CommandObjectMemory
1264 //-------------------------------------------------------------------------
1265 
1266 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
1267     CommandObjectMultiword (interpreter,
1268                             "memory",
1269                             "A set of commands for operating on memory.",
1270                             "memory <subcommand> [<subcommand-options>]")
1271 {
1272     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1273     LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
1274 }
1275 
1276 CommandObjectMemory::~CommandObjectMemory ()
1277 {
1278 }
1279