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
,
36 /*PersonalityEnc=*/None
,
37 /*Arch=*/Triple::x86_64
);
40 void expectDumpResult(const dwarf::CIE
&TestCIE
, bool IsEH
,
41 StringRef ExpectedFirstLine
) {
43 raw_string_ostream
OS(Output
);
44 TestCIE
.dump(OS
, DIDumpOptions(), /*MRI=*/nullptr, IsEH
);
46 StringRef FirstLine
= StringRef(Output
).split('\n').first
;
47 EXPECT_EQ(FirstLine
, ExpectedFirstLine
);
50 void expectDumpResult(const dwarf::FDE
&TestFDE
, bool IsEH
,
51 StringRef ExpectedFirstLine
) {
53 raw_string_ostream
OS(Output
);
54 TestFDE
.dump(OS
, DIDumpOptions(), /*MRI=*/nullptr, IsEH
);
56 StringRef FirstLine
= StringRef(Output
).split('\n').first
;
57 EXPECT_EQ(FirstLine
, ExpectedFirstLine
);
60 TEST(DWARFDebugFrame
, DumpDWARF32CIE
) {
61 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
62 /*Offset=*/0x1111abcd,
63 /*Length=*/0x2222abcd);
64 expectDumpResult(TestCIE
, /*IsEH=*/false, "1111abcd 2222abcd ffffffff CIE");
67 TEST(DWARFDebugFrame
, DumpDWARF64CIE
) {
68 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/true,
69 /*Offset=*/0x1111abcdabcd,
70 /*Length=*/0x2222abcdabcd);
71 expectDumpResult(TestCIE
, /*IsEH=*/false,
72 "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE");
75 TEST(DWARFDebugFrame
, DumpEHCIE
) {
76 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
79 expectDumpResult(TestCIE
, /*IsEH=*/true, "00001000 00000020 00000000 CIE");
82 TEST(DWARFDebugFrame
, DumpEH64CIE
) {
83 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/true,
86 expectDumpResult(TestCIE
, /*IsEH=*/true,
87 "00001000 0000000000000020 00000000 CIE");
90 TEST(DWARFDebugFrame
, DumpDWARF64FDE
) {
91 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/true,
92 /*Offset=*/0x1111abcdabcd,
93 /*Length=*/0x2222abcdabcd);
94 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
95 /*Offset=*/0x3333abcdabcd,
96 /*Length=*/0x4444abcdabcd,
97 /*CIEPointer=*/0x1111abcdabcd,
98 /*InitialLocation=*/0x5555abcdabcd,
99 /*AddressRange=*/0x111111111111,
101 /*LSDAAddress=*/None
,
102 /*Arch=*/Triple::x86_64
);
103 expectDumpResult(TestFDE
, /*IsEH=*/false,
104 "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE "
105 "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde");
108 TEST(DWARFDebugFrame
, DumpEH64FDE
) {
109 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/true,
110 /*Offset=*/0x1111ab9a000c,
112 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
113 /*Offset=*/0x1111abcdabcd,
114 /*Length=*/0x2222abcdabcd,
115 /*CIEPointer=*/0x33abcd,
116 /*InitialLocation=*/0x4444abcdabcd,
117 /*AddressRange=*/0x111111111111,
119 /*LSDAAddress=*/None
,
120 /*Arch=*/Triple::x86_64
);
121 expectDumpResult(TestFDE
, /*IsEH=*/true,
122 "1111abcdabcd 00002222abcdabcd 0033abcd FDE "
123 "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde");
126 static Error
parseCFI(dwarf::CIE
&C
, ArrayRef
<uint8_t> Instructions
,
127 Optional
<uint64_t> Size
= None
) {
128 DWARFDataExtractor
Data(Instructions
, /*IsLittleEndian=*/true,
131 const uint64_t EndOffset
= Size
? *Size
: (uint64_t)Instructions
.size();
132 return C
.cfis().parse(Data
, &Offset
, EndOffset
);
135 static Error
parseCFI(dwarf::FDE
&FDE
, ArrayRef
<uint8_t> Instructions
) {
136 DWARFDataExtractor
Data(Instructions
, /*IsLittleEndian=*/true,
139 return FDE
.cfis().parse(Data
, &Offset
, Instructions
.size());
142 TEST(DWARFDebugFrame
, InvalidCFIOpcodesTest
) {
143 llvm::DenseSet
<uint8_t> ValidExtendedOpcodes
= {
145 dwarf::DW_CFA_advance_loc
,
146 dwarf::DW_CFA_offset
,
147 dwarf::DW_CFA_restore
,
148 dwarf::DW_CFA_set_loc
,
149 dwarf::DW_CFA_advance_loc1
,
150 dwarf::DW_CFA_advance_loc2
,
151 dwarf::DW_CFA_advance_loc4
,
152 dwarf::DW_CFA_offset_extended
,
153 dwarf::DW_CFA_restore_extended
,
154 dwarf::DW_CFA_undefined
,
155 dwarf::DW_CFA_same_value
,
156 dwarf::DW_CFA_register
,
157 dwarf::DW_CFA_remember_state
,
158 dwarf::DW_CFA_restore_state
,
159 dwarf::DW_CFA_def_cfa
,
160 dwarf::DW_CFA_def_cfa_register
,
161 dwarf::DW_CFA_def_cfa_offset
,
162 dwarf::DW_CFA_def_cfa_expression
,
163 dwarf::DW_CFA_expression
,
164 dwarf::DW_CFA_offset_extended_sf
,
165 dwarf::DW_CFA_def_cfa_sf
,
166 dwarf::DW_CFA_def_cfa_offset_sf
,
167 dwarf::DW_CFA_LLVM_def_aspace_cfa
,
168 dwarf::DW_CFA_LLVM_def_aspace_cfa_sf
,
169 dwarf::DW_CFA_val_offset
,
170 dwarf::DW_CFA_val_offset_sf
,
171 dwarf::DW_CFA_val_expression
,
172 dwarf::DW_CFA_MIPS_advance_loc8
,
173 dwarf::DW_CFA_GNU_window_save
,
174 dwarf::DW_CFA_AARCH64_negate_ra_state
,
175 dwarf::DW_CFA_GNU_args_size
};
177 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
181 // See DWARF standard v3, section 7.23: low 6 bits are used to encode an
183 for (uint8_t Code
= 0; Code
<= 63; ++Code
) {
184 if (ValidExtendedOpcodes
.count(Code
))
187 EXPECT_THAT_ERROR(parseCFI(TestCIE
, Code
),
188 FailedWithMessage(("invalid extended CFI opcode 0x" +
189 Twine::utohexstr(Code
))
195 // Here we test how truncated Call Frame Instructions are parsed.
196 TEST(DWARFDebugFrame
, ParseTruncatedCFITest
) {
197 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
201 // Having an empty instructions list is fine.
202 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {}), Succeeded());
204 // Unable to read an opcode, because the instructions list is empty, but we
205 // say to the parser that it is not.
207 parseCFI(TestCIE
, {}, /*Size=*/1),
209 "unexpected end of data at offset 0x0 while reading [0x0, 0x1)"));
211 // Unable to read a truncated DW_CFA_offset instruction.
213 parseCFI(TestCIE
, {dwarf::DW_CFA_offset
}),
214 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
215 "malformed uleb128, extends past end"));
217 // Unable to read a truncated DW_CFA_set_loc instruction.
219 parseCFI(TestCIE
, {dwarf::DW_CFA_set_loc
}),
221 "unexpected end of data at offset 0x1 while reading [0x1, 0x9)"));
223 // Unable to read a truncated DW_CFA_advance_loc1 instruction.
225 parseCFI(TestCIE
, {dwarf::DW_CFA_advance_loc1
}),
227 "unexpected end of data at offset 0x1 while reading [0x1, 0x2)"));
229 // Unable to read a truncated DW_CFA_advance_loc2 instruction.
231 parseCFI(TestCIE
, {dwarf::DW_CFA_advance_loc2
}),
233 "unexpected end of data at offset 0x1 while reading [0x1, 0x3)"));
235 // Unable to read a truncated DW_CFA_advance_loc4 instruction.
237 parseCFI(TestCIE
, {dwarf::DW_CFA_advance_loc4
}),
239 "unexpected end of data at offset 0x1 while reading [0x1, 0x5)"));
241 // A test for an instruction with a single ULEB128 operand.
242 auto CheckOp_ULEB128
= [&](uint8_t Inst
) {
244 parseCFI(TestCIE
, Inst
),
245 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
246 "malformed uleb128, extends past end"));
250 {dwarf::DW_CFA_restore_extended
, dwarf::DW_CFA_undefined
,
251 dwarf::DW_CFA_same_value
, dwarf::DW_CFA_def_cfa_register
,
252 dwarf::DW_CFA_def_cfa_offset
, dwarf::DW_CFA_GNU_args_size
})
253 CheckOp_ULEB128(Inst
);
255 // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction.
257 parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa_offset_sf
}),
258 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
259 "malformed sleb128, extends past end"));
261 // A test for an instruction with two ULEB128 operands.
262 auto CheckOp_ULEB128_ULEB128
= [&](uint8_t Inst
) {
264 parseCFI(TestCIE
, Inst
),
265 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
266 "malformed uleb128, extends past end"));
269 parseCFI(TestCIE
, {Inst
, /*Op1=*/0}),
270 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
271 "malformed uleb128, extends past end"));
274 for (uint8_t Inst
: {dwarf::DW_CFA_offset_extended
, dwarf::DW_CFA_register
,
275 dwarf::DW_CFA_def_cfa
, dwarf::DW_CFA_LLVM_def_aspace_cfa
,
276 dwarf::DW_CFA_val_offset
})
277 CheckOp_ULEB128_ULEB128(Inst
);
279 // A test for an instruction with two operands: ULEB128, SLEB128.
280 auto CheckOp_ULEB128_SLEB128
= [&](uint8_t Inst
) {
282 parseCFI(TestCIE
, Inst
),
283 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
284 "malformed uleb128, extends past end"));
287 parseCFI(TestCIE
, {Inst
, /*Op1=*/0}),
288 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
289 "malformed sleb128, extends past end"));
293 {dwarf::DW_CFA_offset_extended_sf
, dwarf::DW_CFA_def_cfa_sf
,
294 dwarf::DW_CFA_LLVM_def_aspace_cfa_sf
, dwarf::DW_CFA_val_offset_sf
})
295 CheckOp_ULEB128_SLEB128(Inst
);
297 // Unable to read a truncated DW_CFA_def_cfa_expression instruction.
299 parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa_expression
}),
300 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
301 "malformed uleb128, extends past end"));
303 parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa_expression
,
304 /*expression length=*/0x1}),
306 "unexpected end of data at offset 0x2 while reading [0x2, 0x3)"));
307 // The DW_CFA_def_cfa_expression can contain a zero length expression.
308 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa_expression
,
312 // A test for an instruction with three operands: ULEB128, expression length
313 // (ULEB128) and expression bytes.
314 auto CheckOp_ULEB128_Expr
= [&](uint8_t Inst
) {
316 parseCFI(TestCIE
, {Inst
}),
317 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
318 "malformed uleb128, extends past end"));
320 parseCFI(TestCIE
, {Inst
, /*Op1=*/0}),
321 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
322 "malformed uleb128, extends past end"));
323 // A zero length expression is fine
324 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {Inst
,
325 /*Op1=*/0, /*ExprLen=*/0}),
328 parseCFI(TestCIE
, {Inst
,
329 /*Op1=*/0, /*ExprLen=*/1}),
331 "unexpected end of data at offset 0x3 while reading [0x3, 0x4)"));
334 for (uint8_t Inst
: {dwarf::DW_CFA_expression
, dwarf::DW_CFA_val_expression
})
335 CheckOp_ULEB128_Expr(Inst
);
338 void expectDumpResult(const dwarf::UnwindLocation
&Loc
,
339 StringRef ExpectedFirstLine
) {
341 raw_string_ostream
OS(Output
);
344 StringRef FirstLine
= StringRef(Output
).split('\n').first
;
345 EXPECT_EQ(FirstLine
, ExpectedFirstLine
);
348 TEST(DWARFDebugFrame
, DumpUnwindLocations
) {
349 // Test constructing unwind locations and dumping each kind.
350 constexpr int32_t PlusOff
= 8;
351 constexpr int32_t MinusOff
= -8;
352 constexpr uint8_t RegNum
= 12;
353 expectDumpResult(dwarf::UnwindLocation::createUnspecified(), "unspecified");
354 expectDumpResult(dwarf::UnwindLocation::createUndefined(), "undefined");
355 expectDumpResult(dwarf::UnwindLocation::createSame(), "same");
356 expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(PlusOff
),
358 expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff
),
360 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff
),
362 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff
),
366 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum
, PlusOff
),
369 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum
, MinusOff
),
372 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum
, PlusOff
),
375 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum
, MinusOff
),
377 expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12");
378 expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32");
381 void expectDumpResult(const dwarf::RegisterLocations
&Locs
,
382 StringRef ExpectedFirstLine
) {
384 raw_string_ostream
OS(Output
);
387 StringRef FirstLine
= StringRef(Output
).split('\n').first
;
388 EXPECT_EQ(FirstLine
, ExpectedFirstLine
);
391 TEST(DWARFDebugFrame
, RegisterLocations
) {
392 // Test the functionality of the RegisterLocations class.
393 dwarf::RegisterLocations Locs
;
394 expectDumpResult(Locs
, "");
395 EXPECT_FALSE(Locs
.hasLocations());
396 // Set a register location for reg12 to unspecified and verify it dumps
398 Locs
.setRegisterLocation(12, dwarf::UnwindLocation::createUnspecified());
399 EXPECT_TRUE(Locs
.hasLocations());
400 expectDumpResult(Locs
, "reg12=unspecified");
402 // Replace the register location for reg12 to "same" and verify it dumps
403 // correctly after it is modified
404 Locs
.setRegisterLocation(12, dwarf::UnwindLocation::createSame());
405 EXPECT_TRUE(Locs
.hasLocations());
406 expectDumpResult(Locs
, "reg12=same");
408 // Remove the register location for reg12 verify it dumps correctly after it
410 Locs
.removeRegisterLocation(12);
411 EXPECT_FALSE(Locs
.hasLocations());
412 expectDumpResult(Locs
, "");
414 // Verify multiple registers added to the list dump correctly.
415 auto Reg12Loc
= dwarf::UnwindLocation::createAtCFAPlusOffset(4);
416 auto Reg13Loc
= dwarf::UnwindLocation::createAtCFAPlusOffset(8);
417 auto Reg14Loc
= dwarf::UnwindLocation::createSame();
418 Locs
.setRegisterLocation(12, Reg12Loc
);
419 Locs
.setRegisterLocation(13, Reg13Loc
);
420 Locs
.setRegisterLocation(14, Reg14Loc
);
421 EXPECT_TRUE(Locs
.hasLocations());
422 expectDumpResult(Locs
, "reg12=[CFA+4], reg13=[CFA+8], reg14=same");
424 // Verify RegisterLocations::getRegisterLocation() works as expected.
425 Optional
<dwarf::UnwindLocation
> OptionalLoc
;
426 OptionalLoc
= Locs
.getRegisterLocation(0);
427 EXPECT_FALSE(OptionalLoc
.has_value());
429 OptionalLoc
= Locs
.getRegisterLocation(12);
430 EXPECT_TRUE(OptionalLoc
.has_value());
431 EXPECT_EQ(*OptionalLoc
, Reg12Loc
);
433 OptionalLoc
= Locs
.getRegisterLocation(13);
434 EXPECT_TRUE(OptionalLoc
.has_value());
435 EXPECT_EQ(*OptionalLoc
, Reg13Loc
);
437 OptionalLoc
= Locs
.getRegisterLocation(14);
438 EXPECT_TRUE(OptionalLoc
.has_value());
439 EXPECT_EQ(*OptionalLoc
, Reg14Loc
);
441 // Verify registers are correctly removed when multiple exist in the list.
442 Locs
.removeRegisterLocation(13);
443 EXPECT_FALSE(Locs
.getRegisterLocation(13).has_value());
444 EXPECT_TRUE(Locs
.hasLocations());
445 expectDumpResult(Locs
, "reg12=[CFA+4], reg14=same");
446 Locs
.removeRegisterLocation(14);
447 EXPECT_FALSE(Locs
.getRegisterLocation(14).has_value());
448 EXPECT_TRUE(Locs
.hasLocations());
449 expectDumpResult(Locs
, "reg12=[CFA+4]");
450 Locs
.removeRegisterLocation(12);
451 EXPECT_FALSE(Locs
.getRegisterLocation(12).has_value());
452 EXPECT_FALSE(Locs
.hasLocations());
453 expectDumpResult(Locs
, "");
456 // Test that empty rows are not added to UnwindTable when
457 // dwarf::CIE::CFIs or dwarf::FDE::CFIs is empty.
458 TEST(DWARFDebugFrame
, UnwindTableEmptyRows
) {
459 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
463 // Having an empty instructions list is fine.
464 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {}), Succeeded());
465 EXPECT_TRUE(TestCIE
.cfis().empty());
467 // Verify dwarf::UnwindTable::create() won't result in errors and
468 // and empty rows are not added to CIE UnwindTable.
469 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestCIE
);
470 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
471 const size_t ExpectedNumOfRows
= 0;
472 EXPECT_EQ(RowsOrErr
->size(), ExpectedNumOfRows
);
474 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
475 /*Offset=*/0x3333abcdabcd,
476 /*Length=*/0x4444abcdabcd,
477 /*CIEPointer=*/0x1111abcdabcd,
478 /*InitialLocation=*/0x1000,
479 /*AddressRange=*/0x1000,
481 /*LSDAAddress=*/None
,
482 /*Arch=*/Triple::x86_64
);
484 // Having an empty instructions list is fine.
485 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {}), Succeeded());
486 EXPECT_TRUE(TestFDE
.cfis().empty());
488 // Verify dwarf::UnwindTable::create() won't result in errors and
489 // and empty rows are not added to FDE UnwindTable.
490 RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
491 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
492 EXPECT_EQ(RowsOrErr
->size(), ExpectedNumOfRows
);
495 // Test that empty rows are not added to UnwindTable when dwarf::CIE::CFIs
496 // or dwarf::FDE::CFIs is not empty but has only DW_CFA_nop instructions.
497 TEST(DWARFDebugFrame
, UnwindTableEmptyRows_NOPs
) {
498 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
502 // Make a CIE that has only DW_CFA_nop instructions.
503 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_nop
}), Succeeded());
504 EXPECT_TRUE(!TestCIE
.cfis().empty());
506 // Verify dwarf::UnwindTable::create() won't result in errors and
507 // and empty rows are not added to CIE UnwindTable.
508 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestCIE
);
509 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
510 const size_t ExpectedNumOfRows
= 0;
511 EXPECT_EQ(RowsOrErr
->size(), ExpectedNumOfRows
);
513 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
514 /*Offset=*/0x3333abcdabcd,
515 /*Length=*/0x4444abcdabcd,
516 /*CIEPointer=*/0x1111abcdabcd,
517 /*InitialLocation=*/0x1000,
518 /*AddressRange=*/0x1000,
520 /*LSDAAddress=*/None
,
521 /*Arch=*/Triple::x86_64
);
523 // Make an FDE that has only DW_CFA_nop instructions.
524 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_nop
}), Succeeded());
525 EXPECT_TRUE(!TestFDE
.cfis().empty());
527 // Verify dwarf::UnwindTable::create() won't result in errors and
528 // and empty rows are not added to FDE UnwindTable.
529 RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
530 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
531 EXPECT_EQ(RowsOrErr
->size(), ExpectedNumOfRows
);
534 TEST(DWARFDebugFrame
, UnwindTableErrorNonAscendingFDERows
) {
535 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
539 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
540 /*Offset=*/0x3333abcdabcd,
541 /*Length=*/0x4444abcdabcd,
542 /*CIEPointer=*/0x1111abcdabcd,
543 /*InitialLocation=*/0x1000,
544 /*AddressRange=*/0x1000,
546 /*LSDAAddress=*/None
,
547 /*Arch=*/Triple::x86_64
);
549 // Make a CIE that has a valid CFA definition.
550 constexpr uint8_t Reg
= 12;
551 constexpr uint8_t Offset
= 32;
552 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, Reg
, Offset
}),
555 // Make a FDE with DWARF call frame instruction opcodes that have valid
556 // syntax, but will cause an error when we parse them into a UnwindTable.
557 // Here we encode two DW_CFA_set_loc opcodes:
558 // DW_CFA_set_loc(0x1100)
559 // DW_CFA_set_loc(0x1000)
560 // These opcodes cause a new row to be appended to the rows in a UnwindTable
561 // and the resulting rows are not in ascending address order and should cause
562 // a state machine error.
564 parseCFI(TestFDE
, {dwarf::DW_CFA_set_loc
, 0x00, 0x11, 0, 0, 0, 0, 0, 0,
565 dwarf::DW_CFA_set_loc
, 0x00, 0x10, 0, 0, 0, 0, 0, 0}),
568 // Verify we catch state machine error.
569 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
570 EXPECT_THAT_ERROR(RowsOrErr
.takeError(),
571 FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which"
572 " must be greater than the current row "
576 TEST(DWARFDebugFrame
, UnwindTableError_DW_CFA_restore_state
) {
577 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
581 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
582 /*Offset=*/0x3333abcdabcd,
583 /*Length=*/0x4444abcdabcd,
584 /*CIEPointer=*/0x1111abcdabcd,
585 /*InitialLocation=*/0x1000,
586 /*AddressRange=*/0x1000,
588 /*LSDAAddress=*/None
,
589 /*Arch=*/Triple::x86_64
);
591 // Make a CIE that has a valid CFA definition.
592 constexpr uint8_t Reg
= 12;
593 constexpr uint8_t Offset
= 32;
594 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, Reg
, Offset
}),
597 // Make a FDE with DWARF call frame instruction opcodes that have valid
598 // syntax, but will cause an error when we parse them into a UnwindTable.
599 // Here we encode a DW_CFA_restore_state opcode that was not preceded by a
600 // DW_CFA_remember_state, and an error should be returned.
601 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_restore_state
}),
604 // Verify we catch state machine error.
605 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
606 EXPECT_THAT_ERROR(RowsOrErr
.takeError(),
607 FailedWithMessage("DW_CFA_restore_state without a matching "
608 "previous DW_CFA_remember_state"));
611 TEST(DWARFDebugFrame
, UnwindTableError_DW_CFA_GNU_window_save
) {
612 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
616 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
617 /*Offset=*/0x3333abcdabcd,
618 /*Length=*/0x4444abcdabcd,
619 /*CIEPointer=*/0x1111abcdabcd,
620 /*InitialLocation=*/0x1000,
621 /*AddressRange=*/0x1000,
623 /*LSDAAddress=*/None
,
624 /*Arch=*/Triple::x86_64
);
626 // Make a CIE that has a valid CFA definition.
627 constexpr uint8_t Reg
= 12;
628 constexpr uint8_t Offset
= 32;
629 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, Reg
, Offset
}),
632 // Make a FDE with DWARF call frame instruction opcodes that have valid
633 // syntax, but will cause an error when we parse them into a UnwindTable.
634 // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not
635 // found any documentation that describes what this does after some brief
637 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_GNU_window_save
}),
640 // Verify we catch state machine error.
641 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
642 EXPECT_THAT_ERROR(RowsOrErr
.takeError(),
643 FailedWithMessage("DW_CFA opcode 0x2d is not supported for "
644 "architecture x86_64"));
647 TEST(DWARFDebugFrame
, UnwindTableError_DW_CFA_def_cfa_offset
) {
648 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
652 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
653 /*Offset=*/0x3333abcdabcd,
654 /*Length=*/0x4444abcdabcd,
655 /*CIEPointer=*/0x1111abcdabcd,
656 /*InitialLocation=*/0x1000,
657 /*AddressRange=*/0x1000,
659 /*LSDAAddress=*/None
,
660 /*Arch=*/Triple::x86_64
);
662 // Make a CIE that has an invalid CFA definition. We do this so we can try
663 // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate
665 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {}), Succeeded());
667 // Make a FDE with DWARF call frame instruction opcodes that have valid
668 // syntax, but will cause an error when we parse them into a UnwindTable.
669 // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE
670 // didn't define the CFA in terms of a register plus offset, so this should
672 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_def_cfa_offset
, 16}),
675 // Verify we catch state machine error.
676 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
677 EXPECT_THAT_ERROR(RowsOrErr
.takeError(),
678 FailedWithMessage("DW_CFA_def_cfa_offset found when CFA "
679 "rule was not RegPlusOffset"));
682 TEST(DWARFDebugFrame
, UnwindTableDefCFAOffsetSFCFAError
) {
683 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
687 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
688 /*Offset=*/0x3333abcdabcd,
689 /*Length=*/0x4444abcdabcd,
690 /*CIEPointer=*/0x1111abcdabcd,
691 /*InitialLocation=*/0x1000,
692 /*AddressRange=*/0x1000,
694 /*LSDAAddress=*/None
,
695 /*Arch=*/Triple::x86_64
);
697 // Make a CIE that has an invalid CFA definition. We do this so we can try
698 // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an
699 // appropriate error back.
700 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {}), Succeeded());
702 // Make a FDE with DWARF call frame instruction opcodes that have valid
703 // syntax, but will cause an error when we parse them into a UnwindTable.
704 // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE
705 // didn't define the CFA in terms of a register plus offset, so this should
707 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_def_cfa_offset_sf
, 4}),
710 // Verify we catch state machine error.
711 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
712 EXPECT_THAT_ERROR(RowsOrErr
.takeError(),
713 FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA "
714 "rule was not RegPlusOffset"));
717 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_def_cfa_register
) {
718 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
722 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
723 /*Offset=*/0x3333abcdabcd,
724 /*Length=*/0x4444abcdabcd,
725 /*CIEPointer=*/0x1111abcdabcd,
726 /*InitialLocation=*/0x1000,
727 /*AddressRange=*/0x1000,
729 /*LSDAAddress=*/None
,
730 /*Arch=*/Triple::x86_64
);
732 // Make a CIE that has only defines the CFA register with no offset. Some
733 // architectures do this and we must ensure that we set the CFA value to be
734 // equal to that register with no offset.
735 constexpr uint8_t CFAReg
= 12;
736 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa_register
, CFAReg
}),
739 // Make a FDE with DWARF call frame instruction opcodes that have valid
740 // syntax, but will cause an error when we parse them into a UnwindTable.
741 // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but
742 // our CIE didn't define the CFA in terms of a register plus offset, so this
743 // should cause an error.
744 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {}), Succeeded());
746 // Verify we catch state machine error.
747 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
748 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
749 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
750 EXPECT_EQ(Rows
.size(), 1u);
751 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
752 EXPECT_EQ(Rows
[0].getCFAValue(),
753 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg
, 0));
756 TEST(DWARFDebugFrame
, UnwindTableRowPushingOpcodes
) {
757 // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable.
758 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
762 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
763 /*Offset=*/0x3333abcdabcd,
764 /*Length=*/0x4444abcdabcd,
765 /*CIEPointer=*/0x1111abcdabcd,
766 /*InitialLocation=*/0x1000,
767 /*AddressRange=*/0x1000,
769 /*LSDAAddress=*/None
,
770 /*Arch=*/Triple::x86_64
);
772 // Make a CIE that has a valid CFA definition and a single register unwind
773 // rule for register that we will verify is in all of the pushed rows.
774 constexpr uint8_t CFAReg
= 12;
775 constexpr uint8_t CFAOffset
= 32;
776 constexpr uint8_t Reg
= 13;
777 constexpr uint8_t InReg
= 14;
779 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, CFAReg
, CFAOffset
,
780 dwarf::DW_CFA_register
, Reg
, InReg
}),
783 // Make a FDE with DWARF call frame instruction opcodes that use all of the
784 // row pushing opcodes. This will verify that all opcodes that should create
785 // a row are correctly working. Each opcode will push a row prior to
786 // advancing the address, and then a row will be automatically pushed at the
787 // end of the parsing, so we should end up with 6 rows starting at address
788 // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor
790 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_advance_loc
| 4,
791 dwarf::DW_CFA_advance_loc1
,
793 dwarf::DW_CFA_advance_loc2
,
796 dwarf::DW_CFA_advance_loc4
,
801 dwarf::DW_CFA_set_loc
,
812 // Create locations that we expect the UnwindRow objects to contain after
813 // parsing the DWARF call frame instructions.
814 dwarf::RegisterLocations VerifyLocs
;
815 VerifyLocs
.setRegisterLocation(
816 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
818 // Verify we catch state machine error.
819 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
820 ASSERT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
821 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
822 EXPECT_EQ(Rows
.size(), 6u);
823 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
824 EXPECT_EQ(Rows
[0].getRegisterLocations().size(), 1u);
825 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
826 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
827 EXPECT_EQ(Rows
[1].getRegisterLocations().size(), 1u);
828 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs
);
829 EXPECT_EQ(Rows
[2].getAddress(), 0x1008u
);
830 EXPECT_EQ(Rows
[2].getRegisterLocations().size(), 1u);
831 EXPECT_EQ(Rows
[2].getRegisterLocations(), VerifyLocs
);
832 EXPECT_EQ(Rows
[3].getAddress(), 0x100cu
);
833 EXPECT_EQ(Rows
[3].getRegisterLocations().size(), 1u);
834 EXPECT_EQ(Rows
[3].getRegisterLocations(), VerifyLocs
);
835 EXPECT_EQ(Rows
[4].getAddress(), 0x1010u
);
836 EXPECT_EQ(Rows
[4].getRegisterLocations().size(), 1u);
837 EXPECT_EQ(Rows
[4].getRegisterLocations(), VerifyLocs
);
838 EXPECT_EQ(Rows
[5].getAddress(), 0x1014u
);
839 EXPECT_EQ(Rows
[5].getRegisterLocations().size(), 1u);
840 EXPECT_EQ(Rows
[5].getRegisterLocations(), VerifyLocs
);
843 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_restore
) {
844 // Test that DW_CFA_restore works as expected when parsed in the state
846 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
850 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
851 /*Offset=*/0x3333abcdabcd,
852 /*Length=*/0x4444abcdabcd,
853 /*CIEPointer=*/0x1111abcdabcd,
854 /*InitialLocation=*/0x1000,
855 /*AddressRange=*/0x1000,
857 /*LSDAAddress=*/None
,
858 /*Arch=*/Triple::x86_64
);
860 // Make a CIE that has a valid CFA definition and a single register unwind
861 // rule for register that we will verify is in all of the pushed rows.
862 constexpr uint8_t CFAReg
= 12;
863 constexpr uint8_t CFAOffset
= 32;
864 constexpr uint8_t Reg
= 13;
865 constexpr uint8_t InReg
= 14;
866 constexpr int32_t RegCFAOffset
= -8;
868 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, CFAReg
, CFAOffset
,
869 dwarf::DW_CFA_register
, Reg
, InReg
}),
872 // Make a FDE with DWARF call frame instruction opcodes that changes the rule
873 // for register "Reg" to be [CFA-8], then push a row, and then restore the
874 // register unwind rule for "Reg" using DW_CFA_restore. We should end up with
876 // - one with Reg = [CFA-8]
877 // - one with Reg = InReg
878 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_offset
| Reg
, 1,
879 dwarf::DW_CFA_advance_loc
| 4,
880 dwarf::DW_CFA_restore
| Reg
}),
883 // Create locations that we expect the UnwindRow objects to contain after
884 // parsing the DWARF call frame instructions.
885 dwarf::RegisterLocations VerifyLocs1
;
886 VerifyLocs1
.setRegisterLocation(
887 Reg
, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset
));
889 dwarf::RegisterLocations VerifyLocs2
;
890 VerifyLocs2
.setRegisterLocation(
891 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
893 // Verify we catch state machine error.
894 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
895 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
896 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
897 EXPECT_EQ(Rows
.size(), 2u);
898 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
899 EXPECT_EQ(Rows
[0].getRegisterLocations().size(), 1u);
900 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs1
);
901 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
902 EXPECT_EQ(Rows
[1].getRegisterLocations().size(), 1u);
903 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs2
);
906 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_restore_extended
) {
907 // Test that DW_CFA_restore works as expected when parsed in the state
909 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
913 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
914 /*Offset=*/0x3333abcdabcd,
915 /*Length=*/0x4444abcdabcd,
916 /*CIEPointer=*/0x1111abcdabcd,
917 /*InitialLocation=*/0x1000,
918 /*AddressRange=*/0x1000,
920 /*LSDAAddress=*/None
,
921 /*Arch=*/Triple::x86_64
);
923 // Make a CIE that has a valid CFA definition and a single register unwind
924 // rule for register that we will verify is in all of the pushed rows.
925 constexpr uint8_t CFAReg
= 12;
926 constexpr uint8_t CFAOffset
= 32;
927 constexpr uint8_t Reg
= 13;
928 constexpr uint8_t InReg
= 14;
929 constexpr int32_t RegCFAOffset
= -8;
931 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, CFAReg
, CFAOffset
,
932 dwarf::DW_CFA_register
, Reg
, InReg
}),
935 // Make a FDE with DWARF call frame instruction opcodes that changes the rule
936 // for register "Reg" to be [CFA-8], then push a row, and then restore the
937 // register unwind rule for "Reg" using DW_CFA_restore_extended. We should
938 // end up with two rows:
939 // - one with Reg = [CFA-8]
940 // - one with Reg = InReg
941 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_offset
| Reg
, 1,
942 dwarf::DW_CFA_advance_loc
| 4,
943 dwarf::DW_CFA_restore_extended
, Reg
}),
946 // Create locations that we expect the UnwindRow objects to contain after
947 // parsing the DWARF call frame instructions.
948 dwarf::RegisterLocations VerifyLocs1
;
949 VerifyLocs1
.setRegisterLocation(
950 Reg
, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset
));
952 dwarf::RegisterLocations VerifyLocs2
;
953 VerifyLocs2
.setRegisterLocation(
954 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
956 // Verify we catch state machine error.
957 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
958 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
959 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
960 EXPECT_EQ(Rows
.size(), 2u);
961 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
962 EXPECT_EQ(Rows
[0].getRegisterLocations().size(), 1u);
963 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs1
);
964 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
965 EXPECT_EQ(Rows
[1].getRegisterLocations().size(), 1u);
966 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs2
);
969 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_offset
) {
970 // Test that DW_CFA_offset, DW_CFA_offset_extended and
971 // DW_CFA_offset_extended_sf work as expected when parsed in the state
973 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
977 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
978 /*Offset=*/0x3333abcdabcd,
979 /*Length=*/0x4444abcdabcd,
980 /*CIEPointer=*/0x1111abcdabcd,
981 /*InitialLocation=*/0x1000,
982 /*AddressRange=*/0x1000,
984 /*LSDAAddress=*/None
,
985 /*Arch=*/Triple::x86_64
);
987 // Make a CIE that has a valid CFA definition and a single register unwind
988 // rule for register that we will verify is in all of the pushed rows.
989 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
992 // Make a FDE with DWARF call frame instruction opcodes that changes the
993 // unwind rules for the follwing registers:
997 constexpr uint8_t Reg1
= 14;
998 constexpr uint8_t Reg2
= 15;
999 constexpr uint8_t Reg3
= 16;
1000 constexpr uint8_t Neg1SLEB
= 0x7f;
1003 {dwarf::DW_CFA_offset
| Reg1
, 1, dwarf::DW_CFA_offset_extended
,
1004 Reg2
, 2, dwarf::DW_CFA_offset_extended_sf
, Reg3
, Neg1SLEB
}),
1007 // Create locations that we expect the UnwindRow objects to contain after
1008 // parsing the DWARF call frame instructions.
1009 dwarf::RegisterLocations VerifyLocs
;
1010 VerifyLocs
.setRegisterLocation(
1011 Reg1
, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1012 VerifyLocs
.setRegisterLocation(
1013 Reg2
, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1014 VerifyLocs
.setRegisterLocation(
1015 Reg3
, dwarf::UnwindLocation::createAtCFAPlusOffset(8));
1017 // Verify we catch state machine error.
1018 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1019 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1020 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1021 EXPECT_EQ(Rows
.size(), 1u);
1022 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1023 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1026 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_val_offset
) {
1027 // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when
1028 // parsed in the state machine.
1029 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1033 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1034 /*Offset=*/0x3333abcdabcd,
1035 /*Length=*/0x4444abcdabcd,
1036 /*CIEPointer=*/0x1111abcdabcd,
1037 /*InitialLocation=*/0x1000,
1038 /*AddressRange=*/0x1000,
1040 /*LSDAAddress=*/None
,
1041 /*Arch=*/Triple::x86_64
);
1043 // Make a CIE that has a valid CFA definition and a single register unwind
1044 // rule for register that we will verify is in all of the pushed rows.
1045 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1048 // Make a FDE with DWARF call frame instruction opcodes that changes the
1049 // unwind rules for the follwing registers:
1053 constexpr uint8_t Reg1
= 14;
1054 constexpr uint8_t Reg2
= 15;
1055 constexpr uint8_t Neg1SLEB
= 0x7f;
1057 parseCFI(TestFDE
, {dwarf::DW_CFA_val_offset
, Reg1
, 1,
1058 dwarf::DW_CFA_val_offset_sf
, Reg2
, Neg1SLEB
}),
1061 // Create locations that we expect the UnwindRow objects to contain after
1062 // parsing the DWARF call frame instructions.
1063 dwarf::RegisterLocations VerifyLocs
;
1064 VerifyLocs
.setRegisterLocation(
1065 Reg1
, dwarf::UnwindLocation::createIsCFAPlusOffset(-8));
1066 VerifyLocs
.setRegisterLocation(
1067 Reg2
, dwarf::UnwindLocation::createIsCFAPlusOffset(8));
1069 // Verify we catch state machine error.
1070 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1071 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1072 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1073 EXPECT_EQ(Rows
.size(), 1u);
1074 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1075 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1078 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_nop
) {
1079 // Test that DW_CFA_nop works as expected when parsed in the state machine.
1080 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1084 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1085 /*Offset=*/0x3333abcdabcd,
1086 /*Length=*/0x4444abcdabcd,
1087 /*CIEPointer=*/0x1111abcdabcd,
1088 /*InitialLocation=*/0x1000,
1089 /*AddressRange=*/0x1000,
1091 /*LSDAAddress=*/None
,
1092 /*Arch=*/Triple::x86_64
);
1094 // Make a CIE that has a valid CFA definition and a single register unwind
1095 // rule for register that we will verify is in all of the pushed rows.
1096 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1099 // Make a FDE with DWARF call frame instruction opcodes that changes the
1100 // unwind rules for the follwing registers:
1102 // The opcodes for setting Reg1 are preceded by a DW_CFA_nop.
1103 constexpr uint8_t Reg1
= 14;
1105 parseCFI(TestFDE
, {dwarf::DW_CFA_nop
, dwarf::DW_CFA_offset
| Reg1
, 1}),
1108 // Create locations that we expect the UnwindRow objects to contain after
1109 // parsing the DWARF call frame instructions.
1110 dwarf::RegisterLocations VerifyLocs
;
1111 VerifyLocs
.setRegisterLocation(
1112 Reg1
, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1114 // Verify we catch state machine error.
1115 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1116 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1117 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1118 EXPECT_EQ(Rows
.size(), 1u);
1119 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1120 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1123 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_remember_state
) {
1124 // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected
1125 // when parsed in the state machine.
1126 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1130 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1131 /*Offset=*/0x3333abcdabcd,
1132 /*Length=*/0x4444abcdabcd,
1133 /*CIEPointer=*/0x1111abcdabcd,
1134 /*InitialLocation=*/0x1000,
1135 /*AddressRange=*/0x1000,
1137 /*LSDAAddress=*/None
,
1138 /*Arch=*/Triple::x86_64
);
1140 // Make a CIE that has a valid CFA definition and a single register unwind
1141 // rule for register that we will verify is in all of the pushed rows.
1142 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1145 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1147 // 0x1000: CFA=reg12+32: Reg1=[CFA-8]
1148 // 0x1004: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16]
1149 // 0x1008: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24]
1150 // 0x100C: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16]
1151 // 0x1010: CFA=reg12+32: Reg1=[CFA-8]
1152 // This state machine will:
1153 // - set Reg1 location
1154 // - push a row (from DW_CFA_advance_loc)
1155 // - remember the state
1156 // - set Reg2 location
1157 // - push a row (from DW_CFA_advance_loc)
1158 // - remember the state
1159 // - set Reg3 location
1160 // - push a row (from DW_CFA_advance_loc)
1161 // - remember the state where Reg1 and Reg2 were set
1162 // - push a row (from DW_CFA_advance_loc)
1163 // - remember the state where only Reg1 was set
1164 // - push a row (automatically at the end of instruction parsing)
1165 // Then we verify that all registers are correct in all generated rows.
1166 constexpr uint8_t Reg1
= 14;
1167 constexpr uint8_t Reg2
= 15;
1168 constexpr uint8_t Reg3
= 16;
1171 {dwarf::DW_CFA_offset
| Reg1
, 1, dwarf::DW_CFA_advance_loc
| 4,
1172 dwarf::DW_CFA_remember_state
, dwarf::DW_CFA_offset
| Reg2
, 2,
1173 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_remember_state
,
1174 dwarf::DW_CFA_offset
| Reg3
, 3, dwarf::DW_CFA_advance_loc
| 4,
1175 dwarf::DW_CFA_restore_state
, dwarf::DW_CFA_advance_loc
| 4,
1176 dwarf::DW_CFA_restore_state
}),
1179 // Create locations that we expect the UnwindRow objects to contain after
1180 // parsing the DWARF call frame instructions.
1181 dwarf::RegisterLocations VerifyLocs1
;
1182 VerifyLocs1
.setRegisterLocation(
1183 Reg1
, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1185 dwarf::RegisterLocations VerifyLocs2
;
1186 VerifyLocs2
.setRegisterLocation(
1187 Reg1
, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1188 VerifyLocs2
.setRegisterLocation(
1189 Reg2
, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1191 dwarf::RegisterLocations VerifyLocs3
;
1192 VerifyLocs3
.setRegisterLocation(
1193 Reg1
, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1194 VerifyLocs3
.setRegisterLocation(
1195 Reg2
, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1196 VerifyLocs3
.setRegisterLocation(
1197 Reg3
, dwarf::UnwindLocation::createAtCFAPlusOffset(-24));
1199 // Verify we catch state machine error.
1200 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1201 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1202 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1203 EXPECT_EQ(Rows
.size(), 5u);
1204 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1205 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs1
);
1207 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
1208 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs2
);
1210 EXPECT_EQ(Rows
[2].getAddress(), 0x1008u
);
1211 EXPECT_EQ(Rows
[2].getRegisterLocations(), VerifyLocs3
);
1213 EXPECT_EQ(Rows
[3].getAddress(), 0x100Cu
);
1214 EXPECT_EQ(Rows
[3].getRegisterLocations(), VerifyLocs2
);
1216 EXPECT_EQ(Rows
[4].getAddress(), 0x1010u
);
1217 EXPECT_EQ(Rows
[4].getRegisterLocations(), VerifyLocs1
);
1220 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_undefined
) {
1221 // Test that DW_CFA_undefined works as expected when parsed in the state
1223 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1227 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1228 /*Offset=*/0x3333abcdabcd,
1229 /*Length=*/0x4444abcdabcd,
1230 /*CIEPointer=*/0x1111abcdabcd,
1231 /*InitialLocation=*/0x1000,
1232 /*AddressRange=*/0x1000,
1234 /*LSDAAddress=*/None
,
1235 /*Arch=*/Triple::x86_64
);
1237 // Make a CIE that has a valid CFA definition and a single register unwind
1238 // rule for register that we will verify is in all of the pushed rows.
1239 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1242 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1244 // 0x1000: CFA=reg12+32: Reg1=undefined
1245 // Then we verify that all registers are correct in all generated rows.
1246 constexpr uint8_t Reg1
= 14;
1247 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_undefined
, Reg1
}),
1250 // Create locations that we expect the UnwindRow objects to contain after
1251 // parsing the DWARF call frame instructions.
1252 dwarf::RegisterLocations VerifyLocs
;
1253 VerifyLocs
.setRegisterLocation(Reg1
,
1254 dwarf::UnwindLocation::createUndefined());
1256 // Verify we catch state machine error.
1257 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1258 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1259 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1260 EXPECT_EQ(Rows
.size(), 1u);
1261 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1262 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1265 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_same_value
) {
1266 // Test that DW_CFA_same_value works as expected when parsed in the state
1268 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1272 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1273 /*Offset=*/0x3333abcdabcd,
1274 /*Length=*/0x4444abcdabcd,
1275 /*CIEPointer=*/0x1111abcdabcd,
1276 /*InitialLocation=*/0x1000,
1277 /*AddressRange=*/0x1000,
1279 /*LSDAAddress=*/None
,
1280 /*Arch=*/Triple::x86_64
);
1282 // Make a CIE that has a valid CFA definition and a single register unwind
1283 // rule for register that we will verify is in all of the pushed rows.
1284 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1287 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1289 // 0x1000: CFA=reg12+32: Reg1=same
1290 // Then we verify that all registers are correct in all generated rows.
1291 constexpr uint8_t Reg1
= 14;
1292 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_same_value
, Reg1
}),
1295 // Create locations that we expect the UnwindRow objects to contain after
1296 // parsing the DWARF call frame instructions.
1297 dwarf::RegisterLocations VerifyLocs
;
1298 VerifyLocs
.setRegisterLocation(Reg1
, dwarf::UnwindLocation::createSame());
1300 // Verify we catch state machine error.
1301 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1302 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1303 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1304 EXPECT_EQ(Rows
.size(), 1u);
1305 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1306 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1309 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_register
) {
1310 // Test that DW_CFA_register works as expected when parsed in the state
1312 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1316 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1317 /*Offset=*/0x3333abcdabcd,
1318 /*Length=*/0x4444abcdabcd,
1319 /*CIEPointer=*/0x1111abcdabcd,
1320 /*InitialLocation=*/0x1000,
1321 /*AddressRange=*/0x1000,
1323 /*LSDAAddress=*/None
,
1324 /*Arch=*/Triple::x86_64
);
1326 // Make a CIE that has a valid CFA definition and a single register unwind
1327 // rule for register that we will verify is in all of the pushed rows.
1328 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1331 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1333 // 0x1000: CFA=reg12+32: Reg1=same
1334 // Then we verify that all registers are correct in all generated rows.
1335 constexpr uint8_t Reg
= 13;
1336 constexpr uint8_t InReg
= 14;
1337 EXPECT_THAT_ERROR(parseCFI(TestFDE
, {dwarf::DW_CFA_register
, Reg
, InReg
}),
1340 // Create locations that we expect the UnwindRow objects to contain after
1341 // parsing the DWARF call frame instructions.
1342 dwarf::RegisterLocations VerifyLocs
;
1343 VerifyLocs
.setRegisterLocation(
1344 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
1346 // Verify we catch state machine error.
1347 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1348 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1349 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1350 EXPECT_EQ(Rows
.size(), 1u);
1351 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1352 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1355 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_expression
) {
1356 // Test that DW_CFA_expression works as expected when parsed in the state
1358 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1362 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1363 /*Offset=*/0x3333abcdabcd,
1364 /*Length=*/0x4444abcdabcd,
1365 /*CIEPointer=*/0x1111abcdabcd,
1366 /*InitialLocation=*/0x1000,
1367 /*AddressRange=*/0x1000,
1369 /*LSDAAddress=*/None
,
1370 /*Arch=*/Triple::x86_64
);
1372 // Make a CIE that has a valid CFA definition and a single register unwind
1373 // rule for register that we will verify is in all of the pushed rows.
1374 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1377 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1379 // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1380 // Then we verify that all registers are correct in all generated rows.
1381 constexpr uint8_t Reg
= 13;
1382 constexpr uint8_t AddrSize
= 8;
1383 std::vector
<uint8_t> CFIBytes
= {dwarf::DW_CFA_expression
, Reg
, 1,
1384 dwarf::DW_OP_reg12
};
1386 EXPECT_THAT_ERROR(parseCFI(TestFDE
, CFIBytes
), Succeeded());
1388 // Create locations that we expect the UnwindRow objects to contain after
1389 // parsing the DWARF call frame instructions.
1390 dwarf::RegisterLocations VerifyLocs
;
1392 std::vector
<uint8_t> ExprBytes
= {dwarf::DW_OP_reg12
};
1393 DataExtractor
ExprData(ExprBytes
, true, AddrSize
);
1394 DWARFExpression
Expr(ExprData
, AddrSize
);
1395 VerifyLocs
.setRegisterLocation(
1396 Reg
, dwarf::UnwindLocation::createAtDWARFExpression(Expr
));
1398 // Verify we catch state machine error.
1399 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1400 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1401 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1402 EXPECT_EQ(Rows
.size(), 1u);
1403 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1404 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1407 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_val_expression
) {
1408 // Test that DW_CFA_val_expression works as expected when parsed in the state
1410 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1414 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1415 /*Offset=*/0x3333abcdabcd,
1416 /*Length=*/0x4444abcdabcd,
1417 /*CIEPointer=*/0x1111abcdabcd,
1418 /*InitialLocation=*/0x1000,
1419 /*AddressRange=*/0x1000,
1421 /*LSDAAddress=*/None
,
1422 /*Arch=*/Triple::x86_64
);
1424 // Make a CIE that has a valid CFA definition and a single register unwind
1425 // rule for register that we will verify is in all of the pushed rows.
1426 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, 12, 32}),
1429 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1431 // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1432 // Then we verify that all registers are correct in all generated rows.
1433 constexpr uint8_t Reg
= 13;
1434 constexpr uint8_t AddrSize
= 8;
1435 std::vector
<uint8_t> CFIBytes
= {dwarf::DW_CFA_val_expression
, Reg
, 1,
1436 dwarf::DW_OP_reg12
};
1438 EXPECT_THAT_ERROR(parseCFI(TestFDE
, CFIBytes
), Succeeded());
1440 // Create locations that we expect the UnwindRow objects to contain after
1441 // parsing the DWARF call frame instructions.
1442 dwarf::RegisterLocations VerifyLocs
;
1444 std::vector
<uint8_t> ExprBytes
= {dwarf::DW_OP_reg12
};
1445 DataExtractor
ExprData(ExprBytes
, true, AddrSize
);
1446 DWARFExpression
Expr(ExprData
, AddrSize
);
1447 VerifyLocs
.setRegisterLocation(
1448 Reg
, dwarf::UnwindLocation::createIsDWARFExpression(Expr
));
1450 // Verify we catch state machine error.
1451 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1452 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1453 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1454 EXPECT_EQ(Rows
.size(), 1u);
1455 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1456 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1459 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_def_cfa
) {
1460 // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register,
1461 // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when
1462 // parsed in the state machine.
1463 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1467 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1468 /*Offset=*/0x3333abcdabcd,
1469 /*Length=*/0x4444abcdabcd,
1470 /*CIEPointer=*/0x1111abcdabcd,
1471 /*InitialLocation=*/0x1000,
1472 /*AddressRange=*/0x1000,
1474 /*LSDAAddress=*/None
,
1475 /*Arch=*/Triple::x86_64
);
1477 // Make a CIE that has a valid CFA definition and a single register unwind
1478 // rule for register that we will verify is in all of the pushed rows.
1479 constexpr uint8_t CFAReg1
= 12;
1480 constexpr uint8_t CFAOff1
= 32;
1481 constexpr uint8_t CFAReg2
= 13;
1482 constexpr uint8_t CFAOff2
= 48;
1483 constexpr uint8_t Reg
= 13;
1484 constexpr uint8_t InReg
= 14;
1486 EXPECT_THAT_ERROR(parseCFI(TestCIE
, {dwarf::DW_CFA_def_cfa
, CFAReg1
, CFAOff1
,
1487 dwarf::DW_CFA_register
, Reg
, InReg
}),
1490 // Make a FDE with DWARF call frame instruction opcodes that use all of the
1491 // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1492 // create a row are correctly working.
1497 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_register
,
1498 CFAReg2
, dwarf::DW_CFA_advance_loc
| 4,
1499 dwarf::DW_CFA_def_cfa_offset
, CFAOff2
,
1500 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_offset_sf
,
1501 0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1502 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_sf
, CFAReg1
,
1503 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1507 // Create locations that we expect the UnwindRow objects to contain after
1508 // parsing the DWARF call frame instructions.
1509 dwarf::RegisterLocations VerifyLocs
;
1510 VerifyLocs
.setRegisterLocation(
1511 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
1513 // Verify we catch state machine error.
1514 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1515 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1516 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1517 EXPECT_EQ(Rows
.size(), 5u);
1518 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1520 Rows
[0].getCFAValue(),
1521 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1
, CFAOff1
));
1522 EXPECT_EQ(Rows
[0].getRegisterLocations().size(), 1u);
1523 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1525 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
1527 Rows
[1].getCFAValue(),
1528 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff1
));
1529 EXPECT_EQ(Rows
[1].getRegisterLocations().size(), 1u);
1530 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs
);
1532 EXPECT_EQ(Rows
[2].getAddress(), 0x1008u
);
1534 Rows
[2].getCFAValue(),
1535 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff2
));
1536 EXPECT_EQ(Rows
[2].getRegisterLocations().size(), 1u);
1537 EXPECT_EQ(Rows
[2].getRegisterLocations(), VerifyLocs
);
1539 EXPECT_EQ(Rows
[3].getAddress(), 0x100cu
);
1541 Rows
[3].getCFAValue(),
1542 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff1
));
1543 EXPECT_EQ(Rows
[3].getRegisterLocations().size(), 1u);
1544 EXPECT_EQ(Rows
[3].getRegisterLocations(), VerifyLocs
);
1546 EXPECT_EQ(Rows
[4].getAddress(), 0x1010u
);
1548 Rows
[4].getCFAValue(),
1549 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1
, CFAOff2
));
1550 EXPECT_EQ(Rows
[4].getRegisterLocations().size(), 1u);
1551 EXPECT_EQ(Rows
[4].getRegisterLocations(), VerifyLocs
);
1554 TEST(DWARFDebugFrame
, UnwindTable_DW_CFA_LLVM_def_aspace_cfa
) {
1555 // Test that DW_CFA_LLVM_def_aspace_cfa, DW_CFA_LLVM_def_aspace_cfa_sf,
1556 // DW_CFA_def_cfa_register, DW_CFA_def_cfa_offset, and
1557 // DW_CFA_def_cfa_offset_sf works as expected when parsed in the state
1559 dwarf::CIE TestCIE
= createCIE(/*IsDWARF64=*/false,
1563 dwarf::FDE
TestFDE(/*IsDWARF64=*/true,
1564 /*Offset=*/0x3333abcdabcd,
1565 /*Length=*/0x4444abcdabcd,
1566 /*CIEPointer=*/0x1111abcdabcd,
1567 /*InitialLocation=*/0x1000,
1568 /*AddressRange=*/0x1000,
1570 /*LSDAAddress=*/None
,
1571 /*Arch=*/Triple::x86_64
);
1573 // Make a CIE that has a valid CFA definition and a single register unwind
1574 // rule for register that we will verify is in all of the pushed rows.
1575 constexpr uint8_t CFAReg1
= 12;
1576 constexpr uint8_t CFAOff1
= 32;
1577 constexpr uint8_t CFAReg2
= 13;
1578 constexpr uint8_t CFAOff2
= 48;
1579 constexpr uint8_t Reg
= 13;
1580 constexpr uint8_t InReg
= 14;
1581 constexpr uint8_t AddrSpace
= 2;
1584 parseCFI(TestCIE
, {dwarf::DW_CFA_LLVM_def_aspace_cfa
, CFAReg1
, CFAOff1
,
1585 AddrSpace
, dwarf::DW_CFA_register
, Reg
, InReg
}),
1588 // Make a FDE with DWARF call frame instruction opcodes that use all of the
1589 // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1590 // create a row are correctly working.
1595 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_register
,
1596 CFAReg2
, dwarf::DW_CFA_advance_loc
| 4,
1597 dwarf::DW_CFA_def_cfa_offset
, CFAOff2
,
1598 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_offset_sf
,
1599 0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1600 dwarf::DW_CFA_advance_loc
| 4, dwarf::DW_CFA_def_cfa_sf
, CFAReg1
,
1601 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1605 // Create locations that we expect the UnwindRow objects to contain after
1606 // parsing the DWARF call frame instructions.
1607 dwarf::RegisterLocations VerifyLocs
;
1608 VerifyLocs
.setRegisterLocation(
1609 Reg
, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg
, 0));
1611 // Verify we catch state machine error.
1612 Expected
<dwarf::UnwindTable
> RowsOrErr
= dwarf::UnwindTable::create(&TestFDE
);
1613 EXPECT_THAT_ERROR(RowsOrErr
.takeError(), Succeeded());
1614 const dwarf::UnwindTable
&Rows
= RowsOrErr
.get();
1615 EXPECT_EQ(Rows
.size(), 5u);
1616 EXPECT_EQ(Rows
[0].getAddress(), 0x1000u
);
1617 EXPECT_EQ(Rows
[0].getCFAValue(),
1618 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1
, CFAOff1
,
1620 EXPECT_EQ(Rows
[0].getRegisterLocations().size(), 1u);
1621 EXPECT_EQ(Rows
[0].getRegisterLocations(), VerifyLocs
);
1623 EXPECT_EQ(Rows
[1].getAddress(), 0x1004u
);
1624 EXPECT_EQ(Rows
[1].getCFAValue(),
1625 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff1
,
1627 EXPECT_EQ(Rows
[1].getRegisterLocations().size(), 1u);
1628 EXPECT_EQ(Rows
[1].getRegisterLocations(), VerifyLocs
);
1630 EXPECT_EQ(Rows
[2].getAddress(), 0x1008u
);
1631 EXPECT_EQ(Rows
[2].getCFAValue(),
1632 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff2
,
1634 EXPECT_EQ(Rows
[2].getRegisterLocations().size(), 1u);
1635 EXPECT_EQ(Rows
[2].getRegisterLocations(), VerifyLocs
);
1637 EXPECT_EQ(Rows
[3].getAddress(), 0x100cu
);
1638 EXPECT_EQ(Rows
[3].getCFAValue(),
1639 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2
, CFAOff1
,
1641 EXPECT_EQ(Rows
[3].getRegisterLocations().size(), 1u);
1642 EXPECT_EQ(Rows
[3].getRegisterLocations(), VerifyLocs
);
1644 EXPECT_EQ(Rows
[4].getAddress(), 0x1010u
);
1645 EXPECT_EQ(Rows
[4].getCFAValue(),
1646 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1
, CFAOff2
,
1648 EXPECT_EQ(Rows
[4].getRegisterLocations().size(), 1u);
1649 EXPECT_EQ(Rows
[4].getRegisterLocations(), VerifyLocs
);
1652 } // end anonymous namespace