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__
22 #include "libunwind.h"
25 #include "AddressSpace.hpp"
29 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
30 /// See Dwarf Spec for details:
31 /// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
36 typedef typename A::pint_t pint_t;
38 /// Information encoded in a CIE (Common Information Entry)
42 pint_t cieInstructions;
43 uint8_t pointerEncoding;
45 uint8_t personalityEncoding;
46 uint8_t personalityOffsetInCIE;
48 uint32_t codeAlignFactor;
51 bool fdesHaveAugmentationData;
52 uint8_t returnAddressRegister;
55 /// Information about an FDE (Frame Description Entry)
59 pint_t fdeInstructions;
66 kMaxRegisterNumber = 120
68 enum RegisterSavedWhere {
71 kRegisterOffsetFromCFA,
73 kRegisterAtExpression,
76 struct RegisterLocation {
77 RegisterSavedWhere location;
80 /// Information about a frame layout and registers saved determined
81 /// by "running" the dwarf FDE "instructions"
84 int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
85 int64_t cfaExpression; // CFA = expression
86 uint32_t spExtraArgSize;
87 uint32_t codeOffsetAtStackDecrement;
88 bool registersInOtherRegisters;
90 RegisterLocation savedRegisters[kMaxRegisterNumber];
93 struct PrologInfoStackEntry {
94 PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
96 PrologInfoStackEntry *next;
100 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
101 uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
103 static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
104 FDE_Info *fdeInfo, CIE_Info *cieInfo);
105 static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
106 const CIE_Info &cieInfo, pint_t upToPC,
107 PrologInfo *results);
109 static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
112 static bool parseInstructions(A &addressSpace, pint_t instructions,
113 pint_t instructionsEnd, const CIE_Info &cieInfo,
115 PrologInfoStackEntry *&rememberStack,
116 PrologInfo *results);
119 /// Parse a FDE into a CIE_Info and an FDE_Info
120 template <typename A>
121 const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
122 FDE_Info *fdeInfo, CIE_Info *cieInfo) {
124 pint_t cfiLength = (pint_t)addressSpace.get32(p);
126 if (cfiLength == 0xffffffff) {
127 // 0xffffffff means length is really next 8 bytes
128 cfiLength = (pint_t)addressSpace.get64(p);
132 return "FDE has zero length"; // end marker
133 uint32_t ciePointer = addressSpace.get32(p);
135 return "FDE is really a CIE"; // this is a CIE not an FDE
136 pint_t nextCFI = p + cfiLength;
137 pint_t cieStart = p - ciePointer;
138 const char *err = parseCIE(addressSpace, cieStart, cieInfo);
142 // parse pc begin and range
144 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
146 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
147 // parse rest of info
149 // check for augmentation length
150 if (cieInfo->fdesHaveAugmentationData) {
151 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
152 pint_t endOfAug = p + augLen;
153 if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
154 // peek at value (without indirection). Zero means no lsda
155 pint_t lsdaStart = p;
156 if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
158 // reset pointer and re-parse lsda address
161 addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
166 fdeInfo->fdeStart = fdeStart;
167 fdeInfo->fdeLength = nextCFI - fdeStart;
168 fdeInfo->fdeInstructions = p;
169 fdeInfo->pcStart = pcStart;
170 fdeInfo->pcEnd = pcStart + pcRange;
171 return NULL; // success
174 /// Scan an eh_frame section to find an FDE for a pc
175 template <typename A>
176 bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
177 uint32_t sectionLength, pint_t fdeHint,
178 FDE_Info *fdeInfo, CIE_Info *cieInfo) {
179 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
180 pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
181 const pint_t ehSectionEnd = p + sectionLength;
182 while (p < ehSectionEnd) {
183 pint_t currentCFI = p;
184 //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
185 pint_t cfiLength = addressSpace.get32(p);
187 if (cfiLength == 0xffffffff) {
188 // 0xffffffff means length is really next 8 bytes
189 cfiLength = (pint_t)addressSpace.get64(p);
193 return false; // end marker
194 uint32_t id = addressSpace.get32(p);
199 // process FDE to see if it covers pc
200 pint_t nextCFI = p + cfiLength;
201 uint32_t ciePointer = addressSpace.get32(p);
202 pint_t cieStart = p - ciePointer;
203 // validate pointer to CIE is within section
204 if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
205 if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
207 // parse pc begin and range
209 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
210 pint_t pcRange = addressSpace.getEncodedP(
211 p, nextCFI, cieInfo->pointerEncoding & 0x0F);
212 // test if pc is within the function this FDE covers
213 if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
214 // parse rest of info
216 // check for augmentation length
217 if (cieInfo->fdesHaveAugmentationData) {
218 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
219 pint_t endOfAug = p + augLen;
220 if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
221 // peek at value (without indirection). Zero means no lsda
222 pint_t lsdaStart = p;
223 if (addressSpace.getEncodedP(
224 p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
225 // reset pointer and re-parse lsda address
227 fdeInfo->lsda = addressSpace
228 .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
233 fdeInfo->fdeStart = currentCFI;
234 fdeInfo->fdeLength = nextCFI - currentCFI;
235 fdeInfo->fdeInstructions = p;
236 fdeInfo->pcStart = pcStart;
237 fdeInfo->pcEnd = pcStart + pcRange;
240 // pc is not in begin/range, skip this FDE
243 // malformed CIE, now augmentation describing pc range encoding
246 // malformed FDE. CIE is bad
254 /// Extract info from a CIE
255 template <typename A>
256 const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
258 cieInfo->pointerEncoding = 0;
259 cieInfo->lsdaEncoding = DW_EH_PE_omit;
260 cieInfo->personalityEncoding = 0;
261 cieInfo->personalityOffsetInCIE = 0;
262 cieInfo->personality = 0;
263 cieInfo->codeAlignFactor = 0;
264 cieInfo->dataAlignFactor = 0;
265 cieInfo->isSignalFrame = false;
266 cieInfo->fdesHaveAugmentationData = false;
267 cieInfo->cieStart = cie;
269 pint_t cieLength = (pint_t)addressSpace.get32(p);
271 pint_t cieContentEnd = p + cieLength;
272 if (cieLength == 0xffffffff) {
273 // 0xffffffff means length is really next 8 bytes
274 cieLength = (pint_t)addressSpace.get64(p);
276 cieContentEnd = p + cieLength;
280 // CIE ID is always 0
281 if (addressSpace.get32(p) != 0)
282 return "CIE ID is not zero";
284 // Version is always 1 or 3
285 uint8_t version = addressSpace.get8(p);
286 if ((version != 1) && (version != 3))
287 return "CIE version is not 1 or 3";
289 // save start of augmentation string and find end
291 while (addressSpace.get8(p) != 0)
294 // parse code aligment factor
295 cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd);
296 // parse data alignment factor
297 cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
298 // parse return address register
299 uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd);
300 assert(raReg < 255 && "return address register too large");
301 cieInfo->returnAddressRegister = (uint8_t)raReg;
302 // parse augmentation data based on augmentation string
303 const char *result = NULL;
304 if (addressSpace.get8(strStart) == 'z') {
305 // parse augmentation data length
306 addressSpace.getULEB128(p, cieContentEnd);
307 for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
308 switch (addressSpace.get8(s)) {
310 cieInfo->fdesHaveAugmentationData = true;
313 cieInfo->personalityEncoding = addressSpace.get8(p);
315 cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
316 cieInfo->personality = addressSpace
317 .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
320 cieInfo->lsdaEncoding = addressSpace.get8(p);
324 cieInfo->pointerEncoding = addressSpace.get8(p);
328 cieInfo->isSignalFrame = true;
331 // ignore unknown letters
336 cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
337 cieInfo->cieInstructions = p;
342 /// "run" the dwarf instructions and create the abstact PrologInfo for an FDE
343 template <typename A>
344 bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
345 const FDE_Info &fdeInfo,
346 const CIE_Info &cieInfo, pint_t upToPC,
347 PrologInfo *results) {
349 bzero(results, sizeof(PrologInfo));
350 PrologInfoStackEntry *rememberStack = NULL;
352 // parse CIE then FDE instructions
353 return parseInstructions(addressSpace, cieInfo.cieInstructions,
354 cieInfo.cieStart + cieInfo.cieLength, cieInfo,
355 (pint_t)(-1), rememberStack, results) &&
356 parseInstructions(addressSpace, fdeInfo.fdeInstructions,
357 fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
358 upToPC - fdeInfo.pcStart, rememberStack, results);
361 /// "run" the dwarf instructions
362 template <typename A>
363 bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
364 pint_t instructionsEnd,
365 const CIE_Info &cieInfo, pint_t pcoffset,
366 PrologInfoStackEntry *&rememberStack,
367 PrologInfo *results) {
368 const bool logDwarf = false;
369 pint_t p = instructions;
370 pint_t codeOffset = 0;
371 PrologInfo initialState = *results;
373 fprintf(stderr, "parseInstructions(instructions=0x%0llX)\n",
374 (uint64_t) instructionsEnd);
376 // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
377 while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
382 uint8_t opcode = addressSpace.get8(p);
384 PrologInfoStackEntry *entry;
389 fprintf(stderr, "DW_CFA_nop\n");
393 addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
395 fprintf(stderr, "DW_CFA_set_loc\n");
397 case DW_CFA_advance_loc1:
398 codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
401 fprintf(stderr, "DW_CFA_advance_loc1: new offset=%llu\n",
402 (uint64_t)codeOffset);
404 case DW_CFA_advance_loc2:
405 codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
408 fprintf(stderr, "DW_CFA_advance_loc2: new offset=%llu\n",
409 (uint64_t)codeOffset);
411 case DW_CFA_advance_loc4:
412 codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
415 fprintf(stderr, "DW_CFA_advance_loc4: new offset=%llu\n",
416 (uint64_t)codeOffset);
418 case DW_CFA_offset_extended:
419 reg = addressSpace.getULEB128(p, instructionsEnd);
420 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
421 * cieInfo.dataAlignFactor;
422 if (reg > kMaxRegisterNumber) {
424 "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n");
427 results->savedRegisters[reg].location = kRegisterInCFA;
428 results->savedRegisters[reg].value = offset;
430 fprintf(stderr, "DW_CFA_offset_extended(reg=%lld, offset=%lld)\n", reg,
433 case DW_CFA_restore_extended:
434 reg = addressSpace.getULEB128(p, instructionsEnd);
436 if (reg > kMaxRegisterNumber) {
439 "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n");
442 results->savedRegisters[reg] = initialState.savedRegisters[reg];
444 fprintf(stderr, "DW_CFA_restore_extended(reg=%lld)\n", reg);
446 case DW_CFA_undefined:
447 reg = addressSpace.getULEB128(p, instructionsEnd);
448 if (reg > kMaxRegisterNumber) {
450 "malformed DW_CFA_undefined dwarf unwind, reg too big\n");
453 results->savedRegisters[reg].location = kRegisterUnused;
455 fprintf(stderr, "DW_CFA_undefined(reg=%lld)\n", reg);
457 case DW_CFA_same_value:
458 reg = addressSpace.getULEB128(p, instructionsEnd);
459 if (reg > kMaxRegisterNumber) {
461 "malformed DW_CFA_same_value dwarf unwind, reg too big\n");
464 // <rdar://problem/8456377> DW_CFA_same_value unsupported
465 // "same value" means register was stored in frame, but its current
466 // value has not changed, so no need to restore from frame.
467 // We model this as if the register was never saved.
468 results->savedRegisters[reg].location = kRegisterUnused;
469 // set flag to disable conversion to compact unwind
470 results->sameValueUsed = true;
472 fprintf(stderr, "DW_CFA_same_value(reg=%lld)\n", reg);
474 case DW_CFA_register:
475 reg = addressSpace.getULEB128(p, instructionsEnd);
476 reg2 = addressSpace.getULEB128(p, instructionsEnd);
477 if (reg > kMaxRegisterNumber) {
479 "malformed DW_CFA_register dwarf unwind, reg too big\n");
482 if (reg2 > kMaxRegisterNumber) {
484 "malformed DW_CFA_register dwarf unwind, reg2 too big\n");
487 results->savedRegisters[reg].location = kRegisterInRegister;
488 results->savedRegisters[reg].value = (int64_t)reg2;
489 // set flag to disable conversion to compact unwind
490 results->registersInOtherRegisters = true;
492 fprintf(stderr, "DW_CFA_register(reg=%lld, reg2=%lld)\n", reg, reg2);
494 case DW_CFA_remember_state:
495 // avoid operator new, because that would be an upward dependency
496 entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
498 entry->next = rememberStack;
499 entry->info = *results;
500 rememberStack = entry;
505 fprintf(stderr, "DW_CFA_remember_state\n");
507 case DW_CFA_restore_state:
508 if (rememberStack != NULL) {
509 PrologInfoStackEntry *top = rememberStack;
510 *results = top->info;
511 rememberStack = top->next;
517 fprintf(stderr, "DW_CFA_restore_state\n");
520 reg = addressSpace.getULEB128(p, instructionsEnd);
521 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
522 if (reg > kMaxRegisterNumber) {
523 fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n");
526 results->cfaRegister = (uint32_t)reg;
527 results->cfaRegisterOffset = (int32_t)offset;
529 fprintf(stderr, "DW_CFA_def_cfa(reg=%lld, offset=%lld)\n", reg, offset);
531 case DW_CFA_def_cfa_register:
532 reg = addressSpace.getULEB128(p, instructionsEnd);
533 if (reg > kMaxRegisterNumber) {
536 "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n");
539 results->cfaRegister = (uint32_t)reg;
541 fprintf(stderr, "DW_CFA_def_cfa_register(%lld)\n", reg);
543 case DW_CFA_def_cfa_offset:
544 results->cfaRegisterOffset = (int32_t)
545 addressSpace.getULEB128(p, instructionsEnd);
546 results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
548 fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n",
549 results->cfaRegisterOffset);
551 case DW_CFA_def_cfa_expression:
552 results->cfaRegister = 0;
553 results->cfaExpression = (int64_t)p;
554 length = addressSpace.getULEB128(p, instructionsEnd);
558 "DW_CFA_def_cfa_expression(expression=0x%llX, length=%llu)\n",
559 results->cfaExpression, length);
561 case DW_CFA_expression:
562 reg = addressSpace.getULEB128(p, instructionsEnd);
563 if (reg > kMaxRegisterNumber) {
565 "malformed DW_CFA_expression dwarf unwind, reg too big\n");
568 results->savedRegisters[reg].location = kRegisterAtExpression;
569 results->savedRegisters[reg].value = (int64_t)p;
570 length = addressSpace.getULEB128(p, instructionsEnd);
574 "DW_CFA_expression(reg=%lld, expression=0x%llX, length=%llu)\n",
575 reg, results->savedRegisters[reg].value, length);
577 case DW_CFA_offset_extended_sf:
578 reg = addressSpace.getULEB128(p, instructionsEnd);
579 if (reg > kMaxRegisterNumber) {
582 "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n");
586 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
587 results->savedRegisters[reg].location = kRegisterInCFA;
588 results->savedRegisters[reg].value = offset;
590 fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%lld, offset=%lld)\n",
593 case DW_CFA_def_cfa_sf:
594 reg = addressSpace.getULEB128(p, instructionsEnd);
596 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
597 if (reg > kMaxRegisterNumber) {
599 "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n");
602 results->cfaRegister = (uint32_t)reg;
603 results->cfaRegisterOffset = (int32_t)offset;
605 fprintf(stderr, "DW_CFA_def_cfa_sf(reg=%lld, offset=%lld)\n", reg,
608 case DW_CFA_def_cfa_offset_sf:
609 results->cfaRegisterOffset = (int32_t)
610 (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor);
611 results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
613 fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n",
614 results->cfaRegisterOffset);
616 case DW_CFA_val_offset:
617 reg = addressSpace.getULEB128(p, instructionsEnd);
618 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
619 * cieInfo.dataAlignFactor;
620 results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
621 results->savedRegisters[reg].value = offset;
623 fprintf(stderr, "DW_CFA_val_offset(reg=%lld, offset=%lld\n", reg,
626 case DW_CFA_val_offset_sf:
627 reg = addressSpace.getULEB128(p, instructionsEnd);
628 if (reg > kMaxRegisterNumber) {
630 "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n");
634 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
635 results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
636 results->savedRegisters[reg].value = offset;
638 fprintf(stderr, "DW_CFA_val_offset_sf(reg=%lld, offset=%lld\n", reg,
641 case DW_CFA_val_expression:
642 reg = addressSpace.getULEB128(p, instructionsEnd);
643 if (reg > kMaxRegisterNumber) {
645 "malformed DW_CFA_val_expression dwarf unwind, reg too big\n");
648 results->savedRegisters[reg].location = kRegisterIsExpression;
649 results->savedRegisters[reg].value = (int64_t)p;
650 length = addressSpace.getULEB128(p, instructionsEnd);
655 "DW_CFA_val_expression(reg=%lld, expression=0x%llX, length=%lld)\n",
656 reg, results->savedRegisters[reg].value, length);
658 case DW_CFA_GNU_args_size:
659 length = addressSpace.getULEB128(p, instructionsEnd);
660 results->spExtraArgSize = (uint32_t)length;
662 fprintf(stderr, "DW_CFA_GNU_args_size(%lld)\n", length);
664 case DW_CFA_GNU_negative_offset_extended:
665 reg = addressSpace.getULEB128(p, instructionsEnd);
666 if (reg > kMaxRegisterNumber) {
667 fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf "
668 "unwind, reg too big\n");
671 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
672 * cieInfo.dataAlignFactor;
673 results->savedRegisters[reg].location = kRegisterInCFA;
674 results->savedRegisters[reg].value = -offset;
676 fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%lld)\n", offset);
679 operand = opcode & 0x3F;
680 switch (opcode & 0xC0) {
683 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
684 * cieInfo.dataAlignFactor;
685 results->savedRegisters[reg].location = kRegisterInCFA;
686 results->savedRegisters[reg].value = offset;
688 fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%lld)\n", operand,
691 case DW_CFA_advance_loc:
692 codeOffset += operand * cieInfo.codeAlignFactor;
694 fprintf(stderr, "DW_CFA_advance_loc: new offset=%llu\n",
695 (uint64_t)codeOffset);
699 results->savedRegisters[reg] = initialState.savedRegisters[reg];
701 fprintf(stderr, "DW_CFA_restore(reg=%lld)\n", reg);
705 fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode);
714 } // namespace libunwind
716 #endif // __DWARF_PARSER_HPP__