blob: 4b87f697fc03c9c379eea0e8d272cd980cf62085 [file] [log] [blame]
Greg Claytondc5eb692011-04-25 18:36:36 +00001//===-- UnwindTable.cpp -----------------------------------------*- C++ -*-===//
Jason Molendafbcb7f22010-09-10 07:49:16 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Jason Molendafbcb7f22010-09-10 07:49:16 +00006//
7//===----------------------------------------------------------------------===//
8
Greg Claytona51ed9b2010-09-23 01:09:21 +00009#include "lldb/Symbol/UnwindTable.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000010
Greg Claytona51ed9b2010-09-23 01:09:21 +000011#include <stdio.h>
12
Greg Claytona51ed9b2010-09-23 01:09:21 +000013#include "lldb/Core/Module.h"
14#include "lldb/Core/Section.h"
Tamas Berghammer648f3c72015-09-30 13:50:14 +000015#include "lldb/Symbol/ArmUnwindInfo.h"
Jason Molendae589e7e2014-12-08 03:09:00 +000016#include "lldb/Symbol/CompactUnwindInfo.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000017#include "lldb/Symbol/DWARFCallFrameInfo.h"
18#include "lldb/Symbol/FuncUnwinders.h"
19#include "lldb/Symbol/ObjectFile.h"
20#include "lldb/Symbol/SymbolContext.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000021
Adrian Prantl05097242018-04-30 16:49:04 +000022// There is one UnwindTable object per ObjectFile. It contains a list of Unwind
23// objects -- one per function, populated lazily -- for the ObjectFile. Each
24// Unwind object has multiple UnwindPlans for different scenarios.
Jason Molendafbcb7f22010-09-10 07:49:16 +000025
26using namespace lldb;
27using namespace lldb_private;
28
Pavel Labath66d88322019-02-14 14:40:10 +000029UnwindTable::UnwindTable(Module &module)
30 : m_module(module), m_unwinds(), m_initialized(false), m_mutex(),
Kate Stoneb9c1b512016-09-06 20:57:50 +000031 m_eh_frame_up(), m_compact_unwind_up(), m_arm_unwind_up() {}
Jason Molendafbcb7f22010-09-10 07:49:16 +000032
Kate Stoneb9c1b512016-09-06 20:57:50 +000033// We can't do some of this initialization when the ObjectFile is running its
Adrian Prantl05097242018-04-30 16:49:04 +000034// ctor; delay doing it until needed for something.
Jason Molendafbcb7f22010-09-10 07:49:16 +000035
Kate Stoneb9c1b512016-09-06 20:57:50 +000036void UnwindTable::Initialize() {
37 if (m_initialized)
38 return;
Jason Molendafbcb7f22010-09-10 07:49:16 +000039
Kate Stoneb9c1b512016-09-06 20:57:50 +000040 std::lock_guard<std::mutex> guard(m_mutex);
Jason Molenda5cba5692014-06-18 23:32:53 +000041
Kate Stoneb9c1b512016-09-06 20:57:50 +000042 if (m_initialized) // check again once we've acquired the lock
43 return;
Pavel Labathcdda23e2017-06-27 11:16:26 +000044 m_initialized = true;
Pavel Labath66d88322019-02-14 14:40:10 +000045 ObjectFile *object_file = m_module.GetObjectFile();
46 if (!object_file)
47 return;
Jason Molenda5cba5692014-06-18 23:32:53 +000048
Pavel Labathdec96392019-03-18 10:45:02 +000049 SectionList *sl = m_module.GetSectionList();
Pavel Labathcdda23e2017-06-27 11:16:26 +000050 if (!sl)
51 return;
52
53 SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true);
54 if (sect.get()) {
Pavel Labath3f2a0812017-06-28 09:09:19 +000055 m_eh_frame_up.reset(
Pavel Labath66d88322019-02-14 14:40:10 +000056 new DWARFCallFrameInfo(*object_file, sect, DWARFCallFrameInfo::EH));
Kate Stoneb9c1b512016-09-06 20:57:50 +000057 }
58
Pavel Labathcdda23e2017-06-27 11:16:26 +000059 sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true);
60 if (sect) {
61 m_debug_frame_up.reset(
Pavel Labath66d88322019-02-14 14:40:10 +000062 new DWARFCallFrameInfo(*object_file, sect, DWARFCallFrameInfo::DWARF));
Pavel Labathcdda23e2017-06-27 11:16:26 +000063 }
64
65 sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true);
66 if (sect) {
Pavel Labath66d88322019-02-14 14:40:10 +000067 m_compact_unwind_up.reset(new CompactUnwindInfo(*object_file, sect));
Pavel Labathcdda23e2017-06-27 11:16:26 +000068 }
69
70 sect = sl->FindSectionByType(eSectionTypeARMexidx, true);
71 if (sect) {
72 SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true);
73 if (sect_extab.get()) {
Pavel Labath66d88322019-02-14 14:40:10 +000074 m_arm_unwind_up.reset(new ArmUnwindInfo(*object_file, sect, sect_extab));
Pavel Labathcdda23e2017-06-27 11:16:26 +000075 }
76 }
Jason Molendafbcb7f22010-09-10 07:49:16 +000077}
78
Kate Stoneb9c1b512016-09-06 20:57:50 +000079UnwindTable::~UnwindTable() {}
Jason Molendafbcb7f22010-09-10 07:49:16 +000080
Pavel Labathcdda23e2017-06-27 11:16:26 +000081llvm::Optional<AddressRange> UnwindTable::GetAddressRange(const Address &addr,
82 SymbolContext &sc) {
83 AddressRange range;
84
85 // First check the symbol context
86 if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
87 false, range) &&
88 range.GetBaseAddress().IsValid())
89 return range;
90
91 // Does the eh_frame unwind info has a function bounds for this addr?
92 if (m_eh_frame_up && m_eh_frame_up->GetAddressRange(addr, range))
93 return range;
94
95 // Try debug_frame as well
96 if (m_debug_frame_up && m_debug_frame_up->GetAddressRange(addr, range))
97 return range;
98
99 return llvm::None;
100}
101
Jason Molendafbcb7f22010-09-10 07:49:16 +0000102FuncUnwindersSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000103UnwindTable::GetFuncUnwindersContainingAddress(const Address &addr,
104 SymbolContext &sc) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000105 Initialize();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000106
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107 std::lock_guard<std::mutex> guard(m_mutex);
Jason Molenda5cba5692014-06-18 23:32:53 +0000108
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109 // There is an UnwindTable per object file, so we can safely use file handles
110 addr_t file_addr = addr.GetFileAddress();
111 iterator end = m_unwinds.end();
112 iterator insert_pos = end;
113 if (!m_unwinds.empty()) {
114 insert_pos = m_unwinds.lower_bound(file_addr);
115 iterator pos = insert_pos;
116 if ((pos == m_unwinds.end()) ||
117 (pos != m_unwinds.begin() &&
118 pos->second->GetFunctionStartAddress() != addr))
119 --pos;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000120
Kate Stoneb9c1b512016-09-06 20:57:50 +0000121 if (pos->second->ContainsAddress(addr))
122 return pos->second;
123 }
124
Pavel Labathcdda23e2017-06-27 11:16:26 +0000125 auto range_or = GetAddressRange(addr, sc);
126 if (!range_or)
127 return nullptr;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000128
Pavel Labathcdda23e2017-06-27 11:16:26 +0000129 FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, *range_or));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000130 m_unwinds.insert(insert_pos,
Pavel Labathcdda23e2017-06-27 11:16:26 +0000131 std::make_pair(range_or->GetBaseAddress().GetFileAddress(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000132 func_unwinder_sp));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133 return func_unwinder_sp;
Greg Claytonb0848c52011-01-08 00:05:12 +0000134}
135
Kate Stoneb9c1b512016-09-06 20:57:50 +0000136// Ignore any existing FuncUnwinders for this function, create a new one and
Adrian Prantl05097242018-04-30 16:49:04 +0000137// don't add it to the UnwindTable. This is intended for use by target modules
138// show-unwind where we want to create new UnwindPlans, not re-use existing
139// ones.
Jason Molenda380241a2012-07-12 00:20:07 +0000140FuncUnwindersSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141UnwindTable::GetUncachedFuncUnwindersContainingAddress(const Address &addr,
142 SymbolContext &sc) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 Initialize();
Jason Molenda380241a2012-07-12 00:20:07 +0000144
Pavel Labathcdda23e2017-06-27 11:16:26 +0000145 auto range_or = GetAddressRange(addr, sc);
146 if (!range_or)
147 return nullptr;
Jason Molenda380241a2012-07-12 00:20:07 +0000148
Pavel Labathcdda23e2017-06-27 11:16:26 +0000149 return std::make_shared<FuncUnwinders>(*this, *range_or);
Jason Molenda380241a2012-07-12 00:20:07 +0000150}
151
Kate Stoneb9c1b512016-09-06 20:57:50 +0000152void UnwindTable::Dump(Stream &s) {
153 std::lock_guard<std::mutex> guard(m_mutex);
Pavel Labath66d88322019-02-14 14:40:10 +0000154 s.Format("UnwindTable for '{0}':\n", m_module.GetFileSpec());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 const_iterator begin = m_unwinds.begin();
156 const_iterator end = m_unwinds.end();
157 for (const_iterator pos = begin; pos != end; ++pos) {
158 s.Printf("[%u] 0x%16.16" PRIx64 "\n", (unsigned)std::distance(begin, pos),
159 pos->first);
160 }
161 s.EOL();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000162}
163
Kate Stoneb9c1b512016-09-06 20:57:50 +0000164DWARFCallFrameInfo *UnwindTable::GetEHFrameInfo() {
165 Initialize();
166 return m_eh_frame_up.get();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000167}
Jason Molendaab35aa92014-05-23 01:48:10 +0000168
Pavel Labathcdda23e2017-06-27 11:16:26 +0000169DWARFCallFrameInfo *UnwindTable::GetDebugFrameInfo() {
170 Initialize();
171 return m_debug_frame_up.get();
172}
173
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174CompactUnwindInfo *UnwindTable::GetCompactUnwindInfo() {
175 Initialize();
176 return m_compact_unwind_up.get();
Tamas Berghammer648f3c72015-09-30 13:50:14 +0000177}
178
Kate Stoneb9c1b512016-09-06 20:57:50 +0000179ArmUnwindInfo *UnwindTable::GetArmUnwindInfo() {
180 Initialize();
181 return m_arm_unwind_up.get();
Jason Molendae589e7e2014-12-08 03:09:00 +0000182}
183
Pavel Labath66d88322019-02-14 14:40:10 +0000184ArchSpec UnwindTable::GetArchitecture() { return m_module.GetArchitecture(); }
Jason Molenda955dcf22016-05-04 03:09:40 +0000185
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186bool UnwindTable::GetAllowAssemblyEmulationUnwindPlans() {
Pavel Labath66d88322019-02-14 14:40:10 +0000187 if (ObjectFile *object_file = m_module.GetObjectFile())
188 return object_file->AllowAssemblyEmulationUnwindPlans();
189 return false;
Jason Molenda955dcf22016-05-04 03:09:40 +0000190}