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