1 //===----------------------------------------------------------------------===//
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
26 namespace libunwind {
27
28 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
29 /// See DWARF Spec for details:
30 /// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
31 ///
32 template <typename A>
33 class CFI_Parser {
34 public:
35 typedef typename A::pint_t pint_t;
36
37 /// Information encoded in a CIE (Common Information Entry)
38 struct CIE_Info {
39 pint_t cieStart;
40 pint_t cieLength;
41 pint_t cieInstructions;
42 uint8_t pointerEncoding;
43 uint8_t lsdaEncoding;
44 uint8_t personalityEncoding;
45 uint8_t personalityOffsetInCIE;
46 pint_t personality;
47 uint32_t codeAlignFactor;
48 int dataAlignFactor;
49 bool isSignalFrame;
50 bool fdesHaveAugmentationData;
51 uint8_t returnAddressRegister;
52 #if defined(_LIBUNWIND_TARGET_AARCH64)
53 bool addressesSignedWithBKey;
54 bool mteTaggedFrame;
55 #endif
56 };
57
58 /// Information about an FDE (Frame Description Entry)
59 struct FDE_Info {
60 pint_t fdeStart;
61 pint_t fdeLength;
62 pint_t fdeInstructions;
63 pint_t pcStart;
64 pint_t pcEnd;
65 pint_t lsda;
66 };
67
68 enum {
69 kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER
70 };
71 enum RegisterSavedWhere {
72 kRegisterUnused,
73 kRegisterInCFA,
74 kRegisterInCFADecrypt, // sparc64 specific
75 kRegisterOffsetFromCFA,
76 kRegisterInRegister,
77 kRegisterAtExpression,
78 kRegisterIsExpression
79 };
80 struct RegisterLocation {
81 RegisterSavedWhere location;
82 bool initialStateSaved;
83 int64_t value;
84 };
85 /// Information about a frame layout and registers saved determined
86 /// by "running" the DWARF FDE "instructions"
87 struct PrologInfo {
88 uint32_t cfaRegister;
89 int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
90 int64_t cfaExpression; // CFA = expression
91 uint32_t spExtraArgSize;
92 RegisterLocation savedRegisters[kMaxRegisterNumber + 1];
93 #if defined(_LIBUNWIND_TARGET_AARCH64)
94 pint_t ptrAuthDiversifier;
95 #endif
96 enum class InitializeTime { kLazy, kNormal };
97
98 // When saving registers, this data structure is lazily initialized.
PrologInfolibunwind::CFI_Parser::PrologInfo99 PrologInfo(InitializeTime IT = InitializeTime::kNormal) {
100 if (IT == InitializeTime::kNormal)
101 memset(this, 0, sizeof(*this));
102 }
checkSaveRegisterlibunwind::CFI_Parser::PrologInfo103 void checkSaveRegister(uint64_t reg, PrologInfo &initialState) {
104 if (!savedRegisters[reg].initialStateSaved) {
105 initialState.savedRegisters[reg] = savedRegisters[reg];
106 savedRegisters[reg].initialStateSaved = true;
107 }
108 }
setRegisterlibunwind::CFI_Parser::PrologInfo109 void setRegister(uint64_t reg, RegisterSavedWhere newLocation,
110 int64_t newValue, PrologInfo &initialState) {
111 checkSaveRegister(reg, initialState);
112 savedRegisters[reg].location = newLocation;
113 savedRegisters[reg].value = newValue;
114 }
setRegisterLocationlibunwind::CFI_Parser::PrologInfo115 void setRegisterLocation(uint64_t reg, RegisterSavedWhere newLocation,
116 PrologInfo &initialState) {
117 checkSaveRegister(reg, initialState);
118 savedRegisters[reg].location = newLocation;
119 }
setRegisterValuelibunwind::CFI_Parser::PrologInfo120 void setRegisterValue(uint64_t reg, int64_t newValue,
121 PrologInfo &initialState) {
122 checkSaveRegister(reg, initialState);
123 savedRegisters[reg].value = newValue;
124 }
restoreRegisterToInitialStatelibunwind::CFI_Parser::PrologInfo125 void restoreRegisterToInitialState(uint64_t reg, PrologInfo &initialState) {
126 if (savedRegisters[reg].initialStateSaved)
127 savedRegisters[reg] = initialState.savedRegisters[reg];
128 // else the register still holds its initial state
129 }
130 };
131
132 struct PrologInfoStackEntry {
PrologInfoStackEntrylibunwind::CFI_Parser::PrologInfoStackEntry133 PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
134 : next(n), info(i) {}
135 PrologInfoStackEntry *next;
136 PrologInfo info;
137 };
138
139 struct RememberStack {
140 PrologInfoStackEntry *entry;
RememberStacklibunwind::CFI_Parser::RememberStack141 RememberStack() : entry(nullptr) {}
~RememberStacklibunwind::CFI_Parser::RememberStack142 ~RememberStack() {
143 #if defined(_LIBUNWIND_REMEMBER_CLEANUP_NEEDED)
144 // Clean up rememberStack. Even in the case where every
145 // DW_CFA_remember_state is paired with a DW_CFA_restore_state,
146 // parseInstructions can skip restore opcodes if it reaches the target PC
147 // and stops interpreting, so we have to make sure we don't leak memory.
148 while (entry) {
149 PrologInfoStackEntry *next = entry->next;
150 _LIBUNWIND_REMEMBER_FREE(entry);
151 entry = next;
152 }
153 #endif
154 }
155 };
156
157 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
158 size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
159 CIE_Info *cieInfo);
160 static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
161 FDE_Info *fdeInfo, CIE_Info *cieInfo,
162 bool useCIEInfo = false);
163 static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
164 const CIE_Info &cieInfo, pint_t upToPC,
165 int arch, PrologInfo *results);
166
167 static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
168 };
169
170 /// Parse a FDE into a CIE_Info and an FDE_Info. If useCIEInfo is
171 /// true, treat cieInfo as already-parsed CIE_Info (whose start offset
172 /// must match the one specified by the FDE) rather than parsing the
173 /// one indicated within the FDE.
174 template <typename A>
decodeFDE(A & addressSpace,pint_t fdeStart,FDE_Info * fdeInfo,CIE_Info * cieInfo,bool useCIEInfo)175 const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
176 FDE_Info *fdeInfo, CIE_Info *cieInfo,
177 bool useCIEInfo) {
178 pint_t p = fdeStart;
179 pint_t cfiLength = (pint_t)addressSpace.get32(p);
180 p += 4;
181 if (cfiLength == 0xffffffff) {
182 // 0xffffffff means length is really next 8 bytes
183 cfiLength = (pint_t)addressSpace.get64(p);
184 p += 8;
185 }
186 if (cfiLength == 0)
187 return "FDE has zero length"; // zero terminator
188 uint32_t ciePointer = addressSpace.get32(p);
189 if (ciePointer == 0)
190 return "FDE is really a CIE"; // this is a CIE not an FDE
191 pint_t nextCFI = p + cfiLength;
192 pint_t cieStart = p - ciePointer;
193 if (useCIEInfo) {
194 if (cieInfo->cieStart != cieStart)
195 return "CIE start does not match";
196 } else {
197 const char *err = parseCIE(addressSpace, cieStart, cieInfo);
198 if (err != NULL)
199 return err;
200 }
201 p += 4;
202 // Parse pc begin and range.
203 pint_t pcStart =
204 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
205 pint_t pcRange =
206 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
207 // Parse rest of info.
208 fdeInfo->lsda = 0;
209 // Check for augmentation length.
210 if (cieInfo->fdesHaveAugmentationData) {
211 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
212 pint_t endOfAug = p + augLen;
213 if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
214 // Peek at value (without indirection). Zero means no LSDA.
215 pint_t lsdaStart = p;
216 if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
217 0) {
218 // Reset pointer and re-parse LSDA address.
219 p = lsdaStart;
220 fdeInfo->lsda =
221 addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
222 }
223 }
224 p = endOfAug;
225 }
226 fdeInfo->fdeStart = fdeStart;
227 fdeInfo->fdeLength = nextCFI - fdeStart;
228 fdeInfo->fdeInstructions = p;
229 fdeInfo->pcStart = pcStart;
230 fdeInfo->pcEnd = pcStart + pcRange;
231 return NULL; // success
232 }
233
234 /// Scan an eh_frame section to find an FDE for a pc
235 template <typename A>
findFDE(A & addressSpace,pint_t pc,pint_t ehSectionStart,size_t sectionLength,pint_t fdeHint,FDE_Info * fdeInfo,CIE_Info * cieInfo)236 bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
237 size_t sectionLength, pint_t fdeHint,
238 FDE_Info *fdeInfo, CIE_Info *cieInfo) {
239 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
240 pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
241 const pint_t ehSectionEnd = (sectionLength == SIZE_MAX)
242 ? static_cast<pint_t>(-1)
243 : (ehSectionStart + sectionLength);
244 while (p < ehSectionEnd) {
245 pint_t currentCFI = p;
246 //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
247 pint_t cfiLength = addressSpace.get32(p);
248 p += 4;
249 if (cfiLength == 0xffffffff) {
250 // 0xffffffff means length is really next 8 bytes
251 cfiLength = (pint_t)addressSpace.get64(p);
252 p += 8;
253 }
254 if (cfiLength == 0)
255 return false; // zero terminator
256 uint32_t id = addressSpace.get32(p);
257 if (id == 0) {
258 // Skip over CIEs.
259 p += cfiLength;
260 } else {
261 // Process FDE to see if it covers pc.
262 pint_t nextCFI = p + cfiLength;
263 uint32_t ciePointer = addressSpace.get32(p);
264 pint_t cieStart = p - ciePointer;
265 // Validate pointer to CIE is within section.
266 if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
267 if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
268 p += 4;
269 // Parse pc begin and range.
270 pint_t pcStart =
271 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
272 pint_t pcRange = addressSpace.getEncodedP(
273 p, nextCFI, cieInfo->pointerEncoding & 0x0F);
274 // Test if pc is within the function this FDE covers.
275 if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
276 // parse rest of info
277 fdeInfo->lsda = 0;
278 // check for augmentation length
279 if (cieInfo->fdesHaveAugmentationData) {
280 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
281 pint_t endOfAug = p + augLen;
282 if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
283 // Peek at value (without indirection). Zero means no LSDA.
284 pint_t lsdaStart = p;
285 if (addressSpace.getEncodedP(
286 p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
287 // Reset pointer and re-parse LSDA address.
288 p = lsdaStart;
289 fdeInfo->lsda = addressSpace
290 .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
291 }
292 }
293 p = endOfAug;
294 }
295 fdeInfo->fdeStart = currentCFI;
296 fdeInfo->fdeLength = nextCFI - currentCFI;
297 fdeInfo->fdeInstructions = p;
298 fdeInfo->pcStart = pcStart;
299 fdeInfo->pcEnd = pcStart + pcRange;
300 return true;
301 } else {
302 // pc is not in begin/range, skip this FDE
303 }
304 } else {
305 // Malformed CIE, now augmentation describing pc range encoding.
306 }
307 } else {
308 // malformed FDE. CIE is bad
309 }
310 p = nextCFI;
311 }
312 }
313 return false;
314 }
315
316 /// Extract info from a CIE
317 template <typename A>
parseCIE(A & addressSpace,pint_t cie,CIE_Info * cieInfo)318 const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
319 CIE_Info *cieInfo) {
320 cieInfo->pointerEncoding = 0;
321 cieInfo->lsdaEncoding = DW_EH_PE_omit;
322 cieInfo->personalityEncoding = 0;
323 cieInfo->personalityOffsetInCIE = 0;
324 cieInfo->personality = 0;
325 cieInfo->codeAlignFactor = 0;
326 cieInfo->dataAlignFactor = 0;
327 cieInfo->isSignalFrame = false;
328 cieInfo->fdesHaveAugmentationData = false;
329 #if defined(_LIBUNWIND_TARGET_AARCH64)
330 cieInfo->addressesSignedWithBKey = false;
331 cieInfo->mteTaggedFrame = false;
332 #endif
333 cieInfo->cieStart = cie;
334 pint_t p = cie;
335 pint_t cieLength = (pint_t)addressSpace.get32(p);
336 p += 4;
337 pint_t cieContentEnd = p + cieLength;
338 if (cieLength == 0xffffffff) {
339 // 0xffffffff means length is really next 8 bytes
340 cieLength = (pint_t)addressSpace.get64(p);
341 p += 8;
342 cieContentEnd = p + cieLength;
343 }
344 if (cieLength == 0)
345 return NULL;
346 // CIE ID is always 0
347 if (addressSpace.get32(p) != 0)
348 return "CIE ID is not zero";
349 p += 4;
350 // Version is always 1 or 3
351 uint8_t version = addressSpace.get8(p);
352 if ((version != 1) && (version != 3))
353 return "CIE version is not 1 or 3";
354 ++p;
355 // save start of augmentation string and find end
356 pint_t strStart = p;
357 while (addressSpace.get8(p) != 0)
358 ++p;
359 ++p;
360 // parse code alignment factor
361 cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd);
362 // parse data alignment factor
363 cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
364 // parse return address register
365 uint64_t raReg = (version == 1) ? addressSpace.get8(p++)
366 : addressSpace.getULEB128(p, cieContentEnd);
367 assert(raReg < 255 && "return address register too large");
368 cieInfo->returnAddressRegister = (uint8_t)raReg;
369 // parse augmentation data based on augmentation string
370 const char *result = NULL;
371 if (addressSpace.get8(strStart) == 'z') {
372 // parse augmentation data length
373 addressSpace.getULEB128(p, cieContentEnd);
374 for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
375 switch (addressSpace.get8(s)) {
376 case 'z':
377 cieInfo->fdesHaveAugmentationData = true;
378 break;
379 case 'P':
380 cieInfo->personalityEncoding = addressSpace.get8(p);
381 ++p;
382 cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
383 cieInfo->personality = addressSpace
384 .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
385 break;
386 case 'L':
387 cieInfo->lsdaEncoding = addressSpace.get8(p);
388 ++p;
389 break;
390 case 'R':
391 cieInfo->pointerEncoding = addressSpace.get8(p);
392 ++p;
393 break;
394 case 'S':
395 cieInfo->isSignalFrame = true;
396 break;
397 #if defined(_LIBUNWIND_TARGET_AARCH64)
398 case 'B':
399 cieInfo->addressesSignedWithBKey = true;
400 break;
401 case 'G':
402 cieInfo->mteTaggedFrame = true;
403 break;
404 #endif
405 default:
406 // ignore unknown letters
407 break;
408 }
409 }
410 }
411 cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
412 cieInfo->cieInstructions = p;
413 return result;
414 }
415
416
417 /// "run" the DWARF instructions and create the abstract PrologInfo for an FDE
418 template <typename A>
parseFDEInstructions(A & addressSpace,const FDE_Info & fdeInfo,const CIE_Info & cieInfo,pint_t upToPC,int arch,PrologInfo * results)419 bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
420 const FDE_Info &fdeInfo,
421 const CIE_Info &cieInfo, pint_t upToPC,
422 int arch, PrologInfo *results) {
423 // Alloca is used for the allocation of the rememberStack entries. It removes
424 // the dependency on new/malloc but the below for loop can not be refactored
425 // into functions. Entry could be saved during the processing of a CIE and
426 // restored by an FDE.
427 RememberStack rememberStack;
428
429 struct ParseInfo {
430 pint_t instructions;
431 pint_t instructionsEnd;
432 pint_t pcoffset;
433 };
434
435 ParseInfo parseInfoArray[] = {
436 {cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength,
437 (pint_t)(-1)},
438 {fdeInfo.fdeInstructions, fdeInfo.fdeStart + fdeInfo.fdeLength,
439 upToPC - fdeInfo.pcStart}};
440
441 for (const auto &info : parseInfoArray) {
442 pint_t p = info.instructions;
443 pint_t instructionsEnd = info.instructionsEnd;
444 pint_t pcoffset = info.pcoffset;
445 pint_t codeOffset = 0;
446
447 // initialState initialized as registers in results are modified. Use
448 // PrologInfo accessor functions to avoid reading uninitialized data.
449 PrologInfo initialState(PrologInfo::InitializeTime::kLazy);
450
451 _LIBUNWIND_TRACE_DWARF("parseFDEInstructions(instructions=0x%0" PRIx64
452 ")\n",
453 static_cast<uint64_t>(instructionsEnd));
454
455 // see DWARF Spec, section 6.4.2 for details on unwind opcodes
456 while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
457 uint64_t reg;
458 uint64_t reg2;
459 int64_t offset;
460 uint64_t length;
461 uint8_t opcode = addressSpace.get8(p);
462 uint8_t operand;
463
464 ++p;
465 switch (opcode) {
466 case DW_CFA_nop:
467 _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
468 break;
469 case DW_CFA_set_loc:
470 codeOffset = addressSpace.getEncodedP(p, instructionsEnd,
471 cieInfo.pointerEncoding);
472 _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
473 break;
474 case DW_CFA_advance_loc1:
475 codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
476 p += 1;
477 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n",
478 static_cast<uint64_t>(codeOffset));
479 break;
480 case DW_CFA_advance_loc2:
481 codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
482 p += 2;
483 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n",
484 static_cast<uint64_t>(codeOffset));
485 break;
486 case DW_CFA_advance_loc4:
487 codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
488 p += 4;
489 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n",
490 static_cast<uint64_t>(codeOffset));
491 break;
492 case DW_CFA_offset_extended:
493 reg = addressSpace.getULEB128(p, instructionsEnd);
494 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) *
495 cieInfo.dataAlignFactor;
496 if (reg > kMaxRegisterNumber) {
497 _LIBUNWIND_LOG0(
498 "malformed DW_CFA_offset_extended DWARF unwind, reg too big");
499 return false;
500 }
501 results->setRegister(reg, kRegisterInCFA, offset, initialState);
502 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", "
503 "offset=%" PRId64 ")\n",
504 reg, offset);
505 break;
506 case DW_CFA_restore_extended:
507 reg = addressSpace.getULEB128(p, instructionsEnd);
508 if (reg > kMaxRegisterNumber) {
509 _LIBUNWIND_LOG0(
510 "malformed DW_CFA_restore_extended DWARF unwind, reg too big");
511 return false;
512 }
513 results->restoreRegisterToInitialState(reg, initialState);
514 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n",
515 reg);
516 break;
517 case DW_CFA_undefined:
518 reg = addressSpace.getULEB128(p, instructionsEnd);
519 if (reg > kMaxRegisterNumber) {
520 _LIBUNWIND_LOG0(
521 "malformed DW_CFA_undefined DWARF unwind, reg too big");
522 return false;
523 }
524 results->setRegisterLocation(reg, kRegisterUnused, initialState);
525 _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
526 break;
527 case DW_CFA_same_value:
528 reg = addressSpace.getULEB128(p, instructionsEnd);
529 if (reg > kMaxRegisterNumber) {
530 _LIBUNWIND_LOG0(
531 "malformed DW_CFA_same_value DWARF unwind, reg too big");
532 return false;
533 }
534 // <rdar://problem/8456377> DW_CFA_same_value unsupported
535 // "same value" means register was stored in frame, but its current
536 // value has not changed, so no need to restore from frame.
537 // We model this as if the register was never saved.
538 results->setRegisterLocation(reg, kRegisterUnused, initialState);
539 _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg);
540 break;
541 case DW_CFA_register:
542 reg = addressSpace.getULEB128(p, instructionsEnd);
543 reg2 = addressSpace.getULEB128(p, instructionsEnd);
544 if (reg > kMaxRegisterNumber) {
545 _LIBUNWIND_LOG0(
546 "malformed DW_CFA_register DWARF unwind, reg too big");
547 return false;
548 }
549 if (reg2 > kMaxRegisterNumber) {
550 _LIBUNWIND_LOG0(
551 "malformed DW_CFA_register DWARF unwind, reg2 too big");
552 return false;
553 }
554 results->setRegister(reg, kRegisterInRegister, (int64_t)reg2,
555 initialState);
556 _LIBUNWIND_TRACE_DWARF(
557 "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2);
558 break;
559 case DW_CFA_remember_state: {
560 // Avoid operator new because that would be an upward dependency.
561 // Avoid malloc because it needs heap allocation.
562 PrologInfoStackEntry *entry =
563 (PrologInfoStackEntry *)_LIBUNWIND_REMEMBER_ALLOC(
564 sizeof(PrologInfoStackEntry));
565 if (entry != NULL) {
566 entry->next = rememberStack.entry;
567 entry->info = *results;
568 rememberStack.entry = entry;
569 } else {
570 return false;
571 }
572 _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
573 break;
574 }
575 case DW_CFA_restore_state:
576 if (rememberStack.entry != NULL) {
577 PrologInfoStackEntry *top = rememberStack.entry;
578 *results = top->info;
579 rememberStack.entry = top->next;
580 _LIBUNWIND_REMEMBER_FREE(top);
581 } else {
582 return false;
583 }
584 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n");
585 break;
586 case DW_CFA_def_cfa:
587 reg = addressSpace.getULEB128(p, instructionsEnd);
588 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
589 if (reg > kMaxRegisterNumber) {
590 _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
591 return false;
592 }
593 results->cfaRegister = (uint32_t)reg;
594 results->cfaRegisterOffset = (int32_t)offset;
595 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64
596 ")\n",
597 reg, offset);
598 break;
599 case DW_CFA_def_cfa_register:
600 reg = addressSpace.getULEB128(p, instructionsEnd);
601 if (reg > kMaxRegisterNumber) {
602 _LIBUNWIND_LOG0(
603 "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
604 return false;
605 }
606 results->cfaRegister = (uint32_t)reg;
607 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg);
608 break;
609 case DW_CFA_def_cfa_offset:
610 results->cfaRegisterOffset =
611 (int32_t)addressSpace.getULEB128(p, instructionsEnd);
612 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n",
613 results->cfaRegisterOffset);
614 break;
615 case DW_CFA_def_cfa_expression:
616 results->cfaRegister = 0;
617 results->cfaExpression = (int64_t)p;
618 length = addressSpace.getULEB128(p, instructionsEnd);
619 assert(length < static_cast<pint_t>(~0) && "pointer overflow");
620 p += static_cast<pint_t>(length);
621 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64
622 ", length=%" PRIu64 ")\n",
623 results->cfaExpression, length);
624 break;
625 case DW_CFA_expression:
626 reg = addressSpace.getULEB128(p, instructionsEnd);
627 if (reg > kMaxRegisterNumber) {
628 _LIBUNWIND_LOG0(
629 "malformed DW_CFA_expression DWARF unwind, reg too big");
630 return false;
631 }
632 results->setRegister(reg, kRegisterAtExpression, (int64_t)p,
633 initialState);
634 length = addressSpace.getULEB128(p, instructionsEnd);
635 assert(length < static_cast<pint_t>(~0) && "pointer overflow");
636 p += static_cast<pint_t>(length);
637 _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", "
638 "expression=0x%" PRIx64 ", "
639 "length=%" PRIu64 ")\n",
640 reg, results->savedRegisters[reg].value, length);
641 break;
642 case DW_CFA_offset_extended_sf:
643 reg = addressSpace.getULEB128(p, instructionsEnd);
644 if (reg > kMaxRegisterNumber) {
645 _LIBUNWIND_LOG0(
646 "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
647 return false;
648 }
649 offset = addressSpace.getSLEB128(p, instructionsEnd) *
650 cieInfo.dataAlignFactor;
651 results->setRegister(reg, kRegisterInCFA, offset, initialState);
652 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", "
653 "offset=%" PRId64 ")\n",
654 reg, offset);
655 break;
656 case DW_CFA_def_cfa_sf:
657 reg = addressSpace.getULEB128(p, instructionsEnd);
658 offset = addressSpace.getSLEB128(p, instructionsEnd) *
659 cieInfo.dataAlignFactor;
660 if (reg > kMaxRegisterNumber) {
661 _LIBUNWIND_LOG0(
662 "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big");
663 return false;
664 }
665 results->cfaRegister = (uint32_t)reg;
666 results->cfaRegisterOffset = (int32_t)offset;
667 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", "
668 "offset=%" PRId64 ")\n",
669 reg, offset);
670 break;
671 case DW_CFA_def_cfa_offset_sf:
672 results->cfaRegisterOffset =
673 (int32_t)(addressSpace.getSLEB128(p, instructionsEnd) *
674 cieInfo.dataAlignFactor);
675 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n",
676 results->cfaRegisterOffset);
677 break;
678 case DW_CFA_val_offset:
679 reg = addressSpace.getULEB128(p, instructionsEnd);
680 if (reg > kMaxRegisterNumber) {
681 _LIBUNWIND_LOG(
682 "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64
683 ") out of range\n",
684 reg);
685 return false;
686 }
687 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) *
688 cieInfo.dataAlignFactor;
689 results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState);
690 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", "
691 "offset=%" PRId64 "\n",
692 reg, offset);
693 break;
694 case DW_CFA_val_offset_sf:
695 reg = addressSpace.getULEB128(p, instructionsEnd);
696 if (reg > kMaxRegisterNumber) {
697 _LIBUNWIND_LOG0(
698 "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
699 return false;
700 }
701 offset = addressSpace.getSLEB128(p, instructionsEnd) *
702 cieInfo.dataAlignFactor;
703 results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState);
704 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", "
705 "offset=%" PRId64 "\n",
706 reg, offset);
707 break;
708 case DW_CFA_val_expression:
709 reg = addressSpace.getULEB128(p, instructionsEnd);
710 if (reg > kMaxRegisterNumber) {
711 _LIBUNWIND_LOG0(
712 "malformed DW_CFA_val_expression DWARF unwind, reg too big");
713 return false;
714 }
715 results->setRegister(reg, kRegisterIsExpression, (int64_t)p,
716 initialState);
717 length = addressSpace.getULEB128(p, instructionsEnd);
718 assert(length < static_cast<pint_t>(~0) && "pointer overflow");
719 p += static_cast<pint_t>(length);
720 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", "
721 "expression=0x%" PRIx64 ", length=%" PRIu64
722 ")\n",
723 reg, results->savedRegisters[reg].value, length);
724 break;
725 case DW_CFA_GNU_args_size:
726 length = addressSpace.getULEB128(p, instructionsEnd);
727 results->spExtraArgSize = (uint32_t)length;
728 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length);
729 break;
730 case DW_CFA_GNU_negative_offset_extended:
731 reg = addressSpace.getULEB128(p, instructionsEnd);
732 if (reg > kMaxRegisterNumber) {
733 _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF "
734 "unwind, reg too big");
735 return false;
736 }
737 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) *
738 cieInfo.dataAlignFactor;
739 results->setRegister(reg, kRegisterInCFA, -offset, initialState);
740 _LIBUNWIND_TRACE_DWARF(
741 "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
742 break;
743
744 #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) || \
745 defined(_LIBUNWIND_TARGET_SPARC64)
746 // The same constant is used to represent different instructions on
747 // AArch64 (negate_ra_state) and SPARC (window_save).
748 static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save,
749 "uses the same constant");
750 case DW_CFA_AARCH64_negate_ra_state:
751 switch (arch) {
752 #if defined(_LIBUNWIND_TARGET_AARCH64)
753 case REGISTERS_ARM64: {
754 int64_t value =
755 results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x1;
756 results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value,
757 initialState);
758 _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n");
759 } break;
760 #endif
761
762 #if defined(_LIBUNWIND_TARGET_SPARC)
763 // case DW_CFA_GNU_window_save:
764 case REGISTERS_SPARC:
765 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n");
766 for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) {
767 results->setRegister(reg, kRegisterInRegister,
768 ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0,
769 initialState);
770 }
771
772 for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
773 results->setRegister(reg, kRegisterInCFA,
774 ((int64_t)reg - UNW_SPARC_L0) * 4,
775 initialState);
776 }
777 break;
778 #endif
779
780 #if defined(_LIBUNWIND_TARGET_SPARC64)
781 // case DW_CFA_GNU_window_save:
782 case REGISTERS_SPARC64:
783 // Don't save %o0-%o7 on sparc64.
784 // https://reviews.llvm.org/D32450#736405
785
786 for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
787 if (reg == UNW_SPARC_I7)
788 results->setRegister(
789 reg, kRegisterInCFADecrypt,
790 static_cast<int64_t>((reg - UNW_SPARC_L0) * sizeof(pint_t)),
791 initialState);
792 else
793 results->setRegister(
794 reg, kRegisterInCFA,
795 static_cast<int64_t>((reg - UNW_SPARC_L0) * sizeof(pint_t)),
796 initialState);
797 }
798 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save\n");
799 break;
800 #endif
801 }
802 break;
803
804 #if defined(_LIBUNWIND_TARGET_AARCH64)
805 case DW_CFA_AARCH64_negate_ra_state_with_pc: {
806 int64_t value =
807 results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3;
808 results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value,
809 initialState);
810 // When calculating the value of the PC, it is assumed that the CFI
811 // instruction is placed before the signing instruction, however it is
812 // placed after. Because of this, we need to take into account the CFI
813 // instruction is one instruction call later than expected, and reduce
814 // the PC value by 4 bytes to compensate.
815 results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset - 0x4;
816 _LIBUNWIND_TRACE_DWARF(
817 "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n",
818 static_cast<uint64_t>(results->ptrAuthDiversifier));
819 } break;
820 #endif
821
822 #else
823 (void)arch;
824 #endif
825
826 default:
827 operand = opcode & 0x3F;
828 switch (opcode & 0xC0) {
829 case DW_CFA_offset:
830 reg = operand;
831 if (reg > kMaxRegisterNumber) {
832 _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
833 ") out of range",
834 reg);
835 return false;
836 }
837 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) *
838 cieInfo.dataAlignFactor;
839 results->setRegister(reg, kRegisterInCFA, offset, initialState);
840 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
841 operand, offset);
842 break;
843 case DW_CFA_advance_loc:
844 codeOffset += operand * cieInfo.codeAlignFactor;
845 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n",
846 static_cast<uint64_t>(codeOffset));
847 break;
848 case DW_CFA_restore:
849 reg = operand;
850 if (reg > kMaxRegisterNumber) {
851 _LIBUNWIND_LOG(
852 "malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
853 ") out of range",
854 reg);
855 return false;
856 }
857 results->restoreRegisterToInitialState(reg, initialState);
858 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n",
859 static_cast<uint64_t>(operand));
860 break;
861 default:
862 _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode);
863 return false;
864 }
865 }
866 }
867 }
868 return true;
869 }
870
871 } // namespace libunwind
872
873 #endif // __DWARF_PARSER_HPP__
874