diff options
Diffstat (limited to 'source/Symbol/Function.cpp')
-rw-r--r-- | source/Symbol/Function.cpp | 117 |
1 files changed, 99 insertions, 18 deletions
diff --git a/source/Symbol/Function.cpp b/source/Symbol/Function.cpp index f642c186a19f..f792a5c5213e 100644 --- a/source/Symbol/Function.cpp +++ b/source/Symbol/Function.cpp @@ -10,6 +10,7 @@ #include "lldb/Symbol/Function.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" #include "lldb/Core/Section.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/CompileUnit.h" @@ -18,6 +19,7 @@ #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Target/Language.h" +#include "lldb/Utility/Log.h" #include "llvm/Support/Casting.h" using namespace lldb; @@ -131,6 +133,59 @@ size_t InlineFunctionInfo::MemorySize() const { //---------------------------------------------------------------------- // //---------------------------------------------------------------------- +CallEdge::CallEdge(const char *symbol_name, lldb::addr_t return_pc) + : return_pc(return_pc), resolved(false) { + lazy_callee.symbol_name = symbol_name; +} + +void CallEdge::ParseSymbolFileAndResolve(ModuleList &images) { + if (resolved) + return; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + LLDB_LOG(log, "CallEdge: Lazily parsing the call graph for {0}", + lazy_callee.symbol_name); + + auto resolve_lazy_callee = [&]() -> Function * { + ConstString callee_name{lazy_callee.symbol_name}; + SymbolContextList sc_list; + size_t num_matches = + images.FindFunctionSymbols(callee_name, eFunctionNameTypeAuto, sc_list); + if (num_matches == 0 || !sc_list[0].symbol) { + LLDB_LOG(log, "CallEdge: Found no symbols for {0}, cannot resolve it", + callee_name); + return nullptr; + } + Address callee_addr = sc_list[0].symbol->GetAddress(); + if (!callee_addr.IsValid()) { + LLDB_LOG(log, "CallEdge: Invalid symbol address"); + return nullptr; + } + Function *f = callee_addr.CalculateSymbolContextFunction(); + if (!f) { + LLDB_LOG(log, "CallEdge: Could not find complete function"); + return nullptr; + } + return f; + }; + lazy_callee.def = resolve_lazy_callee(); + resolved = true; +} + +Function *CallEdge::GetCallee(ModuleList &images) { + ParseSymbolFileAndResolve(images); + return lazy_callee.def; +} + +lldb::addr_t CallEdge::GetReturnPCAddress(Function &caller, + Target &target) const { + const Address &base = caller.GetAddressRange().GetBaseAddress(); + return base.GetLoadAddress(&target) + return_pc; +} + +//---------------------------------------------------------------------- +// +//---------------------------------------------------------------------- Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid, lldb::user_id_t type_uid, const Mangled &mangled, Type *type, const AddressRange &range) @@ -141,17 +196,6 @@ Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid, assert(comp_unit != nullptr); } -Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid, - lldb::user_id_t type_uid, const char *mangled, Type *type, - const AddressRange &range) - : UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid), - m_type(type), m_mangled(ConstString(mangled), true), m_block(func_uid), - m_range(range), m_frame_base(nullptr), m_flags(), - m_prologue_byte_size(0) { - m_block.SetParentScope(this); - assert(comp_unit != nullptr); -} - Function::~Function() {} void Function::GetStartLineSourceInfo(FileSpec &source_file, @@ -203,16 +247,53 @@ void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) { } } +llvm::MutableArrayRef<CallEdge> Function::GetCallEdges() { + if (m_call_edges_resolved) + return m_call_edges; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + LLDB_LOG(log, "GetCallEdges: Attempting to parse call site info for {0}", + GetDisplayName()); + + m_call_edges_resolved = true; + + // Find the SymbolFile which provided this function's definition. + Block &block = GetBlock(/*can_create*/true); + SymbolFile *sym_file = block.GetSymbolFile(); + if (!sym_file) + return llvm::None; + + // Lazily read call site information from the SymbolFile. + m_call_edges = sym_file->ParseCallEdgesInFunction(GetID()); + + // Sort the call edges to speed up return_pc lookups. + llvm::sort(m_call_edges.begin(), m_call_edges.end(), + [](const CallEdge &LHS, const CallEdge &RHS) { + return LHS.GetUnresolvedReturnPCAddress() < + RHS.GetUnresolvedReturnPCAddress(); + }); + + return m_call_edges; +} + +llvm::MutableArrayRef<CallEdge> Function::GetTailCallingEdges() { + // Call edges are sorted by return PC, and tail calling edges have invalid + // return PCs. Find them at the end of the list. + return GetCallEdges().drop_until([](const CallEdge &edge) { + return edge.GetUnresolvedReturnPCAddress() == LLDB_INVALID_ADDRESS; + }); +} + Block &Function::GetBlock(bool can_create) { if (!m_block.BlockInfoHasBeenParsed() && can_create) { - SymbolContext sc; - CalculateSymbolContext(&sc); - if (sc.module_sp) { - sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc); + ModuleSP module_sp = CalculateSymbolContextModule(); + if (module_sp) { + module_sp->GetSymbolVendor()->ParseBlocksRecursive(*this); } else { - Host::SystemLog(Host::eSystemLogError, "error: unable to find module " - "shared pointer for function '%s' " - "in %s\n", + Host::SystemLog(Host::eSystemLogError, + "error: unable to find module " + "shared pointer for function '%s' " + "in %s\n", GetName().GetCString(), m_comp_unit->GetPath().c_str()); } m_block.SetBlockInfoHasBeenParsed(true, true); |