1 //===- llvm/unittest/DebugInfo/DWARFDebugFrameTest.cpp --------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
10 #include "llvm/ADT/DenseSet.h"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/BinaryFormat/Dwarf.h"
14 #include "llvm/DebugInfo/DIContext.h"
15 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
16 #include "llvm/Testing/Support/Error.h"
17 #include "gtest/gtest.h"
23 dwarf::CIE
createCIE(bool IsDWARF64
, uint64_t Offset
, uint64_t Length
) {
24 return dwarf::CIE(IsDWARF64
, Offset
, Length
,
26 /*Augmentation=*/StringRef(),
28 /*SegmentDescriptorSize=*/0,
29 /*CodeAlignmentFactor=*/1,
30 /*DataAlignmentFactor=*/-8,
31 /*ReturnAddressRegister=*/16,
32 /*AugmentationData=*/StringRef(),
33 /*FDEPointerEncoding=*/dwarf::DW_EH_PE_absptr
,
34 /*LSDAPointerEncoding=*/dwarf::DW_EH_PE_omit
,
35 /*Personality=*/std::nullopt
,
36 /*PersonalityEnc=*/std::nullopt
,
37 /*Arch=*/Triple::x86_64
);
40 void expectDumpResult(const dwarf::CIE
&TestCIE
, bool IsEH
,
41 StringRef ExpectedFirstLine
) {
43 raw_string_ostream
OS(Output
);
44 auto DumpOpts
= DIDumpOptions();
46 TestCIE
.dump(OS
, DumpOpts
);
47 StringRef FirstLine
= StringRef(Output
).split('\n').first
;
48 EXPECT_EQ(FirstLine
, ExpectedFirstLine
);
51 void expectDumpResult(const dwarf::FDE
&TestFDE
, bool IsEH
,
52 StringRef ExpectedFirstLine
) {
54 raw_string_ostream
OS(Output
);
55 auto DumpOpts
= DIDumpOptions();
57 TestFDE
.dump(OS
, DumpOpts
);
58 StringRef FirstLine
= StringRef(Output
).split('\n').first
;
59 EXPECT_EQ(FirstLine
, ExpectedFirstLine
);
62 TEST(DWARFDebugFrame
, DumpDWARF32CIE
) {
63 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
64 /*Offset=*/0x1111abcd,
65 /*Length=*/0x2222abcd);
66 expectDumpResult(TestCIE
, /*IsEH=*/false, "1111abcd 2222abcd ffffffff CIE");
69 TEST(DWARFDebugFrame
, DumpDWARF64CIE
) {
70 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/true,
71 /*Offset=*/0x1111abcdabcd,
72 /*Length=*/0x2222abcdabcd);
73 expectDumpResult(TestCIE
, /*IsEH=*/false,
74 "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE");
77 TEST(DWARFDebugFrame
, DumpEHCIE
) {
78 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
81 expectDumpResult(TestCIE
, /*IsEH=*/true, "00001000 00000020 00000000 CIE");
84 TEST(DWARFDebugFrame
, DumpEH64CIE
) {
85 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/true,
88 expectDumpResult(TestCIE
, /*IsEH=*/true,
89 "00001000 0000000000000020 00000000 CIE");
92 TEST(DWARFDebugFrame
, DumpDWARF64FDE
) {
93 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/true,
94 /*Offset=*/0x1111abcdabcd,
95 /*Length=*/0x2222abcdabcd);
96 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
97 /*Offset=*/0x3333abcdabcd,
98 /*Length=*/0x4444abcdabcd,
99 /*CIEPointer=*/0x1111abcdabcd,
100 /*InitialLocation=*/0x5555abcdabcd,
101 /*AddressRange=*/0x111111111111,
103 /*LSDAAddress=*/std::nullopt
,
104 /*Arch=*/Triple::x86_64
);
105 expectDumpResult(TestFDE
, /*IsEH=*/false,
106 "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE "
107 "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde");
110 TEST(DWARFDebugFrame
, DumpEH64FDE
) {
111 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/true,
112 /*Offset=*/0x1111ab9a000c,
114 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
115 /*Offset=*/0x1111abcdabcd,
116 /*Length=*/0x2222abcdabcd,
117 /*CIEPointer=*/0x33abcd,
118 /*InitialLocation=*/0x4444abcdabcd,
119 /*AddressRange=*/0x111111111111,
121 /*LSDAAddress=*/std::nullopt
,
122 /*Arch=*/Triple::x86_64
);
123 expectDumpResult(TestFDE
, /*IsEH=*/true,
124 "1111abcdabcd 00002222abcdabcd 0033abcd FDE "
125 "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde");
128 static Error
parseCFI(dwarf::CIE
&C
, ArrayRef
<uint8_t> Instructions
,
129 std::optional
<uint64_t> Size
= std::nullopt
) {
130 DWARFDataExtractor
Data(Instructions
, /*IsLittleEndian=*/true,
133 const uint64_t EndOffset
= Size
? *Size
: (uint64_t)Instructions
.size();
134 return C
.cfis().parse(Data
, &Offset
, EndOffset
);
137 static Error
parseCFI(dwarf::FDE
&FDE
, ArrayRef
<uint8_t> Instructions
) {
138 DWARFDataExtractor
Data(Instructions
, /*IsLittleEndian=*/true,
141 return FDE
.cfis().parse(Data
, &Offset
, Instructions
.size());
144 TEST(DWARFDebugFrame
, InvalidCFIOpcodesTest
) {
145 llvm::DenseSet
<uint8_t> ValidExtendedOpcodes
= {
147 dwarf::DW_CFA_advance_loc
,
148 dwarf::DW_CFA_offset
,
149 dwarf::DW_CFA_restore
,
150 dwarf::DW_CFA_set_loc
,
151 dwarf::DW_CFA_advance_loc1
,
152 dwarf::DW_CFA_advance_loc2
,
153 dwarf::DW_CFA_advance_loc4
,
154 dwarf::DW_CFA_offset_extended
,
155 dwarf::DW_CFA_restore_extended
,
156 dwarf::DW_CFA_undefined
,
157 dwarf::DW_CFA_same_value
,
158 dwarf::DW_CFA_register
,
159 dwarf::DW_CFA_remember_state
,
160 dwarf::DW_CFA_restore_state
,
161 dwarf::DW_CFA_def_cfa
,
162 dwarf::DW_CFA_def_cfa_register
,
163 dwarf::DW_CFA_def_cfa_offset
,
164 dwarf::DW_CFA_def_cfa_expression
,
165 dwarf::DW_CFA_expression
,
166 dwarf::DW_CFA_offset_extended_sf
,
167 dwarf::DW_CFA_def_cfa_sf
,
168 dwarf::DW_CFA_def_cfa_offset_sf
,
169 dwarf::DW_CFA_LLVM_def_aspace_cfa
,
170 dwarf::DW_CFA_LLVM_def_aspace_cfa_sf
,
171 dwarf::DW_CFA_val_offset
,
172 dwarf::DW_CFA_val_offset_sf
,
173 dwarf::DW_CFA_val_expression
,
174 dwarf::DW_CFA_MIPS_advance_loc8
,
175 dwarf::DW_CFA_GNU_window_save
,
176 dwarf::DW_CFA_AARCH64_negate_ra_state
,
177 dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc
,
178 dwarf::DW_CFA_GNU_args_size
};
180 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
184 // See DWARF standard v3, section 7.23: low 6 bits are used to encode an
186 for (uint8_t Code
= 0; Code
<= 63; ++Code
) {
187 if (ValidExtendedOpcodes
.count(Code
))
190 EXPECT_THAT_ERROR(parseCFI(TestCIE
, Code
),
191 FailedWithMessage(("invalid extended CFI opcode 0x" +
192 Twine::utohexstr(Code
))
198 // Here we test how truncated Call Frame Instructions are parsed.
199 TEST(DWARFDebugFrame
, ParseTruncatedCFITest
) {
200 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
204 // Having an empty instructions list is fine.
205 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {}), Succeeded());
207 // Unable to read an opcode, because the instructions list is empty, but we
208 // say to the parser that it is not.
210 parseCFI(TestCIE
, {}, /*Size=*/1),
212 "unexpected end of data at offset 0x0 while reading [0x0, 0x1)"));
214 // Unable to read a truncated DW_CFA_offset instruction.
216 parseCFI(TestCIE
, {dwarf::DW_CFA_offset
}),
217 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
218 "malformed uleb128, extends past end"));
220 // Unable to read a truncated DW_CFA_set_loc instruction.
222 parseCFI(TestCIE
, {dwarf::DW_CFA_set_loc
}),
224 "unexpected end of data at offset 0x1 while reading [0x1, 0x9)"));
226 // Unable to read a truncated DW_CFA_advance_loc1 instruction.
228 parseCFI(TestCIE
, {dwarf::DW_CFA_advance_loc1
}),
230 "unexpected end of data at offset 0x1 while reading [0x1, 0x2)"));
232 // Unable to read a truncated DW_CFA_advance_loc2 instruction.
234 parseCFI(TestCIE
, {dwarf::DW_CFA_advance_loc2
}),
236 "unexpected end of data at offset 0x1 while reading [0x1, 0x3)"));
238 // Unable to read a truncated DW_CFA_advance_loc4 instruction.
240 parseCFI(TestCIE
, {dwarf::DW_CFA_advance_loc4
}),
242 "unexpected end of data at offset 0x1 while reading [0x1, 0x5)"));
244 // A test for an instruction with a single ULEB128 operand.
245 auto CheckOp_ULEB128
= [&](uint8_t Inst
) {
247 parseCFI(TestCIE
, Inst
),
248 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
249 "malformed uleb128, extends past end"));
253 {dwarf::DW_CFA_restore_extended
, dwarf::DW_CFA_undefined
,
254 dwarf::DW_CFA_same_value
, dwarf::DW_CFA_def_cfa_register
,
255 dwarf::DW_CFA_def_cfa_offset
, dwarf::DW_CFA_GNU_args_size
})
256 CheckOp_ULEB128(Inst
);
258 // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction.
260 parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa_offset_sf
}),
261 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
262 "malformed sleb128, extends past end"));
264 // A test for an instruction with two ULEB128 operands.
265 auto CheckOp_ULEB128_ULEB128
= [&](uint8_t Inst
) {
267 parseCFI(TestCIE
, Inst
),
268 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
269 "malformed uleb128, extends past end"));
272 parseCFI(TestCIE
, {Inst
, /*Op1=*/0}),
273 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
274 "malformed uleb128, extends past end"));
277 for (uint8_t Inst
: {dwarf::DW_CFA_offset_extended
, dwarf::DW_CFA_register
,
278 dwarf::DW_CFA_def_cfa
, dwarf::DW_CFA_LLVM_def_aspace_cfa
,
279 dwarf::DW_CFA_val_offset
})
280 CheckOp_ULEB128_ULEB128(Inst
);
282 // A test for an instruction with two operands: ULEB128, SLEB128.
283 auto CheckOp_ULEB128_SLEB128
= [&](uint8_t Inst
) {
285 parseCFI(TestCIE
, Inst
),
286 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
287 "malformed uleb128, extends past end"));
290 parseCFI(TestCIE
, {Inst
, /*Op1=*/0}),
291 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
292 "malformed sleb128, extends past end"));
296 {dwarf::DW_CFA_offset_extended_sf
, dwarf::DW_CFA_def_cfa_sf
,
297 dwarf::DW_CFA_LLVM_def_aspace_cfa_sf
, dwarf::DW_CFA_val_offset_sf
})
298 CheckOp_ULEB128_SLEB128(Inst
);
300 // Unable to read a truncated DW_CFA_def_cfa_expression instruction.
302 parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa_expression
}),
303 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
304 "malformed uleb128, extends past end"));
306 parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa_expression
,
307 /*expression length=*/0x1}),
309 "unexpected end of data at offset 0x2 while reading [0x2, 0x3)"));
310 // The DW_CFA_def_cfa_expression can contain a zero length expression.
311 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa_expression
,
315 // A test for an instruction with three operands: ULEB128, expression length
316 // (ULEB128) and expression bytes.
317 auto CheckOp_ULEB128_Expr
= [&](uint8_t Inst
) {
319 parseCFI(TestCIE
, {Inst
}),
320 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
321 "malformed uleb128, extends past end"));
323 parseCFI(TestCIE
, {Inst
, /*Op1=*/0}),
324 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
325 "malformed uleb128, extends past end"));
326 // A zero length expression is fine
327 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {Inst
,
328 /*Op1=*/0, /*ExprLen=*/0}),
331 parseCFI(TestCIE
, {Inst
,
332 /*Op1=*/0, /*ExprLen=*/1}),
334 "unexpected end of data at offset 0x3 while reading [0x3, 0x4)"));
337 for (uint8_t Inst
: {dwarf::DW_CFA_expression
, dwarf::DW_CFA_val_expression
})
338 CheckOp_ULEB128_Expr(Inst
);
341 void expectDumpResult(const dwarf::UnwindLocation
&Loc
,
342 StringRef ExpectedFirstLine
) {
344 raw_string_ostream
OS(Output
);
346 StringRef FirstLine
= StringRef(Output
).split('\n').first
;
347 EXPECT_EQ(FirstLine
, ExpectedFirstLine
);
350 TEST(DWARFDebugFrame
, DumpUnwindLocations
) {
351 // Test constructing unwind locations and dumping each kind.
352 constexpr int32_t PlusOff
= 8;
353 constexpr int32_t MinusOff
= -8;
354 constexpr uint8_t RegNum
= 12;
355 expectDumpResult(dwarf::UnwindLocation::createUnspecified(), "unspecified");
356 expectDumpResult(dwarf::UnwindLocation::createUndefined(), "undefined");
357 expectDumpResult(dwarf::UnwindLocation::createSame(), "same");
358 expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(PlusOff
),
360 expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff
),
362 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff
),
364 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff
),
368 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum
, PlusOff
),
371 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum
, MinusOff
),
374 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum
, PlusOff
),
377 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum
, MinusOff
),
379 expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12");
380 expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32");
383 void expectDumpResult(const dwarf::RegisterLocations
&Locs
,
384 StringRef ExpectedFirstLine
) {
386 raw_string_ostream
OS(Output
);
388 StringRef FirstLine
= StringRef(Output
).split('\n').first
;
389 EXPECT_EQ(FirstLine
, ExpectedFirstLine
);
392 TEST(DWARFDebugFrame
, RegisterLocations
) {
393 // Test the functionality of the RegisterLocations class.
394 dwarf::RegisterLocations Locs
;
395 expectDumpResult(Locs
, "");
396 EXPECT_FALSE(Locs
.hasLocations());
397 // Set a register location for reg12 to unspecified and verify it dumps
399 Locs
.setRegisterLocation(12, dwarf::UnwindLocation::createUnspecified());
400 EXPECT_TRUE(Locs
.hasLocations());
401 expectDumpResult(Locs
, "reg12=unspecified");
403 // Replace the register location for reg12 to "same" and verify it dumps
404 // correctly after it is modified
405 Locs
.setRegisterLocation(12, dwarf::UnwindLocation::createSame());
406 EXPECT_TRUE(Locs
.hasLocations());
407 expectDumpResult(Locs
, "reg12=same");
409 // Remove the register location for reg12 verify it dumps correctly after it
411 Locs
.removeRegisterLocation(12);
412 EXPECT_FALSE(Locs
.hasLocations());
413 expectDumpResult(Locs
, "");
415 // Verify multiple registers added to the list dump correctly.
416 auto Reg12Loc
= dwarf::UnwindLocation::createAtCFAPlusOffset(4);
417 auto Reg13Loc
= dwarf::UnwindLocation::createAtCFAPlusOffset(8);
418 auto Reg14Loc
= dwarf::UnwindLocation::createSame();
419 Locs
.setRegisterLocation(12, Reg12Loc
);
420 Locs
.setRegisterLocation(13, Reg13Loc
);
421 Locs
.setRegisterLocation(14, Reg14Loc
);
422 EXPECT_TRUE(Locs
.hasLocations());
423 expectDumpResult(Locs
, "reg12=[CFA+4], reg13=[CFA+8], reg14=same");
425 // Verify RegisterLocations::getRegisterLocation() works as expected.
426 std::optional
<dwarf::UnwindLocation
> OptionalLoc
;
427 OptionalLoc
= Locs
.getRegisterLocation(0);
428 EXPECT_FALSE(OptionalLoc
.has_value());
430 OptionalLoc
= Locs
.getRegisterLocation(12);
431 EXPECT_TRUE(OptionalLoc
.has_value());
432 EXPECT_EQ(*OptionalLoc
, Reg12Loc
);
434 OptionalLoc
= Locs
.getRegisterLocation(13);
435 EXPECT_TRUE(OptionalLoc
.has_value());
436 EXPECT_EQ(*OptionalLoc
, Reg13Loc
);
438 OptionalLoc
= Locs
.getRegisterLocation(14);
439 EXPECT_TRUE(OptionalLoc
.has_value());
440 EXPECT_EQ(*OptionalLoc
, Reg14Loc
);
442 // Verify registers are correctly removed when multiple exist in the list.
443 Locs
.removeRegisterLocation(13);
444 EXPECT_FALSE(Locs
.getRegisterLocation(13).has_value());
445 EXPECT_TRUE(Locs
.hasLocations());
446 expectDumpResult(Locs
, "reg12=[CFA+4], reg14=same");
447 Locs
.removeRegisterLocation(14);
448 EXPECT_FALSE(Locs
.getRegisterLocation(14).has_value());
449 EXPECT_TRUE(Locs
.hasLocations());
450 expectDumpResult(Locs
, "reg12=[CFA+4]");
451 Locs
.removeRegisterLocation(12);
452 EXPECT_FALSE(Locs
.getRegisterLocation(12).has_value());
453 EXPECT_FALSE(Locs
.hasLocations());
454 expectDumpResult(Locs
, "");
457 // Test that empty rows are not added to UnwindTable when
458 // dwarf::CIE::CFIs or dwarf::FDE::CFIs is empty.
459 TEST(DWARFDebugFrame
, UnwindTableEmptyRows
) {
460 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
464 // Having an empty instructions list is fine.
465 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {}), Succeeded());
466 EXPECT_TRUE(TestCIE
.cfis().empty());
468 // Verify dwarf::UnwindTable::create() won't result in errors and
469 // and empty rows are not added to CIE UnwindTable.
470 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestCIE
);
471 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
472 const size_t ExpectedNumOfRows
= 0;
473 EXPECT_EQ(RowsOrErr
->size(), ExpectedNumOfRows
);
475 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
476 /*Offset=*/0x3333abcdabcd,
477 /*Length=*/0x4444abcdabcd,
478 /*CIEPointer=*/0x1111abcdabcd,
479 /*InitialLocation=*/0x1000,
480 /*AddressRange=*/0x1000,
482 /*LSDAAddress=*/std::nullopt
,
483 /*Arch=*/Triple::x86_64
);
485 // Having an empty instructions list is fine.
486 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {}), Succeeded());
487 EXPECT_TRUE(TestFDE
.cfis().empty());
489 // Verify dwarf::UnwindTable::create() won't result in errors and
490 // and empty rows are not added to FDE UnwindTable.
491 RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
492 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
493 EXPECT_EQ(RowsOrErr
->size(), ExpectedNumOfRows
);
496 // Test that empty rows are not added to UnwindTable when dwarf::CIE::CFIs
497 // or dwarf::FDE::CFIs is not empty but has only DW_CFA_nop instructions.
498 TEST(DWARFDebugFrame
, UnwindTableEmptyRows_NOPs
) {
499 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
503 // Make a CIE that has only DW_CFA_nop instructions.
504 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_nop
}), Succeeded());
505 EXPECT_TRUE(!TestCIE
.cfis().empty());
507 // Verify dwarf::UnwindTable::create() won't result in errors and
508 // and empty rows are not added to CIE UnwindTable.
509 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestCIE
);
510 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
511 const size_t ExpectedNumOfRows
= 0;
512 EXPECT_EQ(RowsOrErr
->size(), ExpectedNumOfRows
);
514 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
515 /*Offset=*/0x3333abcdabcd,
516 /*Length=*/0x4444abcdabcd,
517 /*CIEPointer=*/0x1111abcdabcd,
518 /*InitialLocation=*/0x1000,
519 /*AddressRange=*/0x1000,
521 /*LSDAAddress=*/std::nullopt
,
522 /*Arch=*/Triple::x86_64
);
524 // Make an FDE that has only DW_CFA_nop instructions.
525 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_nop
}), Succeeded());
526 EXPECT_TRUE(!TestFDE
.cfis().empty());
528 // Verify dwarf::UnwindTable::create() won't result in errors and
529 // and empty rows are not added to FDE UnwindTable.
530 RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
531 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
532 EXPECT_EQ(RowsOrErr
->size(), ExpectedNumOfRows
);
535 TEST(DWARFDebugFrame
, UnwindTableErrorNonAscendingFDERows
) {
536 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
540 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
541 /*Offset=*/0x3333abcdabcd,
542 /*Length=*/0x4444abcdabcd,
543 /*CIEPointer=*/0x1111abcdabcd,
544 /*InitialLocation=*/0x1000,
545 /*AddressRange=*/0x1000,
547 /*LSDAAddress=*/std::nullopt
,
548 /*Arch=*/Triple::x86_64
);
550 // Make a CIE that has a valid CFA definition.
551 constexpr uint8_t Reg
= 12;
552 constexpr uint8_t Offset
= 32;
553 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, Reg
, Offset
}),
556 // Make a FDE with DWARF call frame instruction opcodes that have valid
557 // syntax, but will cause an error when we parse them into a UnwindTable.
558 // Here we encode two DW_CFA_set_loc opcodes:
559 // DW_CFA_set_loc(0x1100)
560 // DW_CFA_set_loc(0x1000)
561 // These opcodes cause a new row to be appended to the rows in a UnwindTable
562 // and the resulting rows are not in ascending address order and should cause
563 // a state machine error.
565 parseCFI(TestFDE
, {dwarf::DW_CFA_set_loc
, 0x00, 0x11, 0, 0, 0, 0, 0, 0,
566 dwarf::DW_CFA_set_loc
, 0x00, 0x10, 0, 0, 0, 0, 0, 0}),
569 // Verify we catch state machine error.
570 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
571 EXPECT_THAT_ERROR(RowsOrErr
.takeError(),
572 FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which"
573 " must be greater than the current row "
577 TEST(DWARFDebugFrame
, UnwindTableError_DW_CFA_restore_state
) {
578 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
582 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
583 /*Offset=*/0x3333abcdabcd,
584 /*Length=*/0x4444abcdabcd,
585 /*CIEPointer=*/0x1111abcdabcd,
586 /*InitialLocation=*/0x1000,
587 /*AddressRange=*/0x1000,
589 /*LSDAAddress=*/std::nullopt
,
590 /*Arch=*/Triple::x86_64
);
592 // Make a CIE that has a valid CFA definition.
593 constexpr uint8_t Reg
= 12;
594 constexpr uint8_t Offset
= 32;
595 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, Reg
, Offset
}),
598 // Make a FDE with DWARF call frame instruction opcodes that have valid
599 // syntax, but will cause an error when we parse them into a UnwindTable.
600 // Here we encode a DW_CFA_restore_state opcode that was not preceded by a
601 // DW_CFA_remember_state, and an error should be returned.
602 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_restore_state
}),
605 // Verify we catch state machine error.
606 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
607 EXPECT_THAT_ERROR(RowsOrErr
.takeError(),
608 FailedWithMessage("DW_CFA_restore_state without a matching "
609 "previous DW_CFA_remember_state"));
612 TEST(DWARFDebugFrame
, UnwindTableError_DW_CFA_GNU_window_save
) {
613 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
617 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
618 /*Offset=*/0x3333abcdabcd,
619 /*Length=*/0x4444abcdabcd,
620 /*CIEPointer=*/0x1111abcdabcd,
621 /*InitialLocation=*/0x1000,
622 /*AddressRange=*/0x1000,
624 /*LSDAAddress=*/std::nullopt
,
625 /*Arch=*/Triple::x86_64
);
627 // Make a CIE that has a valid CFA definition.
628 constexpr uint8_t Reg
= 12;
629 constexpr uint8_t Offset
= 32;
630 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, Reg
, Offset
}),
633 // Make a FDE with DWARF call frame instruction opcodes that have valid
634 // syntax, but will cause an error when we parse them into a UnwindTable.
635 // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not
636 // found any documentation that describes what this does after some brief
638 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_GNU_window_save
}),
641 // Verify we catch state machine error.
642 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
643 EXPECT_THAT_ERROR(RowsOrErr
.takeError(),
644 FailedWithMessage("DW_CFA opcode 0x2d is not supported for "
645 "architecture x86_64"));
648 TEST(DWARFDebugFrame
, UnwindTableError_DW_CFA_def_cfa_offset
) {
649 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
653 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
654 /*Offset=*/0x3333abcdabcd,
655 /*Length=*/0x4444abcdabcd,
656 /*CIEPointer=*/0x1111abcdabcd,
657 /*InitialLocation=*/0x1000,
658 /*AddressRange=*/0x1000,
660 /*LSDAAddress=*/std::nullopt
,
661 /*Arch=*/Triple::x86_64
);
663 // Make a CIE that has an invalid CFA definition. We do this so we can try
664 // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate
666 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {}), Succeeded());
668 // Make a FDE with DWARF call frame instruction opcodes that have valid
669 // syntax, but will cause an error when we parse them into a UnwindTable.
670 // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE
671 // didn't define the CFA in terms of a register plus offset, so this should
673 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_def_cfa_offset
, 16}),
676 // Verify we catch state machine error.
677 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
678 EXPECT_THAT_ERROR(RowsOrErr
.takeError(),
679 FailedWithMessage("DW_CFA_def_cfa_offset found when CFA "
680 "rule was not RegPlusOffset"));
683 TEST(DWARFDebugFrame
, UnwindTableDefCFAOffsetSFCFAError
) {
684 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
688 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
689 /*Offset=*/0x3333abcdabcd,
690 /*Length=*/0x4444abcdabcd,
691 /*CIEPointer=*/0x1111abcdabcd,
692 /*InitialLocation=*/0x1000,
693 /*AddressRange=*/0x1000,
695 /*LSDAAddress=*/std::nullopt
,
696 /*Arch=*/Triple::x86_64
);
698 // Make a CIE that has an invalid CFA definition. We do this so we can try
699 // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an
700 // appropriate error back.
701 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {}), Succeeded());
703 // Make a FDE with DWARF call frame instruction opcodes that have valid
704 // syntax, but will cause an error when we parse them into a UnwindTable.
705 // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE
706 // didn't define the CFA in terms of a register plus offset, so this should
708 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_def_cfa_offset_sf
, 4}),
711 // Verify we catch state machine error.
712 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
713 EXPECT_THAT_ERROR(RowsOrErr
.takeError(),
714 FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA "
715 "rule was not RegPlusOffset"));
718 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_def_cfa_register
) {
719 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
723 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
724 /*Offset=*/0x3333abcdabcd,
725 /*Length=*/0x4444abcdabcd,
726 /*CIEPointer=*/0x1111abcdabcd,
727 /*InitialLocation=*/0x1000,
728 /*AddressRange=*/0x1000,
730 /*LSDAAddress=*/std::nullopt
,
731 /*Arch=*/Triple::x86_64
);
733 // Make a CIE that has only defines the CFA register with no offset. Some
734 // architectures do this and we must ensure that we set the CFA value to be
735 // equal to that register with no offset.
736 constexpr uint8_t CFAReg
= 12;
737 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa_register
, CFAReg
}),
740 // Make a FDE with DWARF call frame instruction opcodes that have valid
741 // syntax, but will cause an error when we parse them into a UnwindTable.
742 // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but
743 // our CIE didn't define the CFA in terms of a register plus offset, so this
744 // should cause an error.
745 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {}), Succeeded());
747 // Verify we catch state machine error.
748 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
749 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
750 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
751 EXPECT_EQ(Rows
.size(), 1u);
752 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
753 EXPECT_EQ(Rows
[0].getCFAValue(),
754 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg
, 0));
757 TEST(DWARFDebugFrame
, UnwindTableRowPushingOpcodes
) {
758 // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable.
759 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
763 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
764 /*Offset=*/0x3333abcdabcd,
765 /*Length=*/0x4444abcdabcd,
766 /*CIEPointer=*/0x1111abcdabcd,
767 /*InitialLocation=*/0x1000,
768 /*AddressRange=*/0x1000,
770 /*LSDAAddress=*/std::nullopt
,
771 /*Arch=*/Triple::x86_64
);
773 // Make a CIE that has a valid CFA definition and a single register unwind
774 // rule for register that we will verify is in all of the pushed rows.
775 constexpr uint8_t CFAReg
= 12;
776 constexpr uint8_t CFAOffset
= 32;
777 constexpr uint8_t Reg
= 13;
778 constexpr uint8_t InReg
= 14;
780 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, CFAReg
, CFAOffset
,
781 dwarf::DW_CFA_register
, Reg
, InReg
}),
784 // Make a FDE with DWARF call frame instruction opcodes that use all of the
785 // row pushing opcodes. This will verify that all opcodes that should create
786 // a row are correctly working. Each opcode will push a row prior to
787 // advancing the address, and then a row will be automatically pushed at the
788 // end of the parsing, so we should end up with 6 rows starting at address
789 // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor
791 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_advance_loc
| 4,
792 dwarf::DW_CFA_advance_loc1
,
794 dwarf::DW_CFA_advance_loc2
,
797 dwarf::DW_CFA_advance_loc4
,
802 dwarf::DW_CFA_set_loc
,
813 // Create locations that we expect the UnwindRow objects to contain after
814 // parsing the DWARF call frame instructions.
815 dwarf::RegisterLocations VerifyLocs
;
816 VerifyLocs
.setRegisterLocation(
817 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
819 // Verify we catch state machine error.
820 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
821 ASSERT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
822 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
823 EXPECT_EQ(Rows
.size(), 6u);
824 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
825 EXPECT_EQ(Rows
[0].getRegisterLocations().size(), 1u);
826 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
827 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
828 EXPECT_EQ(Rows
[1].getRegisterLocations().size(), 1u);
829 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs
);
830 EXPECT_EQ(Rows
[2].getAddress(), 0x1008u
);
831 EXPECT_EQ(Rows
[2].getRegisterLocations().size(), 1u);
832 EXPECT_EQ(Rows
[2].getRegisterLocations(), VerifyLocs
);
833 EXPECT_EQ(Rows
[3].getAddress(), 0x100cu
);
834 EXPECT_EQ(Rows
[3].getRegisterLocations().size(), 1u);
835 EXPECT_EQ(Rows
[3].getRegisterLocations(), VerifyLocs
);
836 EXPECT_EQ(Rows
[4].getAddress(), 0x1010u
);
837 EXPECT_EQ(Rows
[4].getRegisterLocations().size(), 1u);
838 EXPECT_EQ(Rows
[4].getRegisterLocations(), VerifyLocs
);
839 EXPECT_EQ(Rows
[5].getAddress(), 0x1014u
);
840 EXPECT_EQ(Rows
[5].getRegisterLocations().size(), 1u);
841 EXPECT_EQ(Rows
[5].getRegisterLocations(), VerifyLocs
);
844 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_restore
) {
845 // Test that DW_CFA_restore works as expected when parsed in the state
847 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
851 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
852 /*Offset=*/0x3333abcdabcd,
853 /*Length=*/0x4444abcdabcd,
854 /*CIEPointer=*/0x1111abcdabcd,
855 /*InitialLocation=*/0x1000,
856 /*AddressRange=*/0x1000,
858 /*LSDAAddress=*/std::nullopt
,
859 /*Arch=*/Triple::x86_64
);
861 // Make a CIE that has a valid CFA definition and a single register unwind
862 // rule for register that we will verify is in all of the pushed rows.
863 constexpr uint8_t CFAReg
= 12;
864 constexpr uint8_t CFAOffset
= 32;
865 constexpr uint8_t Reg
= 13;
866 constexpr uint8_t InReg
= 14;
867 constexpr int32_t RegCFAOffset
= -8;
869 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, CFAReg
, CFAOffset
,
870 dwarf::DW_CFA_register
, Reg
, InReg
}),
873 // Make a FDE with DWARF call frame instruction opcodes that changes the rule
874 // for register "Reg" to be [CFA-8], then push a row, and then restore the
875 // register unwind rule for "Reg" using DW_CFA_restore. We should end up with
877 // - one with Reg = [CFA-8]
878 // - one with Reg = InReg
879 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_offset
| Reg
, 1,
880 dwarf::DW_CFA_advance_loc
| 4,
881 dwarf::DW_CFA_restore
| Reg
}),
884 // Create locations that we expect the UnwindRow objects to contain after
885 // parsing the DWARF call frame instructions.
886 dwarf::RegisterLocations VerifyLocs1
;
887 VerifyLocs1
.setRegisterLocation(
888 Reg
, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset
));
890 dwarf::RegisterLocations VerifyLocs2
;
891 VerifyLocs2
.setRegisterLocation(
892 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
894 // Verify we catch state machine error.
895 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
896 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
897 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
898 EXPECT_EQ(Rows
.size(), 2u);
899 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
900 EXPECT_EQ(Rows
[0].getRegisterLocations().size(), 1u);
901 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs1
);
902 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
903 EXPECT_EQ(Rows
[1].getRegisterLocations().size(), 1u);
904 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs2
);
907 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_restore_extended
) {
908 // Test that DW_CFA_restore works as expected when parsed in the state
910 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
914 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
915 /*Offset=*/0x3333abcdabcd,
916 /*Length=*/0x4444abcdabcd,
917 /*CIEPointer=*/0x1111abcdabcd,
918 /*InitialLocation=*/0x1000,
919 /*AddressRange=*/0x1000,
921 /*LSDAAddress=*/std::nullopt
,
922 /*Arch=*/Triple::x86_64
);
924 // Make a CIE that has a valid CFA definition and a single register unwind
925 // rule for register that we will verify is in all of the pushed rows.
926 constexpr uint8_t CFAReg
= 12;
927 constexpr uint8_t CFAOffset
= 32;
928 constexpr uint8_t Reg
= 13;
929 constexpr uint8_t InReg
= 14;
930 constexpr int32_t RegCFAOffset
= -8;
932 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, CFAReg
, CFAOffset
,
933 dwarf::DW_CFA_register
, Reg
, InReg
}),
936 // Make a FDE with DWARF call frame instruction opcodes that changes the rule
937 // for register "Reg" to be [CFA-8], then push a row, and then restore the
938 // register unwind rule for "Reg" using DW_CFA_restore_extended. We should
939 // end up with two rows:
940 // - one with Reg = [CFA-8]
941 // - one with Reg = InReg
942 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_offset
| Reg
, 1,
943 dwarf::DW_CFA_advance_loc
| 4,
944 dwarf::DW_CFA_restore_extended
, Reg
}),
947 // Create locations that we expect the UnwindRow objects to contain after
948 // parsing the DWARF call frame instructions.
949 dwarf::RegisterLocations VerifyLocs1
;
950 VerifyLocs1
.setRegisterLocation(
951 Reg
, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset
));
953 dwarf::RegisterLocations VerifyLocs2
;
954 VerifyLocs2
.setRegisterLocation(
955 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
957 // Verify we catch state machine error.
958 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
959 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
960 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
961 EXPECT_EQ(Rows
.size(), 2u);
962 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
963 EXPECT_EQ(Rows
[0].getRegisterLocations().size(), 1u);
964 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs1
);
965 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
966 EXPECT_EQ(Rows
[1].getRegisterLocations().size(), 1u);
967 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs2
);
970 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_offset
) {
971 // Test that DW_CFA_offset, DW_CFA_offset_extended and
972 // DW_CFA_offset_extended_sf work as expected when parsed in the state
974 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
978 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
979 /*Offset=*/0x3333abcdabcd,
980 /*Length=*/0x4444abcdabcd,
981 /*CIEPointer=*/0x1111abcdabcd,
982 /*InitialLocation=*/0x1000,
983 /*AddressRange=*/0x1000,
985 /*LSDAAddress=*/std::nullopt
,
986 /*Arch=*/Triple::x86_64
);
988 // Make a CIE that has a valid CFA definition and a single register unwind
989 // rule for register that we will verify is in all of the pushed rows.
990 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
993 // Make a FDE with DWARF call frame instruction opcodes that changes the
994 // unwind rules for the follwing registers:
998 constexpr uint8_t Reg1
= 14;
999 constexpr uint8_t Reg2
= 15;
1000 constexpr uint8_t Reg3
= 16;
1001 constexpr uint8_t Neg1SLEB
= 0x7f;
1004 {dwarf::DW_CFA_offset
| Reg1
, 1, dwarf::DW_CFA_offset_extended
,
1005 Reg2
, 2, dwarf::DW_CFA_offset_extended_sf
, Reg3
, Neg1SLEB
}),
1008 // Create locations that we expect the UnwindRow objects to contain after
1009 // parsing the DWARF call frame instructions.
1010 dwarf::RegisterLocations VerifyLocs
;
1011 VerifyLocs
.setRegisterLocation(
1012 Reg1
, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1013 VerifyLocs
.setRegisterLocation(
1014 Reg2
, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1015 VerifyLocs
.setRegisterLocation(
1016 Reg3
, dwarf::UnwindLocation::createAtCFAPlusOffset(8));
1018 // Verify we catch state machine error.
1019 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1020 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1021 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1022 EXPECT_EQ(Rows
.size(), 1u);
1023 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1024 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1027 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_val_offset
) {
1028 // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when
1029 // parsed in the state machine.
1030 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1034 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1035 /*Offset=*/0x3333abcdabcd,
1036 /*Length=*/0x4444abcdabcd,
1037 /*CIEPointer=*/0x1111abcdabcd,
1038 /*InitialLocation=*/0x1000,
1039 /*AddressRange=*/0x1000,
1041 /*LSDAAddress=*/std::nullopt
,
1042 /*Arch=*/Triple::x86_64
);
1044 // Make a CIE that has a valid CFA definition and a single register unwind
1045 // rule for register that we will verify is in all of the pushed rows.
1046 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1049 // Make a FDE with DWARF call frame instruction opcodes that changes the
1050 // unwind rules for the follwing registers:
1054 constexpr uint8_t Reg1
= 14;
1055 constexpr uint8_t Reg2
= 15;
1056 constexpr uint8_t Neg1SLEB
= 0x7f;
1058 parseCFI(TestFDE
, {dwarf::DW_CFA_val_offset
, Reg1
, 1,
1059 dwarf::DW_CFA_val_offset_sf
, Reg2
, Neg1SLEB
}),
1062 // Create locations that we expect the UnwindRow objects to contain after
1063 // parsing the DWARF call frame instructions.
1064 dwarf::RegisterLocations VerifyLocs
;
1065 VerifyLocs
.setRegisterLocation(
1066 Reg1
, dwarf::UnwindLocation::createIsCFAPlusOffset(-8));
1067 VerifyLocs
.setRegisterLocation(
1068 Reg2
, dwarf::UnwindLocation::createIsCFAPlusOffset(8));
1070 // Verify we catch state machine error.
1071 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1072 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1073 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1074 EXPECT_EQ(Rows
.size(), 1u);
1075 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1076 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1079 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_nop
) {
1080 // Test that DW_CFA_nop works as expected when parsed in the state machine.
1081 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1085 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1086 /*Offset=*/0x3333abcdabcd,
1087 /*Length=*/0x4444abcdabcd,
1088 /*CIEPointer=*/0x1111abcdabcd,
1089 /*InitialLocation=*/0x1000,
1090 /*AddressRange=*/0x1000,
1092 /*LSDAAddress=*/std::nullopt
,
1093 /*Arch=*/Triple::x86_64
);
1095 // Make a CIE that has a valid CFA definition and a single register unwind
1096 // rule for register that we will verify is in all of the pushed rows.
1097 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1100 // Make a FDE with DWARF call frame instruction opcodes that changes the
1101 // unwind rules for the follwing registers:
1103 // The opcodes for setting Reg1 are preceded by a DW_CFA_nop.
1104 constexpr uint8_t Reg1
= 14;
1106 parseCFI(TestFDE
, {dwarf::DW_CFA_nop
, dwarf::DW_CFA_offset
| Reg1
, 1}),
1109 // Create locations that we expect the UnwindRow objects to contain after
1110 // parsing the DWARF call frame instructions.
1111 dwarf::RegisterLocations VerifyLocs
;
1112 VerifyLocs
.setRegisterLocation(
1113 Reg1
, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1115 // Verify we catch state machine error.
1116 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1117 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1118 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1119 EXPECT_EQ(Rows
.size(), 1u);
1120 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1121 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1124 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_remember_state
) {
1125 // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected
1126 // when parsed in the state machine.
1127 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1131 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1132 /*Offset=*/0x3333abcdabcd,
1133 /*Length=*/0x4444abcdabcd,
1134 /*CIEPointer=*/0x1111abcdabcd,
1135 /*InitialLocation=*/0x1000,
1136 /*AddressRange=*/0x1000,
1138 /*LSDAAddress=*/std::nullopt
,
1139 /*Arch=*/Triple::x86_64
);
1141 // Make a CIE that has a valid CFA definition and a single register unwind
1142 // rule for register that we will verify is in all of the pushed rows.
1143 constexpr uint8_t CFAOff1
= 32;
1144 constexpr uint8_t CFAOff2
= 16;
1145 constexpr uint8_t Reg1
= 14;
1146 constexpr uint8_t Reg2
= 15;
1147 constexpr uint8_t Reg3
= 16;
1149 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, CFAOff1
}),
1152 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1154 // 0x1000: CFA=reg12+CFAOff1: Reg1=[CFA-8]
1155 // 0x1004: CFA=reg12+CFAOff1: Reg1=[CFA-8] Reg2=[CFA-16]
1156 // 0x1008: CFA=reg12+CFAOff2: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24]
1157 // 0x100C: CFA=reg12+CFAOff1: Reg1=[CFA-8] Reg2=[CFA-16]
1158 // 0x1010: CFA=reg12+CFAOff1: Reg1=[CFA-8]
1159 // This state machine will:
1160 // - set Reg1 location
1161 // - push a row (from DW_CFA_advance_loc)
1162 // - remember the state
1163 // - set Reg2 location
1164 // - push a row (from DW_CFA_advance_loc)
1165 // - remember the state
1166 // - set CFA offset to CFAOff2
1167 // - set Reg3 location
1168 // - push a row (from DW_CFA_advance_loc)
1169 // - remember the state where Reg1 and Reg2 were set
1170 // - push a row (from DW_CFA_advance_loc)
1171 // - remember the state where only Reg1 was set
1172 // - push a row (automatically at the end of instruction parsing)
1173 // Then we verify that all registers are correct in all generated rows.
1176 {dwarf::DW_CFA_offset
| Reg1
, 1, dwarf::DW_CFA_advance_loc
| 4,
1177 dwarf::DW_CFA_remember_state
, dwarf::DW_CFA_offset
| Reg2
, 2,
1178 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_remember_state
,
1179 dwarf::DW_CFA_def_cfa_offset
, CFAOff2
,
1180 dwarf::DW_CFA_offset
| Reg3
, 3, dwarf::DW_CFA_advance_loc
| 4,
1181 dwarf::DW_CFA_restore_state
, dwarf::DW_CFA_advance_loc
| 4,
1182 dwarf::DW_CFA_restore_state
}),
1185 // Create locations that we expect the UnwindRow objects to contain after
1186 // parsing the DWARF call frame instructions.
1187 dwarf::RegisterLocations VerifyLocs1
;
1188 VerifyLocs1
.setRegisterLocation(
1189 Reg1
, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1191 dwarf::RegisterLocations VerifyLocs2
;
1192 VerifyLocs2
.setRegisterLocation(
1193 Reg1
, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1194 VerifyLocs2
.setRegisterLocation(
1195 Reg2
, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1197 dwarf::RegisterLocations VerifyLocs3
;
1198 VerifyLocs3
.setRegisterLocation(
1199 Reg1
, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1200 VerifyLocs3
.setRegisterLocation(
1201 Reg2
, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1202 VerifyLocs3
.setRegisterLocation(
1203 Reg3
, dwarf::UnwindLocation::createAtCFAPlusOffset(-24));
1205 // Verify we catch state machine error.
1206 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1207 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1208 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1209 EXPECT_EQ(Rows
.size(), 5u);
1210 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1211 EXPECT_EQ(Rows
[0].getCFAValue(),
1212 dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1
));
1213 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs1
);
1215 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
1216 EXPECT_EQ(Rows
[1].getCFAValue(),
1217 dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1
));
1218 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs2
);
1220 EXPECT_EQ(Rows
[2].getAddress(), 0x1008u
);
1221 EXPECT_EQ(Rows
[2].getCFAValue(),
1222 dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff2
));
1223 EXPECT_EQ(Rows
[2].getRegisterLocations(), VerifyLocs3
);
1225 EXPECT_EQ(Rows
[3].getAddress(), 0x100Cu
);
1226 EXPECT_EQ(Rows
[3].getCFAValue(),
1227 dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1
));
1228 EXPECT_EQ(Rows
[3].getRegisterLocations(), VerifyLocs2
);
1230 EXPECT_EQ(Rows
[4].getAddress(), 0x1010u
);
1231 EXPECT_EQ(Rows
[4].getCFAValue(),
1232 dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1
));
1233 EXPECT_EQ(Rows
[4].getRegisterLocations(), VerifyLocs1
);
1236 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_undefined
) {
1237 // Test that DW_CFA_undefined works as expected when parsed in the state
1239 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1243 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1244 /*Offset=*/0x3333abcdabcd,
1245 /*Length=*/0x4444abcdabcd,
1246 /*CIEPointer=*/0x1111abcdabcd,
1247 /*InitialLocation=*/0x1000,
1248 /*AddressRange=*/0x1000,
1250 /*LSDAAddress=*/std::nullopt
,
1251 /*Arch=*/Triple::x86_64
);
1253 // Make a CIE that has a valid CFA definition and a single register unwind
1254 // rule for register that we will verify is in all of the pushed rows.
1255 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1258 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1260 // 0x1000: CFA=reg12+32: Reg1=undefined
1261 // Then we verify that all registers are correct in all generated rows.
1262 constexpr uint8_t Reg1
= 14;
1263 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_undefined
, Reg1
}),
1266 // Create locations that we expect the UnwindRow objects to contain after
1267 // parsing the DWARF call frame instructions.
1268 dwarf::RegisterLocations VerifyLocs
;
1269 VerifyLocs
.setRegisterLocation(Reg1
,
1270 dwarf::UnwindLocation::createUndefined());
1272 // Verify we catch state machine error.
1273 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1274 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1275 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1276 EXPECT_EQ(Rows
.size(), 1u);
1277 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1278 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1281 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_same_value
) {
1282 // Test that DW_CFA_same_value works as expected when parsed in the state
1284 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1288 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1289 /*Offset=*/0x3333abcdabcd,
1290 /*Length=*/0x4444abcdabcd,
1291 /*CIEPointer=*/0x1111abcdabcd,
1292 /*InitialLocation=*/0x1000,
1293 /*AddressRange=*/0x1000,
1295 /*LSDAAddress=*/std::nullopt
,
1296 /*Arch=*/Triple::x86_64
);
1298 // Make a CIE that has a valid CFA definition and a single register unwind
1299 // rule for register that we will verify is in all of the pushed rows.
1300 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1303 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1305 // 0x1000: CFA=reg12+32: Reg1=same
1306 // Then we verify that all registers are correct in all generated rows.
1307 constexpr uint8_t Reg1
= 14;
1308 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_same_value
, Reg1
}),
1311 // Create locations that we expect the UnwindRow objects to contain after
1312 // parsing the DWARF call frame instructions.
1313 dwarf::RegisterLocations VerifyLocs
;
1314 VerifyLocs
.setRegisterLocation(Reg1
, dwarf::UnwindLocation::createSame());
1316 // Verify we catch state machine error.
1317 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1318 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1319 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1320 EXPECT_EQ(Rows
.size(), 1u);
1321 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1322 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1325 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_register
) {
1326 // Test that DW_CFA_register works as expected when parsed in the state
1328 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1332 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1333 /*Offset=*/0x3333abcdabcd,
1334 /*Length=*/0x4444abcdabcd,
1335 /*CIEPointer=*/0x1111abcdabcd,
1336 /*InitialLocation=*/0x1000,
1337 /*AddressRange=*/0x1000,
1339 /*LSDAAddress=*/std::nullopt
,
1340 /*Arch=*/Triple::x86_64
);
1342 // Make a CIE that has a valid CFA definition and a single register unwind
1343 // rule for register that we will verify is in all of the pushed rows.
1344 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1347 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1349 // 0x1000: CFA=reg12+32: Reg1=same
1350 // Then we verify that all registers are correct in all generated rows.
1351 constexpr uint8_t Reg
= 13;
1352 constexpr uint8_t InReg
= 14;
1353 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_register
, Reg
, InReg
}),
1356 // Create locations that we expect the UnwindRow objects to contain after
1357 // parsing the DWARF call frame instructions.
1358 dwarf::RegisterLocations VerifyLocs
;
1359 VerifyLocs
.setRegisterLocation(
1360 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
1362 // Verify we catch state machine error.
1363 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1364 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1365 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1366 EXPECT_EQ(Rows
.size(), 1u);
1367 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1368 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1371 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_expression
) {
1372 // Test that DW_CFA_expression works as expected when parsed in the state
1374 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1378 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1379 /*Offset=*/0x3333abcdabcd,
1380 /*Length=*/0x4444abcdabcd,
1381 /*CIEPointer=*/0x1111abcdabcd,
1382 /*InitialLocation=*/0x1000,
1383 /*AddressRange=*/0x1000,
1385 /*LSDAAddress=*/std::nullopt
,
1386 /*Arch=*/Triple::x86_64
);
1388 // Make a CIE that has a valid CFA definition and a single register unwind
1389 // rule for register that we will verify is in all of the pushed rows.
1390 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1393 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1395 // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1396 // Then we verify that all registers are correct in all generated rows.
1397 constexpr uint8_t Reg
= 13;
1398 constexpr uint8_t AddrSize
= 8;
1399 std::vector
<uint8_t> CFIBytes
= {dwarf::DW_CFA_expression
, Reg
, 1,
1400 dwarf::DW_OP_reg12
};
1402 EXPECT_THAT_ERROR(parseCFI(TestFDE
, CFIBytes
), Succeeded());
1404 // Create locations that we expect the UnwindRow objects to contain after
1405 // parsing the DWARF call frame instructions.
1406 dwarf::RegisterLocations VerifyLocs
;
1408 std::vector
<uint8_t> ExprBytes
= {dwarf::DW_OP_reg12
};
1409 DataExtractor
ExprData(ExprBytes
, true, AddrSize
);
1410 DWARFExpression
Expr(ExprData
, AddrSize
);
1411 VerifyLocs
.setRegisterLocation(
1412 Reg
, dwarf::UnwindLocation::createAtDWARFExpression(Expr
));
1414 // Verify we catch state machine error.
1415 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1416 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1417 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1418 EXPECT_EQ(Rows
.size(), 1u);
1419 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1420 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1423 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_val_expression
) {
1424 // Test that DW_CFA_val_expression works as expected when parsed in the state
1426 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1430 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1431 /*Offset=*/0x3333abcdabcd,
1432 /*Length=*/0x4444abcdabcd,
1433 /*CIEPointer=*/0x1111abcdabcd,
1434 /*InitialLocation=*/0x1000,
1435 /*AddressRange=*/0x1000,
1437 /*LSDAAddress=*/std::nullopt
,
1438 /*Arch=*/Triple::x86_64
);
1440 // Make a CIE that has a valid CFA definition and a single register unwind
1441 // rule for register that we will verify is in all of the pushed rows.
1442 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1445 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1447 // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1448 // Then we verify that all registers are correct in all generated rows.
1449 constexpr uint8_t Reg
= 13;
1450 constexpr uint8_t AddrSize
= 8;
1451 std::vector
<uint8_t> CFIBytes
= {dwarf::DW_CFA_val_expression
, Reg
, 1,
1452 dwarf::DW_OP_reg12
};
1454 EXPECT_THAT_ERROR(parseCFI(TestFDE
, CFIBytes
), Succeeded());
1456 // Create locations that we expect the UnwindRow objects to contain after
1457 // parsing the DWARF call frame instructions.
1458 dwarf::RegisterLocations VerifyLocs
;
1460 std::vector
<uint8_t> ExprBytes
= {dwarf::DW_OP_reg12
};
1461 DataExtractor
ExprData(ExprBytes
, true, AddrSize
);
1462 DWARFExpression
Expr(ExprData
, AddrSize
);
1463 VerifyLocs
.setRegisterLocation(
1464 Reg
, dwarf::UnwindLocation::createIsDWARFExpression(Expr
));
1466 // Verify we catch state machine error.
1467 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1468 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1469 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1470 EXPECT_EQ(Rows
.size(), 1u);
1471 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1472 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1475 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_def_cfa
) {
1476 // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register,
1477 // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when
1478 // parsed in the state machine.
1479 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1483 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1484 /*Offset=*/0x3333abcdabcd,
1485 /*Length=*/0x4444abcdabcd,
1486 /*CIEPointer=*/0x1111abcdabcd,
1487 /*InitialLocation=*/0x1000,
1488 /*AddressRange=*/0x1000,
1490 /*LSDAAddress=*/std::nullopt
,
1491 /*Arch=*/Triple::x86_64
);
1493 // Make a CIE that has a valid CFA definition and a single register unwind
1494 // rule for register that we will verify is in all of the pushed rows.
1495 constexpr uint8_t CFAReg1
= 12;
1496 constexpr uint8_t CFAOff1
= 32;
1497 constexpr uint8_t CFAReg2
= 13;
1498 constexpr uint8_t CFAOff2
= 48;
1499 constexpr uint8_t Reg
= 13;
1500 constexpr uint8_t InReg
= 14;
1502 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, CFAReg1
, CFAOff1
,
1503 dwarf::DW_CFA_register
, Reg
, InReg
}),
1506 // Make a FDE with DWARF call frame instruction opcodes that use all of the
1507 // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1508 // create a row are correctly working.
1513 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_register
,
1514 CFAReg2
, dwarf::DW_CFA_advance_loc
| 4,
1515 dwarf::DW_CFA_def_cfa_offset
, CFAOff2
,
1516 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_offset_sf
,
1517 0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1518 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_sf
, CFAReg1
,
1519 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1523 // Create locations that we expect the UnwindRow objects to contain after
1524 // parsing the DWARF call frame instructions.
1525 dwarf::RegisterLocations VerifyLocs
;
1526 VerifyLocs
.setRegisterLocation(
1527 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
1529 // Verify we catch state machine error.
1530 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1531 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1532 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1533 EXPECT_EQ(Rows
.size(), 5u);
1534 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1536 Rows
[0].getCFAValue(),
1537 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1
, CFAOff1
));
1538 EXPECT_EQ(Rows
[0].getRegisterLocations().size(), 1u);
1539 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1541 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
1543 Rows
[1].getCFAValue(),
1544 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff1
));
1545 EXPECT_EQ(Rows
[1].getRegisterLocations().size(), 1u);
1546 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs
);
1548 EXPECT_EQ(Rows
[2].getAddress(), 0x1008u
);
1550 Rows
[2].getCFAValue(),
1551 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff2
));
1552 EXPECT_EQ(Rows
[2].getRegisterLocations().size(), 1u);
1553 EXPECT_EQ(Rows
[2].getRegisterLocations(), VerifyLocs
);
1555 EXPECT_EQ(Rows
[3].getAddress(), 0x100cu
);
1557 Rows
[3].getCFAValue(),
1558 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff1
));
1559 EXPECT_EQ(Rows
[3].getRegisterLocations().size(), 1u);
1560 EXPECT_EQ(Rows
[3].getRegisterLocations(), VerifyLocs
);
1562 EXPECT_EQ(Rows
[4].getAddress(), 0x1010u
);
1564 Rows
[4].getCFAValue(),
1565 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1
, CFAOff2
));
1566 EXPECT_EQ(Rows
[4].getRegisterLocations().size(), 1u);
1567 EXPECT_EQ(Rows
[4].getRegisterLocations(), VerifyLocs
);
1570 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_LLVM_def_aspace_cfa
) {
1571 // Test that DW_CFA_LLVM_def_aspace_cfa, DW_CFA_LLVM_def_aspace_cfa_sf,
1572 // DW_CFA_def_cfa_register, DW_CFA_def_cfa_offset, and
1573 // DW_CFA_def_cfa_offset_sf works as expected when parsed in the state
1575 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1579 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1580 /*Offset=*/0x3333abcdabcd,
1581 /*Length=*/0x4444abcdabcd,
1582 /*CIEPointer=*/0x1111abcdabcd,
1583 /*InitialLocation=*/0x1000,
1584 /*AddressRange=*/0x1000,
1586 /*LSDAAddress=*/std::nullopt
,
1587 /*Arch=*/Triple::x86_64
);
1589 // Make a CIE that has a valid CFA definition and a single register unwind
1590 // rule for register that we will verify is in all of the pushed rows.
1591 constexpr uint8_t CFAReg1
= 12;
1592 constexpr uint8_t CFAOff1
= 32;
1593 constexpr uint8_t CFAReg2
= 13;
1594 constexpr uint8_t CFAOff2
= 48;
1595 constexpr uint8_t Reg
= 13;
1596 constexpr uint8_t InReg
= 14;
1597 constexpr uint8_t AddrSpace
= 2;
1600 parseCFI(TestCIE
, {dwarf::DW_CFA_LLVM_def_aspace_cfa
, CFAReg1
, CFAOff1
,
1601 AddrSpace
, dwarf::DW_CFA_register
, Reg
, InReg
}),
1604 // Make a FDE with DWARF call frame instruction opcodes that use all of the
1605 // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1606 // create a row are correctly working.
1611 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_register
,
1612 CFAReg2
, dwarf::DW_CFA_advance_loc
| 4,
1613 dwarf::DW_CFA_def_cfa_offset
, CFAOff2
,
1614 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_offset_sf
,
1615 0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1616 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_sf
, CFAReg1
,
1617 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1621 // Create locations that we expect the UnwindRow objects to contain after
1622 // parsing the DWARF call frame instructions.
1623 dwarf::RegisterLocations VerifyLocs
;
1624 VerifyLocs
.setRegisterLocation(
1625 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
1627 // Verify we catch state machine error.
1628 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1629 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1630 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1631 EXPECT_EQ(Rows
.size(), 5u);
1632 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1633 EXPECT_EQ(Rows
[0].getCFAValue(),
1634 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1
, CFAOff1
,
1636 EXPECT_EQ(Rows
[0].getRegisterLocations().size(), 1u);
1637 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1639 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
1640 EXPECT_EQ(Rows
[1].getCFAValue(),
1641 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff1
,
1643 EXPECT_EQ(Rows
[1].getRegisterLocations().size(), 1u);
1644 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs
);
1646 EXPECT_EQ(Rows
[2].getAddress(), 0x1008u
);
1647 EXPECT_EQ(Rows
[2].getCFAValue(),
1648 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff2
,
1650 EXPECT_EQ(Rows
[2].getRegisterLocations().size(), 1u);
1651 EXPECT_EQ(Rows
[2].getRegisterLocations(), VerifyLocs
);
1653 EXPECT_EQ(Rows
[3].getAddress(), 0x100cu
);
1654 EXPECT_EQ(Rows
[3].getCFAValue(),
1655 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff1
,
1657 EXPECT_EQ(Rows
[3].getRegisterLocations().size(), 1u);
1658 EXPECT_EQ(Rows
[3].getRegisterLocations(), VerifyLocs
);
1660 EXPECT_EQ(Rows
[4].getAddress(), 0x1010u
);
1661 EXPECT_EQ(Rows
[4].getCFAValue(),
1662 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1
, CFAOff2
,
1664 EXPECT_EQ(Rows
[4].getRegisterLocations().size(), 1u);
1665 EXPECT_EQ(Rows
[4].getRegisterLocations(), VerifyLocs
);
1668 } // end anonymous namespace