blob: df9f5b9325653675d3a27785f647817dd0970711 [file] [log] [blame]
Greg Claytondc5eb692011-04-25 18:36:36 +00001//===-- UnwindTable.cpp -----------------------------------------*- C++ -*-===//
Jason Molendafbcb7f22010-09-10 07:49:16 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Greg Claytona51ed9b2010-09-23 01:09:21 +000010#include "lldb/Symbol/UnwindTable.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000011
Greg Claytona51ed9b2010-09-23 01:09:21 +000012#include <stdio.h>
13
Greg Claytona51ed9b2010-09-23 01:09:21 +000014#include "lldb/Core/Module.h"
15#include "lldb/Core/Section.h"
16#include "lldb/Symbol/ObjectFile.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000017#include "lldb/Symbol/FuncUnwinders.h"
18#include "lldb/Symbol/SymbolContext.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000019#include "lldb/Symbol/DWARFCallFrameInfo.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000020
21// There is one UnwindTable object per ObjectFile.
22// It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile.
23// Each Unwind object has multiple UnwindPlans for different scenarios.
24
25using namespace lldb;
26using namespace lldb_private;
27
Greg Claytonb0848c52011-01-08 00:05:12 +000028UnwindTable::UnwindTable (ObjectFile& objfile) :
29 m_object_file (objfile),
30 m_unwinds (),
31 m_initialized (false),
Jason Molenda5cba5692014-06-18 23:32:53 +000032 m_mutex (),
Ed Masted4612ad2014-04-20 13:17:36 +000033 m_eh_frame (nullptr)
Jason Molendafbcb7f22010-09-10 07:49:16 +000034{
35}
36
37// We can't do some of this initialization when the ObjectFile is running its ctor; delay doing it
38// until needed for something.
39
40void
Greg Claytonb0848c52011-01-08 00:05:12 +000041UnwindTable::Initialize ()
Jason Molendafbcb7f22010-09-10 07:49:16 +000042{
43 if (m_initialized)
44 return;
45
Jason Molenda5cba5692014-06-18 23:32:53 +000046 Mutex::Locker locker(m_mutex);
47
48 if (m_initialized) // check again once we've acquired the lock
49 return;
50
Jason Molendafbcb7f22010-09-10 07:49:16 +000051 SectionList* sl = m_object_file.GetSectionList ();
52 if (sl)
53 {
54 SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true);
55 if (sect.get())
56 {
57 m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true);
58 }
59 }
60
Jason Molendaab35aa92014-05-23 01:48:10 +000061 m_initialized = true;
Jason Molendafbcb7f22010-09-10 07:49:16 +000062}
63
64UnwindTable::~UnwindTable ()
65{
66 if (m_eh_frame)
67 delete m_eh_frame;
68}
69
70FuncUnwindersSP
71UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
72{
73 FuncUnwindersSP no_unwind_found;
74
Greg Claytonb0848c52011-01-08 00:05:12 +000075 Initialize();
Jason Molendafbcb7f22010-09-10 07:49:16 +000076
Jason Molenda5cba5692014-06-18 23:32:53 +000077 Mutex::Locker locker(m_mutex);
78
Greg Claytonb0848c52011-01-08 00:05:12 +000079 // There is an UnwindTable per object file, so we can safely use file handles
80 addr_t file_addr = addr.GetFileAddress();
81 iterator end = m_unwinds.end ();
82 iterator insert_pos = end;
83 if (!m_unwinds.empty())
84 {
85 insert_pos = m_unwinds.lower_bound (file_addr);
86 iterator pos = insert_pos;
87 if ((pos == m_unwinds.end ()) || (pos != m_unwinds.begin() && pos->second->GetFunctionStartAddress() != addr))
88 --pos;
Jason Molendafbcb7f22010-09-10 07:49:16 +000089
Greg Claytonb0848c52011-01-08 00:05:12 +000090 if (pos->second->ContainsAddress (addr))
91 return pos->second;
Jason Molendafbcb7f22010-09-10 07:49:16 +000092 }
93
94 AddressRange range;
Greg Clayton7e14f912011-04-23 02:04:55 +000095 if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
Jason Molendafbcb7f22010-09-10 07:49:16 +000096 {
Jason Molenda59762002010-11-04 00:53:20 +000097 // Does the eh_frame unwind info has a function bounds for this addr?
Ed Masted4612ad2014-04-20 13:17:36 +000098 if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
Jason Molendafbcb7f22010-09-10 07:49:16 +000099 {
Jason Molenda59762002010-11-04 00:53:20 +0000100 return no_unwind_found;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000101 }
102 }
Jason Molenda59762002010-11-04 00:53:20 +0000103
Jason Molendaab35aa92014-05-23 01:48:10 +0000104 FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, range));
Greg Claytonb0848c52011-01-08 00:05:12 +0000105 m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp));
Michael Sartain762df1f2013-10-10 00:16:10 +0000106// StreamFile s(stdout, false);
Greg Claytonb0848c52011-01-08 00:05:12 +0000107// Dump (s);
108 return func_unwinder_sp;
109}
110
Jason Molenda380241a2012-07-12 00:20:07 +0000111// Ignore any existing FuncUnwinders for this function, create a new one and don't add it to the
112// UnwindTable. This is intended for use by target modules show-unwind where we want to create
113// new UnwindPlans, not re-use existing ones.
114
115FuncUnwindersSP
116UnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
117{
118 FuncUnwindersSP no_unwind_found;
119 Initialize();
120
121 AddressRange range;
122 if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
123 {
124 // Does the eh_frame unwind info has a function bounds for this addr?
Ed Masted4612ad2014-04-20 13:17:36 +0000125 if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
Jason Molenda380241a2012-07-12 00:20:07 +0000126 {
127 return no_unwind_found;
128 }
129 }
130
Jason Molendaab35aa92014-05-23 01:48:10 +0000131 FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, range));
Jason Molenda380241a2012-07-12 00:20:07 +0000132 return func_unwinder_sp;
133}
134
135
Greg Claytonb0848c52011-01-08 00:05:12 +0000136void
137UnwindTable::Dump (Stream &s)
138{
Jason Molenda5cba5692014-06-18 23:32:53 +0000139 Mutex::Locker locker(m_mutex);
Greg Claytonb5ad4ec2013-04-29 17:25:54 +0000140 s.Printf("UnwindTable for '%s':\n", m_object_file.GetFileSpec().GetPath().c_str());
Greg Claytonb0848c52011-01-08 00:05:12 +0000141 const_iterator begin = m_unwinds.begin();
142 const_iterator end = m_unwinds.end();
143 for (const_iterator pos = begin; pos != end; ++pos)
144 {
Daniel Malead01b2952012-11-29 21:49:15 +0000145 s.Printf ("[%u] 0x%16.16" PRIx64 "\n", (unsigned)std::distance (begin, pos), pos->first);
Greg Claytonb0848c52011-01-08 00:05:12 +0000146 }
147 s.EOL();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000148}
149
150DWARFCallFrameInfo *
151UnwindTable::GetEHFrameInfo ()
152{
Greg Claytonb0848c52011-01-08 00:05:12 +0000153 Initialize();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000154 return m_eh_frame;
155}
Jason Molendaab35aa92014-05-23 01:48:10 +0000156
157bool
158UnwindTable::GetArchitecture (lldb_private::ArchSpec &arch)
159{
160 return m_object_file.GetArchitecture (arch);
161}