xref: /netbsd/sys/lib/libunwind/DwarfParser.hpp (revision d9a2620c)
1aa0b96d0Sjoerg //===--------------------------- DwarfParser.hpp --------------------------===//
2aa0b96d0Sjoerg //
3aa0b96d0Sjoerg //                     The LLVM Compiler Infrastructure
4aa0b96d0Sjoerg //
5aa0b96d0Sjoerg // This file is dual licensed under the MIT and the University of Illinois Open
6aa0b96d0Sjoerg // Source Licenses. See LICENSE.TXT for details.
7aa0b96d0Sjoerg //
8aa0b96d0Sjoerg //
9aa0b96d0Sjoerg //  Parses DWARF CFIs (FDEs and CIEs).
10aa0b96d0Sjoerg //
11aa0b96d0Sjoerg //===----------------------------------------------------------------------===//
12aa0b96d0Sjoerg 
13aa0b96d0Sjoerg #ifndef __DWARF_PARSER_HPP__
14aa0b96d0Sjoerg #define __DWARF_PARSER_HPP__
15aa0b96d0Sjoerg 
16aa0b96d0Sjoerg #include <cstdint>
17aa0b96d0Sjoerg #include <cstdlib>
18aa0b96d0Sjoerg 
19aa0b96d0Sjoerg #include "dwarf2.h"
20aa0b96d0Sjoerg #include "AddressSpace.hpp"
21aa0b96d0Sjoerg 
22aa0b96d0Sjoerg namespace _Unwind {
23aa0b96d0Sjoerg 
24aa0b96d0Sjoerg /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
25aa0b96d0Sjoerg /// See Dwarf Spec for details:
26aa0b96d0Sjoerg ///    http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
27aa0b96d0Sjoerg ///
28aa0b96d0Sjoerg template <typename A, typename R> class CFI_Parser {
29aa0b96d0Sjoerg public:
30aa0b96d0Sjoerg   typedef typename A::pint_t pint_t;
31aa0b96d0Sjoerg 
32aa0b96d0Sjoerg   /// Information encoded in a CIE (Common Information Entry)
33aa0b96d0Sjoerg   struct CIE_Info {
34aa0b96d0Sjoerg     pint_t cieStart;
35aa0b96d0Sjoerg     pint_t cieLength;
36aa0b96d0Sjoerg     pint_t cieInstructions;
37aa0b96d0Sjoerg     pint_t personality;
38aa0b96d0Sjoerg     uint32_t codeAlignFactor;
39aa0b96d0Sjoerg     int dataAlignFactor;
40aa0b96d0Sjoerg     uint8_t pointerEncoding;
41aa0b96d0Sjoerg     uint8_t lsdaEncoding;
42aa0b96d0Sjoerg     uint8_t personalityEncoding;
43aa0b96d0Sjoerg     uint8_t personalityOffsetInCIE;
44aa0b96d0Sjoerg     bool isSignalFrame;
45aa0b96d0Sjoerg     bool fdesHaveAugmentationData;
46215abdb1Sjoerg     uint8_t returnAddressRegister;
47aa0b96d0Sjoerg   };
48aa0b96d0Sjoerg 
49aa0b96d0Sjoerg   /// Information about an FDE (Frame Description Entry)
50aa0b96d0Sjoerg   struct FDE_Info {
51aa0b96d0Sjoerg     pint_t fdeStart;
52aa0b96d0Sjoerg     pint_t fdeLength;
53aa0b96d0Sjoerg     pint_t fdeInstructions;
54aa0b96d0Sjoerg     pint_t pcStart;
55aa0b96d0Sjoerg     pint_t pcEnd;
56aa0b96d0Sjoerg     pint_t lsda;
57aa0b96d0Sjoerg   };
58aa0b96d0Sjoerg 
59aa0b96d0Sjoerg   /// Information about a frame layout and registers saved determined
60aa0b96d0Sjoerg   /// by "running" the DWARF FDE "instructions"
61aa0b96d0Sjoerg   enum {
62aa0b96d0Sjoerg     kMaxRegisterNumber = R::LAST_REGISTER + 1
63aa0b96d0Sjoerg   };
64aa0b96d0Sjoerg   enum RegisterSavedWhere {
65aa0b96d0Sjoerg     kRegisterUnused,
66aa0b96d0Sjoerg     kRegisterInCFA,
67aa0b96d0Sjoerg     kRegisterOffsetFromCFA,
68aa0b96d0Sjoerg     kRegisterInRegister,
69aa0b96d0Sjoerg     kRegisterAtExpression,
70aa0b96d0Sjoerg     kRegisterIsExpression,
71aa0b96d0Sjoerg   };
72aa0b96d0Sjoerg   struct RegisterLocation {
73aa0b96d0Sjoerg     RegisterSavedWhere location;
74aa0b96d0Sjoerg     int64_t value;
75aa0b96d0Sjoerg   };
76aa0b96d0Sjoerg   struct PrologInfo {
77aa0b96d0Sjoerg     uint32_t cfaRegister;
78aa0b96d0Sjoerg     int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
79aa0b96d0Sjoerg     int64_t cfaExpression;     // CFA = expression
80aa0b96d0Sjoerg     uint32_t spExtraArgSize;
81aa0b96d0Sjoerg     uint32_t codeOffsetAtStackDecrement;
82aa0b96d0Sjoerg     RegisterLocation savedRegisters[kMaxRegisterNumber];
83aa0b96d0Sjoerg   };
84aa0b96d0Sjoerg 
85aa0b96d0Sjoerg   struct PrologInfoStackEntry {
PrologInfoStackEntry_Unwind::CFI_Parser::PrologInfoStackEntry86aa0b96d0Sjoerg     PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
87aa0b96d0Sjoerg         : next(n), info(i) {}
88aa0b96d0Sjoerg     PrologInfoStackEntry *next;
89aa0b96d0Sjoerg     PrologInfo info;
90aa0b96d0Sjoerg   };
91aa0b96d0Sjoerg 
92aa0b96d0Sjoerg   static void findPCRange(A &, pint_t, pint_t &, pint_t &);
93aa0b96d0Sjoerg 
94aa0b96d0Sjoerg   static bool decodeFDE(A &, pint_t, FDE_Info *, CIE_Info *,
95aa0b96d0Sjoerg                         unw_proc_info_t *ctx);
96aa0b96d0Sjoerg   static bool parseFDEInstructions(A &, const FDE_Info &, const CIE_Info &,
97aa0b96d0Sjoerg                                    pint_t, PrologInfo *, unw_proc_info_t *ctx);
98aa0b96d0Sjoerg 
99aa0b96d0Sjoerg   static bool parseCIE(A &, pint_t, CIE_Info *);
100aa0b96d0Sjoerg 
101aa0b96d0Sjoerg private:
102aa0b96d0Sjoerg   static bool parseInstructions(A &, pint_t, pint_t, const CIE_Info &, pint_t,
103aa0b96d0Sjoerg                                 PrologInfoStackEntry *&, PrologInfo *,
104aa0b96d0Sjoerg                                 unw_proc_info_t *ctx);
105aa0b96d0Sjoerg };
106aa0b96d0Sjoerg 
107aa0b96d0Sjoerg ///
108aa0b96d0Sjoerg /// Parse a FDE and return the last PC it covers.
109aa0b96d0Sjoerg ///
110aa0b96d0Sjoerg template <typename A, typename R>
findPCRange(A & addressSpace,pint_t fde,pint_t & pcStart,pint_t & pcEnd)111aa0b96d0Sjoerg void CFI_Parser<A, R>::findPCRange(A &addressSpace, pint_t fde, pint_t &pcStart,
112aa0b96d0Sjoerg                                    pint_t &pcEnd) {
113aa0b96d0Sjoerg   pcStart = 0;
114aa0b96d0Sjoerg   pcEnd = 0;
115aa0b96d0Sjoerg   pint_t p = fde;
116aa0b96d0Sjoerg   uint64_t cfiLength = addressSpace.get32(p);
117aa0b96d0Sjoerg   p += 4;
118aa0b96d0Sjoerg   if (cfiLength == 0xffffffff) {
119aa0b96d0Sjoerg     // 0xffffffff means length is really the next 8 Bytes.
120aa0b96d0Sjoerg     cfiLength = addressSpace.get64(p);
121aa0b96d0Sjoerg     p += 8;
122aa0b96d0Sjoerg   }
123aa0b96d0Sjoerg   if (cfiLength == 0)
124aa0b96d0Sjoerg     return;
125aa0b96d0Sjoerg   uint32_t ciePointer = addressSpace.get32(p);
126aa0b96d0Sjoerg   if (ciePointer == 0)
127aa0b96d0Sjoerg     return;
128aa0b96d0Sjoerg   pint_t nextCFI = p + cfiLength;
129aa0b96d0Sjoerg   pint_t cieStart = p - ciePointer;
130aa0b96d0Sjoerg   typename CFI_Parser<A, R>::CIE_Info cieInfo;
131aa0b96d0Sjoerg   if (!parseCIE(addressSpace, cieStart, &cieInfo))
132aa0b96d0Sjoerg     return;
133aa0b96d0Sjoerg   p += 4;
134aa0b96d0Sjoerg   // Parse pc begin and range.
135aa0b96d0Sjoerg   pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding, NULL);
136aa0b96d0Sjoerg   pcEnd = pcStart + addressSpace.getEncodedP(
137aa0b96d0Sjoerg                         p, nextCFI, cieInfo.pointerEncoding & 0x0F, NULL);
138aa0b96d0Sjoerg }
139aa0b96d0Sjoerg 
140aa0b96d0Sjoerg ///
141aa0b96d0Sjoerg /// Parse a FDE into a CIE_Info and an FDE_Info
142aa0b96d0Sjoerg ///
143aa0b96d0Sjoerg template <typename A, typename R>
decodeFDE(A & addressSpace,pint_t fdeStart,FDE_Info * fdeInfo,CIE_Info * cieInfo,unw_proc_info_t * ctx)144aa0b96d0Sjoerg bool CFI_Parser<A, R>::decodeFDE(A &addressSpace, pint_t fdeStart,
145aa0b96d0Sjoerg                                  FDE_Info *fdeInfo, CIE_Info *cieInfo,
146aa0b96d0Sjoerg                                  unw_proc_info_t *ctx) {
147aa0b96d0Sjoerg   pint_t p = fdeStart;
148aa0b96d0Sjoerg   uint64_t cfiLength = addressSpace.get32(p);
149aa0b96d0Sjoerg   p += 4;
150aa0b96d0Sjoerg   if (cfiLength == 0xffffffff) {
151aa0b96d0Sjoerg     // 0xffffffff means length is really the next 8 Bytes.
152aa0b96d0Sjoerg     cfiLength = addressSpace.get64(p);
153aa0b96d0Sjoerg     p += 8;
154aa0b96d0Sjoerg   }
155aa0b96d0Sjoerg   if (cfiLength == 0)
156aa0b96d0Sjoerg     return false;
157aa0b96d0Sjoerg   uint32_t ciePointer = addressSpace.get32(p);
158aa0b96d0Sjoerg   if (ciePointer == 0)
159aa0b96d0Sjoerg     return false;
160aa0b96d0Sjoerg   pint_t nextCFI = p + cfiLength;
161aa0b96d0Sjoerg   pint_t cieStart = p - ciePointer;
162aa0b96d0Sjoerg   if (!parseCIE(addressSpace, cieStart, cieInfo))
163aa0b96d0Sjoerg     return false;
164aa0b96d0Sjoerg   p += 4;
165aa0b96d0Sjoerg   // Parse pc begin and range.
166aa0b96d0Sjoerg   pint_t pcStart =
167aa0b96d0Sjoerg       addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding, ctx);
168aa0b96d0Sjoerg   pint_t pcRange = addressSpace.getEncodedP(
169aa0b96d0Sjoerg       p, nextCFI, cieInfo->pointerEncoding & 0x0F, ctx);
170aa0b96d0Sjoerg   // Parse rest of info.
171aa0b96d0Sjoerg   fdeInfo->lsda = 0;
172aa0b96d0Sjoerg   // Check for augmentation length
173aa0b96d0Sjoerg   if (cieInfo->fdesHaveAugmentationData) {
174aa0b96d0Sjoerg     uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
175aa0b96d0Sjoerg     pint_t endOfAug = p + augLen;
17656494fb5Sjoerg     if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
177aa0b96d0Sjoerg       // Peek at value (without indirection).  Zero means no LSDA.
178aa0b96d0Sjoerg       pint_t lsdaStart = p;
179aa0b96d0Sjoerg       if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F,
180aa0b96d0Sjoerg                                    ctx) != 0) {
181aa0b96d0Sjoerg         // Reset pointer and re-parse LSDA address.
182aa0b96d0Sjoerg         p = lsdaStart;
183aa0b96d0Sjoerg         fdeInfo->lsda =
184aa0b96d0Sjoerg             addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding, ctx);
185aa0b96d0Sjoerg       }
186aa0b96d0Sjoerg     }
187aa0b96d0Sjoerg     p = endOfAug;
188aa0b96d0Sjoerg   }
189aa0b96d0Sjoerg   fdeInfo->fdeStart = fdeStart;
190aa0b96d0Sjoerg   fdeInfo->fdeLength = nextCFI - fdeStart;
191aa0b96d0Sjoerg   fdeInfo->fdeInstructions = p;
192aa0b96d0Sjoerg   fdeInfo->pcStart = pcStart;
193aa0b96d0Sjoerg   fdeInfo->pcEnd = pcStart + pcRange;
194aa0b96d0Sjoerg   return true;
195aa0b96d0Sjoerg }
196aa0b96d0Sjoerg 
197aa0b96d0Sjoerg /// Extract info from a CIE
198aa0b96d0Sjoerg template <typename A, typename R>
parseCIE(A & addressSpace,pint_t cie,CIE_Info * cieInfo)199aa0b96d0Sjoerg bool CFI_Parser<A, R>::parseCIE(A &addressSpace, pint_t cie,
200aa0b96d0Sjoerg                                 CIE_Info *cieInfo) {
201aa0b96d0Sjoerg   cieInfo->pointerEncoding = 0;
20256494fb5Sjoerg   cieInfo->lsdaEncoding = DW_EH_PE_omit;
203aa0b96d0Sjoerg   cieInfo->personalityEncoding = 0;
204aa0b96d0Sjoerg   cieInfo->personalityOffsetInCIE = 0;
205aa0b96d0Sjoerg   cieInfo->personality = 0;
206aa0b96d0Sjoerg   cieInfo->codeAlignFactor = 0;
207aa0b96d0Sjoerg   cieInfo->dataAlignFactor = 0;
208aa0b96d0Sjoerg   cieInfo->isSignalFrame = false;
209aa0b96d0Sjoerg   cieInfo->fdesHaveAugmentationData = false;
210aa0b96d0Sjoerg   cieInfo->cieStart = cie;
211aa0b96d0Sjoerg   pint_t p = cie;
212aa0b96d0Sjoerg   uint64_t cieLength = addressSpace.get32(p);
213aa0b96d0Sjoerg   p += 4;
214aa0b96d0Sjoerg   pint_t cieContentEnd = p + cieLength;
215aa0b96d0Sjoerg   if (cieLength == 0xffffffff) {
216aa0b96d0Sjoerg     // 0xffffffff means length is really the next 8 Bytes.
217aa0b96d0Sjoerg     cieLength = addressSpace.get64(p);
218aa0b96d0Sjoerg     p += 8;
219aa0b96d0Sjoerg     cieContentEnd = p + cieLength;
220aa0b96d0Sjoerg   }
221aa0b96d0Sjoerg   if (cieLength == 0)
222aa0b96d0Sjoerg     return true;
223aa0b96d0Sjoerg   // CIE ID is always 0
224aa0b96d0Sjoerg   if (addressSpace.get32(p) != 0)
225aa0b96d0Sjoerg     return false;
226aa0b96d0Sjoerg   p += 4;
227aa0b96d0Sjoerg   // Version is always 1 or 3
228aa0b96d0Sjoerg   uint8_t version = addressSpace.get8(p);
229aa0b96d0Sjoerg   if (version != 1 && version != 3)
230aa0b96d0Sjoerg     return false;
231aa0b96d0Sjoerg   ++p;
232aa0b96d0Sjoerg   // Save start of augmentation string and find end.
233aa0b96d0Sjoerg   pint_t strStart = p;
234aa0b96d0Sjoerg   while (addressSpace.get8(p) != 0)
235aa0b96d0Sjoerg     ++p;
236aa0b96d0Sjoerg   ++p;
237*d9a2620cSandvar   // Parse code alignment factor
238aa0b96d0Sjoerg   cieInfo->codeAlignFactor = addressSpace.getULEB128(p, cieContentEnd);
239aa0b96d0Sjoerg   // Parse data alignment factor
240aa0b96d0Sjoerg   cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd);
241aa0b96d0Sjoerg   // Parse return address register
2421fbf1330Sjoerg   cieInfo->returnAddressRegister = R::dwarf2regno((uint8_t)addressSpace.getULEB128(p, cieContentEnd));
243aa0b96d0Sjoerg   // Parse augmentation data based on augmentation string.
244aa0b96d0Sjoerg   if (addressSpace.get8(strStart) == 'z') {
245aa0b96d0Sjoerg     // parse augmentation data length
246aa0b96d0Sjoerg     addressSpace.getULEB128(p, cieContentEnd);
247aa0b96d0Sjoerg     for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
248aa0b96d0Sjoerg       switch (addressSpace.get8(s)) {
249aa0b96d0Sjoerg       case 'z':
250aa0b96d0Sjoerg         cieInfo->fdesHaveAugmentationData = true;
251aa0b96d0Sjoerg         break;
252aa0b96d0Sjoerg       case 'P':
253aa0b96d0Sjoerg         cieInfo->personalityEncoding = addressSpace.get8(p);
254aa0b96d0Sjoerg         ++p;
255aa0b96d0Sjoerg         cieInfo->personalityOffsetInCIE = p - cie;
256aa0b96d0Sjoerg         cieInfo->personality = addressSpace.getEncodedP(
257aa0b96d0Sjoerg             p, cieContentEnd, cieInfo->personalityEncoding, NULL);
258aa0b96d0Sjoerg         break;
259aa0b96d0Sjoerg       case 'L':
260aa0b96d0Sjoerg         cieInfo->lsdaEncoding = addressSpace.get8(p);
261aa0b96d0Sjoerg         ++p;
262aa0b96d0Sjoerg         break;
263aa0b96d0Sjoerg       case 'R':
264aa0b96d0Sjoerg         cieInfo->pointerEncoding = addressSpace.get8(p);
265aa0b96d0Sjoerg         ++p;
266aa0b96d0Sjoerg         break;
267aa0b96d0Sjoerg       case 'S':
268aa0b96d0Sjoerg         cieInfo->isSignalFrame = true;
269aa0b96d0Sjoerg         break;
270aa0b96d0Sjoerg       default:
271aa0b96d0Sjoerg         // ignore unknown letters
272aa0b96d0Sjoerg         break;
273aa0b96d0Sjoerg       }
274aa0b96d0Sjoerg     }
275aa0b96d0Sjoerg   }
276aa0b96d0Sjoerg   cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
277aa0b96d0Sjoerg   cieInfo->cieInstructions = p;
278aa0b96d0Sjoerg   return true;
279aa0b96d0Sjoerg }
280aa0b96d0Sjoerg 
281aa0b96d0Sjoerg /// "Run" the dwarf instructions and create the abstact PrologInfo for an FDE.
282aa0b96d0Sjoerg template <typename A, typename R>
parseFDEInstructions(A & addressSpace,const FDE_Info & fdeInfo,const CIE_Info & cieInfo,pint_t upToPC,PrologInfo * results,unw_proc_info_t * ctx)283aa0b96d0Sjoerg bool CFI_Parser<A, R>::parseFDEInstructions(A &addressSpace,
284aa0b96d0Sjoerg                                             const FDE_Info &fdeInfo,
285aa0b96d0Sjoerg                                             const CIE_Info &cieInfo,
286aa0b96d0Sjoerg                                             pint_t upToPC, PrologInfo *results,
287aa0b96d0Sjoerg                                             unw_proc_info_t *ctx) {
288aa0b96d0Sjoerg   // Clear results.
289aa0b96d0Sjoerg   memset(results, 0, sizeof(*results));
290aa0b96d0Sjoerg   PrologInfoStackEntry *rememberStack = NULL;
291aa0b96d0Sjoerg 
292aa0b96d0Sjoerg   // First parse the CIE then FDE instructions.
293aa0b96d0Sjoerg   if (!parseInstructions(addressSpace, cieInfo.cieInstructions,
294aa0b96d0Sjoerg                          cieInfo.cieStart + cieInfo.cieLength, cieInfo,
295aa0b96d0Sjoerg                          (pint_t)(-1), rememberStack, results, ctx))
296aa0b96d0Sjoerg     return false;
297aa0b96d0Sjoerg   return parseInstructions(addressSpace, fdeInfo.fdeInstructions,
298aa0b96d0Sjoerg                            fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
299aa0b96d0Sjoerg                            upToPC - fdeInfo.pcStart, rememberStack, results,
300aa0b96d0Sjoerg                            ctx);
301aa0b96d0Sjoerg }
302aa0b96d0Sjoerg 
303aa0b96d0Sjoerg /// "Run" the DWARF instructions.
304aa0b96d0Sjoerg template <typename A, typename R>
305aa0b96d0Sjoerg bool
parseInstructions(A & addressSpace,pint_t instructions,pint_t instructionsEnd,const CIE_Info & cieInfo,pint_t pcoffset,PrologInfoStackEntry * & rememberStack,PrologInfo * results,unw_proc_info_t * ctx)306aa0b96d0Sjoerg CFI_Parser<A, R>::parseInstructions(A &addressSpace, pint_t instructions,
307aa0b96d0Sjoerg                                     pint_t instructionsEnd,
308aa0b96d0Sjoerg                                     const CIE_Info &cieInfo, pint_t pcoffset,
309aa0b96d0Sjoerg                                     PrologInfoStackEntry *&rememberStack,
310aa0b96d0Sjoerg                                     PrologInfo *results, unw_proc_info_t *ctx) {
311aa0b96d0Sjoerg   pint_t p = instructions;
312aa0b96d0Sjoerg   uint32_t codeOffset = 0;
313aa0b96d0Sjoerg   PrologInfo initialState = *results;
314aa0b96d0Sjoerg 
315aa0b96d0Sjoerg   // See Dwarf Spec, section 6.4.2 for details on unwind opcodes.
316aa0b96d0Sjoerg   while (p < instructionsEnd && codeOffset < pcoffset) {
317aa0b96d0Sjoerg     uint64_t reg;
318aa0b96d0Sjoerg     uint64_t reg2;
319aa0b96d0Sjoerg     int64_t offset;
320aa0b96d0Sjoerg     uint64_t length;
321aa0b96d0Sjoerg     uint8_t opcode = addressSpace.get8(p);
322aa0b96d0Sjoerg     uint8_t operand;
323aa0b96d0Sjoerg     PrologInfoStackEntry *entry;
324aa0b96d0Sjoerg     ++p;
325aa0b96d0Sjoerg     switch (opcode) {
326aa0b96d0Sjoerg     case DW_CFA_nop:
327aa0b96d0Sjoerg       break;
328aa0b96d0Sjoerg     case DW_CFA_set_loc:
329aa0b96d0Sjoerg       codeOffset = addressSpace.getEncodedP(p, instructionsEnd,
330aa0b96d0Sjoerg                                             cieInfo.pointerEncoding, ctx);
331aa0b96d0Sjoerg       break;
332aa0b96d0Sjoerg     case DW_CFA_advance_loc1:
333aa0b96d0Sjoerg       codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
334aa0b96d0Sjoerg       p += 1;
335aa0b96d0Sjoerg       break;
336aa0b96d0Sjoerg     case DW_CFA_advance_loc2:
337aa0b96d0Sjoerg       codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
338aa0b96d0Sjoerg       p += 2;
339aa0b96d0Sjoerg       break;
340aa0b96d0Sjoerg     case DW_CFA_advance_loc4:
341aa0b96d0Sjoerg       codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
342aa0b96d0Sjoerg       p += 4;
343aa0b96d0Sjoerg       break;
344aa0b96d0Sjoerg     case DW_CFA_offset_extended:
345aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
346aa0b96d0Sjoerg       offset =
347aa0b96d0Sjoerg           addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
348aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
349aa0b96d0Sjoerg         return false;
350aa0b96d0Sjoerg       results->savedRegisters[reg].location = kRegisterInCFA;
351aa0b96d0Sjoerg       results->savedRegisters[reg].value = offset;
352aa0b96d0Sjoerg       break;
353aa0b96d0Sjoerg     case DW_CFA_restore_extended:
354aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
355aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
356aa0b96d0Sjoerg         return false;
357aa0b96d0Sjoerg       results->savedRegisters[reg] = initialState.savedRegisters[reg];
358aa0b96d0Sjoerg       break;
359aa0b96d0Sjoerg     case DW_CFA_undefined:
360aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
361aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
362aa0b96d0Sjoerg         return false;
363aa0b96d0Sjoerg       results->savedRegisters[reg].location = kRegisterUnused;
364aa0b96d0Sjoerg       break;
365aa0b96d0Sjoerg     case DW_CFA_same_value:
366aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
367aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
368aa0b96d0Sjoerg         return false;
369aa0b96d0Sjoerg       // "same value" means register was stored in frame, but its current
370aa0b96d0Sjoerg       // value has not changed, so no need to restore from frame.
371aa0b96d0Sjoerg       // We model this as if the register was never saved.
372aa0b96d0Sjoerg       results->savedRegisters[reg].location = kRegisterUnused;
373aa0b96d0Sjoerg       break;
374aa0b96d0Sjoerg     case DW_CFA_register:
375aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
376aa0b96d0Sjoerg       reg2 = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
377aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
378aa0b96d0Sjoerg         return false;
379aa0b96d0Sjoerg       if (reg2 > kMaxRegisterNumber)
380aa0b96d0Sjoerg         return false;
381aa0b96d0Sjoerg       results->savedRegisters[reg].location = kRegisterInRegister;
382aa0b96d0Sjoerg       results->savedRegisters[reg].value = reg2;
383aa0b96d0Sjoerg       break;
384aa0b96d0Sjoerg     case DW_CFA_remember_state:
385aa0b96d0Sjoerg       // avoid operator new, because that would be an upward dependency
386aa0b96d0Sjoerg       entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
387aa0b96d0Sjoerg       if (entry == NULL)
388aa0b96d0Sjoerg         return false;
389aa0b96d0Sjoerg 
390aa0b96d0Sjoerg       entry->next = rememberStack;
391aa0b96d0Sjoerg       entry->info = *results;
392aa0b96d0Sjoerg       rememberStack = entry;
393aa0b96d0Sjoerg       break;
394aa0b96d0Sjoerg     case DW_CFA_restore_state:
395aa0b96d0Sjoerg       if (rememberStack == NULL)
396aa0b96d0Sjoerg         return false;
397aa0b96d0Sjoerg       {
398aa0b96d0Sjoerg         PrologInfoStackEntry *top = rememberStack;
399aa0b96d0Sjoerg         *results = top->info;
400aa0b96d0Sjoerg         rememberStack = top->next;
401aa0b96d0Sjoerg         free((char *)top);
402aa0b96d0Sjoerg       }
403aa0b96d0Sjoerg       break;
404aa0b96d0Sjoerg     case DW_CFA_def_cfa:
405aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
406aa0b96d0Sjoerg       offset = addressSpace.getULEB128(p, instructionsEnd);
407aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
408aa0b96d0Sjoerg         return false;
409aa0b96d0Sjoerg       results->cfaRegister = reg;
410aa0b96d0Sjoerg       results->cfaRegisterOffset = offset;
411aa0b96d0Sjoerg       break;
412aa0b96d0Sjoerg     case DW_CFA_def_cfa_register:
413aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
414aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
415aa0b96d0Sjoerg         return false;
416aa0b96d0Sjoerg       results->cfaRegister = reg;
417aa0b96d0Sjoerg       break;
418aa0b96d0Sjoerg     case DW_CFA_def_cfa_offset:
419aa0b96d0Sjoerg       results->cfaRegisterOffset = addressSpace.getULEB128(p, instructionsEnd);
420aa0b96d0Sjoerg       results->codeOffsetAtStackDecrement = codeOffset;
421aa0b96d0Sjoerg       break;
422aa0b96d0Sjoerg     case DW_CFA_def_cfa_expression:
423aa0b96d0Sjoerg       results->cfaRegister = 0;
424aa0b96d0Sjoerg       results->cfaExpression = p;
425aa0b96d0Sjoerg       length = addressSpace.getULEB128(p, instructionsEnd);
426aa0b96d0Sjoerg       p += length;
427aa0b96d0Sjoerg       break;
428aa0b96d0Sjoerg     case DW_CFA_expression:
429aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
430aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
431aa0b96d0Sjoerg         return false;
432aa0b96d0Sjoerg       results->savedRegisters[reg].location = kRegisterAtExpression;
433aa0b96d0Sjoerg       results->savedRegisters[reg].value = p;
434aa0b96d0Sjoerg       length = addressSpace.getULEB128(p, instructionsEnd);
435aa0b96d0Sjoerg       p += length;
436aa0b96d0Sjoerg       break;
437aa0b96d0Sjoerg     case DW_CFA_offset_extended_sf:
438aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
439aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
440aa0b96d0Sjoerg         return false;
441aa0b96d0Sjoerg       offset =
442aa0b96d0Sjoerg           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
443aa0b96d0Sjoerg       results->savedRegisters[reg].location = kRegisterInCFA;
444aa0b96d0Sjoerg       results->savedRegisters[reg].value = offset;
445aa0b96d0Sjoerg       break;
446aa0b96d0Sjoerg     case DW_CFA_def_cfa_sf:
447aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
448aa0b96d0Sjoerg       offset =
449aa0b96d0Sjoerg           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
450aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
451aa0b96d0Sjoerg         return false;
452aa0b96d0Sjoerg       results->cfaRegister = reg;
453aa0b96d0Sjoerg       results->cfaRegisterOffset = offset;
454aa0b96d0Sjoerg       break;
455aa0b96d0Sjoerg     case DW_CFA_def_cfa_offset_sf:
456aa0b96d0Sjoerg       results->cfaRegisterOffset =
457aa0b96d0Sjoerg           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
458aa0b96d0Sjoerg       results->codeOffsetAtStackDecrement = codeOffset;
459aa0b96d0Sjoerg       break;
460aa0b96d0Sjoerg     case DW_CFA_val_offset:
461aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
462aa0b96d0Sjoerg       offset =
463aa0b96d0Sjoerg           addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
46434c84a0dSjoerg       if (reg > kMaxRegisterNumber)
46534c84a0dSjoerg         return false;
466aa0b96d0Sjoerg       results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
467aa0b96d0Sjoerg       results->savedRegisters[reg].value = offset;
468aa0b96d0Sjoerg       break;
469aa0b96d0Sjoerg     case DW_CFA_val_offset_sf:
470aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
471aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
472aa0b96d0Sjoerg         return false;
473aa0b96d0Sjoerg       offset =
474aa0b96d0Sjoerg           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
475aa0b96d0Sjoerg       results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
476aa0b96d0Sjoerg       results->savedRegisters[reg].value = offset;
477aa0b96d0Sjoerg       break;
478aa0b96d0Sjoerg     case DW_CFA_val_expression:
479aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
480aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
481aa0b96d0Sjoerg         return false;
482aa0b96d0Sjoerg       results->savedRegisters[reg].location = kRegisterIsExpression;
483aa0b96d0Sjoerg       results->savedRegisters[reg].value = p;
484aa0b96d0Sjoerg       length = addressSpace.getULEB128(p, instructionsEnd);
485aa0b96d0Sjoerg       p += length;
486aa0b96d0Sjoerg       break;
487f5cf7457Sjoerg     case DW_CFA_GNU_window_save:
488f5cf7457Sjoerg #if defined(__sparc__)
489f5cf7457Sjoerg       for (reg = 8; reg < 16; ++reg) {
490f5cf7457Sjoerg         results->savedRegisters[reg].location = kRegisterInRegister;
491f5cf7457Sjoerg         results->savedRegisters[reg].value = reg + 16;
492f5cf7457Sjoerg       }
493f5cf7457Sjoerg       for (reg = 16; reg < 32; ++reg) {
494f5cf7457Sjoerg         results->savedRegisters[reg].location = kRegisterInCFA;
495f5cf7457Sjoerg         results->savedRegisters[reg].value = (reg - 16) * sizeof(typename R::reg_t);
496f5cf7457Sjoerg       }
497f5cf7457Sjoerg       break;
498f5cf7457Sjoerg #else
499f5cf7457Sjoerg       return false;
500f5cf7457Sjoerg #endif
501aa0b96d0Sjoerg     case DW_CFA_GNU_args_size:
502aa0b96d0Sjoerg       offset = addressSpace.getULEB128(p, instructionsEnd);
503aa0b96d0Sjoerg       results->spExtraArgSize = offset;
504aa0b96d0Sjoerg       break;
505aa0b96d0Sjoerg     case DW_CFA_GNU_negative_offset_extended:
506aa0b96d0Sjoerg       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
507aa0b96d0Sjoerg       if (reg > kMaxRegisterNumber)
508aa0b96d0Sjoerg         return false;
509aa0b96d0Sjoerg       offset =
510aa0b96d0Sjoerg           addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
511aa0b96d0Sjoerg       results->savedRegisters[reg].location = kRegisterInCFA;
512aa0b96d0Sjoerg       results->savedRegisters[reg].value = -offset;
513aa0b96d0Sjoerg       break;
514aa0b96d0Sjoerg     default:
515aa0b96d0Sjoerg       operand = opcode & 0x3F;
516aa0b96d0Sjoerg       switch (opcode & 0xC0) {
517aa0b96d0Sjoerg       case DW_CFA_offset:
518aa0b96d0Sjoerg         reg = R::dwarf2regno(operand);
519aa0b96d0Sjoerg         if (reg > kMaxRegisterNumber)
520aa0b96d0Sjoerg           return false;
521aa0b96d0Sjoerg         offset = addressSpace.getULEB128(p, instructionsEnd) *
522aa0b96d0Sjoerg                  cieInfo.dataAlignFactor;
523aa0b96d0Sjoerg         results->savedRegisters[reg].location = kRegisterInCFA;
524aa0b96d0Sjoerg         results->savedRegisters[reg].value = offset;
525aa0b96d0Sjoerg         break;
526aa0b96d0Sjoerg       case DW_CFA_advance_loc:
527aa0b96d0Sjoerg         codeOffset += operand * cieInfo.codeAlignFactor;
528aa0b96d0Sjoerg         break;
529aa0b96d0Sjoerg       case DW_CFA_restore:
530aa0b96d0Sjoerg         reg = R::dwarf2regno(operand);
531aa0b96d0Sjoerg         if (reg > kMaxRegisterNumber)
532aa0b96d0Sjoerg           return false;
533aa0b96d0Sjoerg         results->savedRegisters[reg] = initialState.savedRegisters[reg];
534aa0b96d0Sjoerg         break;
535aa0b96d0Sjoerg       default:
536aa0b96d0Sjoerg         return false;
537aa0b96d0Sjoerg       }
538aa0b96d0Sjoerg     }
539aa0b96d0Sjoerg   }
540aa0b96d0Sjoerg 
541aa0b96d0Sjoerg   return true;
542aa0b96d0Sjoerg }
543aa0b96d0Sjoerg 
544aa0b96d0Sjoerg } // namespace _Unwind
545aa0b96d0Sjoerg 
546aa0b96d0Sjoerg #endif // __DWARF_PARSER_HPP__
547