aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Symbol/ObjectFile.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-12-02 21:02:54 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-12-02 21:02:54 +0000
commitf65dcba83ce5035ab88a85fe17628b447eb56e1b (patch)
tree35f37bb72b3cfc6060193e66c76ee7c9478969b0 /lldb/source/Symbol/ObjectFile.cpp
parent846a2208a8ab099f595fe7e8b2e6d54a7b5e67fb (diff)
Diffstat (limited to 'lldb/source/Symbol/ObjectFile.cpp')
-rw-r--r--lldb/source/Symbol/ObjectFile.cpp38
1 files changed, 35 insertions, 3 deletions
diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp
index 101af01341a2..bfab741b0d66 100644
--- a/lldb/source/Symbol/ObjectFile.cpp
+++ b/lldb/source/Symbol/ObjectFile.cpp
@@ -244,7 +244,7 @@ ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp,
m_type(eTypeInvalid), m_strata(eStrataInvalid),
m_file_offset(file_offset), m_length(length), m_data(), m_process_wp(),
m_memory_addr(LLDB_INVALID_ADDRESS), m_sections_up(), m_symtab_up(),
- m_synthetic_symbol_idx(0) {
+ m_symtab_once_up(new llvm::once_flag()) {
if (file_spec_ptr)
m_file = *file_spec_ptr;
if (data_sp)
@@ -265,7 +265,7 @@ ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp,
: ModuleChild(module_sp), m_file(), m_type(eTypeInvalid),
m_strata(eStrataInvalid), m_file_offset(0), m_length(0), m_data(),
m_process_wp(process_sp), m_memory_addr(header_addr), m_sections_up(),
- m_symtab_up(), m_synthetic_symbol_idx(0) {
+ m_symtab_up(), m_symtab_once_up(new llvm::once_flag()) {
if (header_data_sp)
m_data.SetData(header_data_sp, 0, header_data_sp->GetByteSize());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
@@ -571,11 +571,13 @@ bool ObjectFile::SplitArchivePathWithObject(llvm::StringRef path_with_object,
void ObjectFile::ClearSymtab() {
ModuleSP module_sp(GetModule());
if (module_sp) {
- std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
LLDB_LOGF(log, "%p ObjectFile::ClearSymtab () symtab = %p",
static_cast<void *>(this),
static_cast<void *>(m_symtab_up.get()));
+ // Since we need to clear the symbol table, we need a new llvm::once_flag
+ // instance so we can safely create another symbol table
+ m_symtab_once_up.reset(new llvm::once_flag());
m_symtab_up.reset();
}
}
@@ -715,3 +717,33 @@ void llvm::format_provider<ObjectFile::Strata>::format(
break;
}
}
+
+
+Symtab *ObjectFile::GetSymtab() {
+ ModuleSP module_sp(GetModule());
+ if (module_sp) {
+ // We can't take the module lock in ObjectFile::GetSymtab() or we can
+ // deadlock in DWARF indexing when any file asks for the symbol table from
+ // an object file. This currently happens in the preloading of symbols in
+ // SymbolFileDWARF::PreloadSymbols() because the main thread will take the
+ // module lock, and then threads will be spun up to index the DWARF and
+ // any of those threads might end up trying to relocate items in the DWARF
+ // sections which causes ObjectFile::GetSectionData(...) to relocate section
+ // data which requires the symbol table.
+ //
+ // So to work around this, we create the symbol table one time using
+ // llvm::once_flag, lock it, and then set the unique pointer. Any other
+ // thread that gets ahold of the symbol table before parsing is done, will
+ // not be able to access the symbol table contents since all APIs in Symtab
+ // are protected by a mutex in the Symtab object itself.
+ llvm::call_once(*m_symtab_once_up, [&]() {
+ ElapsedTime elapsed(module_sp->GetSymtabParseTime());
+ Symtab *symtab = new Symtab(this);
+ std::lock_guard<std::recursive_mutex> symtab_guard(symtab->GetMutex());
+ m_symtab_up.reset(symtab);
+ ParseSymtab(*m_symtab_up);
+ m_symtab_up->Finalize();
+ });
+ }
+ return m_symtab_up.get();
+}