summaryrefslogtreecommitdiff
path: root/source/Symbol/Function.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Symbol/Function.cpp')
-rw-r--r--source/Symbol/Function.cpp117
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);