1 //===--------------------------- DwarfParser.hpp --------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
9 // Parses DWARF CFIs (FDEs and CIEs).
11 //===----------------------------------------------------------------------===//
13 #ifndef __DWARF_PARSER_HPP__
14 #define __DWARF_PARSER_HPP__
20 #include "AddressSpace.hpp"
24 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
25 /// See Dwarf Spec for details:
26 /// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
28 template <typename A
, typename R
> class CFI_Parser
{
30 typedef typename
A::pint_t pint_t
;
32 /// Information encoded in a CIE (Common Information Entry)
36 pint_t cieInstructions
;
38 uint32_t codeAlignFactor
;
40 uint8_t pointerEncoding
;
42 uint8_t personalityEncoding
;
43 uint8_t personalityOffsetInCIE
;
45 bool fdesHaveAugmentationData
;
46 uint8_t returnAddressRegister
;
49 /// Information about an FDE (Frame Description Entry)
53 pint_t fdeInstructions
;
59 /// Information about a frame layout and registers saved determined
60 /// by "running" the DWARF FDE "instructions"
62 kMaxRegisterNumber
= R::LAST_REGISTER
+ 1
64 enum RegisterSavedWhere
{
67 kRegisterOffsetFromCFA
,
69 kRegisterAtExpression
,
70 kRegisterIsExpression
,
72 struct RegisterLocation
{
73 RegisterSavedWhere location
;
78 int32_t cfaRegisterOffset
; // CFA = (cfaRegister)+cfaRegisterOffset
79 int64_t cfaExpression
; // CFA = expression
80 uint32_t spExtraArgSize
;
81 uint32_t codeOffsetAtStackDecrement
;
82 RegisterLocation savedRegisters
[kMaxRegisterNumber
];
85 struct PrologInfoStackEntry
{
86 PrologInfoStackEntry(PrologInfoStackEntry
*n
, const PrologInfo
&i
)
88 PrologInfoStackEntry
*next
;
92 static void findPCRange(A
&, pint_t
, pint_t
&, pint_t
&);
94 static bool decodeFDE(A
&, pint_t
, FDE_Info
*, CIE_Info
*,
95 unw_proc_info_t
*ctx
);
96 static bool parseFDEInstructions(A
&, const FDE_Info
&, const CIE_Info
&,
97 pint_t
, PrologInfo
*, unw_proc_info_t
*ctx
);
99 static bool parseCIE(A
&, pint_t
, CIE_Info
*);
102 static bool parseInstructions(A
&, pint_t
, pint_t
, const CIE_Info
&, pint_t
,
103 PrologInfoStackEntry
*&, PrologInfo
*,
104 unw_proc_info_t
*ctx
);
108 /// Parse a FDE and return the last PC it covers.
110 template <typename A
, typename R
>
111 void CFI_Parser
<A
, R
>::findPCRange(A
&addressSpace
, pint_t fde
, pint_t
&pcStart
,
116 uint64_t cfiLength
= addressSpace
.get32(p
);
118 if (cfiLength
== 0xffffffff) {
119 // 0xffffffff means length is really the next 8 Bytes.
120 cfiLength
= addressSpace
.get64(p
);
125 uint32_t ciePointer
= addressSpace
.get32(p
);
128 pint_t nextCFI
= p
+ cfiLength
;
129 pint_t cieStart
= p
- ciePointer
;
130 typename CFI_Parser
<A
, R
>::CIE_Info cieInfo
;
131 if (!parseCIE(addressSpace
, cieStart
, &cieInfo
))
134 // Parse pc begin and range.
135 pcStart
= addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
.pointerEncoding
, NULL
);
136 pcEnd
= pcStart
+ addressSpace
.getEncodedP(
137 p
, nextCFI
, cieInfo
.pointerEncoding
& 0x0F, NULL
);
141 /// Parse a FDE into a CIE_Info and an FDE_Info
143 template <typename A
, typename R
>
144 bool CFI_Parser
<A
, R
>::decodeFDE(A
&addressSpace
, pint_t fdeStart
,
145 FDE_Info
*fdeInfo
, CIE_Info
*cieInfo
,
146 unw_proc_info_t
*ctx
) {
148 uint64_t cfiLength
= addressSpace
.get32(p
);
150 if (cfiLength
== 0xffffffff) {
151 // 0xffffffff means length is really the next 8 Bytes.
152 cfiLength
= addressSpace
.get64(p
);
157 uint32_t ciePointer
= addressSpace
.get32(p
);
160 pint_t nextCFI
= p
+ cfiLength
;
161 pint_t cieStart
= p
- ciePointer
;
162 if (!parseCIE(addressSpace
, cieStart
, cieInfo
))
165 // Parse pc begin and range.
167 addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->pointerEncoding
, ctx
);
168 pint_t pcRange
= addressSpace
.getEncodedP(
169 p
, nextCFI
, cieInfo
->pointerEncoding
& 0x0F, ctx
);
170 // Parse rest of info.
172 // Check for augmentation length
173 if (cieInfo
->fdesHaveAugmentationData
) {
174 uintptr_t augLen
= addressSpace
.getULEB128(p
, nextCFI
);
175 pint_t endOfAug
= p
+ augLen
;
176 if (cieInfo
->lsdaEncoding
!= DW_EH_PE_omit
) {
177 // Peek at value (without indirection). Zero means no LSDA.
178 pint_t lsdaStart
= p
;
179 if (addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->lsdaEncoding
& 0x0F,
181 // Reset pointer and re-parse LSDA address.
184 addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->lsdaEncoding
, ctx
);
189 fdeInfo
->fdeStart
= fdeStart
;
190 fdeInfo
->fdeLength
= nextCFI
- fdeStart
;
191 fdeInfo
->fdeInstructions
= p
;
192 fdeInfo
->pcStart
= pcStart
;
193 fdeInfo
->pcEnd
= pcStart
+ pcRange
;
197 /// Extract info from a CIE
198 template <typename A
, typename R
>
199 bool CFI_Parser
<A
, R
>::parseCIE(A
&addressSpace
, pint_t cie
,
201 cieInfo
->pointerEncoding
= 0;
202 cieInfo
->lsdaEncoding
= DW_EH_PE_omit
;
203 cieInfo
->personalityEncoding
= 0;
204 cieInfo
->personalityOffsetInCIE
= 0;
205 cieInfo
->personality
= 0;
206 cieInfo
->codeAlignFactor
= 0;
207 cieInfo
->dataAlignFactor
= 0;
208 cieInfo
->isSignalFrame
= false;
209 cieInfo
->fdesHaveAugmentationData
= false;
210 cieInfo
->cieStart
= cie
;
212 uint64_t cieLength
= addressSpace
.get32(p
);
214 pint_t cieContentEnd
= p
+ cieLength
;
215 if (cieLength
== 0xffffffff) {
216 // 0xffffffff means length is really the next 8 Bytes.
217 cieLength
= addressSpace
.get64(p
);
219 cieContentEnd
= p
+ cieLength
;
223 // CIE ID is always 0
224 if (addressSpace
.get32(p
) != 0)
227 // Version is always 1 or 3
228 uint8_t version
= addressSpace
.get8(p
);
229 if (version
!= 1 && version
!= 3)
232 // Save start of augmentation string and find end.
234 while (addressSpace
.get8(p
) != 0)
237 // Parse code aligment factor
238 cieInfo
->codeAlignFactor
= addressSpace
.getULEB128(p
, cieContentEnd
);
239 // Parse data alignment factor
240 cieInfo
->dataAlignFactor
= addressSpace
.getSLEB128(p
, cieContentEnd
);
241 // Parse return address register
242 cieInfo
->returnAddressRegister
= (uint8_t)addressSpace
.getULEB128(p
, cieContentEnd
);
243 // Parse augmentation data based on augmentation string.
244 if (addressSpace
.get8(strStart
) == 'z') {
245 // parse augmentation data length
246 addressSpace
.getULEB128(p
, cieContentEnd
);
247 for (pint_t s
= strStart
; addressSpace
.get8(s
) != '\0'; ++s
) {
248 switch (addressSpace
.get8(s
)) {
250 cieInfo
->fdesHaveAugmentationData
= true;
253 cieInfo
->personalityEncoding
= addressSpace
.get8(p
);
255 cieInfo
->personalityOffsetInCIE
= p
- cie
;
256 cieInfo
->personality
= addressSpace
.getEncodedP(
257 p
, cieContentEnd
, cieInfo
->personalityEncoding
, NULL
);
260 cieInfo
->lsdaEncoding
= addressSpace
.get8(p
);
264 cieInfo
->pointerEncoding
= addressSpace
.get8(p
);
268 cieInfo
->isSignalFrame
= true;
271 // ignore unknown letters
276 cieInfo
->cieLength
= cieContentEnd
- cieInfo
->cieStart
;
277 cieInfo
->cieInstructions
= p
;
281 /// "Run" the dwarf instructions and create the abstact PrologInfo for an FDE.
282 template <typename A
, typename R
>
283 bool CFI_Parser
<A
, R
>::parseFDEInstructions(A
&addressSpace
,
284 const FDE_Info
&fdeInfo
,
285 const CIE_Info
&cieInfo
,
286 pint_t upToPC
, PrologInfo
*results
,
287 unw_proc_info_t
*ctx
) {
289 memset(results
, 0, sizeof(*results
));
290 PrologInfoStackEntry
*rememberStack
= NULL
;
292 // First parse the CIE then FDE instructions.
293 if (!parseInstructions(addressSpace
, cieInfo
.cieInstructions
,
294 cieInfo
.cieStart
+ cieInfo
.cieLength
, cieInfo
,
295 (pint_t
)(-1), rememberStack
, results
, ctx
))
297 return parseInstructions(addressSpace
, fdeInfo
.fdeInstructions
,
298 fdeInfo
.fdeStart
+ fdeInfo
.fdeLength
, cieInfo
,
299 upToPC
- fdeInfo
.pcStart
, rememberStack
, results
,
303 /// "Run" the DWARF instructions.
304 template <typename A
, typename R
>
306 CFI_Parser
<A
, R
>::parseInstructions(A
&addressSpace
, pint_t instructions
,
307 pint_t instructionsEnd
,
308 const CIE_Info
&cieInfo
, pint_t pcoffset
,
309 PrologInfoStackEntry
*&rememberStack
,
310 PrologInfo
*results
, unw_proc_info_t
*ctx
) {
311 pint_t p
= instructions
;
312 uint32_t codeOffset
= 0;
313 PrologInfo initialState
= *results
;
315 // See Dwarf Spec, section 6.4.2 for details on unwind opcodes.
316 while (p
< instructionsEnd
&& codeOffset
< pcoffset
) {
321 uint8_t opcode
= addressSpace
.get8(p
);
323 PrologInfoStackEntry
*entry
;
329 codeOffset
= addressSpace
.getEncodedP(p
, instructionsEnd
,
330 cieInfo
.pointerEncoding
, ctx
);
332 case DW_CFA_advance_loc1
:
333 codeOffset
+= (addressSpace
.get8(p
) * cieInfo
.codeAlignFactor
);
336 case DW_CFA_advance_loc2
:
337 codeOffset
+= (addressSpace
.get16(p
) * cieInfo
.codeAlignFactor
);
340 case DW_CFA_advance_loc4
:
341 codeOffset
+= (addressSpace
.get32(p
) * cieInfo
.codeAlignFactor
);
344 case DW_CFA_offset_extended
:
345 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
347 addressSpace
.getULEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
;
348 if (reg
> kMaxRegisterNumber
)
350 results
->savedRegisters
[reg
].location
= kRegisterInCFA
;
351 results
->savedRegisters
[reg
].value
= offset
;
353 case DW_CFA_restore_extended
:
354 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
355 if (reg
> kMaxRegisterNumber
)
357 results
->savedRegisters
[reg
] = initialState
.savedRegisters
[reg
];
359 case DW_CFA_undefined
:
360 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
361 if (reg
> kMaxRegisterNumber
)
363 results
->savedRegisters
[reg
].location
= kRegisterUnused
;
365 case DW_CFA_same_value
:
366 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
367 if (reg
> kMaxRegisterNumber
)
369 // "same value" means register was stored in frame, but its current
370 // value has not changed, so no need to restore from frame.
371 // We model this as if the register was never saved.
372 results
->savedRegisters
[reg
].location
= kRegisterUnused
;
374 case DW_CFA_register
:
375 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
376 reg2
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
377 if (reg
> kMaxRegisterNumber
)
379 if (reg2
> kMaxRegisterNumber
)
381 results
->savedRegisters
[reg
].location
= kRegisterInRegister
;
382 results
->savedRegisters
[reg
].value
= reg2
;
384 case DW_CFA_remember_state
:
385 // avoid operator new, because that would be an upward dependency
386 entry
= (PrologInfoStackEntry
*)malloc(sizeof(PrologInfoStackEntry
));
390 entry
->next
= rememberStack
;
391 entry
->info
= *results
;
392 rememberStack
= entry
;
394 case DW_CFA_restore_state
:
395 if (rememberStack
== NULL
)
398 PrologInfoStackEntry
*top
= rememberStack
;
399 *results
= top
->info
;
400 rememberStack
= top
->next
;
405 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
406 offset
= addressSpace
.getULEB128(p
, instructionsEnd
);
407 if (reg
> kMaxRegisterNumber
)
409 results
->cfaRegister
= reg
;
410 results
->cfaRegisterOffset
= offset
;
412 case DW_CFA_def_cfa_register
:
413 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
414 if (reg
> kMaxRegisterNumber
)
416 results
->cfaRegister
= reg
;
418 case DW_CFA_def_cfa_offset
:
419 results
->cfaRegisterOffset
= addressSpace
.getULEB128(p
, instructionsEnd
);
420 results
->codeOffsetAtStackDecrement
= codeOffset
;
422 case DW_CFA_def_cfa_expression
:
423 results
->cfaRegister
= 0;
424 results
->cfaExpression
= p
;
425 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
428 case DW_CFA_expression
:
429 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
430 if (reg
> kMaxRegisterNumber
)
432 results
->savedRegisters
[reg
].location
= kRegisterAtExpression
;
433 results
->savedRegisters
[reg
].value
= p
;
434 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
437 case DW_CFA_offset_extended_sf
:
438 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
439 if (reg
> kMaxRegisterNumber
)
442 addressSpace
.getSLEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
;
443 results
->savedRegisters
[reg
].location
= kRegisterInCFA
;
444 results
->savedRegisters
[reg
].value
= offset
;
446 case DW_CFA_def_cfa_sf
:
447 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
449 addressSpace
.getSLEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
;
450 if (reg
> kMaxRegisterNumber
)
452 results
->cfaRegister
= reg
;
453 results
->cfaRegisterOffset
= offset
;
455 case DW_CFA_def_cfa_offset_sf
:
456 results
->cfaRegisterOffset
=
457 addressSpace
.getSLEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
;
458 results
->codeOffsetAtStackDecrement
= codeOffset
;
460 case DW_CFA_val_offset
:
461 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
463 addressSpace
.getULEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
;
464 if (reg
> kMaxRegisterNumber
)
466 results
->savedRegisters
[reg
].location
= kRegisterOffsetFromCFA
;
467 results
->savedRegisters
[reg
].value
= offset
;
469 case DW_CFA_val_offset_sf
:
470 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
471 if (reg
> kMaxRegisterNumber
)
474 addressSpace
.getSLEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
;
475 results
->savedRegisters
[reg
].location
= kRegisterOffsetFromCFA
;
476 results
->savedRegisters
[reg
].value
= offset
;
478 case DW_CFA_val_expression
:
479 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
480 if (reg
> kMaxRegisterNumber
)
482 results
->savedRegisters
[reg
].location
= kRegisterIsExpression
;
483 results
->savedRegisters
[reg
].value
= p
;
484 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
487 case DW_CFA_GNU_window_save
:
488 #if defined(__sparc__)
489 for (reg
= 8; reg
< 16; ++reg
) {
490 results
->savedRegisters
[reg
].location
= kRegisterInRegister
;
491 results
->savedRegisters
[reg
].value
= reg
+ 16;
493 for (reg
= 16; reg
< 32; ++reg
) {
494 results
->savedRegisters
[reg
].location
= kRegisterInCFA
;
495 results
->savedRegisters
[reg
].value
= (reg
- 16) * sizeof(typename
R::reg_t
);
501 case DW_CFA_GNU_args_size
:
502 offset
= addressSpace
.getULEB128(p
, instructionsEnd
);
503 results
->spExtraArgSize
= offset
;
505 case DW_CFA_GNU_negative_offset_extended
:
506 reg
= R::dwarf2regno(addressSpace
.getULEB128(p
, instructionsEnd
));
507 if (reg
> kMaxRegisterNumber
)
510 addressSpace
.getULEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
;
511 results
->savedRegisters
[reg
].location
= kRegisterInCFA
;
512 results
->savedRegisters
[reg
].value
= -offset
;
515 operand
= opcode
& 0x3F;
516 switch (opcode
& 0xC0) {
518 reg
= R::dwarf2regno(operand
);
519 if (reg
> kMaxRegisterNumber
)
521 offset
= addressSpace
.getULEB128(p
, instructionsEnd
) *
522 cieInfo
.dataAlignFactor
;
523 results
->savedRegisters
[reg
].location
= kRegisterInCFA
;
524 results
->savedRegisters
[reg
].value
= offset
;
526 case DW_CFA_advance_loc
:
527 codeOffset
+= operand
* cieInfo
.codeAlignFactor
;
530 reg
= R::dwarf2regno(operand
);
531 if (reg
> kMaxRegisterNumber
)
533 results
->savedRegisters
[reg
] = initialState
.savedRegisters
[reg
];
544 } // namespace _Unwind
546 #endif // __DWARF_PARSER_HPP__