Skip to content

Commit 6cfc90b

Browse files
committed
[Function] Lock the function when parsing call site info
Summary: DWARF-parsing methods in SymbolFileDWARF which update module state typically take the module lock. ParseCallEdgesInFunction doesn't do this, but higher-level locking within lldb::Function (which owns the storage for parsed call edges) is necessary. The lack of locking could explain some as-of-yet unreproducible crashes which occur in Function::GetTailCallingEdges(). In these crashes, the `m_call_edges` vector is non-empty but contains a nullptr, which shouldn't be possible. (If this vector is non-empty, it _must_ contain a non-null unique_ptr.) This may address rdar://55622443 and rdar://65119458. Reviewers: jasonmolenda, friss, jingham Subscribers: aprantl, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D83359
1 parent 0b72b9d commit 6cfc90b

File tree

3 files changed

+12
-0
lines changed

3 files changed

+12
-0
lines changed

lldb/include/lldb/Symbol/Function.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "lldb/Utility/UserID.h"
1818
#include "llvm/ADT/ArrayRef.h"
1919

20+
#include <mutex>
21+
2022
namespace lldb_private {
2123

2224
class ExecutionContext;
@@ -655,6 +657,9 @@ class Function : public UserID, public SymbolContextScope {
655657
uint32_t
656658
m_prologue_byte_size; ///< Compute the prologue size once and cache it
657659

660+
std::mutex
661+
m_call_edges_lock; ///< Exclusive lock that controls read/write
662+
/// access to m_call_edges and m_call_edges_resolved.
658663
bool m_call_edges_resolved = false; ///< Whether call site info has been
659664
/// parsed.
660665
std::vector<std::unique_ptr<CallEdge>> m_call_edges; ///< Outgoing call edges.

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3844,6 +3844,11 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
38443844

38453845
std::vector<std::unique_ptr<lldb_private::CallEdge>>
38463846
SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) {
3847+
// ParseCallEdgesInFunction must be called at the behest of an exclusively
3848+
// locked lldb::Function instance. Storage for parsed call edges is owned by
3849+
// the lldb::Function instance: locking at the SymbolFile level would be too
3850+
// late, because the act of storing results from ParseCallEdgesInFunction
3851+
// would be racy.
38473852
DWARFDIE func_die = GetDIE(func_id.GetID());
38483853
if (func_die.IsValid())
38493854
return CollectCallEdges(GetObjectFile()->GetModule(), func_die);

lldb/source/Symbol/Function.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) {
290290
}
291291

292292
llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetCallEdges() {
293+
std::lock_guard<std::mutex> guard(m_call_edges_lock);
294+
293295
if (m_call_edges_resolved)
294296
return m_call_edges;
295297

0 commit comments

Comments
 (0)