diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-12-02 21:02:54 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-12-02 21:02:54 +0000 |
commit | f65dcba83ce5035ab88a85fe17628b447eb56e1b (patch) | |
tree | 35f37bb72b3cfc6060193e66c76ee7c9478969b0 /lldb/source/Symbol/ObjectFile.cpp | |
parent | 846a2208a8ab099f595fe7e8b2e6d54a7b5e67fb (diff) |
Diffstat (limited to 'lldb/source/Symbol/ObjectFile.cpp')
-rw-r--r-- | lldb/source/Symbol/ObjectFile.cpp | 38 |
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(); +} |