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                 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
617                 result.AppendError(error.AsCString());
618                 result.SetStatus(eReturnStatusFailed);
619                 return false;
620             }
621 
622             if (bytes_read < total_byte_size)
623                 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
624             else
625             {
626                 m_next_addr = addr + bytes_read;
627                 m_prev_byte_size = bytes_read;
628                 m_prev_format_options = m_format_options;
629                 m_prev_memory_options = m_memory_options;
630                 m_prev_outfile_options = m_outfile_options;
631                 m_prev_varobj_options = m_varobj_options;
632             }
633         }
634 
635         StreamFile outfile_stream;
636         Stream *output_stream = NULL;
637         const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
638         if (outfile_spec)
639         {
640             char path[PATH_MAX];
641             outfile_spec.GetPath (path, sizeof(path));
642 
643             uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
644             const bool append = m_outfile_options.GetAppend().GetCurrentValue();
645             if (append)
646                 open_options |= File::eOpenOptionAppend;
647 
648             if (outfile_stream.GetFile ().Open (path, open_options).Success())
649             {
650                 if (m_memory_options.m_output_as_binary)
651                 {
652                     int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
653                     if (bytes_written > 0)
654                     {
655                         result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
656                                                          bytes_written,
657                                                          append ? "appended" : "written",
658                                                          path);
659                         return true;
660                     }
661                     else
662                     {
663                         result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
664                         result.SetStatus(eReturnStatusFailed);
665                         return false;
666                     }
667                 }
668                 else
669                 {
670                     // We are going to write ASCII to the file just point the
671                     // output_stream to our outfile_stream...
672                     output_stream = &outfile_stream;
673                 }
674             }
675             else
676             {
677                 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
678                 result.SetStatus(eReturnStatusFailed);
679                 return false;
680             }
681         }
682         else
683         {
684             output_stream = &result.GetOutputStream();
685         }
686 
687 
688         ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
689         if (clang_ast_type.GetOpaqueQualType())
690         {
691             for (uint32_t i = 0; i<item_count; ++i)
692             {
693                 addr_t item_addr = addr + (i * item_byte_size);
694                 Address address (item_addr);
695                 StreamString name_strm;
696                 name_strm.Printf ("0x%llx", item_addr);
697                 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
698                                                                     name_strm.GetString().c_str(),
699                                                                     address,
700                                                                     clang_ast_type));
701                 if (valobj_sp)
702                 {
703                     if (format != eFormatDefault)
704                         valobj_sp->SetFormat (format);
705 
706                     bool scope_already_checked = true;
707 
708                     ValueObject::DumpValueObjectOptions options;
709                     options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
710                     .SetMaximumDepth(m_varobj_options.max_depth)
711                     .SetShowLocation(m_varobj_options.show_location)
712                     .SetShowTypes(m_varobj_options.show_types)
713                     .SetUseObjectiveC(m_varobj_options.use_objc)
714                     .SetScopeChecked(scope_already_checked)
715                     .SetFlatOutput(m_varobj_options.flat_output)
716                     .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
717                     .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
718                     .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
719                     .SetFormat(format)
720                     .SetSummary();
721                     ValueObject::DumpValueObject (*output_stream,
722                                                   valobj_sp.get(),
723                                                   options);
724                 }
725                 else
726                 {
727                     result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
728                                                   view_as_type_cstr,
729                                                   name_strm.GetString().c_str());
730                     result.SetStatus(eReturnStatusFailed);
731                     return false;
732                 }
733             }
734             return true;
735         }
736 
737         result.SetStatus(eReturnStatusSuccessFinishResult);
738         DataExtractor data (data_sp,
739                             target->GetArchitecture().GetByteOrder(),
740                             target->GetArchitecture().GetAddressByteSize());
741 
742 
743         assert (output_stream);
744         uint32_t bytes_dumped = data.Dump (output_stream,
745                                            0,
746                                            m_format_options.GetFormat(),
747                                            item_byte_size,
748                                            item_count,
749                                            num_per_line,
750                                            addr,
751                                            0,
752                                            0,
753                                            exe_scope);
754         m_next_addr = addr + bytes_dumped;
755         output_stream->EOL();
756         return true;
757     }
758 
759 protected:
760     OptionGroupOptions m_option_group;
761     OptionGroupFormat m_format_options;
762     OptionGroupReadMemory m_memory_options;
763     OptionGroupOutputFile m_outfile_options;
764     OptionGroupValueObjectDisplay m_varobj_options;
765     lldb::addr_t m_next_addr;
766     lldb::addr_t m_prev_byte_size;
767     OptionGroupFormat m_prev_format_options;
768     OptionGroupReadMemory m_prev_memory_options;
769     OptionGroupOutputFile m_prev_outfile_options;
770     OptionGroupValueObjectDisplay m_prev_varobj_options;
771 };
772 
773 
774 OptionDefinition
775 g_memory_write_option_table[] =
776 {
777 { LLDB_OPT_SET_1, true,  "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
778 { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset,   "Start writng bytes from an offset within the input file."},
779 };
780 
781 
782 //----------------------------------------------------------------------
783 // Write memory to the inferior process
784 //----------------------------------------------------------------------
785 class CommandObjectMemoryWrite : public CommandObject
786 {
787 public:
788 
789     class OptionGroupWriteMemory : public OptionGroup
790     {
791     public:
792         OptionGroupWriteMemory () :
793             OptionGroup()
794         {
795         }
796 
797         virtual
798         ~OptionGroupWriteMemory ()
799         {
800         }
801 
802         virtual uint32_t
803         GetNumDefinitions ()
804         {
805             return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
806         }
807 
808         virtual const OptionDefinition*
809         GetDefinitions ()
810         {
811             return g_memory_write_option_table;
812         }
813 
814         virtual Error
815         SetOptionValue (CommandInterpreter &interpreter,
816                         uint32_t option_idx,
817                         const char *option_arg)
818         {
819             Error error;
820             char short_option = (char) g_memory_write_option_table[option_idx].short_option;
821 
822             switch (short_option)
823             {
824                 case 'i':
825                     m_infile.SetFile (option_arg, true);
826                     if (!m_infile.Exists())
827                     {
828                         m_infile.Clear();
829                         error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
830                     }
831                     break;
832 
833                 case 'o':
834                     {
835                         bool success;
836                         m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
837                         if (!success)
838                         {
839                             error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
840                         }
841                     }
842                     break;
843 
844                 default:
845                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
846                     break;
847             }
848             return error;
849         }
850 
851         virtual void
852         OptionParsingStarting (CommandInterpreter &interpreter)
853         {
854             m_infile.Clear();
855             m_infile_offset = 0;
856         }
857 
858         FileSpec m_infile;
859         off_t m_infile_offset;
860     };
861 
862     CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
863         CommandObject (interpreter,
864                        "memory write",
865                        "Write to the memory of the process being debugged.",
866                        //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
867                        NULL,
868                        eFlagProcessMustBeLaunched),
869         m_option_group (interpreter),
870         m_format_options (eFormatBytes, 1, UINT64_MAX),
871         m_memory_options ()
872     {
873         CommandArgumentEntry arg1;
874         CommandArgumentEntry arg2;
875         CommandArgumentData addr_arg;
876         CommandArgumentData value_arg;
877 
878         // Define the first (and only) variant of this arg.
879         addr_arg.arg_type = eArgTypeAddress;
880         addr_arg.arg_repetition = eArgRepeatPlain;
881 
882         // There is only one variant this argument could be; put it into the argument entry.
883         arg1.push_back (addr_arg);
884 
885         // Define the first (and only) variant of this arg.
886         value_arg.arg_type = eArgTypeValue;
887         value_arg.arg_repetition = eArgRepeatPlus;
888 
889         // There is only one variant this argument could be; put it into the argument entry.
890         arg2.push_back (value_arg);
891 
892         // Push the data for the first argument into the m_arguments vector.
893         m_arguments.push_back (arg1);
894         m_arguments.push_back (arg2);
895 
896         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
897         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE  , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
898         m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
899         m_option_group.Finalize();
900 
901     }
902 
903     virtual
904     ~CommandObjectMemoryWrite ()
905     {
906     }
907 
908     Options *
909     GetOptions ()
910     {
911         return &m_option_group;
912     }
913 
914     bool
915     UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
916     {
917         if (total_byte_size > 8)
918             return false;
919 
920         if (total_byte_size == 8)
921             return true;
922 
923         const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
924         return uval64 <= max;
925     }
926 
927     bool
928     SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
929     {
930         if (total_byte_size > 8)
931             return false;
932 
933         if (total_byte_size == 8)
934             return true;
935 
936         const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
937         const int64_t min = ~(max);
938         return min <= sval64 && sval64 <= max;
939     }
940 
941     virtual bool
942     Execute (Args& command,
943              CommandReturnObject &result)
944     {
945         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
946         if (process == NULL)
947         {
948             result.AppendError("need a process to read memory");
949             result.SetStatus(eReturnStatusFailed);
950             return false;
951         }
952 
953         const size_t argc = command.GetArgumentCount();
954 
955         if (m_memory_options.m_infile)
956         {
957             if (argc < 1)
958             {
959                 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
960                 result.SetStatus(eReturnStatusFailed);
961                 return false;
962             }
963         }
964         else if (argc < 2)
965         {
966             result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
967             result.SetStatus(eReturnStatusFailed);
968             return false;
969         }
970 
971         StreamString buffer (Stream::eBinary,
972                              process->GetTarget().GetArchitecture().GetAddressByteSize(),
973                              process->GetTarget().GetArchitecture().GetByteOrder());
974 
975         OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
976         size_t item_byte_size = byte_size_value.GetCurrentValue();
977 
978         lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
979 
980         if (addr == LLDB_INVALID_ADDRESS)
981         {
982             result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
983             result.SetStatus(eReturnStatusFailed);
984             return false;
985         }
986 
987         if (m_memory_options.m_infile)
988         {
989             size_t length = SIZE_MAX;
990             if (item_byte_size > 0)
991                 length = item_byte_size;
992             lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
993             if (data_sp)
994             {
995                 length = data_sp->GetByteSize();
996                 if (length > 0)
997                 {
998                     Error error;
999                     size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1000 
1001                     if (bytes_written == length)
1002                     {
1003                         // All bytes written
1004                         result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
1005                         result.SetStatus(eReturnStatusSuccessFinishResult);
1006                     }
1007                     else if (bytes_written > 0)
1008                     {
1009                         // Some byte written
1010                         result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
1011                         result.SetStatus(eReturnStatusSuccessFinishResult);
1012                     }
1013                     else
1014                     {
1015                         result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1016                         result.SetStatus(eReturnStatusFailed);
1017                     }
1018                 }
1019             }
1020             else
1021             {
1022                 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1023                 result.SetStatus(eReturnStatusFailed);
1024             }
1025             return result.Succeeded();
1026         }
1027         else if (item_byte_size == 0)
1028         {
1029             if (m_format_options.GetFormat() == eFormatPointer)
1030                 item_byte_size = buffer.GetAddressByteSize();
1031             else
1032                 item_byte_size = 1;
1033         }
1034 
1035         command.Shift(); // shift off the address argument
1036         uint64_t uval64;
1037         int64_t sval64;
1038         bool success = false;
1039         const uint32_t num_value_args = command.GetArgumentCount();
1040         uint32_t i;
1041         for (i=0; i<num_value_args; ++i)
1042         {
1043             const char *value_str = command.GetArgumentAtIndex(i);
1044 
1045             switch (m_format_options.GetFormat())
1046             {
1047             case kNumFormats:
1048             case eFormatFloat:  // TODO: add support for floats soon
1049             case eFormatCharPrintable:
1050             case eFormatBytesWithASCII:
1051             case eFormatComplex:
1052             case eFormatEnum:
1053             case eFormatUnicode16:
1054             case eFormatUnicode32:
1055             case eFormatVectorOfChar:
1056             case eFormatVectorOfSInt8:
1057             case eFormatVectorOfUInt8:
1058             case eFormatVectorOfSInt16:
1059             case eFormatVectorOfUInt16:
1060             case eFormatVectorOfSInt32:
1061             case eFormatVectorOfUInt32:
1062             case eFormatVectorOfSInt64:
1063             case eFormatVectorOfUInt64:
1064             case eFormatVectorOfFloat32:
1065             case eFormatVectorOfFloat64:
1066             case eFormatVectorOfUInt128:
1067             case eFormatOSType:
1068             case eFormatComplexInteger:
1069             case eFormatAddressInfo:
1070             case eFormatHexFloat:
1071             case eFormatInstruction:
1072                 result.AppendError("unsupported format for writing memory");
1073                 result.SetStatus(eReturnStatusFailed);
1074                 return false;
1075 
1076             case eFormatDefault:
1077             case eFormatBytes:
1078             case eFormatHex:
1079             case eFormatPointer:
1080 
1081                 // Decode hex bytes
1082                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1083                 if (!success)
1084                 {
1085                     result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1086                     result.SetStatus(eReturnStatusFailed);
1087                     return false;
1088                 }
1089                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1090                 {
1091                     result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1092                     result.SetStatus(eReturnStatusFailed);
1093                     return false;
1094                 }
1095                 buffer.PutMaxHex64 (uval64, item_byte_size);
1096                 break;
1097 
1098             case eFormatBoolean:
1099                 uval64 = Args::StringToBoolean(value_str, false, &success);
1100                 if (!success)
1101                 {
1102                     result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1103                     result.SetStatus(eReturnStatusFailed);
1104                     return false;
1105                 }
1106                 buffer.PutMaxHex64 (uval64, item_byte_size);
1107                 break;
1108 
1109             case eFormatBinary:
1110                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1111                 if (!success)
1112                 {
1113                     result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1114                     result.SetStatus(eReturnStatusFailed);
1115                     return false;
1116                 }
1117                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1118                 {
1119                     result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1120                     result.SetStatus(eReturnStatusFailed);
1121                     return false;
1122                 }
1123                 buffer.PutMaxHex64 (uval64, item_byte_size);
1124                 break;
1125 
1126             case eFormatCharArray:
1127             case eFormatChar:
1128             case eFormatCString:
1129                 if (value_str[0])
1130                 {
1131                     size_t len = strlen (value_str);
1132                     // Include the NULL for C strings...
1133                     if (m_format_options.GetFormat() == eFormatCString)
1134                         ++len;
1135                     Error error;
1136                     if (process->WriteMemory (addr, value_str, len, error) == len)
1137                     {
1138                         addr += len;
1139                     }
1140                     else
1141                     {
1142                         result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1143                         result.SetStatus(eReturnStatusFailed);
1144                         return false;
1145                     }
1146                 }
1147                 break;
1148 
1149             case eFormatDecimal:
1150                 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1151                 if (!success)
1152                 {
1153                     result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1154                     result.SetStatus(eReturnStatusFailed);
1155                     return false;
1156                 }
1157                 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1158                 {
1159                     result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
1160                     result.SetStatus(eReturnStatusFailed);
1161                     return false;
1162                 }
1163                 buffer.PutMaxHex64 (sval64, item_byte_size);
1164                 break;
1165 
1166             case eFormatUnsigned:
1167                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1168                 if (!success)
1169                 {
1170                     result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1171                     result.SetStatus(eReturnStatusFailed);
1172                     return false;
1173                 }
1174                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1175                 {
1176                     result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1177                     result.SetStatus(eReturnStatusFailed);
1178                     return false;
1179                 }
1180                 buffer.PutMaxHex64 (uval64, item_byte_size);
1181                 break;
1182 
1183             case eFormatOctal:
1184                 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1185                 if (!success)
1186                 {
1187                     result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1188                     result.SetStatus(eReturnStatusFailed);
1189                     return false;
1190                 }
1191                 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1192                 {
1193                     result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1194                     result.SetStatus(eReturnStatusFailed);
1195                     return false;
1196                 }
1197                 buffer.PutMaxHex64 (uval64, item_byte_size);
1198                 break;
1199             }
1200         }
1201 
1202         if (!buffer.GetString().empty())
1203         {
1204             Error error;
1205             if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
1206                 return true;
1207             else
1208             {
1209                 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1210                 result.SetStatus(eReturnStatusFailed);
1211                 return false;
1212             }
1213         }
1214         return true;
1215     }
1216 
1217 protected:
1218 
1219     OptionGroupOptions m_option_group;
1220     OptionGroupFormat m_format_options;
1221     OptionGroupWriteMemory m_memory_options;
1222 };
1223 
1224 
1225 //-------------------------------------------------------------------------
1226 // CommandObjectMemory
1227 //-------------------------------------------------------------------------
1228 
1229 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
1230     CommandObjectMultiword (interpreter,
1231                             "memory",
1232                             "A set of commands for operating on memory.",
1233                             "memory <subcommand> [<subcommand-options>]")
1234 {
1235     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1236     LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
1237 }
1238 
1239 CommandObjectMemory::~CommandObjectMemory ()
1240 {
1241 }
1242