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