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