diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp')
| -rw-r--r-- | contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp | 140 |
1 files changed, 54 insertions, 86 deletions
diff --git a/contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp b/contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp index 11bedf3d6052..3aca495696c8 100644 --- a/contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp @@ -30,70 +30,27 @@ using namespace lldb; using namespace lldb_private; UnwindTable::UnwindTable(Module &module) - : m_module(module), m_unwinds(), m_initialized(false), m_mutex(), - m_object_file_unwind_up(), m_eh_frame_up(), m_compact_unwind_up(), - m_arm_unwind_up() {} + : m_module(module), m_unwinds(), m_scanned_all_unwind_sources(false), + m_mutex(), m_object_file_unwind_up(), m_eh_frame_up(), + m_compact_unwind_up(), m_arm_unwind_up() {} // We can't do some of this initialization when the ObjectFile is running its // ctor; delay doing it until needed for something. - void UnwindTable::Initialize() { - if (m_initialized) + if (m_scanned_all_unwind_sources) return; std::lock_guard<std::mutex> guard(m_mutex); - if (m_initialized) // check again once we've acquired the lock - return; - m_initialized = true; - ObjectFile *object_file = m_module.GetObjectFile(); - if (!object_file) - return; - - m_object_file_unwind_up = object_file->CreateCallFrameInfo(); - - SectionList *sl = m_module.GetSectionList(); - if (!sl) + if (m_scanned_all_unwind_sources) // check again once we've acquired the lock return; - SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true); - if (sect.get()) { - m_eh_frame_up = std::make_unique<DWARFCallFrameInfo>( - *object_file, sect, DWARFCallFrameInfo::EH); - } - - sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true); - if (sect) { - m_debug_frame_up = std::make_unique<DWARFCallFrameInfo>( - *object_file, sect, DWARFCallFrameInfo::DWARF); - } - - sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true); - if (sect) { - m_compact_unwind_up = - std::make_unique<CompactUnwindInfo>(*object_file, sect); - } - - sect = sl->FindSectionByType(eSectionTypeARMexidx, true); - if (sect) { - SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true); - if (sect_extab.get()) { - m_arm_unwind_up = - std::make_unique<ArmUnwindInfo>(*object_file, sect, sect_extab); - } - } -} - -void UnwindTable::Update() { - if (!m_initialized) - return Initialize(); - - std::lock_guard<std::mutex> guard(m_mutex); - ObjectFile *object_file = m_module.GetObjectFile(); if (!object_file) return; + m_scanned_all_unwind_sources = true; + if (!m_object_file_unwind_up) m_object_file_unwind_up = object_file->CreateCallFrameInfo(); @@ -102,22 +59,19 @@ void UnwindTable::Update() { return; SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true); - if (!m_eh_frame_up && sect) { + if (!m_eh_frame_up && sect) m_eh_frame_up = std::make_unique<DWARFCallFrameInfo>( *object_file, sect, DWARFCallFrameInfo::EH); - } sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true); - if (!m_debug_frame_up && sect) { + if (!m_debug_frame_up && sect) m_debug_frame_up = std::make_unique<DWARFCallFrameInfo>( *object_file, sect, DWARFCallFrameInfo::DWARF); - } sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true); - if (!m_compact_unwind_up && sect) { + if (!m_compact_unwind_up && sect) m_compact_unwind_up = std::make_unique<CompactUnwindInfo>(*object_file, sect); - } sect = sl->FindSectionByType(eSectionTypeARMexidx, true); if (!m_arm_unwind_up && sect) { @@ -129,65 +83,78 @@ void UnwindTable::Update() { } } +void UnwindTable::ModuleWasUpdated() { + std::lock_guard<std::mutex> guard(m_mutex); + m_scanned_all_unwind_sources = false; + m_unwinds.clear(); +} + UnwindTable::~UnwindTable() = default; -std::optional<AddressRange> -UnwindTable::GetAddressRange(const Address &addr, const SymbolContext &sc) { +AddressRanges UnwindTable::GetAddressRanges(const Address &addr, + const SymbolContext &sc) { AddressRange range; // First check the unwind info from the object file plugin if (m_object_file_unwind_up && m_object_file_unwind_up->GetAddressRange(addr, range)) - return range; + return {range}; // Check the symbol context - if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, - false, range) && - range.GetBaseAddress().IsValid()) - return range; + AddressRanges result; + for (size_t idx = 0; + sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, idx, + false, range) && + range.GetBaseAddress().IsValid(); + ++idx) + result.push_back(range); + if (!result.empty()) + return result; // Does the eh_frame unwind info has a function bounds for this addr? if (m_eh_frame_up && m_eh_frame_up->GetAddressRange(addr, range)) - return range; + return {range}; // Try debug_frame as well if (m_debug_frame_up && m_debug_frame_up->GetAddressRange(addr, range)) - return range; + return {range}; - return std::nullopt; + return {}; +} + +static Address GetFunctionOrSymbolAddress(const Address &addr, + const SymbolContext &sc) { + if (Address result = sc.GetFunctionOrSymbolAddress(); result.IsValid()) + return result; + return addr; } FuncUnwindersSP UnwindTable::GetFuncUnwindersContainingAddress(const Address &addr, - SymbolContext &sc) { + const SymbolContext &sc) { Initialize(); std::lock_guard<std::mutex> guard(m_mutex); // There is an UnwindTable per object file, so we can safely use file handles addr_t file_addr = addr.GetFileAddress(); - iterator end = m_unwinds.end(); - iterator insert_pos = end; - if (!m_unwinds.empty()) { - insert_pos = m_unwinds.lower_bound(file_addr); - iterator pos = insert_pos; - if ((pos == m_unwinds.end()) || - (pos != m_unwinds.begin() && - pos->second->GetFunctionStartAddress() != addr)) - --pos; - + iterator insert_pos = m_unwinds.upper_bound(file_addr); + if (insert_pos != m_unwinds.begin()) { + auto pos = std::prev(insert_pos); if (pos->second->ContainsAddress(addr)) return pos->second; } - auto range_or = GetAddressRange(addr, sc); - if (!range_or) + Address start_addr = GetFunctionOrSymbolAddress(addr, sc); + AddressRanges ranges = GetAddressRanges(addr, sc); + if (ranges.empty()) return nullptr; - FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, *range_or)); - m_unwinds.insert(insert_pos, - std::make_pair(range_or->GetBaseAddress().GetFileAddress(), - func_unwinder_sp)); + auto func_unwinder_sp = + std::make_shared<FuncUnwinders>(*this, start_addr, ranges); + for (const AddressRange &range : ranges) + m_unwinds.emplace_hint(insert_pos, range.GetBaseAddress().GetFileAddress(), + func_unwinder_sp); return func_unwinder_sp; } @@ -199,11 +166,12 @@ FuncUnwindersSP UnwindTable::GetUncachedFuncUnwindersContainingAddress( const Address &addr, const SymbolContext &sc) { Initialize(); - auto range_or = GetAddressRange(addr, sc); - if (!range_or) + Address start_addr = GetFunctionOrSymbolAddress(addr, sc); + AddressRanges ranges = GetAddressRanges(addr, sc); + if (ranges.empty()) return nullptr; - return std::make_shared<FuncUnwinders>(*this, *range_or); + return std::make_shared<FuncUnwinders>(*this, start_addr, std::move(ranges)); } void UnwindTable::Dump(Stream &s) { |
