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