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);  | 
