summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/SymbolFile
diff options
context:
space:
mode:
authorVedant Kumar <vsk@apple.com>2019-09-14 19:43:16 -0700
committerVedant Kumar <vsk@apple.com>2019-11-22 11:50:22 -0800
commit4fdbc0728d4b8acb1921fc48301622e971fc3961 (patch)
tree74a32d9948b5c41de1b711455b2dc54f7b6e5570 /lldb/source/Plugins/SymbolFile
parent3f8a2af8f43faf6da15070108ceeacb9a5d2c42b (diff)
downloadbcm5719-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')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp94
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h2
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 &param : 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;
OpenPOWER on IntegriCloud