Esempio n. 1
0
uint32_t
Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
{
    Mutex::Locker locker (m_mutex);
    uint32_t resolved_flags = 0;

    // Clear the result symbol context in case we don't find anything
    sc.Clear();

    // Get the section from the section/offset address.
    const Section *section = so_addr.GetSection();

    // Make sure the section matches this module before we try and match anything
    if (section && section->GetModule() == this)
    {
        // If the section offset based address resolved itself, then this
        // is the right module.
        sc.module_sp = GetSP();
        resolved_flags |= eSymbolContextModule;

        // Resolve the compile unit, function, block, line table or line
        // entry if requested.
        if (resolve_scope & eSymbolContextCompUnit    ||
            resolve_scope & eSymbolContextFunction    ||
            resolve_scope & eSymbolContextBlock       ||
            resolve_scope & eSymbolContextLineEntry   )
        {
            SymbolVendor *symbols = GetSymbolVendor ();
            if (symbols)
                resolved_flags |= symbols->ResolveSymbolContext (so_addr, resolve_scope, sc);
        }

        // Resolve the symbol if requested, but don't re-look it up if we've already found it.
        if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol))
        {
            ObjectFile* ofile = GetObjectFile();
            if (ofile)
            {
                Symtab *symtab = ofile->GetSymtab();
                if (symtab)
                {
                    if (so_addr.IsSectionOffset())
                    {
                        sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
                        if (sc.symbol)
                            resolved_flags |= eSymbolContextSymbol;
                    }
                }
            }
        }
    }
    return resolved_flags;
}
Esempio n. 2
0
bool
SymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc, 
                                        SymbolContext &next_frame_sc, 
                                        Address &next_frame_pc) const
{
    next_frame_sc.Clear(false);
    next_frame_pc.Clear();

    if (block)
    {
        //const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();
        
        // In order to get the parent of an inlined function we first need to
        // see if we are in an inlined block as "this->block" could be an 
        // inlined block, or a parent of "block" could be. So lets check if
        // this block or one of this blocks parents is an inlined function.
        Block *curr_inlined_block = block->GetContainingInlinedBlock();
        if (curr_inlined_block)
        {
            // "this->block" is contained in an inline function block, so to
            // get the scope above the inlined block, we get the parent of the
            // inlined block itself
            Block *next_frame_block = curr_inlined_block->GetParent();
            // Now calculate the symbol context of the containing block
            next_frame_block->CalculateSymbolContext (&next_frame_sc);
            
            // If we get here we weren't able to find the return line entry using the nesting of the blocks and
            // the line table.  So just use the call site info from our inlined block.
            
            AddressRange range;
            if (curr_inlined_block->GetRangeContainingAddress (curr_frame_pc, range))
            {
                // To see there this new frame block it, we need to look at the
                // call site information from 
                const InlineFunctionInfo* curr_inlined_block_inlined_info = curr_inlined_block->GetInlinedFunctionInfo();
                next_frame_pc = range.GetBaseAddress();
                next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc;
                next_frame_sc.line_entry.file = curr_inlined_block_inlined_info->GetCallSite().GetFile();
                next_frame_sc.line_entry.line = curr_inlined_block_inlined_info->GetCallSite().GetLine();
                next_frame_sc.line_entry.column = curr_inlined_block_inlined_info->GetCallSite().GetColumn();
                return true;
            }
            else
            {
                Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));

                if (log)
                {
                    log->Printf ("warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64,
                                 curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress());
                }
#ifdef LLDB_CONFIGURATION_DEBUG
                else
                {
                    ObjectFile *objfile = NULL;
                    if (module_sp)
                    {
                        SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
                        if (symbol_vendor)
                        {
                            SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
                            if (symbol_file)
                                objfile = symbol_file->GetObjectFile();
                        }
                    }
                    if (objfile)
                    {
                        Host::SystemLog (Host::eSystemLogWarning, 
                                         "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 " in %s\n",
                                         curr_inlined_block->GetID(), 
                                         curr_frame_pc.GetFileAddress(),
                                         objfile->GetFileSpec().GetPath().c_str());
                    }
                    else
                    {
                        Host::SystemLog (Host::eSystemLogWarning, 
                                         "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 "\n",
                                         curr_inlined_block->GetID(), 
                                         curr_frame_pc.GetFileAddress());
                    }
                }
#endif
            }
        }
    }
    
    return false;
}
Esempio n. 3
0
    bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        const int argc = command.GetArgumentCount();

        if (argc != 0)
        {
            result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", GetCommandName());
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
        Target *target = exe_ctx.GetTargetPtr();

        if (target == NULL)
            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;
        }

        SymbolContextList sc_list;
        if (!m_options.symbol_name.empty())
        {
            // Displaying the source for a symbol:
            ConstString name(m_options.symbol_name.c_str());
            bool include_symbols = false;
            bool include_inlines = true;
            bool append = true;
            size_t num_matches = 0;
            
            if (m_options.modules.size() > 0)
            {
                ModuleList matching_modules;
                for (unsigned i = 0, e = m_options.modules.size(); i != e; i++)
                {
                    FileSpec module_file_spec(m_options.modules[i].c_str(), false);
                    if (module_file_spec)
                    {
                        ModuleSpec module_spec (module_file_spec);
                        matching_modules.Clear();
                        target->GetImages().FindModules (module_spec, matching_modules);
                        num_matches += matching_modules.FindFunctions (name, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);
                    }
                }
            }
            else
            {
                num_matches = target->GetImages().FindFunctions (name, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);
            }
            
            SymbolContext sc;

            if (num_matches == 0)
            {
                result.AppendErrorWithFormat("Could not find function named: \"%s\".\n", m_options.symbol_name.c_str());
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            
            sc_list.GetContextAtIndex (0, sc);
            FileSpec start_file;
            uint32_t start_line;
            uint32_t end_line;
            FileSpec end_file;
            if (sc.function != NULL)
            {
                sc.function->GetStartLineSourceInfo (start_file, start_line);
                if (start_line == 0)
                {
                    result.AppendErrorWithFormat("Could not find line information for start of function: \"%s\".\n", m_options.symbol_name.c_str());
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
                sc.function->GetEndLineSourceInfo (end_file, end_line);
            }
            else
            {
                result.AppendErrorWithFormat("Could not find function info for: \"%s\".\n", m_options.symbol_name.c_str());
                result.SetStatus (eReturnStatusFailed);
                return false;
            }

            if (num_matches > 1)
            {
                // This could either be because there are multiple functions of this name, in which case
                // we'll have to specify this further...  Or it could be because there are multiple inlined instances
                // of one function.  So run through the matches and if they all have the same file & line then we can just
                // list one.
                
                bool found_multiple = false;
                
                for (size_t i = 1; i < num_matches; i++)
                {
                    SymbolContext scratch_sc;
                    sc_list.GetContextAtIndex (i, scratch_sc);
                    if (scratch_sc.function != NULL)
                    {
                        FileSpec scratch_file;
                        uint32_t scratch_line;
                        scratch_sc.function->GetStartLineSourceInfo (scratch_file, scratch_line);
                        if (scratch_file != start_file 
                            || scratch_line != start_line)
                        {
                            found_multiple = true;
                            break;
                        }
                    }
                }
                if (found_multiple)
                {
                    StreamString s;
                    for (size_t i = 0; i < num_matches; i++)
                    {
                        SymbolContext scratch_sc;
                        sc_list.GetContextAtIndex (i, scratch_sc);
                        if (scratch_sc.function != NULL)
                        {
                            s.Printf("\n%lu: ", i); 
                            scratch_sc.function->Dump (&s, true);
                        }
                    }
                    result.AppendErrorWithFormat("Multiple functions found matching: %s: \n%s\n", 
                                                 m_options.symbol_name.c_str(),
                                                 s.GetData());
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            
                
            // This is a little hacky, but the first line table entry for a function points to the "{" that 
            // starts the function block.  It would be nice to actually get the function
            // declaration in there too.  So back up a bit, but not further than what you're going to display.
            size_t lines_to_back_up = m_options.num_lines >= 10 ? 5 : m_options.num_lines/2;
            uint32_t line_no;
            if (start_line <= lines_to_back_up)
                line_no = 1;
            else
                line_no = start_line - lines_to_back_up;
                
            // For fun, if the function is shorter than the number of lines we're supposed to display, 
            // only display the function...
            if (end_line != 0)
            {
                if (m_options.num_lines > end_line - line_no)
                    m_options.num_lines = end_line - line_no;
            }
            
            char path_buf[PATH_MAX];
            start_file.GetPath(path_buf, sizeof(path_buf));
            
            if (m_options.show_bp_locs)
            {
                const bool show_inlines = true;
                m_breakpoint_locations.Reset (start_file, 0, show_inlines);
                SearchFilter target_search_filter (exe_ctx.GetTargetSP());
                target_search_filter.Search (m_breakpoint_locations);
            }
            else
                m_breakpoint_locations.Clear();

            result.AppendMessageWithFormat("File: %s.\n", path_buf);
            target->GetSourceManager().DisplaySourceLinesWithLineNumbers (start_file,
                                                                          line_no,
                                                                          0,
                                                                          m_options.num_lines,
                                                                          "",
                                                                          &result.GetOutputStream(),
                                                                          GetBreakpointLocations ());
            
            result.SetStatus (eReturnStatusSuccessFinishResult);
            return true;

        }
        else if (m_options.address != LLDB_INVALID_ADDRESS)
        {
            SymbolContext sc;
            Address so_addr;
            StreamString error_strm;

            if (target->GetSectionLoadList().IsEmpty())
            {
                // The target isn't loaded yet, we need to lookup the file address
                // in all modules
                const ModuleList &module_list = target->GetImages();
                const uint32_t num_modules = module_list.GetSize();
                for (uint32_t i=0; i<num_modules; ++i)
                {
                    ModuleSP module_sp (module_list.GetModuleAtIndex(i));
                    if (module_sp && module_sp->ResolveFileAddress(m_options.address, so_addr))
                    {
                        sc.Clear();
                        if (module_sp->ResolveSymbolContextForAddress (so_addr, eSymbolContextEverything, sc) & eSymbolContextLineEntry)
                            sc_list.Append(sc);
                    }
                }
                
                if (sc_list.GetSize() == 0)
                {
                    result.AppendErrorWithFormat("no modules have source information for file address 0x%" PRIx64 ".\n",
                                                 m_options.address);
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            else
            {
                // The target has some things loaded, resolve this address to a
                // compile unit + file + line and display
                if (target->GetSectionLoadList().ResolveLoadAddress (m_options.address, so_addr))
                {
                    ModuleSP module_sp (so_addr.GetModule());
                    if (module_sp)
                    {
                        sc.Clear();
                        if (module_sp->ResolveSymbolContextForAddress (so_addr, eSymbolContextEverything, sc) & eSymbolContextLineEntry)
                        {
                            sc_list.Append(sc);
                        }
                        else
                        {
                            so_addr.Dump(&error_strm, NULL, Address::DumpStyleModuleWithFileAddress);
                            result.AppendErrorWithFormat("address resolves to %s, but there is no line table information available for this address.\n",
                                                         error_strm.GetData());
                            result.SetStatus (eReturnStatusFailed);
                            return false;
                        }
                    }
                }

                if (sc_list.GetSize() == 0)
                {
                    result.AppendErrorWithFormat("no modules contain load address 0x%" PRIx64 ".\n", m_options.address);
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            uint32_t num_matches = sc_list.GetSize();
            for (uint32_t i=0; i<num_matches; ++i)
            {
                sc_list.GetContextAtIndex(i, sc);
                if (sc.comp_unit)
                {
                    if (m_options.show_bp_locs)
                    {
                        m_breakpoint_locations.Clear();
                        const bool show_inlines = true;
                        m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines);
                        SearchFilter target_search_filter (target->shared_from_this());
                        target_search_filter.Search (m_breakpoint_locations);
                    }
                    
                    bool show_fullpaths = true;
                    bool show_module = true;
                    bool show_inlined_frames = true;
                    sc.DumpStopContext(&result.GetOutputStream(),
                                       exe_ctx.GetBestExecutionContextScope(),
                                       sc.line_entry.range.GetBaseAddress(),
                                       show_fullpaths,
                                       show_module,
                                       show_inlined_frames);
                    result.GetOutputStream().EOL();
                    
                    size_t lines_to_back_up = m_options.num_lines >= 10 ? 5 : m_options.num_lines/2;

                    target->GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
                                                                                  sc.line_entry.line,
                                                                                  lines_to_back_up,
                                                                                  m_options.num_lines - lines_to_back_up,
                                                                                  "->",
                                                                                  &result.GetOutputStream(),
                                                                                  GetBreakpointLocations ());
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
            }
        }
        else if (m_options.file_name.empty())
        {
            // Last valid source manager context, or the current frame if no
            // valid last context in source manager.
            // One little trick here, if you type the exact same list command twice in a row, it is
            // more likely because you typed it once, then typed it again
            if (m_options.start_line == 0)
            {
                if (target->GetSourceManager().DisplayMoreWithLineNumbers (&result.GetOutputStream(),
                                                                                               GetBreakpointLocations ()))
                {
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
            }
            else
            {
                if (m_options.show_bp_locs)
                {
                    SourceManager::FileSP last_file_sp (target->GetSourceManager().GetLastFile ());
                    if (last_file_sp)
                    {
                        const bool show_inlines = true;
                        m_breakpoint_locations.Reset (last_file_sp->GetFileSpec(), 0, show_inlines);
                        SearchFilter target_search_filter (target->shared_from_this());
                        target_search_filter.Search (m_breakpoint_locations);
                    }
                }
                else
                    m_breakpoint_locations.Clear();

                if (target->GetSourceManager().DisplaySourceLinesWithLineNumbersUsingLastFile(
                            m_options.start_line,   // Line to display
                            0,                      // Lines before line to display
                            m_options.num_lines,    // Lines after line to display
                            "",                     // Don't mark "line"
                            &result.GetOutputStream(),
                            GetBreakpointLocations ()))
                {
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }

            }
        }
        else
        {
            const char *filename = m_options.file_name.c_str();

            bool check_inlines = false;
            SymbolContextList sc_list;
            size_t num_matches = 0;
            
            if (m_options.modules.size() > 0)
            {
                ModuleList matching_modules;
                for (unsigned i = 0, e = m_options.modules.size(); i != e; i++)
                {
                    FileSpec module_file_spec(m_options.modules[i].c_str(), false);
                    if (module_file_spec)
                    {
                        ModuleSpec module_spec (module_file_spec);
                        matching_modules.Clear();
                        target->GetImages().FindModules (module_spec, matching_modules);
                        num_matches += matching_modules.ResolveSymbolContextForFilePath (filename,
                                                                                         0,
                                                                                         check_inlines,
                                                                                         eSymbolContextModule | eSymbolContextCompUnit,
                                                                                         sc_list);
                    }
                }
            }
            else
            {
                num_matches = target->GetImages().ResolveSymbolContextForFilePath (filename,
                                                                                   0,
                                                                                   check_inlines,
                                                                                   eSymbolContextModule | eSymbolContextCompUnit,
                                                                                   sc_list);
            }
            
            if (num_matches == 0)
            {
                result.AppendErrorWithFormat("Could not find source file \"%s\".\n", 
                                             m_options.file_name.c_str());
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            
            if (num_matches > 1)
            {
                SymbolContext sc;
                bool got_multiple = false;
                FileSpec *test_cu_spec = NULL;

                for (unsigned i = 0; i < num_matches; i++)
                {
                    sc_list.GetContextAtIndex(i, sc);
                    if (sc.comp_unit)
                    {
                        if (test_cu_spec)
                        {
                            if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit))
                                got_multiple = true;
                                break;
                        }
                        else
                            test_cu_spec = sc.comp_unit;
                    }
                }
                if (got_multiple)
                {
                    result.AppendErrorWithFormat("Multiple source files found matching: \"%s.\"\n", 
                                                 m_options.file_name.c_str());
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            
            SymbolContext sc;
            if (sc_list.GetContextAtIndex(0, sc))
            {
                if (sc.comp_unit)
                {
                    if (m_options.show_bp_locs)
                    {
                        const bool show_inlines = true;
                        m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines);
                        SearchFilter target_search_filter (target->shared_from_this());
                        target_search_filter.Search (m_breakpoint_locations);
                    }
                    else
                        m_breakpoint_locations.Clear();

                    target->GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
                                                                                  m_options.start_line,
                                                                                  0,
                                                                                  m_options.num_lines,
                                                                                  "",
                                                                                  &result.GetOutputStream(),
                                                                                  GetBreakpointLocations ());

                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
                else
                {
                    result.AppendErrorWithFormat("No comp unit found for: \"%s.\"\n", 
                                                 m_options.file_name.c_str());
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
        }
        return result.Succeeded();
    }
Esempio n. 4
0
bool 
Disassembler::PrintInstructions
(
    Disassembler *disasm_ptr,
    Debugger &debugger,
    const ArchSpec &arch,
    const ExecutionContext &exe_ctx,
    uint32_t num_instructions,
    uint32_t num_mixed_context_lines,
    uint32_t options,
    Stream &strm
)
{
    // We got some things disassembled...
    size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
    
    if (num_instructions > 0 && num_instructions < num_instructions_found)
        num_instructions_found = num_instructions;
        
    const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
    uint32_t offset = 0;
    SymbolContext sc;
    SymbolContext prev_sc;
    AddressRange sc_range;
    const Address *pc_addr_ptr = NULL;
    StackFrame *frame = exe_ctx.GetFramePtr();

    TargetSP target_sp (exe_ctx.GetTargetSP());
    SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();

    if (frame)
    {
        pc_addr_ptr = &frame->GetFrameCodeAddress();
    }
    const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
    const bool use_inline_block_range = false;

    const FormatEntity::Entry *disassembly_format = NULL;
    FormatEntity::Entry format;
    if (exe_ctx.HasTargetScope())
    {
        disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat ();
    }
    else
    {
        FormatEntity::Parse("${addr}: ", format);
        disassembly_format = &format;
    }

    // First pass: step through the list of instructions, 
    // find how long the initial addresses strings are, insert padding 
    // in the second pass so the opcodes all line up nicely.
    size_t address_text_size = 0;
    for (size_t i = 0; i < num_instructions_found; ++i)
    {
        Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
        if (inst)
        {
            const Address &addr = inst->GetAddress();
            ModuleSP module_sp (addr.GetModule());
            if (module_sp)
            {
                const uint32_t resolve_mask = eSymbolContextFunction | eSymbolContextSymbol;
                uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
                if (resolved_mask)
                {
                    StreamString strmstr;
                    Debugger::FormatDisassemblerAddress (disassembly_format, &sc, NULL, &exe_ctx, &addr, strmstr);
                    size_t cur_line = strmstr.GetSizeOfLastLine();
                    if (cur_line > address_text_size)
                        address_text_size = cur_line;
                }
                sc.Clear(false);
            }
        }
    }

    for (size_t i = 0; i < num_instructions_found; ++i)
    {
        Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
        if (inst)
        {
            const Address &addr = inst->GetAddress();
            const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;

            prev_sc = sc;

            ModuleSP module_sp (addr.GetModule());
            if (module_sp)
            {
                uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
                if (resolved_mask)
                {
                    if (num_mixed_context_lines)
                    {
                        if (!sc_range.ContainsFileAddress (addr))
                        {
                            sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
                            
                            if (sc != prev_sc)
                            {
                                if (offset != 0)
                                    strm.EOL();
                                
                                sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false, false, true);
                                strm.EOL();
                                
                                if (sc.comp_unit && sc.line_entry.IsValid())
                                {
                                    source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
                                                                                      sc.line_entry.line,
                                                                                      num_mixed_context_lines,
                                                                                      num_mixed_context_lines,
                                                                                      ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
                                                                                      &strm);
                                }
                            }
                        }
                    }
                }
                else
                {
                    sc.Clear(true);
                }
            }

            const bool show_bytes = (options & eOptionShowBytes) != 0;
            inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, NULL, address_text_size);
            strm.EOL();            
        }
        else
        {
            break;
        }
    }
        
    return true;
}
Esempio n. 5
0
bool 
Disassembler::PrintInstructions
(
    Disassembler *disasm_ptr,
    Debugger &debugger,
    const ArchSpec &arch,
    const ExecutionContext &exe_ctx,
    uint32_t num_instructions,
    uint32_t num_mixed_context_lines,
    uint32_t options,
    Stream &strm
)
{
    // We got some things disassembled...
    size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
    
    if (num_instructions > 0 && num_instructions < num_instructions_found)
        num_instructions_found = num_instructions;
        
    const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
    uint32_t offset = 0;
    SymbolContext sc;
    SymbolContext prev_sc;
    AddressRange sc_range;
    const Address *pc_addr_ptr = NULL;
    ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
    Frame *frame = exe_ctx.GetFramePtr();

    TargetSP target_sp (exe_ctx.GetTargetSP());
    SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();

    if (frame)
        pc_addr_ptr = &frame->GetFrameCodeAddress();
    const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
    const bool use_inline_block_range = false;
    for (size_t i=0; i<num_instructions_found; ++i)
    {
        Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
        if (inst)
        {
            const Address &addr = inst->GetAddress();
            const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;

            prev_sc = sc;

            ModuleSP module_sp (addr.GetModule());
            if (module_sp)
            {
                uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
                if (resolved_mask)
                {
                    if (num_mixed_context_lines)
                    {
                        if (!sc_range.ContainsFileAddress (addr))
                        {
                            sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
                            
                            if (sc != prev_sc)
                            {
                                if (offset != 0)
                                    strm.EOL();
                                
                                sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false);
                                strm.EOL();
                                
                                if (sc.comp_unit && sc.line_entry.IsValid())
                                {
                                    source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
                                                                                      sc.line_entry.line,
                                                                                      num_mixed_context_lines,
                                                                                      num_mixed_context_lines,
                                                                                      ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
                                                                                      &strm);
                                }
                            }
                        }
                    }
                    else if ((sc.function || sc.symbol) && (sc.function != prev_sc.function || sc.symbol != prev_sc.symbol))
                    {
                        if (prev_sc.function || prev_sc.symbol)
                            strm.EOL();

                        bool show_fullpaths = false;
                        bool show_module = true;
                        bool show_inlined_frames = true;
                        sc.DumpStopContext (&strm, 
                                            exe_scope, 
                                            addr, 
                                            show_fullpaths,
                                            show_module,
                                            show_inlined_frames);
                        
                        strm << ":\n";
                    }
                }
                else
                {
                    sc.Clear(true);
                }
            }

            if ((options & eOptionMarkPCAddress) && pc_addr_ptr)
            {
                strm.PutCString(inst_is_at_pc ? "-> " : "   ");
            }
            const bool show_bytes = (options & eOptionShowBytes) != 0;
            inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx);
            strm.EOL();            
        }
        else
        {
            break;
        }
    }
        
    return true;
}
Esempio n. 6
0
bool
Disassembler::Disassemble
(
    Debugger &debugger,
    const ArchSpec &arch,
    const ExecutionContext &exe_ctx,
    const AddressRange &disasm_range,
    uint32_t num_mixed_context_lines,
    bool show_bytes,
    Stream &strm
)
{
    if (disasm_range.GetByteSize())
    {
        Disassembler *disassembler = Disassembler::FindPlugin(arch);

        if (disassembler)
        {
            AddressRange range(disasm_range);
            
            Process *process = exe_ctx.process;

            // If we weren't passed in a section offset address range,
            // try and resolve it to something
            if (range.GetBaseAddress().IsSectionOffset() == false)
            {
                if (process && process->IsAlive())
                {
                    process->ResolveLoadAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
                }
                else if (exe_ctx.target)
                {
                    exe_ctx.target->GetImages().ResolveFileAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
                }
            }


            DataExtractor data;
            size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, range, data);
            if (bytes_disassembled == 0)
            {
                return false;
            }
            else
            {
                // We got some things disassembled...
                size_t num_instructions = disassembler->GetInstructionList().GetSize();
                uint32_t offset = 0;
                SymbolContext sc;
                SymbolContext prev_sc;
                AddressRange sc_range;
                if (num_mixed_context_lines)
                    strm.IndentMore ();


                Address addr(range.GetBaseAddress());
    
                // We extract the section to make sure we don't transition out
                // of the current section when disassembling
                const Section *addr_section = addr.GetSection();
                Module *range_module = range.GetBaseAddress().GetModule();

                for (size_t i=0; i<num_instructions; ++i)
                {
                    Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
                    if (inst)
                    {
                        addr_t file_addr = addr.GetFileAddress();
                        if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
                        {
                            if (range_module)
                                range_module->ResolveFileAddress (file_addr, addr);
                            else if (exe_ctx.target)
                                exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
                                
                            addr_section = addr.GetSection();
                        }

                        prev_sc = sc;

                        if (addr_section)
                        {
                            Module *module = addr_section->GetModule();
                            uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
                            if (resolved_mask)
                            {
                                if (prev_sc.function != sc.function || prev_sc.symbol != sc.symbol)
                                {
                                    if (prev_sc.function || prev_sc.symbol)
                                        strm.EOL();

                                    strm << sc.module_sp->GetFileSpec().GetFilename();
                                    
                                    if (sc.function)
                                        strm << '`' << sc.function->GetMangled().GetName();
                                    else if (sc.symbol)
                                        strm << '`' << sc.symbol->GetMangled().GetName();
                                    strm << ":\n";
                                }

                                if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
                                {
                                    sc.GetAddressRange (eSymbolContextEverything, sc_range);
                                        
                                    if (sc != prev_sc)
                                    {
                                        if (offset != 0)
                                            strm.EOL();

                                        sc.DumpStopContext(&strm, process, addr);

                                        if (sc.comp_unit && sc.line_entry.IsValid())
                                        {
                                            debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
                                                                                                           sc.line_entry.line,
                                                                                                           num_mixed_context_lines,
                                                                                                           num_mixed_context_lines,
                                                                                                           num_mixed_context_lines ? "->" : "",
                                                                                                           &strm);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                sc.Clear();
                            }
                        }
                        if (num_mixed_context_lines)
                            strm.IndentMore ();
                        strm.Indent();
                        size_t inst_byte_size = inst->GetByteSize();
                        inst->Dump(&strm, &addr, show_bytes ? &data : NULL, offset, exe_ctx, show_bytes);
                        strm.EOL();
                        offset += inst_byte_size;
                        
                        addr.SetOffset (addr.GetOffset() + inst_byte_size);

                        if (num_mixed_context_lines)
                            strm.IndentLess ();
                    }
                    else
                    {
                        break;
                    }
                }
                if (num_mixed_context_lines)
                    strm.IndentLess ();

            }
        }
        return true;
    }
    return false;
}
Esempio n. 7
0
    bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        const size_t argc = command.GetArgumentCount();

        if (argc != 0)
        {
            result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", GetCommandName());
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Target *target = m_exe_ctx.GetTargetPtr();

        if (!m_options.symbol_name.empty())
        {
            SymbolContextList sc_list;
            ConstString name(m_options.symbol_name.c_str());

            // Displaying the source for a symbol. Search for function named name.
            size_t num_matches = FindMatchingFunctions (target, name, sc_list);
            if (!num_matches)
            {
                // If we didn't find any functions with that name, try searching for symbols
                // that line up exactly with function addresses.
                SymbolContextList sc_list_symbols;
                size_t num_symbol_matches = FindMatchingFunctionSymbols (target, name, sc_list_symbols);
                for (size_t i = 0; i < num_symbol_matches; i++)
                {
                    SymbolContext sc;
                    sc_list_symbols.GetContextAtIndex (i, sc);
                    if (sc.symbol)
                    {
                        const Address &base_address = sc.symbol->GetAddress();
                        Function *function = base_address.CalculateSymbolContextFunction();
                        if (function)
                        {
                            sc_list.Append (SymbolContext(function));
                            num_matches++;
                            break;
                        }
                    }
                }
            }

            if (num_matches == 0)
            {
                result.AppendErrorWithFormat("Could not find function named: \"%s\".\n", m_options.symbol_name.c_str());
                result.SetStatus (eReturnStatusFailed);
                return false;
            }

            if (num_matches > 1)
            {
                std::set<SourceInfo> source_match_set;
                
                bool displayed_something = false;
                for (size_t i = 0; i < num_matches; i++)
                {
                    SymbolContext sc;
                    sc_list.GetContextAtIndex (i, sc);
                    SourceInfo source_info (sc.GetFunctionName(),
                                            sc.GetFunctionStartLineEntry());
                    
                    if (source_info.IsValid())
                    {
                        if (source_match_set.find(source_info) == source_match_set.end())
                        {
                            source_match_set.insert(source_info);
                            if (DisplayFunctionSource (sc, source_info, result))
                                displayed_something = true;
                        }
                    }
                }
                
                if (displayed_something)
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                else
                    result.SetStatus (eReturnStatusFailed);
            }
            else
            {
                SymbolContext sc;
                sc_list.GetContextAtIndex (0, sc);
                SourceInfo source_info;
                
                if (DisplayFunctionSource (sc, source_info, result))
                {
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
                else
                {
                    result.SetStatus (eReturnStatusFailed);
                }
            }
            return result.Succeeded();
        }
        else if (m_options.address != LLDB_INVALID_ADDRESS)
        {
            Address so_addr;
            StreamString error_strm;
            SymbolContextList sc_list;

            if (target->GetSectionLoadList().IsEmpty())
            {
                // The target isn't loaded yet, we need to lookup the file address
                // in all modules
                const ModuleList &module_list = target->GetImages();
                const size_t num_modules = module_list.GetSize();
                for (size_t i=0; i<num_modules; ++i)
                {
                    ModuleSP module_sp (module_list.GetModuleAtIndex(i));
                    if (module_sp && module_sp->ResolveFileAddress(m_options.address, so_addr))
                    {
                        SymbolContext sc;
                        sc.Clear(true);
                        if (module_sp->ResolveSymbolContextForAddress (so_addr, eSymbolContextEverything, sc) & eSymbolContextLineEntry)
                            sc_list.Append(sc);
                    }
                }
                
                if (sc_list.GetSize() == 0)
                {
                    result.AppendErrorWithFormat("no modules have source information for file address 0x%" PRIx64 ".\n",
                                                 m_options.address);
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            else
            {
                // The target has some things loaded, resolve this address to a
                // compile unit + file + line and display
                if (target->GetSectionLoadList().ResolveLoadAddress (m_options.address, so_addr))
                {
                    ModuleSP module_sp (so_addr.GetModule());
                    if (module_sp)
                    {
                        SymbolContext sc;
                        sc.Clear(true);
                        if (module_sp->ResolveSymbolContextForAddress (so_addr, eSymbolContextEverything, sc) & eSymbolContextLineEntry)
                        {
                            sc_list.Append(sc);
                        }
                        else
                        {
                            so_addr.Dump(&error_strm, NULL, Address::DumpStyleModuleWithFileAddress);
                            result.AppendErrorWithFormat("address resolves to %s, but there is no line table information available for this address.\n",
                                                         error_strm.GetData());
                            result.SetStatus (eReturnStatusFailed);
                            return false;
                        }
                    }
                }

                if (sc_list.GetSize() == 0)
                {
                    result.AppendErrorWithFormat("no modules contain load address 0x%" PRIx64 ".\n", m_options.address);
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            uint32_t num_matches = sc_list.GetSize();
            for (uint32_t i=0; i<num_matches; ++i)
            {
                SymbolContext sc;
                sc_list.GetContextAtIndex(i, sc);
                if (sc.comp_unit)
                {
                    if (m_options.show_bp_locs)
                    {
                        m_breakpoint_locations.Clear();
                        const bool show_inlines = true;
                        m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines);
                        SearchFilter target_search_filter (target->shared_from_this());
                        target_search_filter.Search (m_breakpoint_locations);
                    }
                    
                    bool show_fullpaths = true;
                    bool show_module = true;
                    bool show_inlined_frames = true;
                    const bool show_function_arguments = true;
                    sc.DumpStopContext(&result.GetOutputStream(),
                                       m_exe_ctx.GetBestExecutionContextScope(),
                                       sc.line_entry.range.GetBaseAddress(),
                                       show_fullpaths,
                                       show_module,
                                       show_inlined_frames,
                                       show_function_arguments);
                    result.GetOutputStream().EOL();

                    if (m_options.num_lines == 0)
                        m_options.num_lines = 10;
                    
                    size_t lines_to_back_up = m_options.num_lines >= 10 ? 5 : m_options.num_lines/2;

                    target->GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
                                                                                  sc.line_entry.line,
                                                                                  lines_to_back_up,
                                                                                  m_options.num_lines - lines_to_back_up,
                                                                                  "->",
                                                                                  &result.GetOutputStream(),
                                                                                  GetBreakpointLocations ());
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
            }
        }
        else if (m_options.file_name.empty())
        {
            // Last valid source manager context, or the current frame if no
            // valid last context in source manager.
            // One little trick here, if you type the exact same list command twice in a row, it is
            // more likely because you typed it once, then typed it again
            if (m_options.start_line == 0)
            {
                if (target->GetSourceManager().DisplayMoreWithLineNumbers (&result.GetOutputStream(),
                                                                           m_options.num_lines,
                                                                           m_options.reverse,
                                                                           GetBreakpointLocations ()))
                {
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
            }
            else
            {
                if (m_options.num_lines == 0)
                    m_options.num_lines = 10;

                if (m_options.show_bp_locs)
                {
                    SourceManager::FileSP last_file_sp (target->GetSourceManager().GetLastFile ());
                    if (last_file_sp)
                    {
                        const bool show_inlines = true;
                        m_breakpoint_locations.Reset (last_file_sp->GetFileSpec(), 0, show_inlines);
                        SearchFilter target_search_filter (target->shared_from_this());
                        target_search_filter.Search (m_breakpoint_locations);
                    }
                }
                else
                    m_breakpoint_locations.Clear();

                if (target->GetSourceManager().DisplaySourceLinesWithLineNumbersUsingLastFile(
                            m_options.start_line,   // Line to display
                            m_options.num_lines,    // Lines after line to
                            UINT32_MAX,             // Don't mark "line"
                            "",                     // Don't mark "line"
                            &result.GetOutputStream(),
                            GetBreakpointLocations ()))
                {
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }

            }
        }
        else
        {
            const char *filename = m_options.file_name.c_str();

            bool check_inlines = false;
            SymbolContextList sc_list;
            size_t num_matches = 0;
            
            if (m_options.modules.size() > 0)
            {
                ModuleList matching_modules;
                for (size_t i = 0, e = m_options.modules.size(); i < e; ++i)
                {
                    FileSpec module_file_spec(m_options.modules[i].c_str(), false);
                    if (module_file_spec)
                    {
                        ModuleSpec module_spec (module_file_spec);
                        matching_modules.Clear();
                        target->GetImages().FindModules (module_spec, matching_modules);
                        num_matches += matching_modules.ResolveSymbolContextForFilePath (filename,
                                                                                         0,
                                                                                         check_inlines,
                                                                                         eSymbolContextModule | eSymbolContextCompUnit,
                                                                                         sc_list);
                    }
                }
            }
            else
            {
                num_matches = target->GetImages().ResolveSymbolContextForFilePath (filename,
                                                                                   0,
                                                                                   check_inlines,
                                                                                   eSymbolContextModule | eSymbolContextCompUnit,
                                                                                   sc_list);
            }
            
            if (num_matches == 0)
            {
                result.AppendErrorWithFormat("Could not find source file \"%s\".\n", 
                                             m_options.file_name.c_str());
                result.SetStatus (eReturnStatusFailed);
                return false;
            }

            if (num_matches > 1)
            {
                bool got_multiple = false;
                FileSpec *test_cu_spec = NULL;

                for (unsigned i = 0; i < num_matches; i++)
                {
                    SymbolContext sc;
                    sc_list.GetContextAtIndex(i, sc);
                    if (sc.comp_unit)
                    {
                        if (test_cu_spec)
                        {
                            if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit))
                                got_multiple = true;
                            break;
                        }
                        else
                            test_cu_spec = sc.comp_unit;
                    }
                }
                if (got_multiple)
                {
                    result.AppendErrorWithFormat("Multiple source files found matching: \"%s.\"\n",
                                                 m_options.file_name.c_str());
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            
            SymbolContext sc;
            if (sc_list.GetContextAtIndex(0, sc))
            {
                if (sc.comp_unit)
                {
                    if (m_options.show_bp_locs)
                    {
                        const bool show_inlines = true;
                        m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines);
                        SearchFilter target_search_filter (target->shared_from_this());
                        target_search_filter.Search (m_breakpoint_locations);
                    }
                    else
                        m_breakpoint_locations.Clear();

                    if (m_options.num_lines == 0)
                        m_options.num_lines = 10;
                    
                    target->GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
                                                                                  m_options.start_line,
                                                                                  0,
                                                                                  m_options.num_lines,
                                                                                  "",
                                                                                  &result.GetOutputStream(),
                                                                                  GetBreakpointLocations ());

                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
                else
                {
                    result.AppendErrorWithFormat("No comp unit found for: \"%s.\"\n", 
                                                 m_options.file_name.c_str());
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
        }
        return result.Succeeded();
    }