1254721Semaste//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/lldb-python.h"
11254721Semaste
12254721Semaste#include "CommandObjectMemory.h"
13254721Semaste
14254721Semaste// C Includes
15254721Semaste// C++ Includes
16254721Semaste// Other libraries and framework includes
17254721Semaste// Project includes
18254721Semaste#include "lldb/Core/DataBufferHeap.h"
19254721Semaste#include "lldb/Core/DataExtractor.h"
20254721Semaste#include "lldb/Core/Debugger.h"
21254721Semaste#include "lldb/Core/Module.h"
22254721Semaste#include "lldb/Core/StreamString.h"
23254721Semaste#include "lldb/Core/ValueObjectMemory.h"
24254721Semaste#include "lldb/Interpreter/Args.h"
25254721Semaste#include "lldb/Interpreter/CommandReturnObject.h"
26254721Semaste#include "lldb/Interpreter/CommandInterpreter.h"
27254721Semaste#include "lldb/Interpreter/Options.h"
28254721Semaste#include "lldb/Interpreter/OptionGroupFormat.h"
29254721Semaste#include "lldb/Interpreter/OptionGroupOutputFile.h"
30254721Semaste#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
31254721Semaste#include "lldb/Interpreter/OptionValueString.h"
32254721Semaste#include "lldb/Symbol/TypeList.h"
33254721Semaste#include "lldb/Target/Process.h"
34254721Semaste#include "lldb/Target/StackFrame.h"
35254721Semaste
36254721Semasteusing namespace lldb;
37254721Semasteusing namespace lldb_private;
38254721Semaste
39254721Semastestatic OptionDefinition
40254721Semasteg_option_table[] =
41254721Semaste{
42254721Semaste    { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
43254721Semaste    { 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."},
44254721Semaste    { LLDB_OPT_SET_3, true , "type"         ,'t', required_argument, NULL, 0, eArgTypeNone          ,"The name of a type to view memory as."},
45254721Semaste    { LLDB_OPT_SET_1|
46254721Semaste      LLDB_OPT_SET_2|
47254721Semaste      LLDB_OPT_SET_3, false, "force"        ,'r', no_argument,       NULL, 0, eArgTypeNone          ,"Necessary if reading over target.max-memory-read-size bytes."},
48254721Semaste};
49254721Semaste
50254721Semaste
51254721Semaste
52254721Semasteclass OptionGroupReadMemory : public OptionGroup
53254721Semaste{
54254721Semastepublic:
55254721Semaste
56254721Semaste    OptionGroupReadMemory () :
57254721Semaste        m_num_per_line (1,1),
58254721Semaste        m_output_as_binary (false),
59254721Semaste        m_view_as_type()
60254721Semaste    {
61254721Semaste    }
62254721Semaste
63254721Semaste    virtual
64254721Semaste    ~OptionGroupReadMemory ()
65254721Semaste    {
66254721Semaste    }
67254721Semaste
68254721Semaste
69254721Semaste    virtual uint32_t
70254721Semaste    GetNumDefinitions ()
71254721Semaste    {
72254721Semaste        return sizeof (g_option_table) / sizeof (OptionDefinition);
73254721Semaste    }
74254721Semaste
75254721Semaste    virtual const OptionDefinition*
76254721Semaste    GetDefinitions ()
77254721Semaste    {
78254721Semaste        return g_option_table;
79254721Semaste    }
80254721Semaste
81254721Semaste    virtual Error
82254721Semaste    SetOptionValue (CommandInterpreter &interpreter,
83254721Semaste                    uint32_t option_idx,
84254721Semaste                    const char *option_arg)
85254721Semaste    {
86254721Semaste        Error error;
87254721Semaste        const int short_option = g_option_table[option_idx].short_option;
88254721Semaste
89254721Semaste        switch (short_option)
90254721Semaste        {
91254721Semaste            case 'l':
92254721Semaste                error = m_num_per_line.SetValueFromCString (option_arg);
93254721Semaste                if (m_num_per_line.GetCurrentValue() == 0)
94254721Semaste                    error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
95254721Semaste                break;
96254721Semaste
97254721Semaste            case 'b':
98254721Semaste                m_output_as_binary = true;
99254721Semaste                break;
100254721Semaste
101254721Semaste            case 't':
102254721Semaste                error = m_view_as_type.SetValueFromCString (option_arg);
103254721Semaste                break;
104254721Semaste
105254721Semaste            case 'r':
106254721Semaste                m_force = true;
107254721Semaste                break;
108254721Semaste
109254721Semaste            default:
110254721Semaste                error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
111254721Semaste                break;
112254721Semaste        }
113254721Semaste        return error;
114254721Semaste    }
115254721Semaste
116254721Semaste    virtual void
117254721Semaste    OptionParsingStarting (CommandInterpreter &interpreter)
118254721Semaste    {
119254721Semaste        m_num_per_line.Clear();
120254721Semaste        m_output_as_binary = false;
121254721Semaste        m_view_as_type.Clear();
122254721Semaste        m_force = false;
123254721Semaste    }
124254721Semaste
125254721Semaste    Error
126254721Semaste    FinalizeSettings (Target *target, OptionGroupFormat& format_options)
127254721Semaste    {
128254721Semaste        Error error;
129254721Semaste        OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
130254721Semaste        OptionValueUInt64 &count_value = format_options.GetCountValue();
131254721Semaste        const bool byte_size_option_set = byte_size_value.OptionWasSet();
132254721Semaste        const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
133254721Semaste        const bool count_option_set = format_options.GetCountValue().OptionWasSet();
134254721Semaste
135254721Semaste        switch (format_options.GetFormat())
136254721Semaste        {
137254721Semaste            default:
138254721Semaste                break;
139254721Semaste
140254721Semaste            case eFormatBoolean:
141254721Semaste                if (!byte_size_option_set)
142254721Semaste                    byte_size_value = 1;
143254721Semaste                if (!num_per_line_option_set)
144254721Semaste                    m_num_per_line = 1;
145254721Semaste                if (!count_option_set)
146254721Semaste                    format_options.GetCountValue() = 8;
147254721Semaste                break;
148254721Semaste
149254721Semaste            case eFormatCString:
150254721Semaste                break;
151254721Semaste
152254721Semaste            case eFormatInstruction:
153254721Semaste                if (count_option_set)
154254721Semaste                    byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
155254721Semaste                m_num_per_line = 1;
156254721Semaste                break;
157254721Semaste
158254721Semaste            case eFormatAddressInfo:
159254721Semaste                if (!byte_size_option_set)
160254721Semaste                    byte_size_value = target->GetArchitecture().GetAddressByteSize();
161254721Semaste                m_num_per_line = 1;
162254721Semaste                if (!count_option_set)
163254721Semaste                    format_options.GetCountValue() = 8;
164254721Semaste                break;
165254721Semaste
166254721Semaste            case eFormatPointer:
167254721Semaste                byte_size_value = target->GetArchitecture().GetAddressByteSize();
168254721Semaste                if (!num_per_line_option_set)
169254721Semaste                    m_num_per_line = 4;
170254721Semaste                if (!count_option_set)
171254721Semaste                    format_options.GetCountValue() = 8;
172254721Semaste                break;
173254721Semaste
174254721Semaste            case eFormatBinary:
175254721Semaste            case eFormatFloat:
176254721Semaste            case eFormatOctal:
177254721Semaste            case eFormatDecimal:
178254721Semaste            case eFormatEnum:
179254721Semaste            case eFormatUnicode16:
180254721Semaste            case eFormatUnicode32:
181254721Semaste            case eFormatUnsigned:
182254721Semaste            case eFormatHexFloat:
183254721Semaste                if (!byte_size_option_set)
184254721Semaste                    byte_size_value = 4;
185254721Semaste                if (!num_per_line_option_set)
186254721Semaste                    m_num_per_line = 1;
187254721Semaste                if (!count_option_set)
188254721Semaste                    format_options.GetCountValue() = 8;
189254721Semaste                break;
190254721Semaste
191254721Semaste            case eFormatBytes:
192254721Semaste            case eFormatBytesWithASCII:
193254721Semaste                if (byte_size_option_set)
194254721Semaste                {
195254721Semaste                    if (byte_size_value > 1)
196254721Semaste                        error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
197254721Semaste                                                        "\tconsider using a different display format or don't specify the byte size",
198254721Semaste                                                        byte_size_value.GetCurrentValue());
199254721Semaste                }
200254721Semaste                else
201254721Semaste                    byte_size_value = 1;
202254721Semaste                if (!num_per_line_option_set)
203254721Semaste                    m_num_per_line = 16;
204254721Semaste                if (!count_option_set)
205254721Semaste                    format_options.GetCountValue() = 32;
206254721Semaste                break;
207254721Semaste            case eFormatCharArray:
208254721Semaste            case eFormatChar:
209254721Semaste            case eFormatCharPrintable:
210254721Semaste                if (!byte_size_option_set)
211254721Semaste                    byte_size_value = 1;
212254721Semaste                if (!num_per_line_option_set)
213254721Semaste                    m_num_per_line = 32;
214254721Semaste                if (!count_option_set)
215254721Semaste                    format_options.GetCountValue() = 64;
216254721Semaste                break;
217254721Semaste            case eFormatComplex:
218254721Semaste                if (!byte_size_option_set)
219254721Semaste                    byte_size_value = 8;
220254721Semaste                if (!num_per_line_option_set)
221254721Semaste                    m_num_per_line = 1;
222254721Semaste                if (!count_option_set)
223254721Semaste                    format_options.GetCountValue() = 8;
224254721Semaste                break;
225254721Semaste            case eFormatComplexInteger:
226254721Semaste                if (!byte_size_option_set)
227254721Semaste                    byte_size_value = 8;
228254721Semaste                if (!num_per_line_option_set)
229254721Semaste                    m_num_per_line = 1;
230254721Semaste                if (!count_option_set)
231254721Semaste                    format_options.GetCountValue() = 8;
232254721Semaste                break;
233254721Semaste            case eFormatHex:
234254721Semaste                if (!byte_size_option_set)
235254721Semaste                    byte_size_value = 4;
236254721Semaste                if (!num_per_line_option_set)
237254721Semaste                {
238254721Semaste                    switch (byte_size_value)
239254721Semaste                    {
240254721Semaste                        case 1:
241254721Semaste                        case 2:
242254721Semaste                            m_num_per_line = 8;
243254721Semaste                            break;
244254721Semaste                        case 4:
245254721Semaste                            m_num_per_line = 4;
246254721Semaste                            break;
247254721Semaste                        case 8:
248254721Semaste                            m_num_per_line = 2;
249254721Semaste                            break;
250254721Semaste                        default:
251254721Semaste                            m_num_per_line = 1;
252254721Semaste                            break;
253254721Semaste                    }
254254721Semaste                }
255254721Semaste                if (!count_option_set)
256254721Semaste                    count_value = 8;
257254721Semaste                break;
258254721Semaste
259254721Semaste            case eFormatVectorOfChar:
260254721Semaste            case eFormatVectorOfSInt8:
261254721Semaste            case eFormatVectorOfUInt8:
262254721Semaste            case eFormatVectorOfSInt16:
263254721Semaste            case eFormatVectorOfUInt16:
264254721Semaste            case eFormatVectorOfSInt32:
265254721Semaste            case eFormatVectorOfUInt32:
266254721Semaste            case eFormatVectorOfSInt64:
267254721Semaste            case eFormatVectorOfUInt64:
268254721Semaste            case eFormatVectorOfFloat32:
269254721Semaste            case eFormatVectorOfFloat64:
270254721Semaste            case eFormatVectorOfUInt128:
271254721Semaste                if (!byte_size_option_set)
272254721Semaste                    byte_size_value = 128;
273254721Semaste                if (!num_per_line_option_set)
274254721Semaste                    m_num_per_line = 1;
275254721Semaste                if (!count_option_set)
276254721Semaste                    count_value = 4;
277254721Semaste                break;
278254721Semaste        }
279254721Semaste        return error;
280254721Semaste    }
281254721Semaste
282254721Semaste    bool
283254721Semaste    AnyOptionWasSet () const
284254721Semaste    {
285254721Semaste        return m_num_per_line.OptionWasSet() ||
286254721Semaste               m_output_as_binary ||
287254721Semaste               m_view_as_type.OptionWasSet();
288254721Semaste    }
289254721Semaste
290254721Semaste    OptionValueUInt64 m_num_per_line;
291254721Semaste    bool m_output_as_binary;
292254721Semaste    OptionValueString m_view_as_type;
293254721Semaste    bool m_force;
294254721Semaste};
295254721Semaste
296254721Semaste
297254721Semaste
298254721Semaste//----------------------------------------------------------------------
299254721Semaste// Read memory from the inferior process
300254721Semaste//----------------------------------------------------------------------
301254721Semasteclass CommandObjectMemoryRead : public CommandObjectParsed
302254721Semaste{
303254721Semastepublic:
304254721Semaste
305254721Semaste    CommandObjectMemoryRead (CommandInterpreter &interpreter) :
306254721Semaste        CommandObjectParsed (interpreter,
307254721Semaste                             "memory read",
308254721Semaste                             "Read from the memory of the process being debugged.",
309254721Semaste                             NULL,
310254721Semaste                             eFlagRequiresTarget | eFlagProcessMustBePaused),
311254721Semaste        m_option_group (interpreter),
312254721Semaste        m_format_options (eFormatBytesWithASCII, 1, 8),
313254721Semaste        m_memory_options (),
314254721Semaste        m_outfile_options (),
315254721Semaste        m_varobj_options(),
316254721Semaste        m_next_addr(LLDB_INVALID_ADDRESS),
317254721Semaste        m_prev_byte_size(0),
318254721Semaste        m_prev_format_options (eFormatBytesWithASCII, 1, 8),
319254721Semaste        m_prev_memory_options (),
320254721Semaste        m_prev_outfile_options (),
321254721Semaste        m_prev_varobj_options()
322254721Semaste    {
323254721Semaste        CommandArgumentEntry arg1;
324254721Semaste        CommandArgumentEntry arg2;
325254721Semaste        CommandArgumentData start_addr_arg;
326254721Semaste        CommandArgumentData end_addr_arg;
327254721Semaste
328254721Semaste        // Define the first (and only) variant of this arg.
329254721Semaste        start_addr_arg.arg_type = eArgTypeAddressOrExpression;
330254721Semaste        start_addr_arg.arg_repetition = eArgRepeatPlain;
331254721Semaste
332254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
333254721Semaste        arg1.push_back (start_addr_arg);
334254721Semaste
335254721Semaste        // Define the first (and only) variant of this arg.
336254721Semaste        end_addr_arg.arg_type = eArgTypeAddressOrExpression;
337254721Semaste        end_addr_arg.arg_repetition = eArgRepeatOptional;
338254721Semaste
339254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
340254721Semaste        arg2.push_back (end_addr_arg);
341254721Semaste
342254721Semaste        // Push the data for the first argument into the m_arguments vector.
343254721Semaste        m_arguments.push_back (arg1);
344254721Semaste        m_arguments.push_back (arg2);
345254721Semaste
346254721Semaste        // Add the "--format" and "--count" options to group 1 and 3
347254721Semaste        m_option_group.Append (&m_format_options,
348254721Semaste                               OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
349254721Semaste                               LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
350254721Semaste        m_option_group.Append (&m_format_options,
351254721Semaste                               OptionGroupFormat::OPTION_GROUP_GDB_FMT,
352254721Semaste                               LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
353254721Semaste        // Add the "--size" option to group 1 and 2
354254721Semaste        m_option_group.Append (&m_format_options,
355254721Semaste                               OptionGroupFormat::OPTION_GROUP_SIZE,
356254721Semaste                               LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
357254721Semaste        m_option_group.Append (&m_memory_options);
358254721Semaste        m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
359254721Semaste        m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
360254721Semaste        m_option_group.Finalize();
361254721Semaste    }
362254721Semaste
363254721Semaste    virtual
364254721Semaste    ~CommandObjectMemoryRead ()
365254721Semaste    {
366254721Semaste    }
367254721Semaste
368254721Semaste    Options *
369254721Semaste    GetOptions ()
370254721Semaste    {
371254721Semaste        return &m_option_group;
372254721Semaste    }
373254721Semaste
374254721Semaste    virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
375254721Semaste    {
376254721Semaste        return m_cmd_name.c_str();
377254721Semaste    }
378254721Semaste
379254721Semasteprotected:
380254721Semaste    virtual bool
381254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
382254721Semaste    {
383254721Semaste        // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
384254721Semaste        Target *target = m_exe_ctx.GetTargetPtr();
385254721Semaste
386254721Semaste        const size_t argc = command.GetArgumentCount();
387254721Semaste
388254721Semaste        if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
389254721Semaste        {
390254721Semaste            result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
391254721Semaste            result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
392254721Semaste            result.SetStatus(eReturnStatusFailed);
393254721Semaste            return false;
394254721Semaste        }
395254721Semaste
396254721Semaste        ClangASTType clang_ast_type;
397254721Semaste        Error error;
398254721Semaste
399254721Semaste        const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
400254721Semaste        if (view_as_type_cstr && view_as_type_cstr[0])
401254721Semaste        {
402254721Semaste            // We are viewing memory as a type
403254721Semaste
404254721Semaste            SymbolContext sc;
405254721Semaste            const bool exact_match = false;
406254721Semaste            TypeList type_list;
407254721Semaste            uint32_t reference_count = 0;
408254721Semaste            uint32_t pointer_count = 0;
409254721Semaste            size_t idx;
410254721Semaste
411254721Semaste#define ALL_KEYWORDS        \
412254721Semaste    KEYWORD("const")        \
413254721Semaste    KEYWORD("volatile")     \
414254721Semaste    KEYWORD("restrict")     \
415254721Semaste    KEYWORD("struct")       \
416254721Semaste    KEYWORD("class")        \
417254721Semaste    KEYWORD("union")
418254721Semaste
419254721Semaste#define KEYWORD(s) s,
420254721Semaste            static const char *g_keywords[] =
421254721Semaste            {
422254721Semaste                ALL_KEYWORDS
423254721Semaste            };
424254721Semaste#undef KEYWORD
425254721Semaste
426254721Semaste#define KEYWORD(s) (sizeof(s) - 1),
427254721Semaste            static const int g_keyword_lengths[] =
428254721Semaste            {
429254721Semaste                ALL_KEYWORDS
430254721Semaste            };
431254721Semaste#undef KEYWORD
432254721Semaste
433254721Semaste#undef ALL_KEYWORDS
434254721Semaste
435254721Semaste            static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
436254721Semaste            std::string type_str(view_as_type_cstr);
437254721Semaste
438254721Semaste            // Remove all instances of g_keywords that are followed by spaces
439254721Semaste            for (size_t i = 0; i < g_num_keywords; ++i)
440254721Semaste            {
441254721Semaste                const char *keyword = g_keywords[i];
442254721Semaste                int keyword_len = g_keyword_lengths[i];
443254721Semaste
444254721Semaste                idx = 0;
445254721Semaste                while ((idx = type_str.find (keyword, idx)) != std::string::npos)
446254721Semaste                {
447254721Semaste                    if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
448254721Semaste                    {
449254721Semaste                        type_str.erase(idx, keyword_len+1);
450254721Semaste                        idx = 0;
451254721Semaste                    }
452254721Semaste                    else
453254721Semaste                    {
454254721Semaste                        idx += keyword_len;
455254721Semaste                    }
456254721Semaste                }
457254721Semaste            }
458254721Semaste            bool done = type_str.empty();
459254721Semaste            //
460254721Semaste            idx = type_str.find_first_not_of (" \t");
461254721Semaste            if (idx > 0 && idx != std::string::npos)
462254721Semaste                type_str.erase (0, idx);
463254721Semaste            while (!done)
464254721Semaste            {
465254721Semaste                // Strip trailing spaces
466254721Semaste                if (type_str.empty())
467254721Semaste                    done = true;
468254721Semaste                else
469254721Semaste                {
470254721Semaste                    switch (type_str[type_str.size()-1])
471254721Semaste                    {
472254721Semaste                    case '*':
473254721Semaste                        ++pointer_count;
474254721Semaste                        // fall through...
475254721Semaste                    case ' ':
476254721Semaste                    case '\t':
477254721Semaste                        type_str.erase(type_str.size()-1);
478254721Semaste                        break;
479254721Semaste
480254721Semaste                    case '&':
481254721Semaste                        if (reference_count == 0)
482254721Semaste                        {
483254721Semaste                            reference_count = 1;
484254721Semaste                            type_str.erase(type_str.size()-1);
485254721Semaste                        }
486254721Semaste                        else
487254721Semaste                        {
488254721Semaste                            result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
489254721Semaste                            result.SetStatus(eReturnStatusFailed);
490254721Semaste                            return false;
491254721Semaste                        }
492254721Semaste                        break;
493254721Semaste
494254721Semaste                    default:
495254721Semaste                        done = true;
496254721Semaste                        break;
497254721Semaste                    }
498254721Semaste                }
499254721Semaste            }
500254721Semaste
501254721Semaste            ConstString lookup_type_name(type_str.c_str());
502254721Semaste            StackFrame *frame = m_exe_ctx.GetFramePtr();
503254721Semaste            if (frame)
504254721Semaste            {
505254721Semaste                sc = frame->GetSymbolContext (eSymbolContextModule);
506254721Semaste                if (sc.module_sp)
507254721Semaste                {
508254721Semaste                    sc.module_sp->FindTypes (sc,
509254721Semaste                                             lookup_type_name,
510254721Semaste                                             exact_match,
511254721Semaste                                             1,
512254721Semaste                                             type_list);
513254721Semaste                }
514254721Semaste            }
515254721Semaste            if (type_list.GetSize() == 0)
516254721Semaste            {
517254721Semaste                target->GetImages().FindTypes (sc,
518254721Semaste                                               lookup_type_name,
519254721Semaste                                               exact_match,
520254721Semaste                                               1,
521254721Semaste                                               type_list);
522254721Semaste            }
523254721Semaste
524254721Semaste            if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
525254721Semaste            {
526254721Semaste                clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
527254721Semaste                if (tdecl)
528254721Semaste                {
529254721Semaste                    clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
530254721Semaste                }
531254721Semaste            }
532254721Semaste
533254721Semaste            if (clang_ast_type.IsValid() == false)
534254721Semaste            {
535254721Semaste                if (type_list.GetSize() == 0)
536254721Semaste                {
537254721Semaste                    result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
538254721Semaste                                                  lookup_type_name.GetCString(),
539254721Semaste                                                  view_as_type_cstr);
540254721Semaste                    result.SetStatus(eReturnStatusFailed);
541254721Semaste                    return false;
542254721Semaste                }
543254721Semaste                else
544254721Semaste                {
545254721Semaste                    TypeSP type_sp (type_list.GetTypeAtIndex(0));
546254721Semaste                    clang_ast_type = type_sp->GetClangFullType();
547254721Semaste                }
548254721Semaste            }
549254721Semaste
550254721Semaste            while (pointer_count > 0)
551254721Semaste            {
552254721Semaste                ClangASTType pointer_type = clang_ast_type.GetPointerType();
553254721Semaste                if (pointer_type.IsValid())
554254721Semaste                    clang_ast_type = pointer_type;
555254721Semaste                else
556254721Semaste                {
557254721Semaste                    result.AppendError ("unable make a pointer type\n");
558254721Semaste                    result.SetStatus(eReturnStatusFailed);
559254721Semaste                    return false;
560254721Semaste                }
561254721Semaste                --pointer_count;
562254721Semaste            }
563254721Semaste
564254721Semaste            m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize();
565254721Semaste
566254721Semaste            if (m_format_options.GetByteSizeValue() == 0)
567254721Semaste            {
568254721Semaste                result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
569254721Semaste                                              view_as_type_cstr);
570254721Semaste                result.SetStatus(eReturnStatusFailed);
571254721Semaste                return false;
572254721Semaste            }
573254721Semaste
574254721Semaste            if (!m_format_options.GetCountValue().OptionWasSet())
575254721Semaste                m_format_options.GetCountValue() = 1;
576254721Semaste        }
577254721Semaste        else
578254721Semaste        {
579254721Semaste            error = m_memory_options.FinalizeSettings (target, m_format_options);
580254721Semaste        }
581254721Semaste
582254721Semaste        // Look for invalid combinations of settings
583254721Semaste        if (error.Fail())
584254721Semaste        {
585254721Semaste            result.AppendError(error.AsCString());
586254721Semaste            result.SetStatus(eReturnStatusFailed);
587254721Semaste            return false;
588254721Semaste        }
589254721Semaste
590254721Semaste        lldb::addr_t addr;
591254721Semaste        size_t total_byte_size = 0;
592254721Semaste        if (argc == 0)
593254721Semaste        {
594254721Semaste            // Use the last address and byte size and all options as they were
595254721Semaste            // if no options have been set
596254721Semaste            addr = m_next_addr;
597254721Semaste            total_byte_size = m_prev_byte_size;
598254721Semaste            clang_ast_type = m_prev_clang_ast_type;
599254721Semaste            if (!m_format_options.AnyOptionWasSet() &&
600254721Semaste                !m_memory_options.AnyOptionWasSet() &&
601254721Semaste                !m_outfile_options.AnyOptionWasSet() &&
602254721Semaste                !m_varobj_options.AnyOptionWasSet())
603254721Semaste            {
604254721Semaste                m_format_options = m_prev_format_options;
605254721Semaste                m_memory_options = m_prev_memory_options;
606254721Semaste                m_outfile_options = m_prev_outfile_options;
607254721Semaste                m_varobj_options = m_prev_varobj_options;
608254721Semaste            }
609254721Semaste        }
610254721Semaste
611254721Semaste        size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
612254721Semaste        size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
613254721Semaste        const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
614254721Semaste
615254721Semaste        if (total_byte_size == 0)
616254721Semaste        {
617254721Semaste            total_byte_size = item_count * item_byte_size;
618254721Semaste            if (total_byte_size == 0)
619254721Semaste                total_byte_size = 32;
620254721Semaste        }
621254721Semaste
622254721Semaste        if (argc > 0)
623254721Semaste            addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
624254721Semaste
625254721Semaste        if (addr == LLDB_INVALID_ADDRESS)
626254721Semaste        {
627254721Semaste            result.AppendError("invalid start address expression.");
628254721Semaste            result.AppendError(error.AsCString());
629254721Semaste            result.SetStatus(eReturnStatusFailed);
630254721Semaste            return false;
631254721Semaste        }
632254721Semaste
633254721Semaste        if (argc == 2)
634254721Semaste        {
635254721Semaste            lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
636254721Semaste            if (end_addr == LLDB_INVALID_ADDRESS)
637254721Semaste            {
638254721Semaste                result.AppendError("invalid end address expression.");
639254721Semaste                result.AppendError(error.AsCString());
640254721Semaste                result.SetStatus(eReturnStatusFailed);
641254721Semaste                return false;
642254721Semaste            }
643254721Semaste            else if (end_addr <= addr)
644254721Semaste            {
645254721Semaste                result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
646254721Semaste                result.SetStatus(eReturnStatusFailed);
647254721Semaste                return false;
648254721Semaste            }
649254721Semaste            else if (m_format_options.GetCountValue().OptionWasSet())
650254721Semaste            {
651254721Semaste                result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count);
652254721Semaste                result.SetStatus(eReturnStatusFailed);
653254721Semaste                return false;
654254721Semaste            }
655254721Semaste
656254721Semaste            total_byte_size = end_addr - addr;
657254721Semaste            item_count = total_byte_size / item_byte_size;
658254721Semaste        }
659254721Semaste
660254721Semaste        uint32_t max_unforced_size = target->GetMaximumMemReadSize();
661254721Semaste
662254721Semaste        if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
663254721Semaste        {
664254721Semaste            result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
665254721Semaste            result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
666254721Semaste            result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
667254721Semaste            return false;
668254721Semaste        }
669254721Semaste
670254721Semaste        DataBufferSP data_sp;
671254721Semaste        size_t bytes_read = 0;
672254721Semaste        if (clang_ast_type.GetOpaqueQualType())
673254721Semaste        {
674254721Semaste            // Make sure we don't display our type as ASCII bytes like the default memory read
675254721Semaste            if (m_format_options.GetFormatValue().OptionWasSet() == false)
676254721Semaste                m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
677254721Semaste
678254721Semaste            bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue();
679254721Semaste        }
680254721Semaste        else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
681254721Semaste        {
682254721Semaste            data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
683254721Semaste            if (data_sp->GetBytes() == NULL)
684254721Semaste            {
685254721Semaste                result.AppendErrorWithFormat ("can't allocate 0x%zx bytes for the memory read buffer, specify a smaller size to read", total_byte_size);
686254721Semaste                result.SetStatus(eReturnStatusFailed);
687254721Semaste                return false;
688254721Semaste            }
689254721Semaste
690254721Semaste            Address address(addr, NULL);
691254721Semaste            bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
692254721Semaste            if (bytes_read == 0)
693254721Semaste            {
694254721Semaste                const char *error_cstr = error.AsCString();
695254721Semaste                if (error_cstr && error_cstr[0])
696254721Semaste                {
697254721Semaste                    result.AppendError(error_cstr);
698254721Semaste                }
699254721Semaste                else
700254721Semaste                {
701254721Semaste                    result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
702254721Semaste                }
703254721Semaste                result.SetStatus(eReturnStatusFailed);
704254721Semaste                return false;
705254721Semaste            }
706254721Semaste
707254721Semaste            if (bytes_read < total_byte_size)
708254721Semaste                result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
709254721Semaste        }
710254721Semaste        else
711254721Semaste        {
712254721Semaste            // we treat c-strings as a special case because they do not have a fixed size
713254721Semaste            if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
714254721Semaste                item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
715254721Semaste            else
716254721Semaste                item_byte_size = target->GetMaximumSizeOfStringSummary();
717254721Semaste            if (!m_format_options.GetCountValue().OptionWasSet())
718254721Semaste                item_count = 1;
719254721Semaste            data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
720254721Semaste            if (data_sp->GetBytes() == NULL)
721254721Semaste            {
722254721Semaste                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));
723254721Semaste                result.SetStatus(eReturnStatusFailed);
724254721Semaste                return false;
725254721Semaste            }
726254721Semaste            uint8_t *data_ptr = data_sp->GetBytes();
727254721Semaste            auto data_addr = addr;
728254721Semaste            auto count = item_count;
729254721Semaste            item_count = 0;
730254721Semaste            while (item_count < count)
731254721Semaste            {
732254721Semaste                std::string buffer;
733254721Semaste                buffer.resize(item_byte_size+1,0);
734254721Semaste                Error error;
735254721Semaste                size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
736254721Semaste                if (error.Fail())
737254721Semaste                {
738254721Semaste                    result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
739254721Semaste                    result.SetStatus(eReturnStatusFailed);
740254721Semaste                    return false;
741254721Semaste                }
742254721Semaste                if (item_byte_size == read)
743254721Semaste                {
744254721Semaste                    result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
745254721Semaste                    break;
746254721Semaste                }
747254721Semaste                read+=1; // account for final NULL byte
748254721Semaste                memcpy(data_ptr, &buffer[0], read);
749254721Semaste                data_ptr += read;
750254721Semaste                data_addr += read;
751254721Semaste                bytes_read += read;
752254721Semaste                item_count++; // if we break early we know we only read item_count strings
753254721Semaste            }
754254721Semaste            data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
755254721Semaste        }
756254721Semaste
757254721Semaste        m_next_addr = addr + bytes_read;
758254721Semaste        m_prev_byte_size = bytes_read;
759254721Semaste        m_prev_format_options = m_format_options;
760254721Semaste        m_prev_memory_options = m_memory_options;
761254721Semaste        m_prev_outfile_options = m_outfile_options;
762254721Semaste        m_prev_varobj_options = m_varobj_options;
763254721Semaste        m_prev_clang_ast_type = clang_ast_type;
764254721Semaste
765254721Semaste        StreamFile outfile_stream;
766254721Semaste        Stream *output_stream = NULL;
767254721Semaste        const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
768254721Semaste        if (outfile_spec)
769254721Semaste        {
770254721Semaste            char path[PATH_MAX];
771254721Semaste            outfile_spec.GetPath (path, sizeof(path));
772254721Semaste
773254721Semaste            uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
774254721Semaste            const bool append = m_outfile_options.GetAppend().GetCurrentValue();
775254721Semaste            if (append)
776254721Semaste                open_options |= File::eOpenOptionAppend;
777254721Semaste
778254721Semaste            if (outfile_stream.GetFile ().Open (path, open_options).Success())
779254721Semaste            {
780254721Semaste                if (m_memory_options.m_output_as_binary)
781254721Semaste                {
782254721Semaste                    const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
783254721Semaste                    if (bytes_written > 0)
784254721Semaste                    {
785254721Semaste                        result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
786254721Semaste                                                         bytes_written,
787254721Semaste                                                         append ? "appended" : "written",
788254721Semaste                                                         path);
789254721Semaste                        return true;
790254721Semaste                    }
791254721Semaste                    else
792254721Semaste                    {
793254721Semaste                        result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
794254721Semaste                        result.SetStatus(eReturnStatusFailed);
795254721Semaste                        return false;
796254721Semaste                    }
797254721Semaste                }
798254721Semaste                else
799254721Semaste                {
800254721Semaste                    // We are going to write ASCII to the file just point the
801254721Semaste                    // output_stream to our outfile_stream...
802254721Semaste                    output_stream = &outfile_stream;
803254721Semaste                }
804254721Semaste            }
805254721Semaste            else
806254721Semaste            {
807254721Semaste                result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
808254721Semaste                result.SetStatus(eReturnStatusFailed);
809254721Semaste                return false;
810254721Semaste            }
811254721Semaste        }
812254721Semaste        else
813254721Semaste        {
814254721Semaste            output_stream = &result.GetOutputStream();
815254721Semaste        }
816254721Semaste
817254721Semaste
818254721Semaste        ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
819254721Semaste        if (clang_ast_type.GetOpaqueQualType())
820254721Semaste        {
821254721Semaste            for (uint32_t i = 0; i<item_count; ++i)
822254721Semaste            {
823254721Semaste                addr_t item_addr = addr + (i * item_byte_size);
824254721Semaste                Address address (item_addr);
825254721Semaste                StreamString name_strm;
826254721Semaste                name_strm.Printf ("0x%" PRIx64, item_addr);
827254721Semaste                ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
828254721Semaste                                                                    name_strm.GetString().c_str(),
829254721Semaste                                                                    address,
830254721Semaste                                                                    clang_ast_type));
831254721Semaste                if (valobj_sp)
832254721Semaste                {
833254721Semaste                    Format format = m_format_options.GetFormat();
834254721Semaste                    if (format != eFormatDefault)
835254721Semaste                        valobj_sp->SetFormat (format);
836254721Semaste
837254721Semaste                    ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,format));
838254721Semaste
839254721Semaste                    ValueObject::DumpValueObject (*output_stream,
840254721Semaste                                                  valobj_sp.get(),
841254721Semaste                                                  options);
842254721Semaste                }
843254721Semaste                else
844254721Semaste                {
845254721Semaste                    result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
846254721Semaste                                                  view_as_type_cstr,
847254721Semaste                                                  name_strm.GetString().c_str());
848254721Semaste                    result.SetStatus(eReturnStatusFailed);
849254721Semaste                    return false;
850254721Semaste                }
851254721Semaste            }
852254721Semaste            return true;
853254721Semaste        }
854254721Semaste
855254721Semaste        result.SetStatus(eReturnStatusSuccessFinishResult);
856254721Semaste        DataExtractor data (data_sp,
857254721Semaste                            target->GetArchitecture().GetByteOrder(),
858254721Semaste                            target->GetArchitecture().GetAddressByteSize());
859254721Semaste
860254721Semaste        Format format = m_format_options.GetFormat();
861254721Semaste        if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
862254721Semaste            && (item_byte_size != 1)
863254721Semaste            && (item_count == 1))
864254721Semaste        {
865254721Semaste            // this turns requests such as
866254721Semaste            // memory read -fc -s10 -c1 *charPtrPtr
867254721Semaste            // which make no sense (what is a char of size 10?)
868254721Semaste            // into a request for fetching 10 chars of size 1 from the same memory location
869254721Semaste            format = eFormatCharArray;
870254721Semaste            item_count = item_byte_size;
871254721Semaste            item_byte_size = 1;
872254721Semaste        }
873254721Semaste
874254721Semaste        assert (output_stream);
875254721Semaste        size_t bytes_dumped = data.Dump (output_stream,
876254721Semaste                                         0,
877254721Semaste                                         format,
878254721Semaste                                         item_byte_size,
879254721Semaste                                         item_count,
880254721Semaste                                         num_per_line,
881254721Semaste                                         addr,
882254721Semaste                                         0,
883254721Semaste                                         0,
884254721Semaste                                         exe_scope);
885254721Semaste        m_next_addr = addr + bytes_dumped;
886254721Semaste        output_stream->EOL();
887254721Semaste        return true;
888254721Semaste    }
889254721Semaste
890254721Semaste    OptionGroupOptions m_option_group;
891254721Semaste    OptionGroupFormat m_format_options;
892254721Semaste    OptionGroupReadMemory m_memory_options;
893254721Semaste    OptionGroupOutputFile m_outfile_options;
894254721Semaste    OptionGroupValueObjectDisplay m_varobj_options;
895254721Semaste    lldb::addr_t m_next_addr;
896254721Semaste    lldb::addr_t m_prev_byte_size;
897254721Semaste    OptionGroupFormat m_prev_format_options;
898254721Semaste    OptionGroupReadMemory m_prev_memory_options;
899254721Semaste    OptionGroupOutputFile m_prev_outfile_options;
900254721Semaste    OptionGroupValueObjectDisplay m_prev_varobj_options;
901254721Semaste    ClangASTType m_prev_clang_ast_type;
902254721Semaste};
903254721Semaste
904254721Semaste
905254721SemasteOptionDefinition
906254721Semasteg_memory_write_option_table[] =
907254721Semaste{
908254721Semaste{ LLDB_OPT_SET_1, true,  "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
909254721Semaste{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset,   "Start writng bytes from an offset within the input file."},
910254721Semaste};
911254721Semaste
912254721Semaste
913254721Semaste//----------------------------------------------------------------------
914254721Semaste// Write memory to the inferior process
915254721Semaste//----------------------------------------------------------------------
916254721Semasteclass CommandObjectMemoryWrite : public CommandObjectParsed
917254721Semaste{
918254721Semastepublic:
919254721Semaste
920254721Semaste    class OptionGroupWriteMemory : public OptionGroup
921254721Semaste    {
922254721Semaste    public:
923254721Semaste        OptionGroupWriteMemory () :
924254721Semaste            OptionGroup()
925254721Semaste        {
926254721Semaste        }
927254721Semaste
928254721Semaste        virtual
929254721Semaste        ~OptionGroupWriteMemory ()
930254721Semaste        {
931254721Semaste        }
932254721Semaste
933254721Semaste        virtual uint32_t
934254721Semaste        GetNumDefinitions ()
935254721Semaste        {
936254721Semaste            return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
937254721Semaste        }
938254721Semaste
939254721Semaste        virtual const OptionDefinition*
940254721Semaste        GetDefinitions ()
941254721Semaste        {
942254721Semaste            return g_memory_write_option_table;
943254721Semaste        }
944254721Semaste
945254721Semaste        virtual Error
946254721Semaste        SetOptionValue (CommandInterpreter &interpreter,
947254721Semaste                        uint32_t option_idx,
948254721Semaste                        const char *option_arg)
949254721Semaste        {
950254721Semaste            Error error;
951254721Semaste            const int short_option = g_memory_write_option_table[option_idx].short_option;
952254721Semaste
953254721Semaste            switch (short_option)
954254721Semaste            {
955254721Semaste                case 'i':
956254721Semaste                    m_infile.SetFile (option_arg, true);
957254721Semaste                    if (!m_infile.Exists())
958254721Semaste                    {
959254721Semaste                        m_infile.Clear();
960254721Semaste                        error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
961254721Semaste                    }
962254721Semaste                    break;
963254721Semaste
964254721Semaste                case 'o':
965254721Semaste                    {
966254721Semaste                        bool success;
967254721Semaste                        m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
968254721Semaste                        if (!success)
969254721Semaste                        {
970254721Semaste                            error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
971254721Semaste                        }
972254721Semaste                    }
973254721Semaste                    break;
974254721Semaste
975254721Semaste                default:
976254721Semaste                    error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
977254721Semaste                    break;
978254721Semaste            }
979254721Semaste            return error;
980254721Semaste        }
981254721Semaste
982254721Semaste        virtual void
983254721Semaste        OptionParsingStarting (CommandInterpreter &interpreter)
984254721Semaste        {
985254721Semaste            m_infile.Clear();
986254721Semaste            m_infile_offset = 0;
987254721Semaste        }
988254721Semaste
989254721Semaste        FileSpec m_infile;
990254721Semaste        off_t m_infile_offset;
991254721Semaste    };
992254721Semaste
993254721Semaste    CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
994254721Semaste        CommandObjectParsed (interpreter,
995254721Semaste                             "memory write",
996254721Semaste                             "Write to the memory of the process being debugged.",
997254721Semaste                             NULL,
998254721Semaste                             eFlagRequiresProcess | eFlagProcessMustBeLaunched),
999254721Semaste        m_option_group (interpreter),
1000254721Semaste        m_format_options (eFormatBytes, 1, UINT64_MAX),
1001254721Semaste        m_memory_options ()
1002254721Semaste    {
1003254721Semaste        CommandArgumentEntry arg1;
1004254721Semaste        CommandArgumentEntry arg2;
1005254721Semaste        CommandArgumentData addr_arg;
1006254721Semaste        CommandArgumentData value_arg;
1007254721Semaste
1008254721Semaste        // Define the first (and only) variant of this arg.
1009254721Semaste        addr_arg.arg_type = eArgTypeAddress;
1010254721Semaste        addr_arg.arg_repetition = eArgRepeatPlain;
1011254721Semaste
1012254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
1013254721Semaste        arg1.push_back (addr_arg);
1014254721Semaste
1015254721Semaste        // Define the first (and only) variant of this arg.
1016254721Semaste        value_arg.arg_type = eArgTypeValue;
1017254721Semaste        value_arg.arg_repetition = eArgRepeatPlus;
1018254721Semaste
1019254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
1020254721Semaste        arg2.push_back (value_arg);
1021254721Semaste
1022254721Semaste        // Push the data for the first argument into the m_arguments vector.
1023254721Semaste        m_arguments.push_back (arg1);
1024254721Semaste        m_arguments.push_back (arg2);
1025254721Semaste
1026254721Semaste        m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1027254721Semaste        m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE  , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1028254721Semaste        m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1029254721Semaste        m_option_group.Finalize();
1030254721Semaste
1031254721Semaste    }
1032254721Semaste
1033254721Semaste    virtual
1034254721Semaste    ~CommandObjectMemoryWrite ()
1035254721Semaste    {
1036254721Semaste    }
1037254721Semaste
1038254721Semaste    Options *
1039254721Semaste    GetOptions ()
1040254721Semaste    {
1041254721Semaste        return &m_option_group;
1042254721Semaste    }
1043254721Semaste
1044254721Semaste    bool
1045254721Semaste    UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1046254721Semaste    {
1047254721Semaste        if (total_byte_size > 8)
1048254721Semaste            return false;
1049254721Semaste
1050254721Semaste        if (total_byte_size == 8)
1051254721Semaste            return true;
1052254721Semaste
1053254721Semaste        const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1054254721Semaste        return uval64 <= max;
1055254721Semaste    }
1056254721Semaste
1057254721Semaste    bool
1058254721Semaste    SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1059254721Semaste    {
1060254721Semaste        if (total_byte_size > 8)
1061254721Semaste            return false;
1062254721Semaste
1063254721Semaste        if (total_byte_size == 8)
1064254721Semaste            return true;
1065254721Semaste
1066254721Semaste        const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1067254721Semaste        const int64_t min = ~(max);
1068254721Semaste        return min <= sval64 && sval64 <= max;
1069254721Semaste    }
1070254721Semaste
1071254721Semasteprotected:
1072254721Semaste    virtual bool
1073254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
1074254721Semaste    {
1075254721Semaste        // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1076254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
1077254721Semaste
1078254721Semaste        const size_t argc = command.GetArgumentCount();
1079254721Semaste
1080254721Semaste        if (m_memory_options.m_infile)
1081254721Semaste        {
1082254721Semaste            if (argc < 1)
1083254721Semaste            {
1084254721Semaste                result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1085254721Semaste                result.SetStatus(eReturnStatusFailed);
1086254721Semaste                return false;
1087254721Semaste            }
1088254721Semaste        }
1089254721Semaste        else if (argc < 2)
1090254721Semaste        {
1091254721Semaste            result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
1092254721Semaste            result.SetStatus(eReturnStatusFailed);
1093254721Semaste            return false;
1094254721Semaste        }
1095254721Semaste
1096254721Semaste        StreamString buffer (Stream::eBinary,
1097254721Semaste                             process->GetTarget().GetArchitecture().GetAddressByteSize(),
1098254721Semaste                             process->GetTarget().GetArchitecture().GetByteOrder());
1099254721Semaste
1100254721Semaste        OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1101254721Semaste        size_t item_byte_size = byte_size_value.GetCurrentValue();
1102254721Semaste
1103254721Semaste        Error error;
1104254721Semaste        lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1105254721Semaste                                                   command.GetArgumentAtIndex(0),
1106254721Semaste                                                   LLDB_INVALID_ADDRESS,
1107254721Semaste                                                   &error);
1108254721Semaste
1109254721Semaste        if (addr == LLDB_INVALID_ADDRESS)
1110254721Semaste        {
1111254721Semaste            result.AppendError("invalid address expression\n");
1112254721Semaste            result.AppendError(error.AsCString());
1113254721Semaste            result.SetStatus(eReturnStatusFailed);
1114254721Semaste            return false;
1115254721Semaste        }
1116254721Semaste
1117254721Semaste        if (m_memory_options.m_infile)
1118254721Semaste        {
1119254721Semaste            size_t length = SIZE_MAX;
1120254721Semaste            if (item_byte_size > 0)
1121254721Semaste                length = item_byte_size;
1122254721Semaste            lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
1123254721Semaste            if (data_sp)
1124254721Semaste            {
1125254721Semaste                length = data_sp->GetByteSize();
1126254721Semaste                if (length > 0)
1127254721Semaste                {
1128254721Semaste                    Error error;
1129254721Semaste                    size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1130254721Semaste
1131254721Semaste                    if (bytes_written == length)
1132254721Semaste                    {
1133254721Semaste                        // All bytes written
1134254721Semaste                        result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
1135254721Semaste                        result.SetStatus(eReturnStatusSuccessFinishResult);
1136254721Semaste                    }
1137254721Semaste                    else if (bytes_written > 0)
1138254721Semaste                    {
1139254721Semaste                        // Some byte written
1140254721Semaste                        result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr);
1141254721Semaste                        result.SetStatus(eReturnStatusSuccessFinishResult);
1142254721Semaste                    }
1143254721Semaste                    else
1144254721Semaste                    {
1145254721Semaste                        result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1146254721Semaste                        result.SetStatus(eReturnStatusFailed);
1147254721Semaste                    }
1148254721Semaste                }
1149254721Semaste            }
1150254721Semaste            else
1151254721Semaste            {
1152254721Semaste                result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1153254721Semaste                result.SetStatus(eReturnStatusFailed);
1154254721Semaste            }
1155254721Semaste            return result.Succeeded();
1156254721Semaste        }
1157254721Semaste        else if (item_byte_size == 0)
1158254721Semaste        {
1159254721Semaste            if (m_format_options.GetFormat() == eFormatPointer)
1160254721Semaste                item_byte_size = buffer.GetAddressByteSize();
1161254721Semaste            else
1162254721Semaste                item_byte_size = 1;
1163254721Semaste        }
1164254721Semaste
1165254721Semaste        command.Shift(); // shift off the address argument
1166254721Semaste        uint64_t uval64;
1167254721Semaste        int64_t sval64;
1168254721Semaste        bool success = false;
1169254721Semaste        const size_t num_value_args = command.GetArgumentCount();
1170254721Semaste        for (size_t i=0; i<num_value_args; ++i)
1171254721Semaste        {
1172254721Semaste            const char *value_str = command.GetArgumentAtIndex(i);
1173254721Semaste
1174254721Semaste            switch (m_format_options.GetFormat())
1175254721Semaste            {
1176254721Semaste            case kNumFormats:
1177254721Semaste            case eFormatFloat:  // TODO: add support for floats soon
1178254721Semaste            case eFormatCharPrintable:
1179254721Semaste            case eFormatBytesWithASCII:
1180254721Semaste            case eFormatComplex:
1181254721Semaste            case eFormatEnum:
1182254721Semaste            case eFormatUnicode16:
1183254721Semaste            case eFormatUnicode32:
1184254721Semaste            case eFormatVectorOfChar:
1185254721Semaste            case eFormatVectorOfSInt8:
1186254721Semaste            case eFormatVectorOfUInt8:
1187254721Semaste            case eFormatVectorOfSInt16:
1188254721Semaste            case eFormatVectorOfUInt16:
1189254721Semaste            case eFormatVectorOfSInt32:
1190254721Semaste            case eFormatVectorOfUInt32:
1191254721Semaste            case eFormatVectorOfSInt64:
1192254721Semaste            case eFormatVectorOfUInt64:
1193254721Semaste            case eFormatVectorOfFloat32:
1194254721Semaste            case eFormatVectorOfFloat64:
1195254721Semaste            case eFormatVectorOfUInt128:
1196254721Semaste            case eFormatOSType:
1197254721Semaste            case eFormatComplexInteger:
1198254721Semaste            case eFormatAddressInfo:
1199254721Semaste            case eFormatHexFloat:
1200254721Semaste            case eFormatInstruction:
1201254721Semaste            case eFormatVoid:
1202254721Semaste                result.AppendError("unsupported format for writing memory");
1203254721Semaste                result.SetStatus(eReturnStatusFailed);
1204254721Semaste                return false;
1205254721Semaste
1206254721Semaste            case eFormatDefault:
1207254721Semaste            case eFormatBytes:
1208254721Semaste            case eFormatHex:
1209254721Semaste            case eFormatHexUppercase:
1210254721Semaste            case eFormatPointer:
1211254721Semaste
1212254721Semaste                // Decode hex bytes
1213254721Semaste                uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1214254721Semaste                if (!success)
1215254721Semaste                {
1216254721Semaste                    result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1217254721Semaste                    result.SetStatus(eReturnStatusFailed);
1218254721Semaste                    return false;
1219254721Semaste                }
1220254721Semaste                else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1221254721Semaste                {
1222254721Semaste                    result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1223254721Semaste                    result.SetStatus(eReturnStatusFailed);
1224254721Semaste                    return false;
1225254721Semaste                }
1226254721Semaste                buffer.PutMaxHex64 (uval64, item_byte_size);
1227254721Semaste                break;
1228254721Semaste
1229254721Semaste            case eFormatBoolean:
1230254721Semaste                uval64 = Args::StringToBoolean(value_str, false, &success);
1231254721Semaste                if (!success)
1232254721Semaste                {
1233254721Semaste                    result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1234254721Semaste                    result.SetStatus(eReturnStatusFailed);
1235254721Semaste                    return false;
1236254721Semaste                }
1237254721Semaste                buffer.PutMaxHex64 (uval64, item_byte_size);
1238254721Semaste                break;
1239254721Semaste
1240254721Semaste            case eFormatBinary:
1241254721Semaste                uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1242254721Semaste                if (!success)
1243254721Semaste                {
1244254721Semaste                    result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1245254721Semaste                    result.SetStatus(eReturnStatusFailed);
1246254721Semaste                    return false;
1247254721Semaste                }
1248254721Semaste                else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1249254721Semaste                {
1250254721Semaste                    result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1251254721Semaste                    result.SetStatus(eReturnStatusFailed);
1252254721Semaste                    return false;
1253254721Semaste                }
1254254721Semaste                buffer.PutMaxHex64 (uval64, item_byte_size);
1255254721Semaste                break;
1256254721Semaste
1257254721Semaste            case eFormatCharArray:
1258254721Semaste            case eFormatChar:
1259254721Semaste            case eFormatCString:
1260254721Semaste                if (value_str[0])
1261254721Semaste                {
1262254721Semaste                    size_t len = strlen (value_str);
1263254721Semaste                    // Include the NULL for C strings...
1264254721Semaste                    if (m_format_options.GetFormat() == eFormatCString)
1265254721Semaste                        ++len;
1266254721Semaste                    Error error;
1267254721Semaste                    if (process->WriteMemory (addr, value_str, len, error) == len)
1268254721Semaste                    {
1269254721Semaste                        addr += len;
1270254721Semaste                    }
1271254721Semaste                    else
1272254721Semaste                    {
1273254721Semaste                        result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1274254721Semaste                        result.SetStatus(eReturnStatusFailed);
1275254721Semaste                        return false;
1276254721Semaste                    }
1277254721Semaste                }
1278254721Semaste                break;
1279254721Semaste
1280254721Semaste            case eFormatDecimal:
1281254721Semaste                sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1282254721Semaste                if (!success)
1283254721Semaste                {
1284254721Semaste                    result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1285254721Semaste                    result.SetStatus(eReturnStatusFailed);
1286254721Semaste                    return false;
1287254721Semaste                }
1288254721Semaste                else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1289254721Semaste                {
1290254721Semaste                    result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
1291254721Semaste                    result.SetStatus(eReturnStatusFailed);
1292254721Semaste                    return false;
1293254721Semaste                }
1294254721Semaste                buffer.PutMaxHex64 (sval64, item_byte_size);
1295254721Semaste                break;
1296254721Semaste
1297254721Semaste            case eFormatUnsigned:
1298254721Semaste                uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1299254721Semaste                if (!success)
1300254721Semaste                {
1301254721Semaste                    result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1302254721Semaste                    result.SetStatus(eReturnStatusFailed);
1303254721Semaste                    return false;
1304254721Semaste                }
1305254721Semaste                else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1306254721Semaste                {
1307254721Semaste                    result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1308254721Semaste                    result.SetStatus(eReturnStatusFailed);
1309254721Semaste                    return false;
1310254721Semaste                }
1311254721Semaste                buffer.PutMaxHex64 (uval64, item_byte_size);
1312254721Semaste                break;
1313254721Semaste
1314254721Semaste            case eFormatOctal:
1315254721Semaste                uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1316254721Semaste                if (!success)
1317254721Semaste                {
1318254721Semaste                    result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1319254721Semaste                    result.SetStatus(eReturnStatusFailed);
1320254721Semaste                    return false;
1321254721Semaste                }
1322254721Semaste                else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1323254721Semaste                {
1324254721Semaste                    result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1325254721Semaste                    result.SetStatus(eReturnStatusFailed);
1326254721Semaste                    return false;
1327254721Semaste                }
1328254721Semaste                buffer.PutMaxHex64 (uval64, item_byte_size);
1329254721Semaste                break;
1330254721Semaste            }
1331254721Semaste        }
1332254721Semaste
1333254721Semaste        if (!buffer.GetString().empty())
1334254721Semaste        {
1335254721Semaste            Error error;
1336254721Semaste            if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
1337254721Semaste                return true;
1338254721Semaste            else
1339254721Semaste            {
1340254721Semaste                result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1341254721Semaste                result.SetStatus(eReturnStatusFailed);
1342254721Semaste                return false;
1343254721Semaste            }
1344254721Semaste        }
1345254721Semaste        return true;
1346254721Semaste    }
1347254721Semaste
1348254721Semaste    OptionGroupOptions m_option_group;
1349254721Semaste    OptionGroupFormat m_format_options;
1350254721Semaste    OptionGroupWriteMemory m_memory_options;
1351254721Semaste};
1352254721Semaste
1353254721Semaste
1354254721Semaste//-------------------------------------------------------------------------
1355254721Semaste// CommandObjectMemory
1356254721Semaste//-------------------------------------------------------------------------
1357254721Semaste
1358254721SemasteCommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
1359254721Semaste    CommandObjectMultiword (interpreter,
1360254721Semaste                            "memory",
1361254721Semaste                            "A set of commands for operating on memory.",
1362254721Semaste                            "memory <subcommand> [<subcommand-options>]")
1363254721Semaste{
1364254721Semaste    LoadSubCommand ("read",  CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1365254721Semaste    LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
1366254721Semaste}
1367254721Semaste
1368254721SemasteCommandObjectMemory::~CommandObjectMemory ()
1369254721Semaste{
1370254721Semaste}
1371