Changeset View
Changeset View
Standalone View
Standalone View
lldb/source/Symbol/Function.cpp
//===-- Function.cpp --------------------------------------------*- C++ -*-===// | //===-- Function.cpp --------------------------------------------*- C++ -*-===// | ||||
// | // | ||||
// The LLVM Compiler Infrastructure | // The LLVM Compiler Infrastructure | ||||
// | // | ||||
// This file is distributed under the University of Illinois Open Source | // This file is distributed under the University of Illinois Open Source | ||||
// License. See LICENSE.TXT for details. | // License. See LICENSE.TXT for details. | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
#include "lldb/Symbol/Function.h" | #include "lldb/Symbol/Function.h" | ||||
#include "lldb/Core/Disassembler.h" | #include "lldb/Core/Disassembler.h" | ||||
#include "lldb/Core/Module.h" | #include "lldb/Core/Module.h" | ||||
#include "lldb/Core/ModuleList.h" | |||||
#include "lldb/Core/Section.h" | #include "lldb/Core/Section.h" | ||||
#include "lldb/Host/Host.h" | #include "lldb/Host/Host.h" | ||||
#include "lldb/Symbol/CompileUnit.h" | #include "lldb/Symbol/CompileUnit.h" | ||||
#include "lldb/Symbol/CompilerType.h" | #include "lldb/Symbol/CompilerType.h" | ||||
#include "lldb/Symbol/LineTable.h" | #include "lldb/Symbol/LineTable.h" | ||||
#include "lldb/Symbol/SymbolFile.h" | #include "lldb/Symbol/SymbolFile.h" | ||||
#include "lldb/Symbol/SymbolVendor.h" | #include "lldb/Symbol/SymbolVendor.h" | ||||
#include "lldb/Target/Language.h" | #include "lldb/Target/Language.h" | ||||
#include "lldb/Utility/Log.h" | |||||
#include "llvm/Support/Casting.h" | #include "llvm/Support/Casting.h" | ||||
using namespace lldb; | using namespace lldb; | ||||
using namespace lldb_private; | using namespace lldb_private; | ||||
//---------------------------------------------------------------------- | //---------------------------------------------------------------------- | ||||
// Basic function information is contained in the FunctionInfo class. It is | // Basic function information is contained in the FunctionInfo class. It is | ||||
// designed to contain the name, linkage name, and declaration location. | // designed to contain the name, linkage name, and declaration location. | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | |||||
size_t InlineFunctionInfo::MemorySize() const { | size_t InlineFunctionInfo::MemorySize() const { | ||||
return FunctionInfo::MemorySize() + m_mangled.MemorySize(); | return FunctionInfo::MemorySize() + m_mangled.MemorySize(); | ||||
} | } | ||||
//---------------------------------------------------------------------- | //---------------------------------------------------------------------- | ||||
// | // | ||||
//---------------------------------------------------------------------- | //---------------------------------------------------------------------- | ||||
CallEdge::CallEdge(const char *mangled_name, lldb::addr_t return_pc) | |||||
: resolved(false), return_pc(return_pc) { | |||||
lazy_callee.mangled_name = mangled_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.mangled_name); | |||||
auto resolve_lazy_callee = [&]() -> Function * { | |||||
sgraenitz: Easy to confuse with lambda assignment (although it wouldn't make any sense).
```
auto resolve… | |||||
ConstString callee_name{lazy_callee.mangled_name}; | |||||
SymbolContextList sc_list; | |||||
size_t num_matches = | |||||
images.FindFunctionSymbols(callee_name, eFunctionNameTypeAuto, sc_list); | |||||
if (num_matches != 1 || !sc_list[0].symbol) { | |||||
LLDB_LOG(log, "CallEdge: Found {0} symbols for {1}, cannot resolve it", | |||||
num_matches, 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(); | |||||
Address return_pc_addr{base.GetSection(), return_pc}; | |||||
return return_pc_addr.GetLoadAddress(&target); | |||||
} | |||||
//---------------------------------------------------------------------- | |||||
// | |||||
//---------------------------------------------------------------------- | |||||
Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid, | Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid, | ||||
lldb::user_id_t type_uid, const Mangled &mangled, Type *type, | lldb::user_id_t type_uid, const Mangled &mangled, Type *type, | ||||
const AddressRange &range) | const AddressRange &range) | ||||
: UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid), | : UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid), | ||||
m_type(type), m_mangled(mangled), m_block(func_uid), m_range(range), | m_type(type), m_mangled(mangled), m_block(func_uid), m_range(range), | ||||
m_frame_base(nullptr), m_flags(), m_prologue_byte_size(0) { | m_frame_base(nullptr), m_flags(), m_prologue_byte_size(0) { | ||||
m_block.SetParentScope(this); | m_block.SetParentScope(this); | ||||
assert(comp_unit != nullptr); | assert(comp_unit != nullptr); | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) { | ||||
LineEntry line_entry; | LineEntry line_entry; | ||||
if (line_table->FindLineEntryByAddress(scratch_addr, line_entry, nullptr)) { | if (line_table->FindLineEntryByAddress(scratch_addr, line_entry, nullptr)) { | ||||
line_no = line_entry.line; | line_no = line_entry.line; | ||||
source_file = line_entry.file; | source_file = line_entry.file; | ||||
} | } | ||||
} | } | ||||
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. | |||||
std::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) { | Block &Function::GetBlock(bool can_create) { | ||||
if (!m_block.BlockInfoHasBeenParsed() && can_create) { | if (!m_block.BlockInfoHasBeenParsed() && can_create) { | ||||
SymbolContext sc; | SymbolContext sc; | ||||
CalculateSymbolContext(&sc); | CalculateSymbolContext(&sc); | ||||
if (sc.module_sp) { | if (sc.module_sp) { | ||||
sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc); | sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc); | ||||
} else { | } else { | ||||
Host::SystemLog(Host::eSystemLogError, "error: unable to find module " | Host::SystemLog(Host::eSystemLogError, "error: unable to find module " | ||||
▲ Show 20 Lines • Show All 323 Lines • Show Last 20 Lines |
Easy to confuse with lambda assignment (although it wouldn't make any sense).
Maybe?