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