1//===--------------------------- DwarfParser.hpp --------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8// Parses DWARF CFIs (FDEs and CIEs).
9//
10//===----------------------------------------------------------------------===//
11
12#ifndef __DWARF_PARSER_HPP__
13#define __DWARF_PARSER_HPP__
14
15#include <inttypes.h>
16#include <stdint.h>
17#include <stdio.h>
18#include <stdlib.h>
19
20#include "libunwind.h"
21#include "dwarf2.h"
22#include "Registers.hpp"
23
24#include "config.h"
25
26namespace libunwind {
27
28enum {
29 kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER
30};
31
32enum RegisterSavedWhere {
33 kRegisterUnused,
34 kRegisterInCFA,
35 kRegisterOffsetFromCFA,
36 kRegisterInRegister,
37 kRegisterAtExpression,
38 kRegisterIsExpression
39};
40
41struct RegisterLocation {
42 RegisterSavedWhere location;
43 int64_t value;
44};
45
46/// Information about a frame layout and registers saved determined
47/// by "running" the DWARF FDE "instructions"
48struct PrologInfo {
49 uint32_t cfaRegister;
50 int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
51 int64_t cfaExpression; // CFA = expression
52 uint32_t spExtraArgSize;
53 uint32_t codeOffsetAtStackDecrement;
54 bool registersInOtherRegisters;
55 bool sameValueUsed;
56 RegisterLocation savedRegisters[kMaxRegisterNumber + 1];
57};
58
59struct PrologInfoStackEntry {
60 PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
61 : next(n), info(i) {}
62 PrologInfoStackEntry *next;
63 PrologInfo info;
64};
65
66}
67
68namespace {
69// DWARF instructions DW_CFA_remember_state and DW_CFA_restore_state require
70// stack. We cannot use malloc as it is not signal safe. mmap is technically
71// signal safe but allocates pages too slow. Small buffer is introduced instead
72// along with upper bound on maximum stack depth
73
74class StackGuard {
75public:
76 void *push() {
77 if (size + entrySize > capacity) {
78 abort();
79 }
80
81 void* result = static_cast<void *>(buffer + size);
82 size += entrySize;
83 return result;
84 }
85
86 void pop() {
87 if (size < entrySize) {
88 abort();
89 }
90
91 size -= entrySize;
92 }
93
94private:
95 static constexpr size_t entrySize = sizeof(libunwind::PrologInfoStackEntry);
96 static constexpr size_t capacity = entrySize * LIBUNWIND_MAX_STACK_SIZE;
97
98 size_t size = 0;
99 char buffer[capacity];
100};
101}
102
103namespace libunwind {
104/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
105/// See DWARF Spec for details:
106/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
107///
108template <typename A>
109class CFI_Parser {
110public:
111 typedef typename A::pint_t pint_t;
112
113 /// Information encoded in a CIE (Common Information Entry)
114 struct CIE_Info {
115 pint_t cieStart;
116 pint_t cieLength;
117 pint_t cieInstructions;
118 uint8_t pointerEncoding;
119 uint8_t lsdaEncoding;
120 uint8_t personalityEncoding;
121 uint8_t personalityOffsetInCIE;
122 pint_t personality;
123 uint32_t codeAlignFactor;
124 int dataAlignFactor;
125 bool isSignalFrame;
126 bool fdesHaveAugmentationData;
127 uint8_t returnAddressRegister;
128#if defined(_LIBUNWIND_TARGET_AARCH64)
129 bool addressesSignedWithBKey;
130#endif
131 };
132
133 /// Information about an FDE (Frame Description Entry)
134 struct FDE_Info {
135 pint_t fdeStart;
136 pint_t fdeLength;
137 pint_t fdeInstructions;
138 pint_t pcStart;
139 pint_t pcEnd;
140 pint_t lsda;
141 };
142
143 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
144 uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
145 CIE_Info *cieInfo);
146 static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
147 FDE_Info *fdeInfo, CIE_Info *cieInfo);
148 static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
149 const CIE_Info &cieInfo, pint_t upToPC,
150 int arch, PrologInfo *results);
151
152 static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
153
154private:
155 static bool parseInstructions(A &addressSpace, pint_t instructions,
156 pint_t instructionsEnd, const CIE_Info &cieInfo,
157 pint_t pcoffset,
158 PrologInfoStackEntry *&rememberStack, int arch,
159 PrologInfo *results,
160 StackGuard &stack);
161
162};
163
164
165/// Parse a FDE into a CIE_Info and an FDE_Info
166template <typename A>
167const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
168 FDE_Info *fdeInfo, CIE_Info *cieInfo) {
169 pint_t p = fdeStart;
170 pint_t cfiLength = (pint_t)addressSpace.get32(p);
171 p += 4;
172 if (cfiLength == 0xffffffff) {
173 // 0xffffffff means length is really next 8 bytes
174 cfiLength = (pint_t)addressSpace.get64(p);
175 p += 8;
176 }
177 if (cfiLength == 0)
178 return "FDE has zero length"; // end marker
179 uint32_t ciePointer = addressSpace.get32(p);
180 if (ciePointer == 0)
181 return "FDE is really a CIE"; // this is a CIE not an FDE
182 pint_t nextCFI = p + cfiLength;
183 pint_t cieStart = p - ciePointer;
184 const char *err = parseCIE(addressSpace, cieStart, cieInfo);
185 if (err != NULL)
186 return err;
187 p += 4;
188 // Parse pc begin and range.
189 pint_t pcStart =
190 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
191 pint_t pcRange =
192 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
193 // Parse rest of info.
194 fdeInfo->lsda = 0;
195 // Check for augmentation length.
196 if (cieInfo->fdesHaveAugmentationData) {
197 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
198 pint_t endOfAug = p + augLen;
199 if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
200 // Peek at value (without indirection). Zero means no LSDA.
201 pint_t lsdaStart = p;
202 if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
203 0) {
204 // Reset pointer and re-parse LSDA address.
205 p = lsdaStart;
206 fdeInfo->lsda =
207 addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
208 }
209 }
210 p = endOfAug;
211 }
212 fdeInfo->fdeStart = fdeStart;
213 fdeInfo->fdeLength = nextCFI - fdeStart;
214 fdeInfo->fdeInstructions = p;
215 fdeInfo->pcStart = pcStart;
216 fdeInfo->pcEnd = pcStart + pcRange;
217 return NULL; // success
218}
219
220/// Scan an eh_frame section to find an FDE for a pc
221template <typename A>
222bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
223 uint32_t sectionLength, pint_t fdeHint,
224 FDE_Info *fdeInfo, CIE_Info *cieInfo) {
225 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
226 pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
227 const pint_t ehSectionEnd = p + sectionLength;
228 while (p < ehSectionEnd) {
229 pint_t currentCFI = p;
230 //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
231 pint_t cfiLength = addressSpace.get32(p);
232 p += 4;
233 if (cfiLength == 0xffffffff) {
234 // 0xffffffff means length is really next 8 bytes
235 cfiLength = (pint_t)addressSpace.get64(p);
236 p += 8;
237 }
238 if (cfiLength == 0)
239 return false; // end marker
240 uint32_t id = addressSpace.get32(p);
241 if (id == 0) {
242 // Skip over CIEs.
243 p += cfiLength;
244 } else {
245 // Process FDE to see if it covers pc.
246 pint_t nextCFI = p + cfiLength;
247 uint32_t ciePointer = addressSpace.get32(p);
248 pint_t cieStart = p - ciePointer;
249 // Validate pointer to CIE is within section.
250 if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
251 if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
252 p += 4;
253 // Parse pc begin and range.
254 pint_t pcStart =
255 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
256 pint_t pcRange = addressSpace.getEncodedP(
257 p, nextCFI, cieInfo->pointerEncoding & 0x0F);
258 // Test if pc is within the function this FDE covers.
259 if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
260 // parse rest of info
261 fdeInfo->lsda = 0;
262 // check for augmentation length
263 if (cieInfo->fdesHaveAugmentationData) {
264 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
265 pint_t endOfAug = p + augLen;
266 if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
267 // Peek at value (without indirection). Zero means no LSDA.
268 pint_t lsdaStart = p;
269 if (addressSpace.getEncodedP(
270 p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
271 // Reset pointer and re-parse LSDA address.
272 p = lsdaStart;
273 fdeInfo->lsda = addressSpace
274 .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
275 }
276 }
277 p = endOfAug;
278 }
279 fdeInfo->fdeStart = currentCFI;
280 fdeInfo->fdeLength = nextCFI - currentCFI;
281 fdeInfo->fdeInstructions = p;
282 fdeInfo->pcStart = pcStart;
283 fdeInfo->pcEnd = pcStart + pcRange;
284 return true;
285 } else {
286 // pc is not in begin/range, skip this FDE
287 }
288 } else {
289 // Malformed CIE, now augmentation describing pc range encoding.
290 }
291 } else {
292 // malformed FDE. CIE is bad
293 }
294 p = nextCFI;
295 }
296 }
297 return false;
298}
299
300/// Extract info from a CIE
301template <typename A>
302const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
303 CIE_Info *cieInfo) {
304 cieInfo->pointerEncoding = 0;
305 cieInfo->lsdaEncoding = DW_EH_PE_omit;
306 cieInfo->personalityEncoding = 0;
307 cieInfo->personalityOffsetInCIE = 0;
308 cieInfo->personality = 0;
309 cieInfo->codeAlignFactor = 0;
310 cieInfo->dataAlignFactor = 0;
311 cieInfo->isSignalFrame = false;
312 cieInfo->fdesHaveAugmentationData = false;
313#if defined(_LIBUNWIND_TARGET_AARCH64)
314 cieInfo->addressesSignedWithBKey = false;
315#endif
316 cieInfo->cieStart = cie;
317 pint_t p = cie;
318 pint_t cieLength = (pint_t)addressSpace.get32(p);
319 p += 4;
320 pint_t cieContentEnd = p + cieLength;
321 if (cieLength == 0xffffffff) {
322 // 0xffffffff means length is really next 8 bytes
323 cieLength = (pint_t)addressSpace.get64(p);
324 p += 8;
325 cieContentEnd = p + cieLength;
326 }
327 if (cieLength == 0)
328 return NULL;
329 // CIE ID is always 0
330 if (addressSpace.get32(p) != 0)
331 return "CIE ID is not zero";
332 p += 4;
333 // Version is always 1 or 3
334 uint8_t version = addressSpace.get8(p);
335 if ((version != 1) && (version != 3))
336 return "CIE version is not 1 or 3";
337 ++p;
338 // save start of augmentation string and find end
339 pint_t strStart = p;
340 while (addressSpace.get8(p) != 0)
341 ++p;
342 ++p;
343 // parse code aligment factor
344 cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd);
345 // parse data alignment factor
346 cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
347 // parse return address register
348 uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd);
349 assert(raReg < 255 && "return address register too large");
350 cieInfo->returnAddressRegister = (uint8_t)raReg;
351 // parse augmentation data based on augmentation string
352 const char *result = NULL;
353 if (addressSpace.get8(strStart) == 'z') {
354 // parse augmentation data length
355 addressSpace.getULEB128(p, cieContentEnd);
356 for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
357 switch (addressSpace.get8(s)) {
358 case 'z':
359 cieInfo->fdesHaveAugmentationData = true;
360 break;
361 case 'P':
362 cieInfo->personalityEncoding = addressSpace.get8(p);
363 ++p;
364 cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
365 cieInfo->personality = addressSpace
366 .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
367 break;
368 case 'L':
369 cieInfo->lsdaEncoding = addressSpace.get8(p);
370 ++p;
371 break;
372 case 'R':
373 cieInfo->pointerEncoding = addressSpace.get8(p);
374 ++p;
375 break;
376 case 'S':
377 cieInfo->isSignalFrame = true;
378 break;
379#if defined(_LIBUNWIND_TARGET_AARCH64)
380 case 'B':
381 cieInfo->addressesSignedWithBKey = true;
382 break;
383#endif
384 default:
385 // ignore unknown letters
386 break;
387 }
388 }
389 }
390 cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
391 cieInfo->cieInstructions = p;
392 return result;
393}
394
395
396/// "run" the DWARF instructions and create the abstact PrologInfo for an FDE
397template <typename A>
398bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
399 const FDE_Info &fdeInfo,
400 const CIE_Info &cieInfo, pint_t upToPC,
401 int arch, PrologInfo *results) {
402 // clear results
403 memset(results, '\0', sizeof(PrologInfo));
404 PrologInfoStackEntry *rememberStack = NULL;
405
406 StackGuard stack;
407
408 // parse CIE then FDE instructions
409 return parseInstructions(addressSpace, cieInfo.cieInstructions,
410 cieInfo.cieStart + cieInfo.cieLength, cieInfo,
411 (pint_t)(-1), rememberStack, arch, results, stack) &&
412 parseInstructions(addressSpace, fdeInfo.fdeInstructions,
413 fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
414 upToPC - fdeInfo.pcStart, rememberStack, arch,
415 results, stack);
416}
417
418/// "run" the DWARF instructions
419template <typename A>
420bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
421 pint_t instructionsEnd,
422 const CIE_Info &cieInfo, pint_t pcoffset,
423 PrologInfoStackEntry *&rememberStack,
424 int arch, PrologInfo *results,
425 StackGuard &stack) {
426 pint_t p = instructions;
427 pint_t codeOffset = 0;
428 PrologInfo initialState = *results;
429
430 _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n",
431 static_cast<uint64_t>(instructionsEnd));
432
433 // see DWARF Spec, section 6.4.2 for details on unwind opcodes
434 while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
435 uint64_t reg;
436 uint64_t reg2;
437 int64_t offset;
438 uint64_t length;
439 uint8_t opcode = addressSpace.get8(p);
440 uint8_t operand;
441 PrologInfoStackEntry *entry;
442 ++p;
443 switch (opcode) {
444 case DW_CFA_nop:
445 _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
446 break;
447 case DW_CFA_set_loc:
448 codeOffset =
449 addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
450 _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
451 break;
452 case DW_CFA_advance_loc1:
453 codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
454 p += 1;
455 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n",
456 static_cast<uint64_t>(codeOffset));
457 break;
458 case DW_CFA_advance_loc2:
459 codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
460 p += 2;
461 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n",
462 static_cast<uint64_t>(codeOffset));
463 break;
464 case DW_CFA_advance_loc4:
465 codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
466 p += 4;
467 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n",
468 static_cast<uint64_t>(codeOffset));
469 break;
470 case DW_CFA_offset_extended:
471 reg = addressSpace.getULEB128(p, instructionsEnd);
472 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
473 * cieInfo.dataAlignFactor;
474 if (reg > kMaxRegisterNumber) {
475 _LIBUNWIND_LOG0(
476 "malformed DW_CFA_offset_extended DWARF unwind, reg too big");
477 return false;
478 }
479 results->savedRegisters[reg].location = kRegisterInCFA;
480 results->savedRegisters[reg].value = offset;
481 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", "
482 "offset=%" PRId64 ")\n",
483 reg, offset);
484 break;
485 case DW_CFA_restore_extended:
486 reg = addressSpace.getULEB128(p, instructionsEnd);
487 if (reg > kMaxRegisterNumber) {
488 _LIBUNWIND_LOG0(
489 "malformed DW_CFA_restore_extended DWARF unwind, reg too big");
490 return false;
491 }
492 results->savedRegisters[reg] = initialState.savedRegisters[reg];
493 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg);
494 break;
495 case DW_CFA_undefined:
496 reg = addressSpace.getULEB128(p, instructionsEnd);
497 if (reg > kMaxRegisterNumber) {
498 _LIBUNWIND_LOG0(
499 "malformed DW_CFA_undefined DWARF unwind, reg too big");
500 return false;
501 }
502 results->savedRegisters[reg].location = kRegisterUnused;
503 _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
504 break;
505 case DW_CFA_same_value:
506 reg = addressSpace.getULEB128(p, instructionsEnd);
507 if (reg > kMaxRegisterNumber) {
508 _LIBUNWIND_LOG0(
509 "malformed DW_CFA_same_value DWARF unwind, reg too big");
510 return false;
511 }
512 // <rdar://problem/8456377> DW_CFA_same_value unsupported
513 // "same value" means register was stored in frame, but its current
514 // value has not changed, so no need to restore from frame.
515 // We model this as if the register was never saved.
516 results->savedRegisters[reg].location = kRegisterUnused;
517 // set flag to disable conversion to compact unwind
518 results->sameValueUsed = true;
519 _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg);
520 break;
521 case DW_CFA_register:
522 reg = addressSpace.getULEB128(p, instructionsEnd);
523 reg2 = addressSpace.getULEB128(p, instructionsEnd);
524 if (reg > kMaxRegisterNumber) {
525 _LIBUNWIND_LOG0(
526 "malformed DW_CFA_register DWARF unwind, reg too big");
527 return false;
528 }
529 if (reg2 > kMaxRegisterNumber) {
530 _LIBUNWIND_LOG0(
531 "malformed DW_CFA_register DWARF unwind, reg2 too big");
532 return false;
533 }
534 results->savedRegisters[reg].location = kRegisterInRegister;
535 results->savedRegisters[reg].value = (int64_t)reg2;
536 // set flag to disable conversion to compact unwind
537 results->registersInOtherRegisters = true;
538 _LIBUNWIND_TRACE_DWARF(
539 "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2);
540 break;
541 case DW_CFA_remember_state:
542 // avoid operator new, because that would be an upward dependency
543 entry = (PrologInfoStackEntry *)stack.push();
544 if (entry != NULL) {
545 entry->next = rememberStack;
546 entry->info = *results;
547 rememberStack = entry;
548 } else {
549 return false;
550 }
551 _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
552 break;
553 case DW_CFA_restore_state:
554 if (rememberStack != NULL) {
555 PrologInfoStackEntry *top = rememberStack;
556 *results = top->info;
557 rememberStack = top->next;
558 stack.pop();
559 } else {
560 return false;
561 }
562 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n");
563 break;
564 case DW_CFA_def_cfa:
565 reg = addressSpace.getULEB128(p, instructionsEnd);
566 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
567 if (reg > kMaxRegisterNumber) {
568 _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
569 return false;
570 }
571 results->cfaRegister = (uint32_t)reg;
572 results->cfaRegisterOffset = (int32_t)offset;
573 _LIBUNWIND_TRACE_DWARF(
574 "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", reg, offset);
575 break;
576 case DW_CFA_def_cfa_register:
577 reg = addressSpace.getULEB128(p, instructionsEnd);
578 if (reg > kMaxRegisterNumber) {
579 _LIBUNWIND_LOG0(
580 "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
581 return false;
582 }
583 results->cfaRegister = (uint32_t)reg;
584 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg);
585 break;
586 case DW_CFA_def_cfa_offset:
587 results->cfaRegisterOffset = (int32_t)
588 addressSpace.getULEB128(p, instructionsEnd);
589 results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
590 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n",
591 results->cfaRegisterOffset);
592 break;
593 case DW_CFA_def_cfa_expression:
594 results->cfaRegister = 0;
595 results->cfaExpression = (int64_t)p;
596 length = addressSpace.getULEB128(p, instructionsEnd);
597 assert(length < static_cast<pint_t>(~0) && "pointer overflow");
598 p += static_cast<pint_t>(length);
599 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64
600 ", length=%" PRIu64 ")\n",
601 results->cfaExpression, length);
602 break;
603 case DW_CFA_expression:
604 reg = addressSpace.getULEB128(p, instructionsEnd);
605 if (reg > kMaxRegisterNumber) {
606 _LIBUNWIND_LOG0(
607 "malformed DW_CFA_expression DWARF unwind, reg too big");
608 return false;
609 }
610 results->savedRegisters[reg].location = kRegisterAtExpression;
611 results->savedRegisters[reg].value = (int64_t)p;
612 length = addressSpace.getULEB128(p, instructionsEnd);
613 assert(length < static_cast<pint_t>(~0) && "pointer overflow");
614 p += static_cast<pint_t>(length);
615 _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", "
616 "expression=0x%" PRIx64 ", "
617 "length=%" PRIu64 ")\n",
618 reg, results->savedRegisters[reg].value, length);
619 break;
620 case DW_CFA_offset_extended_sf:
621 reg = addressSpace.getULEB128(p, instructionsEnd);
622 if (reg > kMaxRegisterNumber) {
623 _LIBUNWIND_LOG0(
624 "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
625 return false;
626 }
627 offset =
628 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
629 results->savedRegisters[reg].location = kRegisterInCFA;
630 results->savedRegisters[reg].value = offset;
631 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", "
632 "offset=%" PRId64 ")\n",
633 reg, offset);
634 break;
635 case DW_CFA_def_cfa_sf:
636 reg = addressSpace.getULEB128(p, instructionsEnd);
637 offset =
638 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
639 if (reg > kMaxRegisterNumber) {
640 _LIBUNWIND_LOG0(
641 "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big");
642 return false;
643 }
644 results->cfaRegister = (uint32_t)reg;
645 results->cfaRegisterOffset = (int32_t)offset;
646 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", "
647 "offset=%" PRId64 ")\n",
648 reg, offset);
649 break;
650 case DW_CFA_def_cfa_offset_sf:
651 results->cfaRegisterOffset = (int32_t)
652 (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor);
653 results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
654 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n",
655 results->cfaRegisterOffset);
656 break;
657 case DW_CFA_val_offset:
658 reg = addressSpace.getULEB128(p, instructionsEnd);
659 if (reg > kMaxRegisterNumber) {
660 _LIBUNWIND_LOG(
661 "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64
662 ") out of range\n",
663 reg);
664 return false;
665 }
666 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
667 * cieInfo.dataAlignFactor;
668 results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
669 results->savedRegisters[reg].value = offset;
670 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", "
671 "offset=%" PRId64 "\n",
672 reg, offset);
673 break;
674 case DW_CFA_val_offset_sf:
675 reg = addressSpace.getULEB128(p, instructionsEnd);
676 if (reg > kMaxRegisterNumber) {
677 _LIBUNWIND_LOG0(
678 "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
679 return false;
680 }
681 offset =
682 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
683 results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
684 results->savedRegisters[reg].value = offset;
685 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", "
686 "offset=%" PRId64 "\n",
687 reg, offset);
688 break;
689 case DW_CFA_val_expression:
690 reg = addressSpace.getULEB128(p, instructionsEnd);
691 if (reg > kMaxRegisterNumber) {
692 _LIBUNWIND_LOG0(
693 "malformed DW_CFA_val_expression DWARF unwind, reg too big");
694 return false;
695 }
696 results->savedRegisters[reg].location = kRegisterIsExpression;
697 results->savedRegisters[reg].value = (int64_t)p;
698 length = addressSpace.getULEB128(p, instructionsEnd);
699 assert(length < static_cast<pint_t>(~0) && "pointer overflow");
700 p += static_cast<pint_t>(length);
701 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", "
702 "expression=0x%" PRIx64 ", length=%" PRIu64 ")\n",
703 reg, results->savedRegisters[reg].value, length);
704 break;
705 case DW_CFA_GNU_args_size:
706 length = addressSpace.getULEB128(p, instructionsEnd);
707 results->spExtraArgSize = (uint32_t)length;
708 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length);
709 break;
710 case DW_CFA_GNU_negative_offset_extended:
711 reg = addressSpace.getULEB128(p, instructionsEnd);
712 if (reg > kMaxRegisterNumber) {
713 _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF "
714 "unwind, reg too big");
715 return false;
716 }
717 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
718 * cieInfo.dataAlignFactor;
719 results->savedRegisters[reg].location = kRegisterInCFA;
720 results->savedRegisters[reg].value = -offset;
721 _LIBUNWIND_TRACE_DWARF(
722 "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
723 break;
724
725#if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC)
726 // The same constant is used to represent different instructions on
727 // AArch64 (negate_ra_state) and SPARC (window_save).
728 static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save,
729 "uses the same constant");
730 case DW_CFA_AARCH64_negate_ra_state:
731 switch (arch) {
732#if defined(_LIBUNWIND_TARGET_AARCH64)
733 case REGISTERS_ARM64:
734 results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1;
735 _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n");
736 break;
737#endif
738#if defined(_LIBUNWIND_TARGET_SPARC)
739 // case DW_CFA_GNU_window_save:
740 case REGISTERS_SPARC:
741 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n");
742 for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) {
743 results->savedRegisters[reg].location = kRegisterInRegister;
744 results->savedRegisters[reg].value =
745 ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0;
746 }
747
748 for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
749 results->savedRegisters[reg].location = kRegisterInCFA;
750 results->savedRegisters[reg].value =
751 ((int64_t)reg - UNW_SPARC_L0) * 4;
752 }
753 break;
754#endif
755 }
756 break;
757#else
758 (void)arch;
759#endif
760
761 default:
762 operand = opcode & 0x3F;
763 switch (opcode & 0xC0) {
764 case DW_CFA_offset:
765 reg = operand;
766 if (reg > kMaxRegisterNumber) {
767 _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
768 ") out of range",
769 reg);
770 return false;
771 }
772 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
773 * cieInfo.dataAlignFactor;
774 results->savedRegisters[reg].location = kRegisterInCFA;
775 results->savedRegisters[reg].value = offset;
776 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
777 operand, offset);
778 break;
779 case DW_CFA_advance_loc:
780 codeOffset += operand * cieInfo.codeAlignFactor;
781 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n",
782 static_cast<uint64_t>(codeOffset));
783 break;
784 case DW_CFA_restore:
785 reg = operand;
786 if (reg > kMaxRegisterNumber) {
787 _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
788 ") out of range",
789 reg);
790 return false;
791 }
792 results->savedRegisters[reg] = initialState.savedRegisters[reg];
793 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n",
794 static_cast<uint64_t>(operand));
795 break;
796 default:
797 _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode);
798 return false;
799 }
800 }
801 }
802
803 return true;
804}
805
806} // namespace libunwind
807
808#endif // __DWARF_PARSER_HPP__
809