diff options
author | Vedant Kumar <vsk@apple.com> | 2019-09-14 19:43:16 -0700 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2019-11-22 11:50:22 -0800 |
commit | 4fdbc0728d4b8acb1921fc48301622e971fc3961 (patch) | |
tree | 74a32d9948b5c41de1b711455b2dc54f7b6e5570 /lldb/source/Plugins/SymbolFile | |
parent | 3f8a2af8f43faf6da15070108ceeacb9a5d2c42b (diff) | |
download | bcm5719-llvm-4fdbc0728d4b8acb1921fc48301622e971fc3961.tar.gz bcm5719-llvm-4fdbc0728d4b8acb1921fc48301622e971fc3961.zip |
[DWARF] Handle call sites with indirect call targets
Split CallEdge into DirectCallEdge and IndirectCallEdge. Teach
DWARFExpression how to evaluate entry values in cases where the current
activation was created by an indirect call.
rdar://57094085
Differential Revision: https://reviews.llvm.org/D70100
Diffstat (limited to 'lldb/source/Plugins/SymbolFile')
4 files changed, 77 insertions, 23 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 08dcfa57ffe..fcdff01dd20 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3781,8 +3781,8 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { if (child.Tag() != DW_TAG_call_site_parameter) continue; - llvm::Optional<DWARFExpression> LocationInCallee = {}; - llvm::Optional<DWARFExpression> LocationInCaller = {}; + llvm::Optional<DWARFExpression> LocationInCallee; + llvm::Optional<DWARFExpression> LocationInCaller; DWARFAttributes attributes; const size_t num_attributes = child.GetAttributes(attributes); @@ -3821,7 +3821,7 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { } /// Collect call graph edges present in a function DIE. -static std::vector<lldb_private::CallEdge> +static std::vector<std::unique_ptr<lldb_private::CallEdge>> CollectCallEdges(ModuleSP module, DWARFDIE function_die) { // Check if the function has a supported call site-related attribute. // TODO: In the future it may be worthwhile to support call_all_source_calls. @@ -3839,32 +3839,87 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) { // to be DWARF5-compliant. This may need to be done lazily to be performant. // For now, assume that all entries are nested directly under the subprogram // (this is the kind of DWARF LLVM produces) and parse them eagerly. - std::vector<CallEdge> call_edges; + std::vector<std::unique_ptr<CallEdge>> call_edges; for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid(); child = child.GetSibling()) { if (child.Tag() != DW_TAG_call_site) continue; - // Extract DW_AT_call_origin (the call target's DIE). - DWARFDIE call_origin = child.GetReferencedDIE(DW_AT_call_origin); - if (!call_origin.IsValid()) { - LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}", - function_die.GetPubname()); + llvm::Optional<DWARFDIE> call_origin; + llvm::Optional<DWARFExpression> call_target; + addr_t return_pc = LLDB_INVALID_ADDRESS; + + DWARFAttributes attributes; + const size_t num_attributes = child.GetAttributes(attributes); + for (size_t i = 0; i < num_attributes; ++i) { + DWARFFormValue form_value; + if (!attributes.ExtractFormValueAtIndex(i, form_value)) { + LLDB_LOG(log, "CollectCallEdges: Could not extract TAG_call_site form"); + break; + } + + dw_attr_t attr = attributes.AttributeAtIndex(i); + + // Extract DW_AT_call_origin (the call target's DIE). + if (attr == DW_AT_call_origin) { + call_origin = form_value.Reference(); + if (!call_origin->IsValid()) { + LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}", + function_die.GetPubname()); + break; + } + } + + // Extract DW_AT_call_return_pc (the PC the call returns to) if it's + // available. It should only ever be unavailable for tail call edges, in + // which case use LLDB_INVALID_ADDRESS. + if (attr == DW_AT_call_return_pc) + return_pc = form_value.Address(); + + // Extract DW_AT_call_target (the location of the address of the indirect + // call). + if (attr == DW_AT_call_target) { + if (!DWARFFormValue::IsBlockForm(form_value.Form())) { + LLDB_LOG(log, + "CollectCallEdges: AT_call_target does not have block form"); + break; + } + + auto data = child.GetData(); + uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); + uint32_t block_length = form_value.Unsigned(); + call_target = DWARFExpression( + module, DataExtractor(data, block_offset, block_length), + child.GetCU()); + } + } + if (!call_origin && !call_target) { + LLDB_LOG(log, "CollectCallEdges: call site without any call target"); continue; } - // Extract DW_AT_call_return_pc (the PC the call returns to) if it's - // available. It should only ever be unavailable for tail call edges, in - // which case use LLDB_INVALID_ADDRESS. - addr_t return_pc = child.GetAttributeValueAsAddress(DW_AT_call_return_pc, - LLDB_INVALID_ADDRESS); - // Extract call site parameters. CallSiteParameterArray parameters = CollectCallSiteParameters(module, child); - LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})", - call_origin.GetPubname(), return_pc); + std::unique_ptr<CallEdge> edge; + if (call_origin) { + LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})", + call_origin->GetPubname(), return_pc); + edge = std::make_unique<DirectCallEdge>(call_origin->GetMangledName(), + return_pc, std::move(parameters)); + } else { + if (log) { + StreamString call_target_desc; + call_target->GetDescription(&call_target_desc, eDescriptionLevelBrief, + LLDB_INVALID_ADDRESS, nullptr); + LLDB_LOG(log, "CollectCallEdges: Found indirect call target: {0}", + call_target_desc.GetString()); + } + edge = std::make_unique<IndirectCallEdge>(*call_target, return_pc, + std::move(parameters)); + } + if (log && parameters.size()) { for (const CallSiteParameter ¶m : parameters) { StreamString callee_loc_desc, caller_loc_desc; @@ -3879,13 +3934,12 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) { } } - call_edges.emplace_back(call_origin.GetMangledName(), return_pc, - std::move(parameters)); + call_edges.push_back(std::move(edge)); } return call_edges; } -std::vector<lldb_private::CallEdge> +std::vector<std::unique_ptr<lldb_private::CallEdge>> SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) { DWARFDIE func_die = GetDIE(func_id.GetID()); if (func_die.IsValid()) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index a86350844ef..9e4e4279eec 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -307,7 +307,7 @@ public: DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx, const DWARFDIE &die); - std::vector<lldb_private::CallEdge> + std::vector<std::unique_ptr<lldb_private::CallEdge>> ParseCallEdgesInFunction(UserID func_id) override; void Dump(lldb_private::Stream &s) override; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 4cac7e73d74..dbdbf499294 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1076,7 +1076,7 @@ void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, } } -std::vector<lldb_private::CallEdge> +std::vector<std::unique_ptr<lldb_private::CallEdge>> SymbolFileDWARFDebugMap::ParseCallEdgesInFunction(UserID func_id) { uint32_t oso_idx = GetOSOIndexFromUserID(func_id.GetID()); SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 0f47348bc84..035a902498b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -136,7 +136,7 @@ public: void GetTypes(lldb_private::SymbolContextScope *sc_scope, lldb::TypeClass type_mask, lldb_private::TypeList &type_list) override; - std::vector<lldb_private::CallEdge> + std::vector<std::unique_ptr<lldb_private::CallEdge>> ParseCallEdgesInFunction(lldb_private::UserID func_id) override; void DumpClangAST(lldb_private::Stream &s) override; |