1*30fdc8d8SChris Lattner //===-- DWARFCallFrameInfo.cpp ----------------------------------*- C++ -*-===//
2*30fdc8d8SChris Lattner //
3*30fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
4*30fdc8d8SChris Lattner //
5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
7*30fdc8d8SChris Lattner //
8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
9*30fdc8d8SChris Lattner 
10*30fdc8d8SChris Lattner 
11*30fdc8d8SChris Lattner // C Includes
12*30fdc8d8SChris Lattner // C++ Includes
13*30fdc8d8SChris Lattner #include <list>
14*30fdc8d8SChris Lattner 
15*30fdc8d8SChris Lattner // Other libraries and framework includes
16*30fdc8d8SChris Lattner // Project includes
17*30fdc8d8SChris Lattner #include "lldb/Symbol/DWARFCallFrameInfo.h"
18*30fdc8d8SChris Lattner #include "lldb/Core/ArchSpec.h"
19*30fdc8d8SChris Lattner #include "lldb/Core/Module.h"
20*30fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h"
21*30fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
22*30fdc8d8SChris Lattner #include "lldb/Core/Section.h"
23*30fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
24*30fdc8d8SChris Lattner 
25*30fdc8d8SChris Lattner using namespace lldb;
26*30fdc8d8SChris Lattner using namespace lldb_private;
27*30fdc8d8SChris Lattner 
28*30fdc8d8SChris Lattner static void
29*30fdc8d8SChris Lattner DumpRegisterName (Stream *s, Thread *thread, const ArchSpec *arch, uint32_t reg_kind, uint32_t reg_num)
30*30fdc8d8SChris Lattner {
31*30fdc8d8SChris Lattner     const char *reg_name = NULL;
32*30fdc8d8SChris Lattner     RegisterContext *reg_ctx = NULL;
33*30fdc8d8SChris Lattner     if (thread)
34*30fdc8d8SChris Lattner     {
35*30fdc8d8SChris Lattner         reg_ctx = thread->GetRegisterContext();
36*30fdc8d8SChris Lattner         if (reg_ctx)
37*30fdc8d8SChris Lattner             reg_name = reg_ctx->GetRegisterName (reg_ctx->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num));
38*30fdc8d8SChris Lattner     }
39*30fdc8d8SChris Lattner 
40*30fdc8d8SChris Lattner     if (reg_name == NULL && arch != NULL)
41*30fdc8d8SChris Lattner     {
42*30fdc8d8SChris Lattner         switch (reg_kind)
43*30fdc8d8SChris Lattner         {
44*30fdc8d8SChris Lattner         case eRegisterKindDWARF: reg_name = arch->GetRegisterName(reg_num, eRegisterKindDWARF); break;
45*30fdc8d8SChris Lattner         case eRegisterKindGCC: reg_name = arch->GetRegisterName(reg_num, eRegisterKindGCC); break;
46*30fdc8d8SChris Lattner         default:
47*30fdc8d8SChris Lattner             break;
48*30fdc8d8SChris Lattner         }
49*30fdc8d8SChris Lattner     }
50*30fdc8d8SChris Lattner 
51*30fdc8d8SChris Lattner     if (reg_name)
52*30fdc8d8SChris Lattner         s->PutCString(reg_name);
53*30fdc8d8SChris Lattner     else
54*30fdc8d8SChris Lattner     {
55*30fdc8d8SChris Lattner         const char *reg_kind_name = NULL;
56*30fdc8d8SChris Lattner         switch (reg_kind)
57*30fdc8d8SChris Lattner         {
58*30fdc8d8SChris Lattner         case eRegisterKindDWARF: reg_kind_name = "dwarf-reg"; break;
59*30fdc8d8SChris Lattner         case eRegisterKindGCC: reg_kind_name = "compiler-reg"; break;
60*30fdc8d8SChris Lattner         case eRegisterKindGeneric: reg_kind_name = "generic-reg"; break;
61*30fdc8d8SChris Lattner         default:
62*30fdc8d8SChris Lattner             break;
63*30fdc8d8SChris Lattner         }
64*30fdc8d8SChris Lattner         if (reg_kind_name)
65*30fdc8d8SChris Lattner             s->Printf("%s(%u)", reg_kind_name, reg_num);
66*30fdc8d8SChris Lattner         else
67*30fdc8d8SChris Lattner             s->Printf("reg(%d.%u)", reg_kind, reg_num);
68*30fdc8d8SChris Lattner     }
69*30fdc8d8SChris Lattner }
70*30fdc8d8SChris Lattner 
71*30fdc8d8SChris Lattner 
72*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::RegisterLocation
73*30fdc8d8SChris Lattner 
74*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::RegisterLocation() :
75*30fdc8d8SChris Lattner     m_type(isSame)
76*30fdc8d8SChris Lattner {
77*30fdc8d8SChris Lattner }
78*30fdc8d8SChris Lattner 
79*30fdc8d8SChris Lattner 
80*30fdc8d8SChris Lattner bool
81*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::operator == (const DWARFCallFrameInfo::RegisterLocation& rhs) const
82*30fdc8d8SChris Lattner {
83*30fdc8d8SChris Lattner     if (m_type != rhs.m_type)
84*30fdc8d8SChris Lattner         return false;
85*30fdc8d8SChris Lattner     switch (m_type)
86*30fdc8d8SChris Lattner     {
87*30fdc8d8SChris Lattner         case unspecified:
88*30fdc8d8SChris Lattner         case isUndefined:
89*30fdc8d8SChris Lattner         case isSame:
90*30fdc8d8SChris Lattner             return true;
91*30fdc8d8SChris Lattner 
92*30fdc8d8SChris Lattner         case atCFAPlusOffset:
93*30fdc8d8SChris Lattner             return m_location.offset == rhs.m_location.offset;
94*30fdc8d8SChris Lattner 
95*30fdc8d8SChris Lattner         case isCFAPlusOffset:
96*30fdc8d8SChris Lattner             return m_location.offset == rhs.m_location.offset;
97*30fdc8d8SChris Lattner 
98*30fdc8d8SChris Lattner         case inOtherRegister:
99*30fdc8d8SChris Lattner             return m_location.reg_num == rhs.m_location.reg_num;
100*30fdc8d8SChris Lattner 
101*30fdc8d8SChris Lattner         default:
102*30fdc8d8SChris Lattner             break;
103*30fdc8d8SChris Lattner     }
104*30fdc8d8SChris Lattner     return false;
105*30fdc8d8SChris Lattner }
106*30fdc8d8SChris Lattner 
107*30fdc8d8SChris Lattner void
108*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetUnspecified()
109*30fdc8d8SChris Lattner {
110*30fdc8d8SChris Lattner     m_type = unspecified;
111*30fdc8d8SChris Lattner }
112*30fdc8d8SChris Lattner 
113*30fdc8d8SChris Lattner void
114*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetUndefined()
115*30fdc8d8SChris Lattner {
116*30fdc8d8SChris Lattner     m_type = isUndefined;
117*30fdc8d8SChris Lattner }
118*30fdc8d8SChris Lattner 
119*30fdc8d8SChris Lattner void
120*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetSame()
121*30fdc8d8SChris Lattner {
122*30fdc8d8SChris Lattner     m_type = isSame;
123*30fdc8d8SChris Lattner }
124*30fdc8d8SChris Lattner 
125*30fdc8d8SChris Lattner void
126*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetAtCFAPlusOffset(int64_t offset)
127*30fdc8d8SChris Lattner {
128*30fdc8d8SChris Lattner     m_type = atCFAPlusOffset;
129*30fdc8d8SChris Lattner     m_location.offset = offset;
130*30fdc8d8SChris Lattner }
131*30fdc8d8SChris Lattner 
132*30fdc8d8SChris Lattner void
133*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetIsCFAPlusOffset(int64_t offset)
134*30fdc8d8SChris Lattner {
135*30fdc8d8SChris Lattner     m_type = isCFAPlusOffset;
136*30fdc8d8SChris Lattner     m_location.offset = offset;
137*30fdc8d8SChris Lattner }
138*30fdc8d8SChris Lattner 
139*30fdc8d8SChris Lattner void
140*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetInRegister (uint32_t reg_num)
141*30fdc8d8SChris Lattner {
142*30fdc8d8SChris Lattner     m_type = inOtherRegister;
143*30fdc8d8SChris Lattner     m_location.reg_num = reg_num;
144*30fdc8d8SChris Lattner }
145*30fdc8d8SChris Lattner 
146*30fdc8d8SChris Lattner void
147*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len)
148*30fdc8d8SChris Lattner {
149*30fdc8d8SChris Lattner     m_type = atDWARFExpression;
150*30fdc8d8SChris Lattner     m_location.expr.opcodes = opcodes;
151*30fdc8d8SChris Lattner     m_location.expr.length = len;
152*30fdc8d8SChris Lattner }
153*30fdc8d8SChris Lattner 
154*30fdc8d8SChris Lattner void
155*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
156*30fdc8d8SChris Lattner {
157*30fdc8d8SChris Lattner     m_type = isDWARFExpression;
158*30fdc8d8SChris Lattner     m_location.expr.opcodes = opcodes;
159*30fdc8d8SChris Lattner     m_location.expr.length = len;
160*30fdc8d8SChris Lattner }
161*30fdc8d8SChris Lattner 
162*30fdc8d8SChris Lattner void
163*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::Dump(Stream *s, const DWARFCallFrameInfo &cfi, Thread *thread, const Row *row, uint32_t reg_num) const
164*30fdc8d8SChris Lattner {
165*30fdc8d8SChris Lattner     const ArchSpec *arch = cfi.GetArchitecture();
166*30fdc8d8SChris Lattner     const uint32_t reg_kind = cfi.GetRegisterKind();
167*30fdc8d8SChris Lattner 
168*30fdc8d8SChris Lattner     DumpRegisterName (s, thread, arch, reg_kind, reg_num);
169*30fdc8d8SChris Lattner     s->PutChar('=');
170*30fdc8d8SChris Lattner 
171*30fdc8d8SChris Lattner     switch (m_type)
172*30fdc8d8SChris Lattner     {
173*30fdc8d8SChris Lattner     case unspecified:
174*30fdc8d8SChris Lattner         s->PutChar('?');
175*30fdc8d8SChris Lattner         break;
176*30fdc8d8SChris Lattner 
177*30fdc8d8SChris Lattner     case isUndefined:
178*30fdc8d8SChris Lattner         s->PutCString("undefined");
179*30fdc8d8SChris Lattner         break;
180*30fdc8d8SChris Lattner 
181*30fdc8d8SChris Lattner     case isSame:
182*30fdc8d8SChris Lattner         s->PutCString("same");
183*30fdc8d8SChris Lattner         break;
184*30fdc8d8SChris Lattner 
185*30fdc8d8SChris Lattner     case atCFAPlusOffset:
186*30fdc8d8SChris Lattner         s->PutChar('[');
187*30fdc8d8SChris Lattner         // Fall through to isCFAPlusOffset...
188*30fdc8d8SChris Lattner     case isCFAPlusOffset:
189*30fdc8d8SChris Lattner         {
190*30fdc8d8SChris Lattner             DumpRegisterName (s, thread, arch, reg_kind, row->GetCFARegister());
191*30fdc8d8SChris Lattner             int32_t offset = row->GetCFAOffset() + m_location.offset;
192*30fdc8d8SChris Lattner             if (offset != 0)
193*30fdc8d8SChris Lattner                 s->Printf("%-+d", offset);
194*30fdc8d8SChris Lattner             if (m_type == atCFAPlusOffset)
195*30fdc8d8SChris Lattner                 s->PutChar(']');
196*30fdc8d8SChris Lattner         }
197*30fdc8d8SChris Lattner         break;
198*30fdc8d8SChris Lattner 
199*30fdc8d8SChris Lattner     case inOtherRegister:
200*30fdc8d8SChris Lattner         DumpRegisterName (s, thread, arch, reg_kind, m_location.reg_num);
201*30fdc8d8SChris Lattner         break;
202*30fdc8d8SChris Lattner 
203*30fdc8d8SChris Lattner     case atDWARFExpression:
204*30fdc8d8SChris Lattner         s->PutCString("[EXPR] ");
205*30fdc8d8SChris Lattner         break;
206*30fdc8d8SChris Lattner 
207*30fdc8d8SChris Lattner     case isDWARFExpression:
208*30fdc8d8SChris Lattner         s->PutCString("EXPR ");
209*30fdc8d8SChris Lattner         break;
210*30fdc8d8SChris Lattner     }
211*30fdc8d8SChris Lattner }
212*30fdc8d8SChris Lattner 
213*30fdc8d8SChris Lattner 
214*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::Row
215*30fdc8d8SChris Lattner 
216*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::Row() :
217*30fdc8d8SChris Lattner     m_offset(0),
218*30fdc8d8SChris Lattner     m_cfa_reg_num(0),
219*30fdc8d8SChris Lattner     m_cfa_offset(0),
220*30fdc8d8SChris Lattner     m_register_locations()
221*30fdc8d8SChris Lattner {
222*30fdc8d8SChris Lattner }
223*30fdc8d8SChris Lattner 
224*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::~Row()
225*30fdc8d8SChris Lattner {
226*30fdc8d8SChris Lattner }
227*30fdc8d8SChris Lattner 
228*30fdc8d8SChris Lattner void
229*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::Clear()
230*30fdc8d8SChris Lattner {
231*30fdc8d8SChris Lattner     m_register_locations.clear();
232*30fdc8d8SChris Lattner }
233*30fdc8d8SChris Lattner bool
234*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::GetRegisterInfo (uint32_t reg_num, DWARFCallFrameInfo::RegisterLocation& register_location) const
235*30fdc8d8SChris Lattner {
236*30fdc8d8SChris Lattner     collection::const_iterator pos = m_register_locations.find(reg_num);
237*30fdc8d8SChris Lattner     if (pos != m_register_locations.end())
238*30fdc8d8SChris Lattner     {
239*30fdc8d8SChris Lattner         register_location = pos->second;
240*30fdc8d8SChris Lattner         return true;
241*30fdc8d8SChris Lattner     }
242*30fdc8d8SChris Lattner     return false;
243*30fdc8d8SChris Lattner }
244*30fdc8d8SChris Lattner 
245*30fdc8d8SChris Lattner void
246*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::SetRegisterInfo (uint32_t reg_num, const RegisterLocation& register_location)
247*30fdc8d8SChris Lattner {
248*30fdc8d8SChris Lattner     m_register_locations[reg_num] = register_location;
249*30fdc8d8SChris Lattner }
250*30fdc8d8SChris Lattner 
251*30fdc8d8SChris Lattner 
252*30fdc8d8SChris Lattner void
253*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::Dump(Stream* s, const DWARFCallFrameInfo &cfi, Thread *thread, lldb::addr_t base_addr) const
254*30fdc8d8SChris Lattner {
255*30fdc8d8SChris Lattner     const ArchSpec *arch = cfi.GetArchitecture();
256*30fdc8d8SChris Lattner     const uint32_t reg_kind = cfi.GetRegisterKind();
257*30fdc8d8SChris Lattner     collection::const_iterator pos, end = m_register_locations.end();
258*30fdc8d8SChris Lattner     s->Indent();
259*30fdc8d8SChris Lattner     s->Printf("0x%16.16llx: CFA=", m_offset + base_addr);
260*30fdc8d8SChris Lattner     DumpRegisterName(s, thread, arch, reg_kind, m_cfa_reg_num);
261*30fdc8d8SChris Lattner     if (m_cfa_offset != 0)
262*30fdc8d8SChris Lattner         s->Printf("%-+lld", m_cfa_offset);
263*30fdc8d8SChris Lattner 
264*30fdc8d8SChris Lattner     for (pos = m_register_locations.begin(); pos != end; ++pos)
265*30fdc8d8SChris Lattner     {
266*30fdc8d8SChris Lattner         s->PutChar(' ');
267*30fdc8d8SChris Lattner         pos->second.Dump(s, cfi, thread, this, pos->first);
268*30fdc8d8SChris Lattner     }
269*30fdc8d8SChris Lattner     s->EOL();
270*30fdc8d8SChris Lattner }
271*30fdc8d8SChris Lattner 
272*30fdc8d8SChris Lattner 
273*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::FDE
274*30fdc8d8SChris Lattner 
275*30fdc8d8SChris Lattner 
276*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::FDE (dw_offset_t offset, const AddressRange &range) :
277*30fdc8d8SChris Lattner     m_fde_offset (offset),
278*30fdc8d8SChris Lattner     m_range (range),
279*30fdc8d8SChris Lattner     m_row_list ()
280*30fdc8d8SChris Lattner {
281*30fdc8d8SChris Lattner }
282*30fdc8d8SChris Lattner 
283*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::~FDE()
284*30fdc8d8SChris Lattner {
285*30fdc8d8SChris Lattner }
286*30fdc8d8SChris Lattner 
287*30fdc8d8SChris Lattner void
288*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::AppendRow (const Row &row)
289*30fdc8d8SChris Lattner {
290*30fdc8d8SChris Lattner     if (m_row_list.empty() || m_row_list.back().GetOffset() != row.GetOffset())
291*30fdc8d8SChris Lattner         m_row_list.push_back(row);
292*30fdc8d8SChris Lattner     else
293*30fdc8d8SChris Lattner         m_row_list.back() = row;
294*30fdc8d8SChris Lattner }
295*30fdc8d8SChris Lattner 
296*30fdc8d8SChris Lattner void
297*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::Dump (Stream *s, const DWARFCallFrameInfo &cfi, Thread* thread) const
298*30fdc8d8SChris Lattner {
299*30fdc8d8SChris Lattner     s->Indent();
300*30fdc8d8SChris Lattner     s->Printf("FDE{0x%8.8x} ", m_fde_offset);
301*30fdc8d8SChris Lattner     m_range.Dump(s, NULL, Address::DumpStyleFileAddress);
302*30fdc8d8SChris Lattner     lldb::addr_t fde_base_addr = m_range.GetBaseAddress().GetFileAddress();
303*30fdc8d8SChris Lattner     s->EOL();
304*30fdc8d8SChris Lattner     s->IndentMore();
305*30fdc8d8SChris Lattner     collection::const_iterator pos, end = m_row_list.end();
306*30fdc8d8SChris Lattner     for (pos = m_row_list.begin(); pos != end; ++pos)
307*30fdc8d8SChris Lattner     {
308*30fdc8d8SChris Lattner         pos->Dump(s, cfi, thread, fde_base_addr);
309*30fdc8d8SChris Lattner     }
310*30fdc8d8SChris Lattner     s->IndentLess();
311*30fdc8d8SChris Lattner }
312*30fdc8d8SChris Lattner 
313*30fdc8d8SChris Lattner const AddressRange &
314*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::GetAddressRange() const
315*30fdc8d8SChris Lattner {
316*30fdc8d8SChris Lattner     return m_range;
317*30fdc8d8SChris Lattner }
318*30fdc8d8SChris Lattner 
319*30fdc8d8SChris Lattner bool
320*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::IsValidRowIndex (uint32_t idx) const
321*30fdc8d8SChris Lattner {
322*30fdc8d8SChris Lattner     return idx < m_row_list.size();
323*30fdc8d8SChris Lattner }
324*30fdc8d8SChris Lattner 
325*30fdc8d8SChris Lattner const DWARFCallFrameInfo::Row&
326*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::GetRowAtIndex (uint32_t idx)
327*30fdc8d8SChris Lattner {
328*30fdc8d8SChris Lattner     // You must call IsValidRowIndex(idx) first before calling this!!!
329*30fdc8d8SChris Lattner     return m_row_list[idx];
330*30fdc8d8SChris Lattner }
331*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::FDEInfo
332*30fdc8d8SChris Lattner 
333*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDEInfo::FDEInfo () :
334*30fdc8d8SChris Lattner     fde_offset (0),
335*30fdc8d8SChris Lattner     fde_sp()
336*30fdc8d8SChris Lattner {
337*30fdc8d8SChris Lattner }
338*30fdc8d8SChris Lattner 
339*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDEInfo::FDEInfo (off_t offset) :
340*30fdc8d8SChris Lattner     fde_offset(offset),
341*30fdc8d8SChris Lattner     fde_sp()
342*30fdc8d8SChris Lattner {
343*30fdc8d8SChris Lattner }
344*30fdc8d8SChris Lattner 
345*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::CIE
346*30fdc8d8SChris Lattner 
347*30fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::CIE(dw_offset_t offset) :
348*30fdc8d8SChris Lattner     cie_offset (offset),
349*30fdc8d8SChris Lattner     version (0),
350*30fdc8d8SChris Lattner     augmentation(),
351*30fdc8d8SChris Lattner     code_align (0),
352*30fdc8d8SChris Lattner     data_align (0),
353*30fdc8d8SChris Lattner     return_addr_reg_num (0),
354*30fdc8d8SChris Lattner     inst_offset (0),
355*30fdc8d8SChris Lattner     inst_length (0),
356*30fdc8d8SChris Lattner     ptr_encoding (DW_GNU_EH_PE_absptr)
357*30fdc8d8SChris Lattner {
358*30fdc8d8SChris Lattner }
359*30fdc8d8SChris Lattner 
360*30fdc8d8SChris Lattner 
361*30fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::~CIE()
362*30fdc8d8SChris Lattner {
363*30fdc8d8SChris Lattner }
364*30fdc8d8SChris Lattner 
365*30fdc8d8SChris Lattner void
366*30fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::Dump(Stream *s, Thread* thread, const ArchSpec *arch, uint32_t reg_kind) const
367*30fdc8d8SChris Lattner {
368*30fdc8d8SChris Lattner     s->Indent();
369*30fdc8d8SChris Lattner     s->Printf("CIE{0x%8.8x} version=%u, code_align=%u, data_align=%d, return_addr_reg=", cie_offset, version, code_align, data_align);
370*30fdc8d8SChris Lattner     DumpRegisterName(s, thread, arch, reg_kind, return_addr_reg_num);
371*30fdc8d8SChris Lattner     s->Printf(", instr_offset=0x%8.8x, instr_length=%u, ptr_encoding=0x%02x\n",
372*30fdc8d8SChris Lattner             inst_offset,
373*30fdc8d8SChris Lattner             inst_length,
374*30fdc8d8SChris Lattner             ptr_encoding);
375*30fdc8d8SChris Lattner }
376*30fdc8d8SChris Lattner 
377*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::CIE
378*30fdc8d8SChris Lattner 
379*30fdc8d8SChris Lattner DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile *objfile, Section *section, uint32_t reg_kind) :
380*30fdc8d8SChris Lattner     m_objfile (objfile),
381*30fdc8d8SChris Lattner     m_section (section),
382*30fdc8d8SChris Lattner     m_reg_kind (reg_kind),  // The flavor of registers that the CFI data uses (One of the defines that starts with "LLDB_REGKIND_")
383*30fdc8d8SChris Lattner     m_cfi_data (),
384*30fdc8d8SChris Lattner     m_cie_map (),
385*30fdc8d8SChris Lattner     m_fde_map ()
386*30fdc8d8SChris Lattner {
387*30fdc8d8SChris Lattner     if (objfile && section)
388*30fdc8d8SChris Lattner     {
389*30fdc8d8SChris Lattner         section->ReadSectionDataFromObjectFile (objfile, m_cfi_data);
390*30fdc8d8SChris Lattner     }
391*30fdc8d8SChris Lattner }
392*30fdc8d8SChris Lattner 
393*30fdc8d8SChris Lattner DWARFCallFrameInfo::~DWARFCallFrameInfo()
394*30fdc8d8SChris Lattner {
395*30fdc8d8SChris Lattner }
396*30fdc8d8SChris Lattner 
397*30fdc8d8SChris Lattner bool
398*30fdc8d8SChris Lattner DWARFCallFrameInfo::IsEHFrame() const
399*30fdc8d8SChris Lattner {
400*30fdc8d8SChris Lattner     return (m_reg_kind == eRegisterKindGCC);
401*30fdc8d8SChris Lattner }
402*30fdc8d8SChris Lattner 
403*30fdc8d8SChris Lattner const ArchSpec *
404*30fdc8d8SChris Lattner DWARFCallFrameInfo::GetArchitecture() const
405*30fdc8d8SChris Lattner {
406*30fdc8d8SChris Lattner     if (m_objfile && m_objfile->GetModule())
407*30fdc8d8SChris Lattner         return &m_objfile->GetModule()->GetArchitecture();
408*30fdc8d8SChris Lattner     return NULL;
409*30fdc8d8SChris Lattner }
410*30fdc8d8SChris Lattner 
411*30fdc8d8SChris Lattner uint32_t
412*30fdc8d8SChris Lattner DWARFCallFrameInfo::GetRegisterKind () const
413*30fdc8d8SChris Lattner {
414*30fdc8d8SChris Lattner     return m_reg_kind;
415*30fdc8d8SChris Lattner }
416*30fdc8d8SChris Lattner 
417*30fdc8d8SChris Lattner void
418*30fdc8d8SChris Lattner DWARFCallFrameInfo::SetRegisterKind (uint32_t reg_kind)
419*30fdc8d8SChris Lattner {
420*30fdc8d8SChris Lattner     m_reg_kind = reg_kind;
421*30fdc8d8SChris Lattner }
422*30fdc8d8SChris Lattner 
423*30fdc8d8SChris Lattner 
424*30fdc8d8SChris Lattner 
425*30fdc8d8SChris Lattner 
426*30fdc8d8SChris Lattner const DWARFCallFrameInfo::CIE*
427*30fdc8d8SChris Lattner DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset)
428*30fdc8d8SChris Lattner {
429*30fdc8d8SChris Lattner     Index ();
430*30fdc8d8SChris Lattner 
431*30fdc8d8SChris Lattner     cie_map_t::iterator pos = m_cie_map.find(cie_offset);
432*30fdc8d8SChris Lattner 
433*30fdc8d8SChris Lattner     if (pos != m_cie_map.end())
434*30fdc8d8SChris Lattner     {
435*30fdc8d8SChris Lattner         // Parse and cache the CIE
436*30fdc8d8SChris Lattner         if (pos->second.get() == NULL)
437*30fdc8d8SChris Lattner             pos->second = ParseCIE (cie_offset);
438*30fdc8d8SChris Lattner 
439*30fdc8d8SChris Lattner         return pos->second.get();
440*30fdc8d8SChris Lattner     }
441*30fdc8d8SChris Lattner     return NULL;
442*30fdc8d8SChris Lattner }
443*30fdc8d8SChris Lattner 
444*30fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::shared_ptr
445*30fdc8d8SChris Lattner DWARFCallFrameInfo::ParseCIE (const dw_offset_t cie_offset)
446*30fdc8d8SChris Lattner {
447*30fdc8d8SChris Lattner     CIE::shared_ptr cie_sp(new CIE(cie_offset));
448*30fdc8d8SChris Lattner     const bool for_eh_frame = IsEHFrame();
449*30fdc8d8SChris Lattner     dw_offset_t offset = cie_offset;
450*30fdc8d8SChris Lattner     const uint32_t length = m_cfi_data.GetU32(&offset);
451*30fdc8d8SChris Lattner     const dw_offset_t cie_id = m_cfi_data.GetU32(&offset);
452*30fdc8d8SChris Lattner     const dw_offset_t end_offset = cie_offset + length + 4;
453*30fdc8d8SChris Lattner     if (length > 0 && (!for_eh_frame && cie_id == 0xfffffffful) || (for_eh_frame && cie_id == 0ul))
454*30fdc8d8SChris Lattner     {
455*30fdc8d8SChris Lattner         size_t i;
456*30fdc8d8SChris Lattner         //    cie.offset = cie_offset;
457*30fdc8d8SChris Lattner         //    cie.length = length;
458*30fdc8d8SChris Lattner         //    cie.cieID = cieID;
459*30fdc8d8SChris Lattner         cie_sp->ptr_encoding = DW_GNU_EH_PE_absptr;
460*30fdc8d8SChris Lattner         cie_sp->version = m_cfi_data.GetU8(&offset);
461*30fdc8d8SChris Lattner 
462*30fdc8d8SChris Lattner         for (i=0; i<CFI_AUG_MAX_SIZE; ++i)
463*30fdc8d8SChris Lattner         {
464*30fdc8d8SChris Lattner             cie_sp->augmentation[i] = m_cfi_data.GetU8(&offset);
465*30fdc8d8SChris Lattner             if (cie_sp->augmentation[i] == '\0')
466*30fdc8d8SChris Lattner             {
467*30fdc8d8SChris Lattner                 // Zero out remaining bytes in augmentation string
468*30fdc8d8SChris Lattner                 for (size_t j = i+1; j<CFI_AUG_MAX_SIZE; ++j)
469*30fdc8d8SChris Lattner                     cie_sp->augmentation[j] = '\0';
470*30fdc8d8SChris Lattner 
471*30fdc8d8SChris Lattner                 break;
472*30fdc8d8SChris Lattner             }
473*30fdc8d8SChris Lattner         }
474*30fdc8d8SChris Lattner 
475*30fdc8d8SChris Lattner         if (i == CFI_AUG_MAX_SIZE && cie_sp->augmentation[CFI_AUG_MAX_SIZE-1] != '\0')
476*30fdc8d8SChris Lattner         {
477*30fdc8d8SChris Lattner             fprintf(stderr, "CIE parse error: CIE augmentation string was too large for the fixed sized buffer of %d bytes.\n", CFI_AUG_MAX_SIZE);
478*30fdc8d8SChris Lattner             return cie_sp;
479*30fdc8d8SChris Lattner         }
480*30fdc8d8SChris Lattner         cie_sp->code_align = (uint32_t)m_cfi_data.GetULEB128(&offset);
481*30fdc8d8SChris Lattner         cie_sp->data_align = (int32_t)m_cfi_data.GetSLEB128(&offset);
482*30fdc8d8SChris Lattner         cie_sp->return_addr_reg_num = m_cfi_data.GetU8(&offset);
483*30fdc8d8SChris Lattner 
484*30fdc8d8SChris Lattner         if (cie_sp->augmentation[0])
485*30fdc8d8SChris Lattner         {
486*30fdc8d8SChris Lattner             // Get the length of the eh_frame augmentation data
487*30fdc8d8SChris Lattner             // which starts with a ULEB128 length in bytes
488*30fdc8d8SChris Lattner             const size_t aug_data_len = (size_t)m_cfi_data.GetULEB128(&offset);
489*30fdc8d8SChris Lattner             const size_t aug_data_end = offset + aug_data_len;
490*30fdc8d8SChris Lattner             const size_t aug_str_len = strlen(cie_sp->augmentation);
491*30fdc8d8SChris Lattner             // A 'z' may be present as the first character of the string.
492*30fdc8d8SChris Lattner             // If present, the Augmentation Data field shall be present.
493*30fdc8d8SChris Lattner             // The contents of the Augmentation Data shall be intepreted
494*30fdc8d8SChris Lattner             // according to other characters in the Augmentation String.
495*30fdc8d8SChris Lattner             if (cie_sp->augmentation[0] == 'z')
496*30fdc8d8SChris Lattner             {
497*30fdc8d8SChris Lattner                 // Extract the Augmentation Data
498*30fdc8d8SChris Lattner                 size_t aug_str_idx = 0;
499*30fdc8d8SChris Lattner                 for (aug_str_idx = 1; aug_str_idx < aug_str_len; aug_str_idx++)
500*30fdc8d8SChris Lattner                 {
501*30fdc8d8SChris Lattner                     char aug = cie_sp->augmentation[aug_str_idx];
502*30fdc8d8SChris Lattner                     switch (aug)
503*30fdc8d8SChris Lattner                     {
504*30fdc8d8SChris Lattner                         case 'L':
505*30fdc8d8SChris Lattner                             // Indicates the presence of one argument in the
506*30fdc8d8SChris Lattner                             // Augmentation Data of the CIE, and a corresponding
507*30fdc8d8SChris Lattner                             // argument in the Augmentation Data of the FDE. The
508*30fdc8d8SChris Lattner                             // argument in the Augmentation Data of the CIE is
509*30fdc8d8SChris Lattner                             // 1-byte and represents the pointer encoding used
510*30fdc8d8SChris Lattner                             // for the argument in the Augmentation Data of the
511*30fdc8d8SChris Lattner                             // FDE, which is the address of a language-specific
512*30fdc8d8SChris Lattner                             // data area (LSDA). The size of the LSDA pointer is
513*30fdc8d8SChris Lattner                             // specified by the pointer encoding used.
514*30fdc8d8SChris Lattner                             m_cfi_data.GetU8(&offset);
515*30fdc8d8SChris Lattner                             break;
516*30fdc8d8SChris Lattner 
517*30fdc8d8SChris Lattner                         case 'P':
518*30fdc8d8SChris Lattner                             // Indicates the presence of two arguments in the
519*30fdc8d8SChris Lattner                             // Augmentation Data of the cie_sp-> The first argument
520*30fdc8d8SChris Lattner                             // is 1-byte and represents the pointer encoding
521*30fdc8d8SChris Lattner                             // used for the second argument, which is the
522*30fdc8d8SChris Lattner                             // address of a personality routine handler. The
523*30fdc8d8SChris Lattner                             // size of the personality routine pointer is
524*30fdc8d8SChris Lattner                             // specified by the pointer encoding used.
525*30fdc8d8SChris Lattner                         {
526*30fdc8d8SChris Lattner                             uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset);
527*30fdc8d8SChris Lattner                             m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS);
528*30fdc8d8SChris Lattner                         }
529*30fdc8d8SChris Lattner                             break;
530*30fdc8d8SChris Lattner 
531*30fdc8d8SChris Lattner                         case 'R':
532*30fdc8d8SChris Lattner                             // A 'R' may be present at any position after the
533*30fdc8d8SChris Lattner                             // first character of the string. The Augmentation
534*30fdc8d8SChris Lattner                             // Data shall include a 1 byte argument that
535*30fdc8d8SChris Lattner                             // represents the pointer encoding for the address
536*30fdc8d8SChris Lattner                             // pointers used in the FDE.
537*30fdc8d8SChris Lattner                             cie_sp->ptr_encoding = m_cfi_data.GetU8(&offset);
538*30fdc8d8SChris Lattner                             break;
539*30fdc8d8SChris Lattner                     }
540*30fdc8d8SChris Lattner                 }
541*30fdc8d8SChris Lattner             }
542*30fdc8d8SChris Lattner             else if (strcmp(cie_sp->augmentation, "eh") == 0)
543*30fdc8d8SChris Lattner             {
544*30fdc8d8SChris Lattner                 // If the Augmentation string has the value "eh", then
545*30fdc8d8SChris Lattner                 // the EH Data field shall be present
546*30fdc8d8SChris Lattner             }
547*30fdc8d8SChris Lattner 
548*30fdc8d8SChris Lattner             // Set the offset to be the end of the augmentation data just in case
549*30fdc8d8SChris Lattner             // we didn't understand any of the data.
550*30fdc8d8SChris Lattner             offset = (uint32_t)aug_data_end;
551*30fdc8d8SChris Lattner         }
552*30fdc8d8SChris Lattner 
553*30fdc8d8SChris Lattner         if (end_offset > offset)
554*30fdc8d8SChris Lattner         {
555*30fdc8d8SChris Lattner             cie_sp->inst_offset = offset;
556*30fdc8d8SChris Lattner             cie_sp->inst_length = end_offset - offset;
557*30fdc8d8SChris Lattner         }
558*30fdc8d8SChris Lattner     }
559*30fdc8d8SChris Lattner 
560*30fdc8d8SChris Lattner     return cie_sp;
561*30fdc8d8SChris Lattner }
562*30fdc8d8SChris Lattner 
563*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::shared_ptr
564*30fdc8d8SChris Lattner DWARFCallFrameInfo::ParseFDE(const dw_offset_t fde_offset)
565*30fdc8d8SChris Lattner {
566*30fdc8d8SChris Lattner     const bool for_eh_frame = IsEHFrame();
567*30fdc8d8SChris Lattner     FDE::shared_ptr fde_sp;
568*30fdc8d8SChris Lattner 
569*30fdc8d8SChris Lattner     dw_offset_t offset = fde_offset;
570*30fdc8d8SChris Lattner     const uint32_t length = m_cfi_data.GetU32(&offset);
571*30fdc8d8SChris Lattner     dw_offset_t cie_offset = m_cfi_data.GetU32(&offset);
572*30fdc8d8SChris Lattner     const dw_offset_t end_offset = fde_offset + length + 4;
573*30fdc8d8SChris Lattner 
574*30fdc8d8SChris Lattner     // Translate the CIE_id from the eh_frame format, which
575*30fdc8d8SChris Lattner     // is relative to the FDE offset, into a __eh_frame section
576*30fdc8d8SChris Lattner     // offset
577*30fdc8d8SChris Lattner     if (for_eh_frame)
578*30fdc8d8SChris Lattner         cie_offset = offset - (cie_offset + 4);
579*30fdc8d8SChris Lattner 
580*30fdc8d8SChris Lattner     const CIE* cie = GetCIE(cie_offset);
581*30fdc8d8SChris Lattner     if (cie)
582*30fdc8d8SChris Lattner     {
583*30fdc8d8SChris Lattner         const lldb::addr_t pc_rel_addr = m_section->GetFileAddress();
584*30fdc8d8SChris Lattner         const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
585*30fdc8d8SChris Lattner         const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
586*30fdc8d8SChris Lattner         lldb::addr_t range_base = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr);
587*30fdc8d8SChris Lattner         lldb::addr_t range_len = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_GNU_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr);
588*30fdc8d8SChris Lattner 
589*30fdc8d8SChris Lattner         if (cie->augmentation[0] == 'z')
590*30fdc8d8SChris Lattner         {
591*30fdc8d8SChris Lattner             uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
592*30fdc8d8SChris Lattner             offset += aug_data_len;
593*30fdc8d8SChris Lattner         }
594*30fdc8d8SChris Lattner 
595*30fdc8d8SChris Lattner         AddressRange fde_range (range_base, range_len, m_objfile->GetSectionList ());
596*30fdc8d8SChris Lattner         fde_sp.reset(new FDE(fde_offset, fde_range));
597*30fdc8d8SChris Lattner         if (offset < end_offset)
598*30fdc8d8SChris Lattner         {
599*30fdc8d8SChris Lattner             dw_offset_t fde_instr_offset = offset;
600*30fdc8d8SChris Lattner             uint32_t fde_instr_length = end_offset - offset;
601*30fdc8d8SChris Lattner             if (cie->inst_length > 0)
602*30fdc8d8SChris Lattner                 ParseInstructions(cie, fde_sp.get(), cie->inst_offset, cie->inst_length);
603*30fdc8d8SChris Lattner             ParseInstructions(cie, fde_sp.get(), fde_instr_offset, fde_instr_length);
604*30fdc8d8SChris Lattner         }
605*30fdc8d8SChris Lattner     }
606*30fdc8d8SChris Lattner     return fde_sp;
607*30fdc8d8SChris Lattner }
608*30fdc8d8SChris Lattner 
609*30fdc8d8SChris Lattner const DWARFCallFrameInfo::FDE *
610*30fdc8d8SChris Lattner DWARFCallFrameInfo::FindFDE(const Address &addr)
611*30fdc8d8SChris Lattner {
612*30fdc8d8SChris Lattner     Index ();
613*30fdc8d8SChris Lattner 
614*30fdc8d8SChris Lattner     VMRange find_range(addr.GetFileAddress(), 0);
615*30fdc8d8SChris Lattner     fde_map_t::iterator pos = m_fde_map.lower_bound (find_range);
616*30fdc8d8SChris Lattner     fde_map_t::iterator end = m_fde_map.end();
617*30fdc8d8SChris Lattner 
618*30fdc8d8SChris Lattner     if (pos != end)
619*30fdc8d8SChris Lattner     {
620*30fdc8d8SChris Lattner         if (pos->first.Contains(find_range.GetBaseAddress()))
621*30fdc8d8SChris Lattner         {
622*30fdc8d8SChris Lattner             // Parse and cache the FDE if we already haven't
623*30fdc8d8SChris Lattner             if (pos->second.fde_sp.get() == NULL)
624*30fdc8d8SChris Lattner                 pos->second.fde_sp = ParseFDE(pos->second.fde_offset);
625*30fdc8d8SChris Lattner 
626*30fdc8d8SChris Lattner             return pos->second.fde_sp.get();
627*30fdc8d8SChris Lattner         }
628*30fdc8d8SChris Lattner     }
629*30fdc8d8SChris Lattner     return NULL;
630*30fdc8d8SChris Lattner }
631*30fdc8d8SChris Lattner 
632*30fdc8d8SChris Lattner 
633*30fdc8d8SChris Lattner void
634*30fdc8d8SChris Lattner DWARFCallFrameInfo::Index ()
635*30fdc8d8SChris Lattner {
636*30fdc8d8SChris Lattner     if (m_flags.IsClear(eFlagParsedIndex))
637*30fdc8d8SChris Lattner     {
638*30fdc8d8SChris Lattner         m_flags.Set (eFlagParsedIndex);
639*30fdc8d8SChris Lattner         const bool for_eh_frame = IsEHFrame();
640*30fdc8d8SChris Lattner         CIE::shared_ptr empty_cie_sp;
641*30fdc8d8SChris Lattner         dw_offset_t offset = 0;
642*30fdc8d8SChris Lattner         // Parse all of the CIEs first since we will need them to be able to
643*30fdc8d8SChris Lattner         // properly parse the FDE addresses due to them possibly having
644*30fdc8d8SChris Lattner         // GNU pointer encodings in their augmentations...
645*30fdc8d8SChris Lattner         while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8))
646*30fdc8d8SChris Lattner         {
647*30fdc8d8SChris Lattner             const dw_offset_t curr_offset = offset;
648*30fdc8d8SChris Lattner             const uint32_t length = m_cfi_data.GetU32(&offset);
649*30fdc8d8SChris Lattner             const dw_offset_t next_offset = offset + length;
650*30fdc8d8SChris Lattner             const dw_offset_t cie_id = m_cfi_data.GetU32(&offset);
651*30fdc8d8SChris Lattner 
652*30fdc8d8SChris Lattner             bool is_cie = for_eh_frame ?  cie_id == 0 : cie_id == UINT32_MAX;
653*30fdc8d8SChris Lattner             if (is_cie)
654*30fdc8d8SChris Lattner                 m_cie_map[curr_offset]= ParseCIE(curr_offset);
655*30fdc8d8SChris Lattner 
656*30fdc8d8SChris Lattner             offset = next_offset;
657*30fdc8d8SChris Lattner         }
658*30fdc8d8SChris Lattner 
659*30fdc8d8SChris Lattner         // Now go back through and index all FDEs
660*30fdc8d8SChris Lattner         offset = 0;
661*30fdc8d8SChris Lattner         const lldb::addr_t pc_rel_addr = m_section->GetFileAddress();
662*30fdc8d8SChris Lattner         const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
663*30fdc8d8SChris Lattner         const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
664*30fdc8d8SChris Lattner         while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8))
665*30fdc8d8SChris Lattner         {
666*30fdc8d8SChris Lattner             const dw_offset_t curr_offset = offset;
667*30fdc8d8SChris Lattner             const uint32_t length = m_cfi_data.GetU32(&offset);
668*30fdc8d8SChris Lattner             const dw_offset_t next_offset = offset + length;
669*30fdc8d8SChris Lattner             const dw_offset_t cie_id = m_cfi_data.GetU32(&offset);
670*30fdc8d8SChris Lattner 
671*30fdc8d8SChris Lattner             bool is_fde = for_eh_frame ?  cie_id != 0 : cie_id != UINT32_MAX;
672*30fdc8d8SChris Lattner             if (is_fde)
673*30fdc8d8SChris Lattner             {
674*30fdc8d8SChris Lattner                 dw_offset_t cie_offset;
675*30fdc8d8SChris Lattner                 if (for_eh_frame)
676*30fdc8d8SChris Lattner                     cie_offset = offset - (cie_id + 4);
677*30fdc8d8SChris Lattner                 else
678*30fdc8d8SChris Lattner                     cie_offset = cie_id;
679*30fdc8d8SChris Lattner 
680*30fdc8d8SChris Lattner                 const CIE* cie = GetCIE(cie_offset);
681*30fdc8d8SChris Lattner                 assert(cie);
682*30fdc8d8SChris Lattner                 lldb::addr_t addr = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr);
683*30fdc8d8SChris Lattner                 lldb::addr_t length = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_GNU_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr);
684*30fdc8d8SChris Lattner                 m_fde_map[VMRange(addr, addr + length)] = FDEInfo(curr_offset);
685*30fdc8d8SChris Lattner             }
686*30fdc8d8SChris Lattner 
687*30fdc8d8SChris Lattner             offset = next_offset;
688*30fdc8d8SChris Lattner         }
689*30fdc8d8SChris Lattner     }
690*30fdc8d8SChris Lattner }
691*30fdc8d8SChris Lattner 
692*30fdc8d8SChris Lattner //----------------------------------------------------------------------
693*30fdc8d8SChris Lattner // Parse instructions for a FDE. The initial instruction for the CIE
694*30fdc8d8SChris Lattner // are parsed first, then the instructions for the FDE are parsed
695*30fdc8d8SChris Lattner //----------------------------------------------------------------------
696*30fdc8d8SChris Lattner void
697*30fdc8d8SChris Lattner DWARFCallFrameInfo::ParseInstructions(const CIE *cie, FDE *fde, dw_offset_t instr_offset, uint32_t instr_length)
698*30fdc8d8SChris Lattner {
699*30fdc8d8SChris Lattner     if (cie != NULL && fde == NULL)
700*30fdc8d8SChris Lattner         return;
701*30fdc8d8SChris Lattner 
702*30fdc8d8SChris Lattner     uint32_t reg_num = 0;
703*30fdc8d8SChris Lattner     int32_t op_offset = 0;
704*30fdc8d8SChris Lattner     uint32_t tmp_uval32;
705*30fdc8d8SChris Lattner     uint32_t code_align = cie->code_align;
706*30fdc8d8SChris Lattner     int32_t data_align = cie->data_align;
707*30fdc8d8SChris Lattner     typedef std::list<Row> RowStack;
708*30fdc8d8SChris Lattner 
709*30fdc8d8SChris Lattner     RowStack row_stack;
710*30fdc8d8SChris Lattner     Row row;
711*30fdc8d8SChris Lattner     if (fde->IsValidRowIndex(0))
712*30fdc8d8SChris Lattner         row = fde->GetRowAtIndex(0);
713*30fdc8d8SChris Lattner 
714*30fdc8d8SChris Lattner     dw_offset_t offset = instr_offset;
715*30fdc8d8SChris Lattner     const dw_offset_t end_offset = instr_offset + instr_length;
716*30fdc8d8SChris Lattner     RegisterLocation reg_location;
717*30fdc8d8SChris Lattner     while (m_cfi_data.ValidOffset(offset) && offset < end_offset)
718*30fdc8d8SChris Lattner     {
719*30fdc8d8SChris Lattner         uint8_t inst = m_cfi_data.GetU8(&offset);
720*30fdc8d8SChris Lattner         uint8_t primary_opcode  = inst & 0xC0;
721*30fdc8d8SChris Lattner         uint8_t extended_opcode = inst & 0x3F;
722*30fdc8d8SChris Lattner 
723*30fdc8d8SChris Lattner         if (primary_opcode)
724*30fdc8d8SChris Lattner         {
725*30fdc8d8SChris Lattner             switch (primary_opcode)
726*30fdc8d8SChris Lattner             {
727*30fdc8d8SChris Lattner                 case DW_CFA_advance_loc :   // (Row Creation Instruction)
728*30fdc8d8SChris Lattner                     {   // 0x40 - high 2 bits are 0x1, lower 6 bits are delta
729*30fdc8d8SChris Lattner                         // takes a single argument that represents a constant delta. The
730*30fdc8d8SChris Lattner                         // required action is to create a new table row with a location
731*30fdc8d8SChris Lattner                         // value that is computed by taking the current entry's location
732*30fdc8d8SChris Lattner                         // value and adding (delta * code_align). All other
733*30fdc8d8SChris Lattner                         // values in the new row are initially identical to the current row.
734*30fdc8d8SChris Lattner                         fde->AppendRow(row);
735*30fdc8d8SChris Lattner                         row.SlideOffset(extended_opcode * code_align);
736*30fdc8d8SChris Lattner                     }
737*30fdc8d8SChris Lattner                     break;
738*30fdc8d8SChris Lattner 
739*30fdc8d8SChris Lattner                 case DW_CFA_offset      :
740*30fdc8d8SChris Lattner                     {   // 0x80 - high 2 bits are 0x2, lower 6 bits are register
741*30fdc8d8SChris Lattner                         // takes two arguments: an unsigned LEB128 constant representing a
742*30fdc8d8SChris Lattner                         // factored offset and a register number. The required action is to
743*30fdc8d8SChris Lattner                         // change the rule for the register indicated by the register number
744*30fdc8d8SChris Lattner                         // to be an offset(N) rule with a value of
745*30fdc8d8SChris Lattner                         // (N = factored offset * data_align).
746*30fdc8d8SChris Lattner                         reg_num = extended_opcode;
747*30fdc8d8SChris Lattner                         op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
748*30fdc8d8SChris Lattner                         reg_location.SetAtCFAPlusOffset(op_offset);
749*30fdc8d8SChris Lattner                         row.SetRegisterInfo (reg_num, reg_location);
750*30fdc8d8SChris Lattner                     }
751*30fdc8d8SChris Lattner                     break;
752*30fdc8d8SChris Lattner 
753*30fdc8d8SChris Lattner                 case DW_CFA_restore     :
754*30fdc8d8SChris Lattner                     {   // 0xC0 - high 2 bits are 0x3, lower 6 bits are register
755*30fdc8d8SChris Lattner                         // takes a single argument that represents a register number. The
756*30fdc8d8SChris Lattner                         // required action is to change the rule for the indicated register
757*30fdc8d8SChris Lattner                         // to the rule assigned it by the initial_instructions in the CIE.
758*30fdc8d8SChris Lattner                         reg_num = extended_opcode;
759*30fdc8d8SChris Lattner                         // We only keep enough register locations around to
760*30fdc8d8SChris Lattner                         // unwind what is in our thread, and these are organized
761*30fdc8d8SChris Lattner                         // by the register index in that state, so we need to convert our
762*30fdc8d8SChris Lattner                         // GCC register number from the EH frame info, to a registe index
763*30fdc8d8SChris Lattner 
764*30fdc8d8SChris Lattner                         if (fde->IsValidRowIndex(0) && fde->GetRowAtIndex(0).GetRegisterInfo(reg_num, reg_location))
765*30fdc8d8SChris Lattner                             row.SetRegisterInfo (reg_num, reg_location);
766*30fdc8d8SChris Lattner                     }
767*30fdc8d8SChris Lattner                     break;
768*30fdc8d8SChris Lattner             }
769*30fdc8d8SChris Lattner         }
770*30fdc8d8SChris Lattner         else
771*30fdc8d8SChris Lattner         {
772*30fdc8d8SChris Lattner             switch (extended_opcode)
773*30fdc8d8SChris Lattner             {
774*30fdc8d8SChris Lattner                 case DW_CFA_nop                 : // 0x0
775*30fdc8d8SChris Lattner                     break;
776*30fdc8d8SChris Lattner 
777*30fdc8d8SChris Lattner                 case DW_CFA_set_loc             : // 0x1 (Row Creation Instruction)
778*30fdc8d8SChris Lattner                     {
779*30fdc8d8SChris Lattner                         // DW_CFA_set_loc takes a single argument that represents an address.
780*30fdc8d8SChris Lattner                         // The required action is to create a new table row using the
781*30fdc8d8SChris Lattner                         // specified address as the location. All other values in the new row
782*30fdc8d8SChris Lattner                         // are initially identical to the current row. The new location value
783*30fdc8d8SChris Lattner                         // should always be greater than the current one.
784*30fdc8d8SChris Lattner                         fde->AppendRow(row);
785*30fdc8d8SChris Lattner                         row.SetOffset(m_cfi_data.GetPointer(&offset) - fde->GetAddressRange().GetBaseAddress().GetFileAddress());
786*30fdc8d8SChris Lattner                     }
787*30fdc8d8SChris Lattner                     break;
788*30fdc8d8SChris Lattner 
789*30fdc8d8SChris Lattner                 case DW_CFA_advance_loc1        : // 0x2 (Row Creation Instruction)
790*30fdc8d8SChris Lattner                     {
791*30fdc8d8SChris Lattner                         // takes a single uword argument that represents a constant delta.
792*30fdc8d8SChris Lattner                         // This instruction is identical to DW_CFA_advance_loc except for the
793*30fdc8d8SChris Lattner                         // encoding and size of the delta argument.
794*30fdc8d8SChris Lattner                         fde->AppendRow(row);
795*30fdc8d8SChris Lattner                         row.SlideOffset (m_cfi_data.GetU8(&offset) * code_align);
796*30fdc8d8SChris Lattner                     }
797*30fdc8d8SChris Lattner                     break;
798*30fdc8d8SChris Lattner 
799*30fdc8d8SChris Lattner                 case DW_CFA_advance_loc2        : // 0x3 (Row Creation Instruction)
800*30fdc8d8SChris Lattner                     {
801*30fdc8d8SChris Lattner                         // takes a single uword argument that represents a constant delta.
802*30fdc8d8SChris Lattner                         // This instruction is identical to DW_CFA_advance_loc except for the
803*30fdc8d8SChris Lattner                         // encoding and size of the delta argument.
804*30fdc8d8SChris Lattner                         fde->AppendRow(row);
805*30fdc8d8SChris Lattner                         row.SlideOffset (m_cfi_data.GetU16(&offset) * code_align);
806*30fdc8d8SChris Lattner                     }
807*30fdc8d8SChris Lattner                     break;
808*30fdc8d8SChris Lattner 
809*30fdc8d8SChris Lattner                 case DW_CFA_advance_loc4        : // 0x4 (Row Creation Instruction)
810*30fdc8d8SChris Lattner                     {
811*30fdc8d8SChris Lattner                         // takes a single uword argument that represents a constant delta.
812*30fdc8d8SChris Lattner                         // This instruction is identical to DW_CFA_advance_loc except for the
813*30fdc8d8SChris Lattner                         // encoding and size of the delta argument.
814*30fdc8d8SChris Lattner                         fde->AppendRow(row);
815*30fdc8d8SChris Lattner                         row.SlideOffset (m_cfi_data.GetU32(&offset) * code_align);
816*30fdc8d8SChris Lattner                     }
817*30fdc8d8SChris Lattner                     break;
818*30fdc8d8SChris Lattner 
819*30fdc8d8SChris Lattner                 case DW_CFA_offset_extended     : // 0x5
820*30fdc8d8SChris Lattner                     {
821*30fdc8d8SChris Lattner                         // takes two unsigned LEB128 arguments representing a register number
822*30fdc8d8SChris Lattner                         // and a factored offset. This instruction is identical to DW_CFA_offset
823*30fdc8d8SChris Lattner                         // except for the encoding and size of the register argument.
824*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
825*30fdc8d8SChris Lattner                         op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
826*30fdc8d8SChris Lattner                         reg_location.SetAtCFAPlusOffset(op_offset);
827*30fdc8d8SChris Lattner                         row.SetRegisterInfo (reg_num, reg_location);
828*30fdc8d8SChris Lattner                     }
829*30fdc8d8SChris Lattner                     break;
830*30fdc8d8SChris Lattner 
831*30fdc8d8SChris Lattner                 case DW_CFA_restore_extended    : // 0x6
832*30fdc8d8SChris Lattner                     {
833*30fdc8d8SChris Lattner                         // takes a single unsigned LEB128 argument that represents a register
834*30fdc8d8SChris Lattner                         // number. This instruction is identical to DW_CFA_restore except for
835*30fdc8d8SChris Lattner                         // the encoding and size of the register argument.
836*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
837*30fdc8d8SChris Lattner                         if (fde->IsValidRowIndex(0) && fde->GetRowAtIndex(0).GetRegisterInfo(reg_num, reg_location))
838*30fdc8d8SChris Lattner                             row.SetRegisterInfo (reg_num, reg_location);
839*30fdc8d8SChris Lattner                     }
840*30fdc8d8SChris Lattner                     break;
841*30fdc8d8SChris Lattner 
842*30fdc8d8SChris Lattner                 case DW_CFA_undefined           : // 0x7
843*30fdc8d8SChris Lattner                     {
844*30fdc8d8SChris Lattner                         // takes a single unsigned LEB128 argument that represents a register
845*30fdc8d8SChris Lattner                         // number. The required action is to set the rule for the specified
846*30fdc8d8SChris Lattner                         // register to undefined.
847*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
848*30fdc8d8SChris Lattner                         reg_location.SetUndefined();
849*30fdc8d8SChris Lattner                         row.SetRegisterInfo (reg_num, reg_location);
850*30fdc8d8SChris Lattner                     }
851*30fdc8d8SChris Lattner                     break;
852*30fdc8d8SChris Lattner 
853*30fdc8d8SChris Lattner                 case DW_CFA_same_value          : // 0x8
854*30fdc8d8SChris Lattner                     {
855*30fdc8d8SChris Lattner                         // takes a single unsigned LEB128 argument that represents a register
856*30fdc8d8SChris Lattner                         // number. The required action is to set the rule for the specified
857*30fdc8d8SChris Lattner                         // register to same value.
858*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
859*30fdc8d8SChris Lattner                         reg_location.SetSame();
860*30fdc8d8SChris Lattner                         row.SetRegisterInfo (reg_num, reg_location);
861*30fdc8d8SChris Lattner                     }
862*30fdc8d8SChris Lattner                     break;
863*30fdc8d8SChris Lattner 
864*30fdc8d8SChris Lattner                 case DW_CFA_register            : // 0x9
865*30fdc8d8SChris Lattner                     {
866*30fdc8d8SChris Lattner                         // takes two unsigned LEB128 arguments representing register numbers.
867*30fdc8d8SChris Lattner                         // The required action is to set the rule for the first register to be
868*30fdc8d8SChris Lattner                         // the second register.
869*30fdc8d8SChris Lattner 
870*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
871*30fdc8d8SChris Lattner                         uint32_t other_reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
872*30fdc8d8SChris Lattner                         reg_location.SetInRegister(other_reg_num);
873*30fdc8d8SChris Lattner                         row.SetRegisterInfo (reg_num, reg_location);
874*30fdc8d8SChris Lattner                     }
875*30fdc8d8SChris Lattner                     break;
876*30fdc8d8SChris Lattner 
877*30fdc8d8SChris Lattner                 case DW_CFA_remember_state      : // 0xA
878*30fdc8d8SChris Lattner                     // These instructions define a stack of information. Encountering the
879*30fdc8d8SChris Lattner                     // DW_CFA_remember_state instruction means to save the rules for every
880*30fdc8d8SChris Lattner                     // register on the current row on the stack. Encountering the
881*30fdc8d8SChris Lattner                     // DW_CFA_restore_state instruction means to pop the set of rules off
882*30fdc8d8SChris Lattner                     // the stack and place them in the current row. (This operation is
883*30fdc8d8SChris Lattner                     // useful for compilers that move epilogue code into the body of a
884*30fdc8d8SChris Lattner                     // function.)
885*30fdc8d8SChris Lattner                     row_stack.push_back(row);
886*30fdc8d8SChris Lattner                     break;
887*30fdc8d8SChris Lattner 
888*30fdc8d8SChris Lattner                 case DW_CFA_restore_state       : // 0xB
889*30fdc8d8SChris Lattner                     // These instructions define a stack of information. Encountering the
890*30fdc8d8SChris Lattner                     // DW_CFA_remember_state instruction means to save the rules for every
891*30fdc8d8SChris Lattner                     // register on the current row on the stack. Encountering the
892*30fdc8d8SChris Lattner                     // DW_CFA_restore_state instruction means to pop the set of rules off
893*30fdc8d8SChris Lattner                     // the stack and place them in the current row. (This operation is
894*30fdc8d8SChris Lattner                     // useful for compilers that move epilogue code into the body of a
895*30fdc8d8SChris Lattner                     // function.)
896*30fdc8d8SChris Lattner                     {
897*30fdc8d8SChris Lattner                         row = row_stack.back();
898*30fdc8d8SChris Lattner                         row_stack.pop_back();
899*30fdc8d8SChris Lattner                     }
900*30fdc8d8SChris Lattner                     break;
901*30fdc8d8SChris Lattner 
902*30fdc8d8SChris Lattner                 case DW_CFA_def_cfa             : // 0xC    (CFA Definition Instruction)
903*30fdc8d8SChris Lattner                     {
904*30fdc8d8SChris Lattner                         // Takes two unsigned LEB128 operands representing a register
905*30fdc8d8SChris Lattner                         // number and a (non-factored) offset. The required action
906*30fdc8d8SChris Lattner                         // is to define the current CFA rule to use the provided
907*30fdc8d8SChris Lattner                         // register and offset.
908*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
909*30fdc8d8SChris Lattner                         op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
910*30fdc8d8SChris Lattner                         row.SetCFARegister (reg_num);
911*30fdc8d8SChris Lattner                         row.SetCFAOffset (op_offset);
912*30fdc8d8SChris Lattner                     }
913*30fdc8d8SChris Lattner                     break;
914*30fdc8d8SChris Lattner 
915*30fdc8d8SChris Lattner                 case DW_CFA_def_cfa_register    : // 0xD    (CFA Definition Instruction)
916*30fdc8d8SChris Lattner                     {
917*30fdc8d8SChris Lattner                         // takes a single unsigned LEB128 argument representing a register
918*30fdc8d8SChris Lattner                         // number. The required action is to define the current CFA rule to
919*30fdc8d8SChris Lattner                         // use the provided register (but to keep the old offset).
920*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
921*30fdc8d8SChris Lattner                         row.SetCFARegister (reg_num);
922*30fdc8d8SChris Lattner                     }
923*30fdc8d8SChris Lattner                     break;
924*30fdc8d8SChris Lattner 
925*30fdc8d8SChris Lattner                 case DW_CFA_def_cfa_offset      : // 0xE    (CFA Definition Instruction)
926*30fdc8d8SChris Lattner                     {
927*30fdc8d8SChris Lattner                         // Takes a single unsigned LEB128 operand representing a
928*30fdc8d8SChris Lattner                         // (non-factored) offset. The required action is to define
929*30fdc8d8SChris Lattner                         // the current CFA rule to use the provided offset (but
930*30fdc8d8SChris Lattner                         // to keep the old register).
931*30fdc8d8SChris Lattner                         op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
932*30fdc8d8SChris Lattner                         row.SetCFAOffset (op_offset);
933*30fdc8d8SChris Lattner                     }
934*30fdc8d8SChris Lattner                     break;
935*30fdc8d8SChris Lattner 
936*30fdc8d8SChris Lattner                 case DW_CFA_def_cfa_expression  : // 0xF    (CFA Definition Instruction)
937*30fdc8d8SChris Lattner                     {
938*30fdc8d8SChris Lattner                         size_t block_len = (size_t)m_cfi_data.GetULEB128(&offset);
939*30fdc8d8SChris Lattner                         offset += (uint32_t)block_len;
940*30fdc8d8SChris Lattner                     }
941*30fdc8d8SChris Lattner                     break;
942*30fdc8d8SChris Lattner 
943*30fdc8d8SChris Lattner                 case DW_CFA_expression          : // 0x10
944*30fdc8d8SChris Lattner                     {
945*30fdc8d8SChris Lattner                         // Takes two operands: an unsigned LEB128 value representing
946*30fdc8d8SChris Lattner                         // a register number, and a DW_FORM_block value representing a DWARF
947*30fdc8d8SChris Lattner                         // expression. The required action is to change the rule for the
948*30fdc8d8SChris Lattner                         // register indicated by the register number to be an expression(E)
949*30fdc8d8SChris Lattner                         // rule where E is the DWARF expression. That is, the DWARF
950*30fdc8d8SChris Lattner                         // expression computes the address. The value of the CFA is
951*30fdc8d8SChris Lattner                         // pushed on the DWARF evaluation stack prior to execution of
952*30fdc8d8SChris Lattner                         // the DWARF expression.
953*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
954*30fdc8d8SChris Lattner                         uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
955*30fdc8d8SChris Lattner                         const uint8_t *block_data = (uint8_t *)m_cfi_data.GetData(&offset, block_len);
956*30fdc8d8SChris Lattner 
957*30fdc8d8SChris Lattner                         reg_location.SetAtDWARFExpression(block_data, block_len);
958*30fdc8d8SChris Lattner                         row.SetRegisterInfo (reg_num, reg_location);
959*30fdc8d8SChris Lattner                     }
960*30fdc8d8SChris Lattner                     break;
961*30fdc8d8SChris Lattner 
962*30fdc8d8SChris Lattner                 case DW_CFA_offset_extended_sf  : // 0x11
963*30fdc8d8SChris Lattner                     {
964*30fdc8d8SChris Lattner                         // takes two operands: an unsigned LEB128 value representing a
965*30fdc8d8SChris Lattner                         // register number and a signed LEB128 factored offset. This
966*30fdc8d8SChris Lattner                         // instruction is identical to DW_CFA_offset_extended except
967*30fdc8d8SChris Lattner                         //that the second operand is signed and factored.
968*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
969*30fdc8d8SChris Lattner                         op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
970*30fdc8d8SChris Lattner                         reg_location.SetAtCFAPlusOffset(op_offset);
971*30fdc8d8SChris Lattner                         row.SetRegisterInfo (reg_num, reg_location);
972*30fdc8d8SChris Lattner                     }
973*30fdc8d8SChris Lattner                     break;
974*30fdc8d8SChris Lattner 
975*30fdc8d8SChris Lattner                 case DW_CFA_def_cfa_sf          : // 0x12   (CFA Definition Instruction)
976*30fdc8d8SChris Lattner                     {
977*30fdc8d8SChris Lattner                         // Takes two operands: an unsigned LEB128 value representing
978*30fdc8d8SChris Lattner                         // a register number and a signed LEB128 factored offset.
979*30fdc8d8SChris Lattner                         // This instruction is identical to DW_CFA_def_cfa except
980*30fdc8d8SChris Lattner                         // that the second operand is signed and factored.
981*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
982*30fdc8d8SChris Lattner                         op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
983*30fdc8d8SChris Lattner                         row.SetCFARegister (reg_num);
984*30fdc8d8SChris Lattner                         row.SetCFAOffset (op_offset);
985*30fdc8d8SChris Lattner                     }
986*30fdc8d8SChris Lattner                     break;
987*30fdc8d8SChris Lattner 
988*30fdc8d8SChris Lattner                 case DW_CFA_def_cfa_offset_sf   : // 0x13   (CFA Definition Instruction)
989*30fdc8d8SChris Lattner                     {
990*30fdc8d8SChris Lattner                         // takes a signed LEB128 operand representing a factored
991*30fdc8d8SChris Lattner                         // offset. This instruction is identical to  DW_CFA_def_cfa_offset
992*30fdc8d8SChris Lattner                         // except that the operand is signed and factored.
993*30fdc8d8SChris Lattner                         op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
994*30fdc8d8SChris Lattner                         row.SetCFAOffset (op_offset);
995*30fdc8d8SChris Lattner                     }
996*30fdc8d8SChris Lattner                     break;
997*30fdc8d8SChris Lattner 
998*30fdc8d8SChris Lattner                 case DW_CFA_val_expression      :   // 0x16
999*30fdc8d8SChris Lattner                     {
1000*30fdc8d8SChris Lattner                         // takes two operands: an unsigned LEB128 value representing a register
1001*30fdc8d8SChris Lattner                         // number, and a DW_FORM_block value representing a DWARF expression.
1002*30fdc8d8SChris Lattner                         // The required action is to change the rule for the register indicated
1003*30fdc8d8SChris Lattner                         // by the register number to be a val_expression(E) rule where E is the
1004*30fdc8d8SChris Lattner                         // DWARF expression. That is, the DWARF expression computes the value of
1005*30fdc8d8SChris Lattner                         // the given register. The value of the CFA is pushed on the DWARF
1006*30fdc8d8SChris Lattner                         // evaluation stack prior to execution of the DWARF expression.
1007*30fdc8d8SChris Lattner                         reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
1008*30fdc8d8SChris Lattner                         uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
1009*30fdc8d8SChris Lattner                         const uint8_t* block_data = (uint8_t*)m_cfi_data.GetData(&offset, block_len);
1010*30fdc8d8SChris Lattner //#if defined(__i386__) || defined(__x86_64__)
1011*30fdc8d8SChris Lattner //                      // The EH frame info for EIP and RIP contains code that looks for traps to
1012*30fdc8d8SChris Lattner //                      // be a specific type and increments the PC.
1013*30fdc8d8SChris Lattner //                      // For i386:
1014*30fdc8d8SChris Lattner //                      // DW_CFA_val_expression where:
1015*30fdc8d8SChris Lattner //                      // eip = DW_OP_breg6(+28), DW_OP_deref, DW_OP_dup, DW_OP_plus_uconst(0x34),
1016*30fdc8d8SChris Lattner //                      //       DW_OP_deref, DW_OP_swap, DW_OP_plus_uconst(0), DW_OP_deref,
1017*30fdc8d8SChris Lattner //                      //       DW_OP_dup, DW_OP_lit3, DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne,
1018*30fdc8d8SChris Lattner //                      //       DW_OP_and, DW_OP_plus
1019*30fdc8d8SChris Lattner //                      // This basically does a:
1020*30fdc8d8SChris Lattner //                      // eip = ucontenxt.mcontext32->gpr.eip;
1021*30fdc8d8SChris Lattner //                      // if (ucontenxt.mcontext32->exc.trapno != 3 && ucontenxt.mcontext32->exc.trapno != 4)
1022*30fdc8d8SChris Lattner //                      //   eip++;
1023*30fdc8d8SChris Lattner //                      //
1024*30fdc8d8SChris Lattner //                      // For x86_64:
1025*30fdc8d8SChris Lattner //                      // DW_CFA_val_expression where:
1026*30fdc8d8SChris Lattner //                      // rip =  DW_OP_breg3(+48), DW_OP_deref, DW_OP_dup, DW_OP_plus_uconst(0x90), DW_OP_deref,
1027*30fdc8d8SChris Lattner //                      //          DW_OP_swap, DW_OP_plus_uconst(0), DW_OP_deref_size(4), DW_OP_dup, DW_OP_lit3,
1028*30fdc8d8SChris Lattner //                      //          DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne, DW_OP_and, DW_OP_plus
1029*30fdc8d8SChris Lattner //                      // This basically does a:
1030*30fdc8d8SChris Lattner //                      // rip = ucontenxt.mcontext64->gpr.rip;
1031*30fdc8d8SChris Lattner //                      // if (ucontenxt.mcontext64->exc.trapno != 3 && ucontenxt.mcontext64->exc.trapno != 4)
1032*30fdc8d8SChris Lattner //                      //   rip++;
1033*30fdc8d8SChris Lattner //                      // The trap comparisons and increments are not needed as it hoses up the unwound PC which
1034*30fdc8d8SChris Lattner //                      // is expected to point at least past the instruction that causes the fault/trap. So we
1035*30fdc8d8SChris Lattner //                      // take it out by trimming the expression right at the first "DW_OP_swap" opcodes
1036*30fdc8d8SChris Lattner //                      if (block_data != NULL && thread->GetPCRegNum(Thread::GCC) == reg_num)
1037*30fdc8d8SChris Lattner //                      {
1038*30fdc8d8SChris Lattner //                          if (thread->Is64Bit())
1039*30fdc8d8SChris Lattner //                          {
1040*30fdc8d8SChris Lattner //                              if (block_len > 9 && block_data[8] == DW_OP_swap && block_data[9] == DW_OP_plus_uconst)
1041*30fdc8d8SChris Lattner //                                  block_len = 8;
1042*30fdc8d8SChris Lattner //                          }
1043*30fdc8d8SChris Lattner //                          else
1044*30fdc8d8SChris Lattner //                          {
1045*30fdc8d8SChris Lattner //                              if (block_len > 8 && block_data[7] == DW_OP_swap && block_data[8] == DW_OP_plus_uconst)
1046*30fdc8d8SChris Lattner //                                  block_len = 7;
1047*30fdc8d8SChris Lattner //                          }
1048*30fdc8d8SChris Lattner //                      }
1049*30fdc8d8SChris Lattner //#endif
1050*30fdc8d8SChris Lattner                         reg_location.SetIsDWARFExpression(block_data, block_len);
1051*30fdc8d8SChris Lattner                         row.SetRegisterInfo (reg_num, reg_location);
1052*30fdc8d8SChris Lattner                     }
1053*30fdc8d8SChris Lattner                     break;
1054*30fdc8d8SChris Lattner 
1055*30fdc8d8SChris Lattner                 case DW_CFA_val_offset          :   // 0x14
1056*30fdc8d8SChris Lattner                 case DW_CFA_val_offset_sf       :   // 0x15
1057*30fdc8d8SChris Lattner                 default:
1058*30fdc8d8SChris Lattner                     tmp_uval32 = extended_opcode;
1059*30fdc8d8SChris Lattner                     break;
1060*30fdc8d8SChris Lattner             }
1061*30fdc8d8SChris Lattner         }
1062*30fdc8d8SChris Lattner     }
1063*30fdc8d8SChris Lattner     fde->AppendRow(row);
1064*30fdc8d8SChris Lattner }
1065*30fdc8d8SChris Lattner 
1066*30fdc8d8SChris Lattner void
1067*30fdc8d8SChris Lattner DWARFCallFrameInfo::ParseAll()
1068*30fdc8d8SChris Lattner {
1069*30fdc8d8SChris Lattner     Index();
1070*30fdc8d8SChris Lattner     fde_map_t::iterator pos, end = m_fde_map.end();
1071*30fdc8d8SChris Lattner     for (pos = m_fde_map.begin(); pos != end; ++ pos)
1072*30fdc8d8SChris Lattner     {
1073*30fdc8d8SChris Lattner         if (pos->second.fde_sp.get() == NULL)
1074*30fdc8d8SChris Lattner             pos->second.fde_sp = ParseFDE(pos->second.fde_offset);
1075*30fdc8d8SChris Lattner     }
1076*30fdc8d8SChris Lattner }
1077*30fdc8d8SChris Lattner 
1078*30fdc8d8SChris Lattner 
1079*30fdc8d8SChris Lattner //bool
1080*30fdc8d8SChris Lattner //DWARFCallFrameInfo::UnwindRegisterAtIndex
1081*30fdc8d8SChris Lattner //(
1082*30fdc8d8SChris Lattner //  const uint32_t reg_idx,
1083*30fdc8d8SChris Lattner //  const Thread* currState,
1084*30fdc8d8SChris Lattner //  const DWARFCallFrameInfo::Row* row,
1085*30fdc8d8SChris Lattner //  mapped_memory_t * memCache,
1086*30fdc8d8SChris Lattner //  Thread* unwindState
1087*30fdc8d8SChris Lattner //)
1088*30fdc8d8SChris Lattner //{
1089*30fdc8d8SChris Lattner //    bool get_reg_success = false;
1090*30fdc8d8SChris Lattner //
1091*30fdc8d8SChris Lattner //    const RegLocation* regLocation = row->regs.GetRegisterInfo(reg_idx);
1092*30fdc8d8SChris Lattner //
1093*30fdc8d8SChris Lattner //  // On some systems, we may not get unwind info for the program counter,
1094*30fdc8d8SChris Lattner //  // but the return address register can be used to get that information.
1095*30fdc8d8SChris Lattner //    if (reg_idx == currState->GetPCRegNum(Thread::Index))
1096*30fdc8d8SChris Lattner //    {
1097*30fdc8d8SChris Lattner //      const RegLocation* returnAddrRegLocation = row->regs.GetRegisterInfo(currState->GetRARegNum(Thread::Index));
1098*30fdc8d8SChris Lattner //      if (regLocation == NULL)
1099*30fdc8d8SChris Lattner //      {
1100*30fdc8d8SChris Lattner //          // We have nothing to the program counter, so lets see if this
1101*30fdc8d8SChris Lattner //          // thread state has a return address (link register) that can
1102*30fdc8d8SChris Lattner //          // help us track down the previous PC
1103*30fdc8d8SChris Lattner //          regLocation = returnAddrRegLocation;
1104*30fdc8d8SChris Lattner //      }
1105*30fdc8d8SChris Lattner //      else if (regLocation->type == RegLocation::unspecified)
1106*30fdc8d8SChris Lattner //      {
1107*30fdc8d8SChris Lattner //          // We did have a location that didn't specify a value for unwinding
1108*30fdc8d8SChris Lattner //          // the PC, so if there is a info for the return return address
1109*30fdc8d8SChris Lattner //          // register (link register) lets use that
1110*30fdc8d8SChris Lattner //          if (returnAddrRegLocation)
1111*30fdc8d8SChris Lattner //              regLocation = returnAddrRegLocation;
1112*30fdc8d8SChris Lattner //      }
1113*30fdc8d8SChris Lattner //    }
1114*30fdc8d8SChris Lattner //
1115*30fdc8d8SChris Lattner //    if (regLocation)
1116*30fdc8d8SChris Lattner //    {
1117*30fdc8d8SChris Lattner //      mach_vm_address_t unwoundRegValue = INVALID_VMADDR;
1118*30fdc8d8SChris Lattner //      switch (regLocation->type)
1119*30fdc8d8SChris Lattner //      {
1120*30fdc8d8SChris Lattner //          case RegLocation::undefined:
1121*30fdc8d8SChris Lattner //              // Register is not available, mark it as invalid
1122*30fdc8d8SChris Lattner //              unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
1123*30fdc8d8SChris Lattner //              return true;
1124*30fdc8d8SChris Lattner //
1125*30fdc8d8SChris Lattner //          case RegLocation::unspecified:
1126*30fdc8d8SChris Lattner //              // Nothing to do if it is the same
1127*30fdc8d8SChris Lattner //              return true;
1128*30fdc8d8SChris Lattner //
1129*30fdc8d8SChris Lattner //          case RegLocation::same:
1130*30fdc8d8SChris Lattner //              // Nothing to do if it is the same
1131*30fdc8d8SChris Lattner //              return true;
1132*30fdc8d8SChris Lattner //
1133*30fdc8d8SChris Lattner //          case RegLocation::atFPPlusOffset:
1134*30fdc8d8SChris Lattner //          case RegLocation::isFPPlusOffset:
1135*30fdc8d8SChris Lattner //          {
1136*30fdc8d8SChris Lattner //              uint64_t unwindAddress = currState->GetRegisterValue(row->cfa_register, Thread::GCC, INVALID_VMADDR, &get_reg_success);
1137*30fdc8d8SChris Lattner //
1138*30fdc8d8SChris Lattner //              if (get_reg_success)
1139*30fdc8d8SChris Lattner //              {
1140*30fdc8d8SChris Lattner //                  unwindAddress += row->cfa_offset + regLocation->location.offset;
1141*30fdc8d8SChris Lattner //
1142*30fdc8d8SChris Lattner //                  if (regLocation->type == RegLocation::isFPPlusOffset)
1143*30fdc8d8SChris Lattner //                  {
1144*30fdc8d8SChris Lattner //                      unwindState->SetRegisterValue(reg_idx, Thread::Index, unwindAddress);
1145*30fdc8d8SChris Lattner //                      return true;
1146*30fdc8d8SChris Lattner //                  }
1147*30fdc8d8SChris Lattner //                  else
1148*30fdc8d8SChris Lattner //                  {
1149*30fdc8d8SChris Lattner //                      kern_return_t err = mapped_memory_read_pointer(memCache, unwindAddress, &unwoundRegValue);
1150*30fdc8d8SChris Lattner //                      if (err != KERN_SUCCESS)
1151*30fdc8d8SChris Lattner //                      {
1152*30fdc8d8SChris Lattner //                          unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
1153*30fdc8d8SChris Lattner //                          return false;
1154*30fdc8d8SChris Lattner //                      }
1155*30fdc8d8SChris Lattner //                      unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue);
1156*30fdc8d8SChris Lattner //                      return true;
1157*30fdc8d8SChris Lattner //                  }
1158*30fdc8d8SChris Lattner //              }
1159*30fdc8d8SChris Lattner //              else
1160*30fdc8d8SChris Lattner //              {
1161*30fdc8d8SChris Lattner //                  unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
1162*30fdc8d8SChris Lattner //              }
1163*30fdc8d8SChris Lattner //              return false;
1164*30fdc8d8SChris Lattner //          }
1165*30fdc8d8SChris Lattner //              break;
1166*30fdc8d8SChris Lattner //
1167*30fdc8d8SChris Lattner //          case RegLocation::atDWARFExpression:
1168*30fdc8d8SChris Lattner //          case RegLocation::isDWARFExpression:
1169*30fdc8d8SChris Lattner //          {
1170*30fdc8d8SChris Lattner //              bool swap = false;
1171*30fdc8d8SChris Lattner //              DWARFExpressionBaton baton = { currState, memCache, swap };
1172*30fdc8d8SChris Lattner //              uint64_t expr_result = 0;
1173*30fdc8d8SChris Lattner //              CSBinaryDataRef opcodes(regLocation->location.expr.opcodes, regLocation->location.expr.length, swap);
1174*30fdc8d8SChris Lattner //              opcodes.SetPointerSize(currState->Is64Bit() ? 8 : 4);
1175*30fdc8d8SChris Lattner //              const char * expr_err = CSDWARFExpression::Evaluate(DWARFExpressionReadMemoryDCScriptInterpreter::Type,
1176*30fdc8d8SChris Lattner //                                                                  DWARFExpressionReadRegisterDCScriptInterpreter::Type,
1177*30fdc8d8SChris Lattner //                                                                  &baton,
1178*30fdc8d8SChris Lattner //                                                                  opcodes,
1179*30fdc8d8SChris Lattner //                                                                  0,
1180*30fdc8d8SChris Lattner //                                                                  regLocation->location.expr.length,
1181*30fdc8d8SChris Lattner //                                                                  NULL,
1182*30fdc8d8SChris Lattner //                                                                  expr_result);
1183*30fdc8d8SChris Lattner //              if (expr_err == NULL)
1184*30fdc8d8SChris Lattner //              {
1185*30fdc8d8SChris Lattner //                  // SUCCESS!
1186*30fdc8d8SChris Lattner //                  if (regLocation->type == RegLocation::isDWARFExpression)
1187*30fdc8d8SChris Lattner //                  {
1188*30fdc8d8SChris Lattner //                      unwindState->SetRegisterValue(reg_idx, Thread::Index, expr_result);
1189*30fdc8d8SChris Lattner //                      return true;
1190*30fdc8d8SChris Lattner //                  }
1191*30fdc8d8SChris Lattner //                  else
1192*30fdc8d8SChris Lattner //                  {
1193*30fdc8d8SChris Lattner //                      kern_return_t err = mapped_memory_read_pointer(memCache, expr_result, &unwoundRegValue);
1194*30fdc8d8SChris Lattner //                      if (err != KERN_SUCCESS)
1195*30fdc8d8SChris Lattner //                      {
1196*30fdc8d8SChris Lattner //                          unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
1197*30fdc8d8SChris Lattner //                          return false;
1198*30fdc8d8SChris Lattner //                      }
1199*30fdc8d8SChris Lattner //                      unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue);
1200*30fdc8d8SChris Lattner //                      return true;
1201*30fdc8d8SChris Lattner //                  }
1202*30fdc8d8SChris Lattner //              }
1203*30fdc8d8SChris Lattner //              else
1204*30fdc8d8SChris Lattner //              {
1205*30fdc8d8SChris Lattner //                  // FAIL
1206*30fdc8d8SChris Lattner //                  unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
1207*30fdc8d8SChris Lattner //              }
1208*30fdc8d8SChris Lattner //              return false;
1209*30fdc8d8SChris Lattner //          }
1210*30fdc8d8SChris Lattner //              break;
1211*30fdc8d8SChris Lattner //
1212*30fdc8d8SChris Lattner //
1213*30fdc8d8SChris Lattner //          case RegLocation::inRegister:
1214*30fdc8d8SChris Lattner //              // The value is in another register.
1215*30fdc8d8SChris Lattner //              unwoundRegValue = currState->GetRegisterValue(regLocation->location.reg, Thread::GCC, 0, &get_reg_success);
1216*30fdc8d8SChris Lattner //              if (get_reg_success)
1217*30fdc8d8SChris Lattner //              {
1218*30fdc8d8SChris Lattner //                  unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue);
1219*30fdc8d8SChris Lattner //                  return true;
1220*30fdc8d8SChris Lattner //              }
1221*30fdc8d8SChris Lattner //              return false;
1222*30fdc8d8SChris Lattner //
1223*30fdc8d8SChris Lattner //          default:
1224*30fdc8d8SChris Lattner //              break;
1225*30fdc8d8SChris Lattner //      }
1226*30fdc8d8SChris Lattner //    }
1227*30fdc8d8SChris Lattner //
1228*30fdc8d8SChris Lattner //    if (reg_idx == currState->GetSPRegNum(Thread::Index))
1229*30fdc8d8SChris Lattner //    {
1230*30fdc8d8SChris Lattner //      uint64_t cfa = currState->GetRegisterValue(row->cfa_register, Thread::GCC, 0, &get_reg_success);
1231*30fdc8d8SChris Lattner //      if (get_reg_success)
1232*30fdc8d8SChris Lattner //      {
1233*30fdc8d8SChris Lattner //          return unwindState->SetSP(cfa + row->cfa_offset);
1234*30fdc8d8SChris Lattner //      }
1235*30fdc8d8SChris Lattner //      else
1236*30fdc8d8SChris Lattner //      {
1237*30fdc8d8SChris Lattner //          unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
1238*30fdc8d8SChris Lattner //          return false;
1239*30fdc8d8SChris Lattner //      }
1240*30fdc8d8SChris Lattner //    }
1241*30fdc8d8SChris Lattner //
1242*30fdc8d8SChris Lattner //    return false;
1243*30fdc8d8SChris Lattner //}
1244*30fdc8d8SChris Lattner 
1245*30fdc8d8SChris Lattner void
1246*30fdc8d8SChris Lattner DWARFCallFrameInfo::Dump(Stream *s, Thread *thread) const
1247*30fdc8d8SChris Lattner {
1248*30fdc8d8SChris Lattner     s->Indent();
1249*30fdc8d8SChris Lattner     s->Printf("DWARFCallFrameInfo for ");
1250*30fdc8d8SChris Lattner     *s << m_objfile->GetFileSpec();
1251*30fdc8d8SChris Lattner     if (m_flags.IsSet(eFlagParsedIndex))
1252*30fdc8d8SChris Lattner     {
1253*30fdc8d8SChris Lattner         s->Printf(" (CIE[%zu], FDE[%zu])\n", m_cie_map.size(), m_fde_map.size());
1254*30fdc8d8SChris Lattner         s->IndentMore();
1255*30fdc8d8SChris Lattner         cie_map_t::const_iterator cie_pos, cie_end = m_cie_map.end();
1256*30fdc8d8SChris Lattner         const ArchSpec *arch = &m_objfile->GetModule()->GetArchitecture();
1257*30fdc8d8SChris Lattner 
1258*30fdc8d8SChris Lattner         for (cie_pos = m_cie_map.begin(); cie_pos != cie_end; ++ cie_pos)
1259*30fdc8d8SChris Lattner         {
1260*30fdc8d8SChris Lattner             if (cie_pos->second.get() == NULL)
1261*30fdc8d8SChris Lattner             {
1262*30fdc8d8SChris Lattner                 s->Indent();
1263*30fdc8d8SChris Lattner                 s->Printf("CIE{0x%8.8x} - unparsed\n", cie_pos->first);
1264*30fdc8d8SChris Lattner             }
1265*30fdc8d8SChris Lattner             else
1266*30fdc8d8SChris Lattner             {
1267*30fdc8d8SChris Lattner                 cie_pos->second->Dump(s, thread, arch, m_reg_kind);
1268*30fdc8d8SChris Lattner             }
1269*30fdc8d8SChris Lattner         }
1270*30fdc8d8SChris Lattner 
1271*30fdc8d8SChris Lattner         fde_map_t::const_iterator fde_pos, fde_end = m_fde_map.end();
1272*30fdc8d8SChris Lattner         for (fde_pos = m_fde_map.begin(); fde_pos != fde_end; ++ fde_pos)
1273*30fdc8d8SChris Lattner         {
1274*30fdc8d8SChris Lattner             if (fde_pos->second.fde_sp.get() == NULL)
1275*30fdc8d8SChris Lattner             {
1276*30fdc8d8SChris Lattner                 s->Indent();
1277*30fdc8d8SChris Lattner                 s->Printf("FDE{0x%8.8x} - unparsed\n", fde_pos->second.fde_offset);
1278*30fdc8d8SChris Lattner             }
1279*30fdc8d8SChris Lattner             else
1280*30fdc8d8SChris Lattner             {
1281*30fdc8d8SChris Lattner                 fde_pos->second.fde_sp->Dump(s, *this, thread);
1282*30fdc8d8SChris Lattner             }
1283*30fdc8d8SChris Lattner         }
1284*30fdc8d8SChris Lattner         s->IndentLess();
1285*30fdc8d8SChris Lattner     }
1286*30fdc8d8SChris Lattner     else
1287*30fdc8d8SChris Lattner     {
1288*30fdc8d8SChris Lattner         s->PutCString(" (not indexed yet)\n");
1289*30fdc8d8SChris Lattner     }
1290*30fdc8d8SChris Lattner }
1291*30fdc8d8SChris Lattner 
1292*30fdc8d8SChris Lattner 
1293*30fdc8d8SChris Lattner //uint32_t
1294*30fdc8d8SChris Lattner //DWARFCallFrameInfo::UnwindThreadState(const Thread* currState, mapped_memory_t *memCache, bool is_first_frame, Thread* unwindState)
1295*30fdc8d8SChris Lattner //{
1296*30fdc8d8SChris Lattner //  if (currState == NULL || unwindState == NULL)
1297*30fdc8d8SChris Lattner //      return 0;
1298*30fdc8d8SChris Lattner //
1299*30fdc8d8SChris Lattner //    *unwindState = *currState;
1300*30fdc8d8SChris Lattner //    uint32_t numRegisterUnwound = 0;
1301*30fdc8d8SChris Lattner //    uint64_t currPC = currState->GetPC(INVALID_VMADDR);
1302*30fdc8d8SChris Lattner //
1303*30fdc8d8SChris Lattner //    if (currPC != INVALID_VMADDR)
1304*30fdc8d8SChris Lattner //    {
1305*30fdc8d8SChris Lattner //      // If this is not the first frame, we care about the previous instruction
1306*30fdc8d8SChris Lattner //      // since it will be at the instruction following the instruction that
1307*30fdc8d8SChris Lattner //      // made the function call.
1308*30fdc8d8SChris Lattner //      uint64_t unwindPC = currPC;
1309*30fdc8d8SChris Lattner //      if (unwindPC > 0 && !is_first_frame)
1310*30fdc8d8SChris Lattner //          --unwindPC;
1311*30fdc8d8SChris Lattner //
1312*30fdc8d8SChris Lattner //#if defined(__i386__) || defined(__x86_64__)
1313*30fdc8d8SChris Lattner //      // Only on i386 do we have __IMPORT segments that contain trampolines
1314*30fdc8d8SChris Lattner //      if (!currState->Is64Bit() && ImportRangesContainsAddress(unwindPC))
1315*30fdc8d8SChris Lattner //      {
1316*30fdc8d8SChris Lattner //          uint64_t curr_sp = currState->GetSP(INVALID_VMADDR);
1317*30fdc8d8SChris Lattner //          mach_vm_address_t pc = INVALID_VMADDR;
1318*30fdc8d8SChris Lattner //          unwindState->SetSP(curr_sp + 4);
1319*30fdc8d8SChris Lattner //          kern_return_t err = mapped_memory_read_pointer(memCache, curr_sp, &pc);
1320*30fdc8d8SChris Lattner //          if (err == KERN_SUCCESS)
1321*30fdc8d8SChris Lattner //          {
1322*30fdc8d8SChris Lattner //              unwindState->SetPC(pc);
1323*30fdc8d8SChris Lattner //              return 2;
1324*30fdc8d8SChris Lattner //          }
1325*30fdc8d8SChris Lattner //      }
1326*30fdc8d8SChris Lattner //#endif
1327*30fdc8d8SChris Lattner //      FDE *fde = FindFDE(unwindPC);
1328*30fdc8d8SChris Lattner //      if (fde)
1329*30fdc8d8SChris Lattner //      {
1330*30fdc8d8SChris Lattner //          FindRowUserData rowUserData (currState, unwindPC);
1331*30fdc8d8SChris Lattner //          ParseInstructions (currState, fde, FindRowForAddress, &rowUserData);
1332*30fdc8d8SChris Lattner //
1333*30fdc8d8SChris Lattner //          const uint32_t numRegs = currState->NumRegisters();
1334*30fdc8d8SChris Lattner //          for (uint32_t regNum = 0; regNum < numRegs; regNum++)
1335*30fdc8d8SChris Lattner //          {
1336*30fdc8d8SChris Lattner //              if (UnwindRegisterAtIndex(regNum, currState, &rowUserData.state, memCache, unwindState))
1337*30fdc8d8SChris Lattner //                  numRegisterUnwound++;
1338*30fdc8d8SChris Lattner //          }
1339*30fdc8d8SChris Lattner //      }
1340*30fdc8d8SChris Lattner //    }
1341*30fdc8d8SChris Lattner //    return numRegisterUnwound;
1342*30fdc8d8SChris Lattner //}
1343*30fdc8d8SChris Lattner 
1344*30fdc8d8SChris Lattner 
1345