Beispiel #1
0
    virtual bool
    Execute (Args& command,
             CommandReturnObject &result)
    {
        Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
        if (process == NULL)
        {
            result.AppendError("need a process to read memory");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }
        const size_t argc = command.GetArgumentCount();

        if (argc == 0 || argc > 2)
        {
            result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        size_t item_byte_size = m_options.m_byte_size;
        if (item_byte_size == 0)
        {
            if (m_options.m_format == eFormatPointer)
                item_byte_size = process->GetTarget().GetArchitecture().GetAddressByteSize();
            else
                item_byte_size = 1;
        }

        size_t item_count = m_options.m_count;

        size_t num_per_line = m_options.m_num_per_line;
        if (num_per_line == 0)
        {
            num_per_line = (16/item_byte_size);
            if (num_per_line == 0)
                num_per_line = 1;
        }

        size_t total_byte_size = m_options.m_count * item_byte_size;
        if (total_byte_size == 0)
            total_byte_size = 32;

        lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);

        if (addr == LLDB_INVALID_ADDRESS)
        {
            result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        if (argc == 2)
        {
            lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
            if (end_addr == LLDB_INVALID_ADDRESS)
            {
                result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else if (end_addr <= addr)
            {
                result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else if (item_count != 0)
            {
                result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            total_byte_size = end_addr - addr;
            item_count = total_byte_size / item_byte_size;
        }
        else
        {
            if (item_count == 0)
                item_count = 32;
        }

        DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0'));
        Error error;
        size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
        if (bytes_read == 0)
        {
            result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
            result.AppendError(error.AsCString());
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        if (bytes_read < total_byte_size)
            result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);

        result.SetStatus(eReturnStatusSuccessFinishResult);
        DataExtractor data (data_sp, 
                            process->GetTarget().GetArchitecture().GetByteOrder(), 
                            process->GetTarget().GetArchitecture().GetAddressByteSize());

        StreamFile outfile_stream;
        Stream *output_stream = NULL;

        if (m_options.m_outfile_filespec)
        {
            char path[PATH_MAX];
            m_options.m_outfile_filespec.GetPath (path, sizeof(path));
            char mode[16] = { 'w', '\0' };
            if (m_options.m_append_to_outfile)
                mode[0] = 'a';
                
            if (outfile_stream.GetFile ().Open (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
            {
                if (m_options.m_output_as_binary)
                {
                    int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
                    if (bytes_written > 0)
                    {
                        result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", 
                                                         bytes_written, 
                                                         m_options.m_append_to_outfile ? "appended" : "written", 
                                                         path);
                        return true;
                    }
                    else 
                    {
                        result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
                        result.SetStatus(eReturnStatusFailed);
                        return false;
                    }
                }
                else
                {
                    // We are going to write ASCII to the file just point the
                    // output_stream to our outfile_stream...
                    output_stream = &outfile_stream;
                }
            }
            else 
            {
                result.AppendErrorWithFormat("Failed to open file '%s' with a mode of '%s'.\n", path, mode);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
        }
        else 
        {
            output_stream = &result.GetOutputStream();
        }

        assert (output_stream);
        data.Dump (output_stream,
                   0,
                   m_options.m_format,
                   item_byte_size,
                   item_count,
                   num_per_line,
                   addr,
                   0,
                   0);
        output_stream->EOL();
        return true;
    }
bool
CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
{
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target == NULL)
    {
        result.AppendError ("invalid target, create a debug target using the 'target create' command");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    if (!m_options.arch.IsValid())
        m_options.arch = target->GetArchitecture();

    if (!m_options.arch.IsValid())
    {
        result.AppendError ("use the --arch option or set the target architecure to disassemble");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }

    const char *plugin_name = m_options.GetPluginName ();
    const char *flavor_string = m_options.GetFlavorString();

    DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name);

    if (!disassembler)
    {
        if (plugin_name)
        {
            result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n",
                                          plugin_name,
                                          m_options.arch.GetArchitectureName());
        }
        else
            result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n", 
                                          m_options.arch.GetArchitectureName());
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    else if (flavor_string != NULL && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string))
        result.AppendWarningWithFormat("invalid disassembler flavor \"%s\", using default.\n", flavor_string);

    result.SetStatus (eReturnStatusSuccessFinishResult);

    if (command.GetArgumentCount() != 0)
    {
        result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n");
        GetOptions()->GenerateOptionUsage (result.GetErrorStream(), this);
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    
    if (m_options.show_mixed && m_options.num_lines_context == 0)
        m_options.num_lines_context = 1;

    // Always show the PC in the disassembly
    uint32_t options = Disassembler::eOptionMarkPCAddress;

    // Mark the source line for the current PC only if we are doing mixed source and assembly
    if (m_options.show_mixed)
        options |= Disassembler::eOptionMarkPCSourceLine;

    if (m_options.show_bytes)
        options |= Disassembler::eOptionShowBytes;

    if (m_options.raw)
        options |= Disassembler::eOptionRawOuput;

    if (!m_options.func_name.empty())
    {
        ConstString name(m_options.func_name.c_str());
        
        if (Disassembler::Disassemble (m_interpreter.GetDebugger(), 
                                       m_options.arch,
                                       plugin_name,
                                       flavor_string,
                                       m_exe_ctx,
                                       name,
                                       NULL,    // Module *
                                       m_options.num_instructions,
                                       m_options.show_mixed ? m_options.num_lines_context : 0,
                                       options,
                                       result.GetOutputStream()))
        {
            result.SetStatus (eReturnStatusSuccessFinishResult);
        }
        else
        {
            result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
            result.SetStatus (eReturnStatusFailed);
        }
    } 
    else
    {
        std::vector<AddressRange> ranges;
        AddressRange range;
        StackFrame *frame = m_exe_ctx.GetFramePtr();
        if (m_options.frame_line)
        {
            if (frame == NULL)
            {
                result.AppendError ("Cannot disassemble around the current line without a selected frame.\n");
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            LineEntry pc_line_entry (frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
            if (pc_line_entry.IsValid())
            {
                range = pc_line_entry.range;
            }
            else
            {
                m_options.at_pc = true; // No line entry, so just disassemble around the current pc
                m_options.show_mixed = false;
            }
        }
        else if (m_options.current_function)
        {
            if (frame == NULL)
            {
                result.AppendError ("Cannot disassemble around the current function without a selected frame.\n");
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
            if (symbol)
            {
                range.GetBaseAddress() = symbol->GetAddress();
                range.SetByteSize(symbol->GetByteSize());
            }
        }

        // Did the "m_options.frame_line" find a valid range already? If so
        // skip the rest...
        if (range.GetByteSize() == 0)
        {
            if (m_options.at_pc)
            {
                if (frame == NULL)
                {
                    result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
                range.GetBaseAddress() = frame->GetFrameCodeAddress();
                if (m_options.num_instructions == 0)
                {
                    // Disassembling at the PC always disassembles some number of instructions (not the whole function).
                    m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
                }
                ranges.push_back(range);
            }
            else
            {
                range.GetBaseAddress().SetOffset (m_options.start_addr);
                if (range.GetBaseAddress().IsValid())
                {
                    if (m_options.end_addr != LLDB_INVALID_ADDRESS)
                    {
                        if (m_options.end_addr <= m_options.start_addr)
                        {
                            result.AppendErrorWithFormat ("End address before start address.\n");
                            result.SetStatus (eReturnStatusFailed);
                            return false;            
                        }
                        range.SetByteSize (m_options.end_addr - m_options.start_addr);
                    }
                    ranges.push_back(range);
                }
                else
                {
                    if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS 
                        && target)
                    {
                        if (!target->GetSectionLoadList().IsEmpty())
                        {
                            bool failed = false;
                            Address symbol_containing_address;
                            if (target->GetSectionLoadList().ResolveLoadAddress (m_options.symbol_containing_addr, symbol_containing_address))
                            {
                                ModuleSP module_sp (symbol_containing_address.GetModule());
                                SymbolContext sc;
                                bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
                                module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc,
                                                                           resolve_tail_call_address);
                                if (sc.function || sc.symbol)
                                {
                                    sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
                                }
                                else
                                {
                                    failed = true;
                                }
                            }
                            else
                            {
                                failed = true;
                            }
                            if (failed)
                            {
                                result.AppendErrorWithFormat ("Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr);
                                result.SetStatus (eReturnStatusFailed);
                                return false;
                            }
                            ranges.push_back(range);
                        }
                        else
                        {
                            for (lldb::ModuleSP module_sp : target->GetImages().Modules())
                            {
                                lldb::addr_t file_addr = m_options.symbol_containing_addr;
                                Address file_address;
                                if (module_sp->ResolveFileAddress(file_addr, file_address))
                                {
                                    SymbolContext sc;
                                    bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
                                    module_sp->ResolveSymbolContextForAddress (file_address, eSymbolContextEverything, sc, resolve_tail_call_address);
                                    if (sc.function || sc.symbol)
                                    {
                                        sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
                                        ranges.push_back(range);
                                    }
                                }
                            }
                            
                        }
                    }
                }
            }
        }
        else
            ranges.push_back(range);

        if (m_options.num_instructions != 0)
        {
            if (ranges.size() == 0)
            {
                // The default action is to disassemble the current frame function.
                if (frame)
                {
                    SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
                    if (sc.function)
                        range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress();
                    else if (sc.symbol && sc.symbol->ValueIsAddress())
                        range.GetBaseAddress() = sc.symbol->GetAddress();
                    else
                        range.GetBaseAddress() = frame->GetFrameCodeAddress();
                }
                
                if (!range.GetBaseAddress().IsValid())
                {
                    result.AppendError ("invalid frame");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            
            bool print_sc_header = ranges.size() > 1;
            for (AddressRange cur_range : ranges)
            {
                if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
                                               m_options.arch,
                                               plugin_name,
                                               flavor_string,
                                               m_exe_ctx,
                                               cur_range.GetBaseAddress(),
                                               m_options.num_instructions,
                                               m_options.show_mixed ? m_options.num_lines_context : 0,
                                               options,
                                               result.GetOutputStream()))
                {
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
                else
                {
                    if (m_options.start_addr != LLDB_INVALID_ADDRESS)
                        result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
                    else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS)
                        result.AppendErrorWithFormat ("Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", m_options.symbol_containing_addr);
                    result.SetStatus (eReturnStatusFailed);
                }
            }
            if (print_sc_header)
                result.AppendMessage("\n");
        }
        else
        {
            if (ranges.size() == 0)
            {
                // The default action is to disassemble the current frame function.
                if (frame)
                {
                    SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
                    if (sc.function)
                        range = sc.function->GetAddressRange();
                    else if (sc.symbol && sc.symbol->ValueIsAddress())
                    {
                        range.GetBaseAddress() = sc.symbol->GetAddress();
                        range.SetByteSize (sc.symbol->GetByteSize());
                    }
                    else
                        range.GetBaseAddress() = frame->GetFrameCodeAddress();
                }
                else
                {
                    result.AppendError ("invalid frame");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
                ranges.push_back(range);
            }
            
            bool print_sc_header = ranges.size() > 1;
            for (AddressRange cur_range : ranges)
            {
                if (cur_range.GetByteSize() == 0)
                    cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);

                if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
                                               m_options.arch,
                                               plugin_name,
                                               flavor_string,
                                               m_exe_ctx,
                                               cur_range,
                                               m_options.num_instructions,
                                               m_options.show_mixed ? m_options.num_lines_context : 0,
                                               options,
                                               result.GetOutputStream()))
                {
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
                else
                {
                    result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
                    result.SetStatus (eReturnStatusFailed);            
                }
                if (print_sc_header)
                    result.AppendMessage("\n");
            }
        }
    }

    return result.Succeeded();
}
Beispiel #3
0
    virtual bool
    DoExecute (Args& command,
             CommandReturnObject &result)
    {
        ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
        Target *target = exe_ctx.GetTargetPtr();
        if (target == NULL)
        {
            result.AppendError("need at least a target to read memory");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }
        const size_t argc = command.GetArgumentCount();

        
        if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
        {
            result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        ClangASTType clang_ast_type;        
        Error error;

        Format format = m_format_options.GetFormat();
        const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
        if (view_as_type_cstr && view_as_type_cstr[0])
        {
            // We are viewing memory as a type
            SymbolContext sc;
            const bool exact_match = false;
            TypeList type_list;
            uint32_t reference_count = 0;
            uint32_t pointer_count = 0;
            size_t idx;
            
#define ALL_KEYWORDS        \
    KEYWORD("const")        \
    KEYWORD("volatile")     \
    KEYWORD("restrict")     \
    KEYWORD("struct")       \
    KEYWORD("class")        \
    KEYWORD("union")
            
#define KEYWORD(s) s,
            static const char *g_keywords[] =
            {
                ALL_KEYWORDS
            };
#undef KEYWORD

#define KEYWORD(s) (sizeof(s) - 1),
            static const int g_keyword_lengths[] =
            {
                ALL_KEYWORDS
            };
#undef KEYWORD
            
#undef ALL_KEYWORDS
            
            static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
            std::string type_str(view_as_type_cstr);
            
            // Remove all instances of g_keywords that are followed by spaces
            for (size_t i = 0; i < g_num_keywords; ++i)
            {
                const char *keyword = g_keywords[i];
                int keyword_len = g_keyword_lengths[i];
                
                idx = 0;
                while ((idx = type_str.find (keyword, idx)) != std::string::npos)
                {
                    if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
                    {
                        type_str.erase(idx, keyword_len+1);
                        idx = 0;
                    }
                    else
                    {
                        idx += keyword_len;
                    }
                }
            }
            bool done = type_str.empty();
            // 
            idx = type_str.find_first_not_of (" \t");
            if (idx > 0 && idx != std::string::npos)
                type_str.erase (0, idx);
            while (!done)
            {
                // Strip trailing spaces
                if (type_str.empty())
                    done = true;
                else
                {
                    switch (type_str[type_str.size()-1])
                    {
                    case '*':
                        ++pointer_count;
                        // fall through...
                    case ' ':
                    case '\t':
                        type_str.erase(type_str.size()-1);
                        break;

                    case '&':
                        if (reference_count == 0)
                        {
                            reference_count = 1;
                            type_str.erase(type_str.size()-1);
                        }
                        else
                        {
                            result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
                            result.SetStatus(eReturnStatusFailed);
                            return false;
                        }
                        break;

                    default:
                        done = true;
                        break;
                    }
                }
            }
                    
            ConstString lookup_type_name(type_str.c_str());
            StackFrame *frame = exe_ctx.GetFramePtr();
            if (frame)
            {
                sc = frame->GetSymbolContext (eSymbolContextModule);
                if (sc.module_sp)
                {
                    sc.module_sp->FindTypes (sc,
                                             lookup_type_name,
                                             exact_match,
                                             1, 
                                             type_list);
                }
            }
            if (type_list.GetSize() == 0)
            {
                target->GetImages().FindTypes (sc, 
                                               lookup_type_name, 
                                               exact_match, 
                                               1, 
                                               type_list);
            }
            
            if (type_list.GetSize() == 0)
            {
                result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", 
                                              lookup_type_name.GetCString(), 
                                              view_as_type_cstr);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            
            TypeSP type_sp (type_list.GetTypeAtIndex(0));
            clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
            
            while (pointer_count > 0)
            {
                clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
                if (pointer_type)
                    clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
                else
                {
                    result.AppendError ("unable make a pointer type\n");
                    result.SetStatus(eReturnStatusFailed);
                    return false;
                }
                --pointer_count;
            }

            m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
            
            if (m_format_options.GetByteSizeValue() == 0)
            {
                result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 
                                              view_as_type_cstr);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            
            if (!m_format_options.GetCountValue().OptionWasSet())
                m_format_options.GetCountValue() = 1;
        }
        else
        {
            error = m_memory_options.FinalizeSettings (target, m_format_options);
        }

        // Look for invalid combinations of settings
        if (error.Fail())
        {
            result.AppendErrorWithFormat("%s", error.AsCString());
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        lldb::addr_t addr;
        size_t total_byte_size = 0;
        if (argc == 0)
        {
            // Use the last address and byte size and all options as they were
            // if no options have been set
            addr = m_next_addr;
            total_byte_size = m_prev_byte_size;
            if (!m_format_options.AnyOptionWasSet() && 
                !m_memory_options.AnyOptionWasSet() &&
                !m_outfile_options.AnyOptionWasSet() &&
                !m_varobj_options.AnyOptionWasSet())
            {
                m_format_options = m_prev_format_options;
                m_memory_options = m_prev_memory_options;
                m_outfile_options = m_prev_outfile_options;
                m_varobj_options = m_prev_varobj_options;
            }
        }

        size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
        const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
        const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();

        if (total_byte_size == 0)
        {
            total_byte_size = item_count * item_byte_size;
            if (total_byte_size == 0)
                total_byte_size = 32;
        }

        if (argc > 0)
            addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);

        if (addr == LLDB_INVALID_ADDRESS)
        {
            result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        if (argc == 2)
        {
            lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
            if (end_addr == LLDB_INVALID_ADDRESS)
            {
                result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else if (end_addr <= addr)
            {
                result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else if (m_format_options.GetCountValue().OptionWasSet())
            {
                result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            total_byte_size = end_addr - addr;
            item_count = total_byte_size / item_byte_size;
        }
        
        if (total_byte_size > 1024 && !m_memory_options.m_force)
        {
            result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
            result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
            return false;
        }
        
        DataBufferSP data_sp;
        size_t bytes_read = 0;
        if (!clang_ast_type.GetOpaqueQualType())
        {
            data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
            Address address(addr, NULL);
            bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
            if (bytes_read == 0)
            {
                const char *error_cstr = error.AsCString();
                if (error_cstr && error_cstr[0])
                {
                    result.AppendError(error_cstr);
                }
                else
                {
                    result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr);
                }
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            
            if (bytes_read < total_byte_size)
                result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
            else
            {
                m_next_addr = addr + bytes_read;
                m_prev_byte_size = bytes_read; 
                m_prev_format_options = m_format_options;
                m_prev_memory_options = m_memory_options;
                m_prev_outfile_options = m_outfile_options;
                m_prev_varobj_options = m_varobj_options;
            }
        }

        StreamFile outfile_stream;
        Stream *output_stream = NULL;
        const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
        if (outfile_spec)
        {
            char path[PATH_MAX];
            outfile_spec.GetPath (path, sizeof(path));
            
            uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
            const bool append = m_outfile_options.GetAppend().GetCurrentValue();
            if (append)
                open_options |= File::eOpenOptionAppend;
            
            if (outfile_stream.GetFile ().Open (path, open_options).Success())
            {
                if (m_memory_options.m_output_as_binary)
                {
                    int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
                    if (bytes_written > 0)
                    {
                        result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", 
                                                         bytes_written, 
                                                         append ? "appended" : "written", 
                                                         path);
                        return true;
                    }
                    else 
                    {
                        result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
                        result.SetStatus(eReturnStatusFailed);
                        return false;
                    }
                }
                else
                {
                    // We are going to write ASCII to the file just point the
                    // output_stream to our outfile_stream...
                    output_stream = &outfile_stream;
                }
            }
            else 
            {
                result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
        }
        else 
        {
            output_stream = &result.GetOutputStream();
        }


        ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
        if (clang_ast_type.GetOpaqueQualType())
        {
            for (uint32_t i = 0; i<item_count; ++i)
            {
                addr_t item_addr = addr + (i * item_byte_size);
                Address address (item_addr);
                StreamString name_strm;
                name_strm.Printf ("0x%llx", item_addr);
                ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 
                                                                    name_strm.GetString().c_str(), 
                                                                    address, 
                                                                    clang_ast_type));
                if (valobj_sp)
                {
                    if (format != eFormatDefault)
                        valobj_sp->SetFormat (format);

                    bool scope_already_checked = true;
                    
                    ValueObject::DumpValueObjectOptions options;
                    options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
                    .SetMaximumDepth(m_varobj_options.max_depth)
                    .SetShowLocation(m_varobj_options.show_location)
                    .SetShowTypes(m_varobj_options.show_types)
                    .SetUseObjectiveC(m_varobj_options.use_objc)
                    .SetScopeChecked(scope_already_checked)
                    .SetFlatOutput(m_varobj_options.flat_output)
                    .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
                    .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
                    .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
                    .SetFormat(format)
                    .SetSummary();
                    ValueObject::DumpValueObject (*output_stream,
                                                  valobj_sp.get(),
                                                  options);
                }
                else
                {
                    result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 
                                                  view_as_type_cstr, 
                                                  name_strm.GetString().c_str());
                    result.SetStatus(eReturnStatusFailed);
                    return false;
                }
            }
            return true;
        }

        result.SetStatus(eReturnStatusSuccessFinishResult);
        DataExtractor data (data_sp, 
                            target->GetArchitecture().GetByteOrder(), 
                            target->GetArchitecture().GetAddressByteSize());


        assert (output_stream);
        uint32_t bytes_dumped = data.Dump (output_stream,
                                           0,
                                           m_format_options.GetFormat(),
                                           item_byte_size,
                                           item_count,
                                           num_per_line,
                                           addr,
                                           0,
                                           0,
                                           exe_scope);
        m_next_addr = addr + bytes_dumped;
        output_stream->EOL();
        return true;
    }