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