Ejemplo n.º 1
0
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
        StackFrame *frame = exe_ctx.GetFramePtr();
        if (frame == NULL)
        {
            result.AppendError ("you must be stopped in a valid stack frame to view frame variables.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Stream &s = result.GetOutputStream();

        bool get_file_globals = true;
        
        // Be careful about the stack frame, if any summary formatter runs code, it might clear the StackFrameList
        // for the thread.  So hold onto a shared pointer to the frame so it stays alive.
        
        VariableList *variable_list = frame->GetVariableList (get_file_globals);

        VariableSP var_sp;
        ValueObjectSP valobj_sp;

        const char *name_cstr = NULL;
        size_t idx;
        
        TypeSummaryImplSP summary_format_sp;
        if (!m_option_variable.summary.IsCurrentValueEmpty())
            DataVisualization::NamedSummaryFormats::GetSummaryFormat(ConstString(m_option_variable.summary.GetCurrentValue()), summary_format_sp);
        else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
            summary_format_sp.reset(new StringSummaryFormat(TypeSummaryImpl::Flags(),m_option_variable.summary_string.GetCurrentValue()));
        
        ValueObject::DumpValueObjectOptions options;
        
        options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
            .SetMaximumDepth(m_varobj_options.max_depth)
            .SetShowTypes(m_varobj_options.show_types)
            .SetShowLocation(m_varobj_options.show_location)
            .SetUseObjectiveC(m_varobj_options.use_objc)
            .SetUseDynamicType(m_varobj_options.use_dynamic)
            .SetUseSyntheticValue(m_varobj_options.use_synth)
            .SetFlatOutput(m_varobj_options.flat_output)
            .SetOmitSummaryDepth(m_varobj_options.no_summary_depth)
            .SetIgnoreCap(m_varobj_options.ignore_cap)
            .SetSummary(summary_format_sp);

        if (m_varobj_options.be_raw)
            options.SetRawDisplay(true);
        
        if (variable_list)
        {
            const Format format = m_option_format.GetFormat();
            options.SetFormat(format);

            if (command.GetArgumentCount() > 0)
            {
                VariableList regex_var_list;

                // If we have any args to the variable command, we will make
                // variable objects from them...
                for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx)
                {
                    if (m_option_variable.use_regex)
                    {
                        const uint32_t regex_start_index = regex_var_list.GetSize();
                        RegularExpression regex (name_cstr);
                        if (regex.Compile(name_cstr))
                        {
                            size_t num_matches = 0;
                            const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, 
                                                                                                     regex_var_list, 
                                                                                                     num_matches);
                            if (num_new_regex_vars > 0)
                            {
                                for (uint32_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize(); 
                                     regex_idx < end_index;
                                     ++regex_idx)
                                {
                                    var_sp = regex_var_list.GetVariableAtIndex (regex_idx);
                                    if (var_sp)
                                    {
                                        valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic);
                                        if (valobj_sp)
                                        {
//                                            if (format != eFormatDefault)
//                                                valobj_sp->SetFormat (format);
                                            
                                            if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile())
                                            {
                                                bool show_fullpaths = false;
                                                bool show_module = true;
                                                if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
                                                    s.PutCString (": ");
                                            }
                                            ValueObject::DumpValueObject (result.GetOutputStream(), 
                                                                          valobj_sp.get(),
                                                                          options);
                                        }
                                    }
                                }
                            }
                            else if (num_matches == 0)
                            {
                                result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr);
                            }
                        }
                        else
                        {
                            char regex_error[1024];
                            if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
                                result.GetErrorStream().Printf ("error: %s\n", regex_error);
                            else
                                result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr);
                        }
                    }
                    else // No regex, either exact variable names or variable expressions.
                    {
                        Error error;
                        uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
                                                     StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
                        lldb::VariableSP var_sp;
                        valobj_sp = frame->GetValueForVariableExpressionPath (name_cstr, 
                                                                              m_varobj_options.use_dynamic, 
                                                                              expr_path_options,
                                                                              var_sp,
                                                                              error);
                        if (valobj_sp)
                        {
//                            if (format != eFormatDefault)
//                                valobj_sp->SetFormat (format);
                            if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration ().GetFile())
                            {
                                var_sp->GetDeclaration ().DumpStopContext (&s, false);
                                s.PutCString (": ");
                            }
                            
                            options.SetFormat(format);

                            Stream &output_stream = result.GetOutputStream();
                            options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL);
                            ValueObject::DumpValueObject (output_stream, 
                                                          valobj_sp.get(), 
                                                          options);
                        }
                        else
                        {
                            const char *error_cstr = error.AsCString(NULL);
                            if (error_cstr)
                                result.GetErrorStream().Printf("error: %s\n", error_cstr);
                            else
                                result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", name_cstr);
                        }
                    }
                }
            }
            else // No command arg specified.  Use variable_list, instead.
            {
                const uint32_t num_variables = variable_list->GetSize();
                if (num_variables > 0)
                {
                    for (uint32_t i=0; i<num_variables; i++)
                    {
                        var_sp = variable_list->GetVariableAtIndex(i);
                        bool dump_variable = true;
                        switch (var_sp->GetScope())
                        {
                            case eValueTypeVariableGlobal:
                                dump_variable = m_option_variable.show_globals;
                                if (dump_variable && m_option_variable.show_scope)
                                    s.PutCString("GLOBAL: ");
                                break;

                            case eValueTypeVariableStatic:
                                dump_variable = m_option_variable.show_globals;
                                if (dump_variable && m_option_variable.show_scope)
                                    s.PutCString("STATIC: ");
                                break;

                            case eValueTypeVariableArgument:
                                dump_variable = m_option_variable.show_args;
                                if (dump_variable && m_option_variable.show_scope)
                                    s.PutCString("   ARG: ");
                                break;

                            case eValueTypeVariableLocal:
                                dump_variable = m_option_variable.show_locals;
                                if (dump_variable && m_option_variable.show_scope)
                                    s.PutCString(" LOCAL: ");
                                break;

                            default:
                                break;
                        }

                        if (dump_variable)
                        {
                            // Use the variable object code to make sure we are
                            // using the same APIs as the the public API will be
                            // using...
                            valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, 
                                                                               m_varobj_options.use_dynamic);
                            if (valobj_sp)
                            {
//                                if (format != eFormatDefault)
//                                    valobj_sp->SetFormat (format);

                                // When dumping all variables, don't print any variables
                                // that are not in scope to avoid extra unneeded output
                                if (valobj_sp->IsInScope ())
                                {
                                    if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile())
                                    {
                                        var_sp->GetDeclaration ().DumpStopContext (&s, false);
                                        s.PutCString (": ");
                                    }
                                    
                                    options.SetFormat(format);
                                    options.SetRootValueObjectName(name_cstr);
                                    ValueObject::DumpValueObject (result.GetOutputStream(), 
                                                                  valobj_sp.get(), 
                                                                  options);
                                }
                            }
                        }
                    }
                }
            }
            result.SetStatus (eReturnStatusSuccessFinishResult);
        }
        
        if (m_interpreter.TruncationWarningNecessary())
        {
            result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
                                            m_cmd_name.c_str());
            m_interpreter.TruncationWarningGiven();
        }
        
        return result.Succeeded();
    }
Ejemplo n.º 2
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;
    }