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 CommandObject
287 {
288 public:
289 
290     CommandObjectMemoryRead (CommandInterpreter &interpreter) :
291         CommandObject (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     virtual bool
365     Execute (Args& command,
366              CommandReturnObject &result)
367     {
368         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
369         Target *target = exe_ctx.GetTargetPtr();
370         if (target == NULL)
371         {
372             result.AppendError("need at least a target to read memory");
373             result.SetStatus(eReturnStatusFailed);
374             return false;
375         }
376         const size_t argc = command.GetArgumentCount();
377 
378 
379         if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
380         {
381             result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
382             result.SetStatus(eReturnStatusFailed);
383             return false;
384         }
385 
386         ClangASTType clang_ast_type;
387         Error error;
388 
389         Format format = m_format_options.GetFormat();
390         const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
391         if (view_as_type_cstr && view_as_type_cstr[0])
392         {
393             // We are viewing memory as a type
394             SymbolContext sc;
395             const bool exact_match = false;
396             TypeList type_list;
397             uint32_t reference_count = 0;
398             uint32_t pointer_count = 0;
399             size_t idx;
400             static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
401             static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
402             std::string type_str(view_as_type_cstr);
403 
404             // Remove all instances of g_keywords that are followed by spaces
405             for (size_t i = 0; i < g_num_keywords; ++i)
406             {
407                 const char *keyword = g_keywords[i];
408                 int keyword_len = ::strlen (keyword);
409                 while ((idx = type_str.find (keyword)) != std::string::npos)
410                 {
411                     if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
412                         type_str.erase(idx, keyword_len+1);
413                 }
414             }
415             bool done = type_str.empty();
416             //
417             idx = type_str.find_first_not_of (" \t");
418             if (idx > 0 && idx != std::string::npos)
419                 type_str.erase (0, idx);
420             while (!done)
421             {
422                 // Strip trailing spaces
423                 if (type_str.empty())
424                     done = true;
425                 else
426                 {
427                     switch (type_str[type_str.size()-1])
428                     {
429                     case '*':
430                         ++pointer_count;
431                         // fall through...
432                     case ' ':
433                     case '\t':
434                         type_str.erase(type_str.size()-1);
435                         break;
436 
437                     case '&':
438                         if (reference_count == 0)
439                         {
440                             reference_count = 1;
441                             type_str.erase(type_str.size()-1);
442                         }
443                         else
444                         {
445                             result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
446                             result.SetStatus(eReturnStatusFailed);
447                             return false;
448                         }
449                         break;
450 
451                     default:
452                         done = true;
453                         break;
454                     }
455                 }
456             }
457 
458             ConstString lookup_type_name(type_str.c_str());
459             StackFrame *frame = exe_ctx.GetFramePtr();
460             if (frame)
461             {
462                 sc = frame->GetSymbolContext (eSymbolContextModule);
463                 if (sc.module_sp)
464                 {
465                     sc.module_sp->FindTypes (sc,
466                                              lookup_type_name,
467                                              exact_match,
468                                              1,
469                                              type_list);
470                 }
471             }
472             if (type_list.GetSize() == 0)
473             {
474                 target->GetImages().FindTypes (sc,
475                                                lookup_type_name,
476                                                exact_match,
477                                                1,
478                                                type_list);
479             }
480 
481             if (type_list.GetSize() == 0)
482             {
483                 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
484                                               lookup_type_name.GetCString(),
485                                               view_as_type_cstr);
486                 result.SetStatus(eReturnStatusFailed);
487                 return false;
488             }
489 
490             TypeSP type_sp (type_list.GetTypeAtIndex(0));
491             clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
492 
493             while (pointer_count > 0)
494             {
495                 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
496                 if (pointer_type)
497                     clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
498                 else
499                 {
500                     result.AppendError ("unable make a pointer type\n");
501                     result.SetStatus(eReturnStatusFailed);
502                     return false;
503                 }
504                 --pointer_count;
505             }
506 
507             m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
508 
509             if (m_format_options.GetByteSizeValue() == 0)
510             {
511                 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
512                                               view_as_type_cstr);
513                 result.SetStatus(eReturnStatusFailed);
514                 return false;
515             }
516 
517             if (!m_format_options.GetCountValue().OptionWasSet())
518                 m_format_options.GetCountValue() = 1;
519         }
520         else
521         {
522             error = m_memory_options.FinalizeSettings (target, m_format_options);
523         }
524 
525         // Look for invalid combinations of settings
526         if (error.Fail())
527         {
528             result.AppendErrorWithFormat("%s", error.AsCString());
529             result.SetStatus(eReturnStatusFailed);
530             return false;
531         }
532 
533         lldb::addr_t addr;
534         size_t total_byte_size = 0;
535         if (argc == 0)
536         {
537             // Use the last address and byte size and all options as they were
538             // if no options have been set
539             addr = m_next_addr;
540             total_byte_size = m_prev_byte_size;
541             if (!m_format_options.AnyOptionWasSet() &&
542                 !m_memory_options.AnyOptionWasSet() &&
543                 !m_outfile_options.AnyOptionWasSet() &&
544                 !m_varobj_options.AnyOptionWasSet())
545             {
546                 m_format_options = m_prev_format_options;
547                 m_memory_options = m_prev_memory_options;
548                 m_outfile_options = m_prev_outfile_options;
549                 m_varobj_options = m_prev_varobj_options;
550             }
551         }
552 
553         size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
554         const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
555         const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
556 
557         if (total_byte_size == 0)
558         {
559             total_byte_size = item_count * item_byte_size;
560             if (total_byte_size == 0)
561                 total_byte_size = 32;
562         }
563 
564         if (argc > 0)
565             addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
566 
567         if (addr == LLDB_INVALID_ADDRESS)
568         {
569             result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
570             result.SetStatus(eReturnStatusFailed);
571             return false;
572         }
573 
574         if (argc == 2)
575         {
576             lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
577             if (end_addr == LLDB_INVALID_ADDRESS)
578             {
579                 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
580                 result.SetStatus(eReturnStatusFailed);
581                 return false;
582             }
583             else if (end_addr <= addr)
584             {
585                 result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
586                 result.SetStatus(eReturnStatusFailed);
587                 return false;
588             }
589             else if (m_format_options.GetCountValue().OptionWasSet())
590             {
591                 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count);
592                 result.SetStatus(eReturnStatusFailed);
593                 return false;
594             }
595 
596             total_byte_size = end_addr - addr;
597             item_count = total_byte_size / item_byte_size;
598         }
599 
600         if (total_byte_size > 1024 && !m_memory_options.m_force)
601         {
602             result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
603             result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
604             return false;
605         }
606 
607         DataBufferSP data_sp;
608         size_t bytes_read = 0;
609         if (!clang_ast_type.GetOpaqueQualType())
610         {
611             data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
612             Address address(addr, NULL);
613             bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
614             if (bytes_read == 0)
615             {
616                 const char *error_cstr = error.AsCString();
617                 if (error_cstr && error_cstr[0])
618                 {
619                     result.AppendError(error_cstr);
620                 }
621                 else
622                 {
623                     result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr);
624                 }
625                 result.SetStatus(eReturnStatusFailed);
626                 return false;
627             }
628 
629             if (bytes_read < total_byte_size)
630                 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
631             else
632             {
633                 m_next_addr = addr + bytes_read;
634                 m_prev_byte_size = bytes_read;
635                 m_prev_format_options = m_format_options;
636                 m_prev_memory_options = m_memory_options;
637                 m_prev_outfile_options = m_outfile_options;
638                 m_prev_varobj_options = m_varobj_options;
639             }
640         }
641 
642         StreamFile outfile_stream;
643         Stream *output_stream = NULL;
644         const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
645         if (outfile_spec)
646         {
647             char path[PATH_MAX];
648             outfile_spec.GetPath (path, sizeof(path));
649 
650             uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
651             const bool append = m_outfile_options.GetAppend().GetCurrentValue();
652             if (append)
653                 open_options |= File::eOpenOptionAppend;
654 
655             if (outfile_stream.GetFile ().Open (path, open_options).Success())
656             {
657                 if (m_memory_options.m_output_as_binary)
658                 {
659                     int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
660                     if (bytes_written > 0)
661                     {
662                         result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
663                                                          bytes_written,
664                                                          append ? "appended" : "written",
665                                                          path);
666                         return true;
667                     }
668                     else
669                     {
670                         result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
671                         result.SetStatus(eReturnStatusFailed);
672                         return false;
673                     }
674                 }
675                 else
676                 {
677                     // We are going to write ASCII to the file just point the
678                     // output_stream to our outfile_stream...
679                     output_stream = &outfile_stream;
680                 }
681             }
682             else
683             {
684                 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
685                 result.SetStatus(eReturnStatusFailed);
686                 return false;
687             }
688         }
689         else
690         {
691             output_stream = &result.GetOutputStream();
692         }
693 
694 
695         ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
696         if (clang_ast_type.GetOpaqueQualType())
697         {
698             for (uint32_t i = 0; i<item_count; ++i)
699             {
700                 addr_t item_addr = addr + (i * item_byte_size);
701                 Address address (item_addr);
702                 StreamString name_strm;
703                 name_strm.Printf ("0x%llx", item_addr);
704                 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
705                                                                     name_strm.GetString().c_str(),
706                                                                     address,
707                                                                     clang_ast_type));
708                 if (valobj_sp)
709                 {
710                     if (format != eFormatDefault)
711                         valobj_sp->SetFormat (format);
712 
713                     bool scope_already_checked = true;
714 
715                     ValueObject::DumpValueObjectOptions options;
716                     options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
717                     .SetMaximumDepth(m_varobj_options.max_depth)
718                     .SetShowLocation(m_varobj_options.show_location)
719                     .SetShowTypes(m_varobj_options.show_types)
720                     .SetUseObjectiveC(m_varobj_options.use_objc)
721                     .SetScopeChecked(scope_already_checked)
722                     .SetFlatOutput(m_varobj_options.flat_output)
723                     .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
724                     .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
725                     .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
726                     .SetFormat(format)
727                     .SetSummary();
728                     ValueObject::DumpValueObject (*output_stream,
729                                                   valobj_sp.get(),
730                                                   options);
731                 }
732                 else
733                 {
734                     result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
735                                                   view_as_type_cstr,
736                                                   name_strm.GetString().c_str());
737                     result.SetStatus(eReturnStatusFailed);
738                     return false;
739                 }
740             }
741             return true;
742         }
743 
744         result.SetStatus(eReturnStatusSuccessFinishResult);
745         DataExtractor data (data_sp,
746                             target->GetArchitecture().GetByteOrder(),
747                             target->GetArchitecture().GetAddressByteSize());
748 
749 
750         assert (output_stream);
751         uint32_t bytes_dumped = data.Dump (output_stream,
752                                            0,
753                                            m_format_options.GetFormat(),
754                                            item_byte_size,
755                                            item_count,
756                                            num_per_line,
757                                            addr,
758                                            0,
759                                            0,
760                                            exe_scope);
761         m_next_addr = addr + bytes_dumped;
762         output_stream->EOL();
763         return true;
764     }
765 
766 protected:
767     OptionGroupOptions m_option_group;
768     OptionGroupFormat m_format_options;
769     OptionGroupReadMemory m_memory_options;
770     OptionGroupOutputFile m_outfile_options;
771     OptionGroupValueObjectDisplay m_varobj_options;
772     lldb::addr_t m_next_addr;
773     lldb::addr_t m_prev_byte_size;
774     OptionGroupFormat m_prev_format_options;
775     OptionGroupReadMemory m_prev_memory_options;
776     OptionGroupOutputFile m_prev_outfile_options;
777     OptionGroupValueObjectDisplay m_prev_varobj_options;
778 };
779 
780 
781 OptionDefinition
782 g_memory_write_option_table[] =
783 {
784 { LLDB_OPT_SET_1, true,  "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
785 { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset,   "Start writng bytes from an offset within the input file."},
786 };
787 
788 
789 //----------------------------------------------------------------------
790 // Write memory to the inferior process
791 //----------------------------------------------------------------------
792 class CommandObjectMemoryWrite : public CommandObject
793 {
794 public:
795 
796     class OptionGroupWriteMemory : public OptionGroup
797     {
798     public:
799         OptionGroupWriteMemory () :
800             OptionGroup()
801         {
802         }
803 
804         virtual
805         ~OptionGroupWriteMemory ()
806         {
807         }
808 
809         virtual uint32_t
810         GetNumDefinitions ()
811         {
812             return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
813         }
814 
815         virtual const OptionDefinition*
816         GetDefinitions ()
817         {
818             return g_memory_write_option_table;
819         }
820 
821         virtual Error
822         SetOptionValue (CommandInterpreter &interpreter,
823                         uint32_t option_idx,
824                         const char *option_arg)
825         {
826             Error error;
827             char short_option = (char) g_memory_write_option_table[option_idx].short_option;
828 
829             switch (short_option)
830             {
831                 case 'i':
832                     m_infile.SetFile (option_arg, true);
833                     if (!m_infile.Exists())
834                     {
835                         m_infile.Clear();
836                         error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
837                     }
838                     break;
839 
840                 case 'o':
841                     {
842                         bool success;
843                         m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
844                         if (!success)
845                         {
846                             error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
847                         }
848                     }
849                     break;
850 
851                 default:
852                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
853                     break;
854             }
855             return error;
856         }
857 
858         virtual void
859         OptionParsingStarting (CommandInterpreter &interpreter)
860         {
861             m_infile.Clear();
862             m_infile_offset = 0;
863         }
864 
865         FileSpec m_infile;
866         off_t m_infile_offset;
867     };
868 
869     CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
870         CommandObject (interpreter,
871                        "memory write",
872                        "Write to the memory of the process being debugged.",
873                        //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
874                        NULL,
875                        eFlagProcessMustBeLaunched),
876         m_option_group (interpreter),
877         m_format_options (eFormatBytes, 1, UINT64_MAX),
878         m_memory_options ()
879     {
880         CommandArgumentEntry arg1;
881         CommandArgumentEntry arg2;
882         CommandArgumentData addr_arg;
883         CommandArgumentData value_arg;
884 
885         // Define the first (and only) variant of this arg.
886         addr_arg.arg_type = eArgTypeAddress;
887         addr_arg.arg_repetition = eArgRepeatPlain;
888 
889         // There is only one variant this argument could be; put it into the argument entry.
890         arg1.push_back (addr_arg);
891 
892         // Define the first (and only) variant of this arg.
893         value_arg.arg_type = eArgTypeValue;
894         value_arg.arg_repetition = eArgRepeatPlus;
895 
896         // There is only one variant this argument could be; put it into the argument entry.
897         arg2.push_back (value_arg);
898 
899         // Push the data for the first argument into the m_arguments vector.
900         m_arguments.push_back (arg1);
901         m_arguments.push_back (arg2);
902 
903         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
904         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE  , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
905         m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
906         m_option_group.Finalize();
907 
908     }
909 
910     virtual
911     ~CommandObjectMemoryWrite ()
912     {
913     }
914 
915     Options *
916     GetOptions ()
917     {
918         return &m_option_group;
919     }
920 
921     bool
922     UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
923     {
924         if (total_byte_size > 8)
925             return false;
926 
927         if (total_byte_size == 8)
928             return true;
929 
930         const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
931         return uval64 <= max;
932     }
933 
934     bool
935     SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
936     {
937         if (total_byte_size > 8)
938             return false;
939 
940         if (total_byte_size == 8)
941             return true;
942 
943         const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
944         const int64_t min = ~(max);
945         return min <= sval64 && sval64 <= max;
946     }
947 
948     virtual bool
949     Execute (Args& command,
950              CommandReturnObject &result)
951     {
952         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
953         if (process == NULL)
954         {
955             result.AppendError("need a process to read memory");
956             result.SetStatus(eReturnStatusFailed);
957             return false;
958         }
959 
960         const size_t argc = command.GetArgumentCount();
961 
962         if (m_memory_options.m_infile)
963         {
964             if (argc < 1)
965             {
966                 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
967                 result.SetStatus(eReturnStatusFailed);
968                 return false;
969             }
970         }
971         else if (argc < 2)
972         {
973             result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
974             result.SetStatus(eReturnStatusFailed);
975             return false;
976         }
977 
978         StreamString buffer (Stream::eBinary,
979                              process->GetTarget().GetArchitecture().GetAddressByteSize(),
980                              process->GetTarget().GetArchitecture().GetByteOrder());
981 
982         OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
983         size_t item_byte_size = byte_size_value.GetCurrentValue();
984 
985         lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
986 
987         if (addr == LLDB_INVALID_ADDRESS)
988         {
989             result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
990             result.SetStatus(eReturnStatusFailed);
991             return false;
992         }
993 
994         if (m_memory_options.m_infile)
995         {
996             size_t length = SIZE_MAX;
997             if (item_byte_size > 0)
998                 length = item_byte_size;
999             lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
1000             if (data_sp)
1001             {
1002                 length = data_sp->GetByteSize();
1003                 if (length > 0)
1004                 {
1005                     Error error;
1006                     size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1007 
1008                     if (bytes_written == length)
1009                     {
1010                         // All bytes written
1011                         result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
1012                         result.SetStatus(eReturnStatusSuccessFinishResult);
1013                     }
1014                     else if (bytes_written > 0)
1015                     {
1016                         // Some byte written
1017                         result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
1018                         result.SetStatus(eReturnStatusSuccessFinishResult);
1019                     }
1020                     else
1021                     {
1022                         result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1023                         result.SetStatus(eReturnStatusFailed);
1024                     }
1025                 }
1026             }
1027             else
1028             {
1029                 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1030                 result.SetStatus(eReturnStatusFailed);
1031             }
1032             return result.Succeeded();
1033         }
1034         else if (item_byte_size == 0)
1035         {
1036             if (m_format_options.GetFormat() == eFormatPointer)
1037                 item_byte_size = buffer.GetAddressByteSize();
1038             else
1039                 item_byte_size = 1;
1040         }
1041 
1042         command.Shift(); // shift off the address argument
1043         uint64_t uval64;
1044         int64_t sval64;
1045         bool success = false;
1046         const uint32_t num_value_args = command.GetArgumentCount();
1047         uint32_t i;
1048         for (i=0; i<num_value_args; ++i)
1049         {
1050             const char *value_str = command.GetArgumentAtIndex(i);
1051 
1052             switch (m_format_options.GetFormat())
1053             {
1054             case kNumFormats:
1055             case eFormatFloat:  // TODO: add support for floats soon
1056             case eFormatCharPrintable:
1057             case eFormatBytesWithASCII:
1058             case eFormatComplex:
1059             case eFormatEnum:
1060             case eFormatUnicode16:
1061             case eFormatUnicode32:
1062             case eFormatVectorOfChar:
1063             case eFormatVectorOfSInt8:
1064             case eFormatVectorOfUInt8:
1065             case eFormatVectorOfSInt16:
1066             case eFormatVectorOfUInt16:
1067             case eFormatVectorOfSInt32:
1068             case eFormatVectorOfUInt32:
1069             case eFormatVectorOfSInt64:
1070             case eFormatVectorOfUInt64:
1071             case eFormatVectorOfFloat32:
1072             case eFormatVectorOfFloat64:
1073             case eFormatVectorOfUInt128:
1074             case eFormatOSType:
1075             case eFormatComplexInteger:
1076             case eFormatAddressInfo:
1077             case eFormatHexFloat:
1078             case eFormatInstruction:
1079                 result.AppendError("unsupported format for writing memory");
1080                 result.SetStatus(eReturnStatusFailed);
1081                 return false;
1082 
1083             case eFormatDefault:
1084             case eFormatBytes:
1085             case eFormatHex:
1086             case eFormatPointer:
1087 
1088                 // Decode hex bytes
1089                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1090                 if (!success)
1091                 {
1092                     result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1093                     result.SetStatus(eReturnStatusFailed);
1094                     return false;
1095                 }
1096                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1097                 {
1098                     result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1099                     result.SetStatus(eReturnStatusFailed);
1100                     return false;
1101                 }
1102                 buffer.PutMaxHex64 (uval64, item_byte_size);
1103                 break;
1104 
1105             case eFormatBoolean:
1106                 uval64 = Args::StringToBoolean(value_str, false, &success);
1107                 if (!success)
1108                 {
1109                     result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1110                     result.SetStatus(eReturnStatusFailed);
1111                     return false;
1112                 }
1113                 buffer.PutMaxHex64 (uval64, item_byte_size);
1114                 break;
1115 
1116             case eFormatBinary:
1117                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1118                 if (!success)
1119                 {
1120                     result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1121                     result.SetStatus(eReturnStatusFailed);
1122                     return false;
1123                 }
1124                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1125                 {
1126                     result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1127                     result.SetStatus(eReturnStatusFailed);
1128                     return false;
1129                 }
1130                 buffer.PutMaxHex64 (uval64, item_byte_size);
1131                 break;
1132 
1133             case eFormatCharArray:
1134             case eFormatChar:
1135             case eFormatCString:
1136                 if (value_str[0])
1137                 {
1138                     size_t len = strlen (value_str);
1139                     // Include the NULL for C strings...
1140                     if (m_format_options.GetFormat() == eFormatCString)
1141                         ++len;
1142                     Error error;
1143                     if (process->WriteMemory (addr, value_str, len, error) == len)
1144                     {
1145                         addr += len;
1146                     }
1147                     else
1148                     {
1149                         result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1150                         result.SetStatus(eReturnStatusFailed);
1151                         return false;
1152                     }
1153                 }
1154                 break;
1155 
1156             case eFormatDecimal:
1157                 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1158                 if (!success)
1159                 {
1160                     result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1161                     result.SetStatus(eReturnStatusFailed);
1162                     return false;
1163                 }
1164                 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1165                 {
1166                     result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
1167                     result.SetStatus(eReturnStatusFailed);
1168                     return false;
1169                 }
1170                 buffer.PutMaxHex64 (sval64, item_byte_size);
1171                 break;
1172 
1173             case eFormatUnsigned:
1174                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1175                 if (!success)
1176                 {
1177                     result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1178                     result.SetStatus(eReturnStatusFailed);
1179                     return false;
1180                 }
1181                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1182                 {
1183                     result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1184                     result.SetStatus(eReturnStatusFailed);
1185                     return false;
1186                 }
1187                 buffer.PutMaxHex64 (uval64, item_byte_size);
1188                 break;
1189 
1190             case eFormatOctal:
1191                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1192                 if (!success)
1193                 {
1194                     result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1195                     result.SetStatus(eReturnStatusFailed);
1196                     return false;
1197                 }
1198                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1199                 {
1200                     result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1201                     result.SetStatus(eReturnStatusFailed);
1202                     return false;
1203                 }
1204                 buffer.PutMaxHex64 (uval64, item_byte_size);
1205                 break;
1206             }
1207         }
1208 
1209         if (!buffer.GetString().empty())
1210         {
1211             Error error;
1212             if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
1213                 return true;
1214             else
1215             {
1216                 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1217                 result.SetStatus(eReturnStatusFailed);
1218                 return false;
1219             }
1220         }
1221         return true;
1222     }
1223 
1224 protected:
1225 
1226     OptionGroupOptions m_option_group;
1227     OptionGroupFormat m_format_options;
1228     OptionGroupWriteMemory m_memory_options;
1229 };
1230 
1231 
1232 //-------------------------------------------------------------------------
1233 // CommandObjectMemory
1234 //-------------------------------------------------------------------------
1235 
1236 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
1237     CommandObjectMultiword (interpreter,
1238                             "memory",
1239                             "A set of commands for operating on memory.",
1240                             "memory <subcommand> [<subcommand-options>]")
1241 {
1242     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1243     LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
1244 }
1245 
1246 CommandObjectMemory::~CommandObjectMemory ()
1247 {
1248 }
1249