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