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