Skip to content

Commit 8f60ed1

Browse files
committed
[lldb] Change Module to have a concrete UnwindTable, update (llvm#101130)
Currently a Module has a std::optional<UnwindTable> which is created when the UnwindTable is requested from outside the Module. The idea is to delay its creation until the Module has an ObjectFile initialized, which will have been done by the time we're doing an unwind. However, Module::GetUnwindTable wasn't doing any locking, so it was possible for two threads to ask for the UnwindTable for the first time, one would be created and returned while another thread would create one, destroy the first in the process of emplacing it. It was an uncommon crash, but it was possible. Grabbing the Module's mutex would be one way to address it, but when loading ELF binaries, we start creating the SymbolTable on one thread (ObjectFileELF) grabbing the Module's mutex, and then spin up worker threads to parse the individual DWARF compilation units, which then try to also get the UnwindTable and deadlock if they try to get the Module's mutex. This changes Module to have a concrete UnwindTable as an ivar, and when it adds an ObjectFile or SymbolFileVendor, it will call the Update method on it, which will re-evaluate which sections exist in the ObjectFile/SymbolFile. UnwindTable used to have an Initialize method which set all the sections, and an Update method which would set some of them if they weren't set. I unified these with the Initialize method taking a `force` option to re-initialize the section pointers even if they had been done already before. This is addressing a rare crash report we've received, and also a failure Adrian spotted on the -fsanitize=address CI bot last week, it's still uncommon with ASAN but it can happen with the standard testsuite. rdar://128876433 (cherry picked from commit 7ad073a)
1 parent 3751470 commit 8f60ed1

File tree

4 files changed

+41
-75
lines changed

4 files changed

+41
-75
lines changed

lldb/include/lldb/Core/Module.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,9 +1041,9 @@ class Module : public std::enable_shared_from_this<Module>,
10411041
lldb::ObjectFileSP m_objfile_sp; ///< A shared pointer to the object file
10421042
/// parser for this module as it may or may
10431043
/// not be shared with the SymbolFile
1044-
std::optional<UnwindTable> m_unwind_table; ///< Table of FuncUnwinders
1045-
/// objects created for this
1046-
/// Module's functions
1044+
UnwindTable m_unwind_table; ///< Table of FuncUnwinders
1045+
/// objects created for this
1046+
/// Module's functions
10471047
lldb::SymbolVendorUP
10481048
m_symfile_up; ///< A pointer to the symbol vendor for this module.
10491049
std::vector<lldb::SymbolVendorUP>

lldb/include/lldb/Symbol/UnwindTable.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ class UnwindTable {
5757

5858
ArchSpec GetArchitecture();
5959

60-
/// Called after a SymbolFile has been added to a Module to add any new
61-
/// unwind sections that may now be available.
62-
void Update();
60+
/// Called after an ObjectFile/SymbolFile has been added to a Module to add
61+
/// any new unwind sections that may now be available.
62+
void ModuleWasUpdated();
6363

6464
private:
6565
void Dump(Stream &s);
@@ -75,7 +75,11 @@ class UnwindTable {
7575
Module &m_module;
7676
collection m_unwinds;
7777

78-
bool m_initialized; // delay some initialization until ObjectFile is set up
78+
bool m_scanned_all_unwind_sources; // true when we have looked at the
79+
// ObjectFile and SymbolFile for all
80+
// sources of unwind information; false if
81+
// we haven't done that yet, or one of the
82+
// files has been updated in the Module.
7983
std::mutex m_mutex;
8084

8185
std::unique_ptr<CallFrameInfo> m_object_file_unwind_up;

lldb/source/Core/Module.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ Module *Module::GetAllocatedModuleAtIndex(size_t idx) {
136136
}
137137

138138
Module::Module(const ModuleSpec &module_spec)
139-
: m_file_has_changed(false), m_first_file_changed_log(false) {
139+
: m_unwind_table(*this), m_file_has_changed(false),
140+
m_first_file_changed_log(false) {
140141
// Scope for locker below...
141142
{
142143
std::lock_guard<std::recursive_mutex> guard(
@@ -242,8 +243,8 @@ Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
242243
const llvm::sys::TimePoint<> &object_mod_time)
243244
: m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)),
244245
m_arch(arch), m_file(file_spec), m_object_offset(object_offset),
245-
m_object_mod_time(object_mod_time), m_file_has_changed(false),
246-
m_first_file_changed_log(false) {
246+
m_object_mod_time(object_mod_time), m_unwind_table(*this),
247+
m_file_has_changed(false), m_first_file_changed_log(false) {
247248
// Scope for locker below...
248249
{
249250
std::lock_guard<std::recursive_mutex> guard(
@@ -262,7 +263,9 @@ Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
262263
m_object_name.AsCString(""), m_object_name.IsEmpty() ? "" : ")");
263264
}
264265

265-
Module::Module() : m_file_has_changed(false), m_first_file_changed_log(false) {
266+
Module::Module()
267+
: m_unwind_table(*this), m_file_has_changed(false),
268+
m_first_file_changed_log(false) {
266269
std::lock_guard<std::recursive_mutex> guard(
267270
GetAllocationModuleCollectionMutex());
268271
GetModuleCollection().push_back(this);
@@ -331,6 +334,8 @@ ObjectFile *Module::GetMemoryObjectFile(const lldb::ProcessSP &process_sp,
331334
// Augment the arch with the target's information in case
332335
// we are unable to extract the os/environment from memory.
333336
m_arch.MergeFrom(process_sp->GetTarget().GetArchitecture());
337+
338+
m_unwind_table.ModuleWasUpdated();
334339
} else {
335340
error.SetErrorString("unable to find suitable object file plug-in");
336341
}
@@ -1046,8 +1051,7 @@ SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) {
10461051
m_symfile_up.reset(
10471052
SymbolVendor::FindPlugin(shared_from_this(), feedback_strm));
10481053
m_did_load_symfile = true;
1049-
if (m_unwind_table)
1050-
m_unwind_table->Update();
1054+
m_unwind_table.ModuleWasUpdated();
10511055
}
10521056
}
10531057
}
@@ -1345,6 +1349,8 @@ ObjectFile *Module::GetObjectFile() {
13451349
// more specific than the generic COFF architecture, only merge in
13461350
// those values that overwrite unspecified unknown values.
13471351
m_arch.MergeFrom(m_objfile_sp->GetArchitecture());
1352+
1353+
m_unwind_table.ModuleWasUpdated();
13481354
} else {
13491355
ReportError("failed to load objfile for {0}",
13501356
GetFileSpec().GetPath().c_str());
@@ -1374,12 +1380,9 @@ void Module::SectionFileAddressesChanged() {
13741380
}
13751381

13761382
UnwindTable &Module::GetUnwindTable() {
1377-
if (!m_unwind_table) {
1378-
if (!m_symfile_spec)
1379-
SymbolLocator::DownloadSymbolFileAsync(GetUUID());
1380-
m_unwind_table.emplace(*this);
1381-
}
1382-
return *m_unwind_table;
1383+
if (!m_symfile_spec)
1384+
SymbolLocator::DownloadSymbolFileAsync(GetUUID());
1385+
return m_unwind_table;
13831386
}
13841387

13851388
SectionList *Module::GetUnifiedSectionList() {

lldb/source/Symbol/UnwindTable.cpp

Lines changed: 15 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -30,70 +30,27 @@ using namespace lldb;
3030
using namespace lldb_private;
3131

3232
UnwindTable::UnwindTable(Module &module)
33-
: m_module(module), m_unwinds(), m_initialized(false), m_mutex(),
34-
m_object_file_unwind_up(), m_eh_frame_up(), m_compact_unwind_up(),
35-
m_arm_unwind_up() {}
33+
: m_module(module), m_unwinds(), m_scanned_all_unwind_sources(false),
34+
m_mutex(), m_object_file_unwind_up(), m_eh_frame_up(),
35+
m_compact_unwind_up(), m_arm_unwind_up() {}
3636

3737
// We can't do some of this initialization when the ObjectFile is running its
3838
// ctor; delay doing it until needed for something.
39-
4039
void UnwindTable::Initialize() {
41-
if (m_initialized)
40+
if (m_scanned_all_unwind_sources)
4241
return;
4342

4443
std::lock_guard<std::mutex> guard(m_mutex);
4544

46-
if (m_initialized) // check again once we've acquired the lock
47-
return;
48-
m_initialized = true;
49-
ObjectFile *object_file = m_module.GetObjectFile();
50-
if (!object_file)
45+
if (m_scanned_all_unwind_sources) // check again once we've acquired the lock
5146
return;
5247

53-
m_object_file_unwind_up = object_file->CreateCallFrameInfo();
54-
55-
SectionList *sl = m_module.GetSectionList();
56-
if (!sl)
57-
return;
58-
59-
SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true);
60-
if (sect.get()) {
61-
m_eh_frame_up = std::make_unique<DWARFCallFrameInfo>(
62-
*object_file, sect, DWARFCallFrameInfo::EH);
63-
}
64-
65-
sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true);
66-
if (sect) {
67-
m_debug_frame_up = std::make_unique<DWARFCallFrameInfo>(
68-
*object_file, sect, DWARFCallFrameInfo::DWARF);
69-
}
70-
71-
sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true);
72-
if (sect) {
73-
m_compact_unwind_up =
74-
std::make_unique<CompactUnwindInfo>(*object_file, sect);
75-
}
76-
77-
sect = sl->FindSectionByType(eSectionTypeARMexidx, true);
78-
if (sect) {
79-
SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true);
80-
if (sect_extab.get()) {
81-
m_arm_unwind_up =
82-
std::make_unique<ArmUnwindInfo>(*object_file, sect, sect_extab);
83-
}
84-
}
85-
}
86-
87-
void UnwindTable::Update() {
88-
if (!m_initialized)
89-
return Initialize();
90-
91-
std::lock_guard<std::mutex> guard(m_mutex);
92-
9348
ObjectFile *object_file = m_module.GetObjectFile();
9449
if (!object_file)
9550
return;
9651

52+
m_scanned_all_unwind_sources = true;
53+
9754
if (!m_object_file_unwind_up)
9855
m_object_file_unwind_up = object_file->CreateCallFrameInfo();
9956

@@ -102,22 +59,19 @@ void UnwindTable::Update() {
10259
return;
10360

10461
SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true);
105-
if (!m_eh_frame_up && sect) {
62+
if (!m_eh_frame_up && sect)
10663
m_eh_frame_up = std::make_unique<DWARFCallFrameInfo>(
10764
*object_file, sect, DWARFCallFrameInfo::EH);
108-
}
10965

11066
sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true);
111-
if (!m_debug_frame_up && sect) {
67+
if (!m_debug_frame_up && sect)
11268
m_debug_frame_up = std::make_unique<DWARFCallFrameInfo>(
11369
*object_file, sect, DWARFCallFrameInfo::DWARF);
114-
}
11570

11671
sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true);
117-
if (!m_compact_unwind_up && sect) {
72+
if (!m_compact_unwind_up && sect)
11873
m_compact_unwind_up =
11974
std::make_unique<CompactUnwindInfo>(*object_file, sect);
120-
}
12175

12276
sect = sl->FindSectionByType(eSectionTypeARMexidx, true);
12377
if (!m_arm_unwind_up && sect) {
@@ -129,6 +83,11 @@ void UnwindTable::Update() {
12983
}
13084
}
13185

86+
void UnwindTable::ModuleWasUpdated() {
87+
std::lock_guard<std::mutex> guard(m_mutex);
88+
m_scanned_all_unwind_sources = false;
89+
}
90+
13291
UnwindTable::~UnwindTable() = default;
13392

13493
std::optional<AddressRange>

0 commit comments

Comments
 (0)