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