[clangd] Re-land "support outgoing calls in call hierarchy" (#117673)
[llvm-project.git] / llvm / unittests / DebugInfo / DWARF / DWARFDebugFrameTest.cpp
blob2be656547c92e01cf4e4629ce156ae4b23d6f347
1 //===- llvm/unittest/DebugInfo/DWARFDebugFrameTest.cpp --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
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"
19 using namespace llvm;
21 namespace {
23 dwarf::CIE createCIE(bool IsDWARF64, uint64_t Offset, uint64_t Length) {
24 return dwarf::CIE(IsDWARF64, Offset, Length,
25 /*Version=*/3,
26 /*Augmentation=*/StringRef(),
27 /*AddressSize=*/8,
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) {
42 std::string Output;
43 raw_string_ostream OS(Output);
44 auto DumpOpts = DIDumpOptions();
45 DumpOpts.IsEH = IsEH;
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) {
53 std::string Output;
54 raw_string_ostream OS(Output);
55 auto DumpOpts = DIDumpOptions();
56 DumpOpts.IsEH = IsEH;
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,
79 /*Offset=*/0x1000,
80 /*Length=*/0x20);
81 expectDumpResult(TestCIE, /*IsEH=*/true, "00001000 00000020 00000000 CIE");
84 TEST(DWARFDebugFrame, DumpEH64CIE) {
85 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
86 /*Offset=*/0x1000,
87 /*Length=*/0x20);
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,
102 /*Cie=*/&TestCIE,
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,
113 /*Length=*/0x20);
114 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
115 /*Offset=*/0x1111abcdabcd,
116 /*Length=*/0x2222abcdabcd,
117 /*CIEPointer=*/0x33abcd,
118 /*InitialLocation=*/0x4444abcdabcd,
119 /*AddressRange=*/0x111111111111,
120 /*Cie=*/&TestCIE,
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,
131 /*AddressSize=*/8);
132 uint64_t Offset = 0;
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,
139 /*AddressSize=*/8);
140 uint64_t Offset = 0;
141 return FDE.cfis().parse(Data, &Offset, Instructions.size());
144 TEST(DWARFDebugFrame, InvalidCFIOpcodesTest) {
145 llvm::DenseSet<uint8_t> ValidExtendedOpcodes = {
146 dwarf::DW_CFA_nop,
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,
181 /*Offset=*/0x0,
182 /*Length=*/0xff);
184 // See DWARF standard v3, section 7.23: low 6 bits are used to encode an
185 // extended opcode.
186 for (uint8_t Code = 0; Code <= 63; ++Code) {
187 if (ValidExtendedOpcodes.count(Code))
188 continue;
190 EXPECT_THAT_ERROR(parseCFI(TestCIE, Code),
191 FailedWithMessage(("invalid extended CFI opcode 0x" +
192 Twine::utohexstr(Code))
193 .str()
194 .c_str()));
198 // Here we test how truncated Call Frame Instructions are parsed.
199 TEST(DWARFDebugFrame, ParseTruncatedCFITest) {
200 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
201 /*Offset=*/0x0,
202 /*Length=*/0xff);
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.
209 EXPECT_THAT_ERROR(
210 parseCFI(TestCIE, {}, /*Size=*/1),
211 FailedWithMessage(
212 "unexpected end of data at offset 0x0 while reading [0x0, 0x1)"));
214 // Unable to read a truncated DW_CFA_offset instruction.
215 EXPECT_THAT_ERROR(
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.
221 EXPECT_THAT_ERROR(
222 parseCFI(TestCIE, {dwarf::DW_CFA_set_loc}),
223 FailedWithMessage(
224 "unexpected end of data at offset 0x1 while reading [0x1, 0x9)"));
226 // Unable to read a truncated DW_CFA_advance_loc1 instruction.
227 EXPECT_THAT_ERROR(
228 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}),
229 FailedWithMessage(
230 "unexpected end of data at offset 0x1 while reading [0x1, 0x2)"));
232 // Unable to read a truncated DW_CFA_advance_loc2 instruction.
233 EXPECT_THAT_ERROR(
234 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}),
235 FailedWithMessage(
236 "unexpected end of data at offset 0x1 while reading [0x1, 0x3)"));
238 // Unable to read a truncated DW_CFA_advance_loc4 instruction.
239 EXPECT_THAT_ERROR(
240 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}),
241 FailedWithMessage(
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) {
246 EXPECT_THAT_ERROR(
247 parseCFI(TestCIE, Inst),
248 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
249 "malformed uleb128, extends past end"));
252 for (uint8_t Inst :
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.
259 EXPECT_THAT_ERROR(
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) {
266 EXPECT_THAT_ERROR(
267 parseCFI(TestCIE, Inst),
268 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
269 "malformed uleb128, extends past end"));
271 EXPECT_THAT_ERROR(
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) {
284 EXPECT_THAT_ERROR(
285 parseCFI(TestCIE, Inst),
286 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
287 "malformed uleb128, extends past end"));
289 EXPECT_THAT_ERROR(
290 parseCFI(TestCIE, {Inst, /*Op1=*/0}),
291 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
292 "malformed sleb128, extends past end"));
295 for (uint8_t Inst :
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.
301 EXPECT_THAT_ERROR(
302 parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}),
303 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
304 "malformed uleb128, extends past end"));
305 EXPECT_THAT_ERROR(
306 parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
307 /*expression length=*/0x1}),
308 FailedWithMessage(
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,
312 /*ExprLen=*/0}),
313 Succeeded());
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) {
318 EXPECT_THAT_ERROR(
319 parseCFI(TestCIE, {Inst}),
320 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
321 "malformed uleb128, extends past end"));
322 EXPECT_THAT_ERROR(
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}),
329 Succeeded());
330 EXPECT_THAT_ERROR(
331 parseCFI(TestCIE, {Inst,
332 /*Op1=*/0, /*ExprLen=*/1}),
333 FailedWithMessage(
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) {
343 std::string Output;
344 raw_string_ostream OS(Output);
345 OS << Loc;
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),
359 "CFA+8");
360 expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff),
361 "CFA-8");
362 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff),
363 "[CFA+8]");
364 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff),
365 "[CFA-8]");
367 expectDumpResult(
368 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, PlusOff),
369 "reg12+8");
370 expectDumpResult(
371 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, MinusOff),
372 "reg12-8");
373 expectDumpResult(
374 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, PlusOff),
375 "[reg12+8]");
376 expectDumpResult(
377 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, MinusOff),
378 "[reg12-8]");
379 expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12");
380 expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32");
383 void expectDumpResult(const dwarf::RegisterLocations &Locs,
384 StringRef ExpectedFirstLine) {
385 std::string Output;
386 raw_string_ostream OS(Output);
387 OS << Locs;
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
398 // correctly.
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
410 // is removed.
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,
461 /*Offset=*/0x0,
462 /*Length=*/0xff);
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,
481 /*Cie=*/&TestCIE,
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,
500 /*Offset=*/0x0,
501 /*Length=*/0xff);
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,
520 /*Cie=*/&TestCIE,
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,
537 /*Offset=*/0x0,
538 /*Length=*/0xff);
540 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
541 /*Offset=*/0x3333abcdabcd,
542 /*Length=*/0x4444abcdabcd,
543 /*CIEPointer=*/0x1111abcdabcd,
544 /*InitialLocation=*/0x1000,
545 /*AddressRange=*/0x1000,
546 /*Cie=*/&TestCIE,
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}),
554 Succeeded());
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.
564 EXPECT_THAT_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}),
567 Succeeded());
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 "
574 "address 0x1100"));
577 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) {
578 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
579 /*Offset=*/0x0,
580 /*Length=*/0xff);
582 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
583 /*Offset=*/0x3333abcdabcd,
584 /*Length=*/0x4444abcdabcd,
585 /*CIEPointer=*/0x1111abcdabcd,
586 /*InitialLocation=*/0x1000,
587 /*AddressRange=*/0x1000,
588 /*Cie=*/&TestCIE,
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}),
596 Succeeded());
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}),
603 Succeeded());
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,
614 /*Offset=*/0x0,
615 /*Length=*/0xff);
617 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
618 /*Offset=*/0x3333abcdabcd,
619 /*Length=*/0x4444abcdabcd,
620 /*CIEPointer=*/0x1111abcdabcd,
621 /*InitialLocation=*/0x1000,
622 /*AddressRange=*/0x1000,
623 /*Cie=*/&TestCIE,
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}),
631 Succeeded());
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
637 // searching.
638 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}),
639 Succeeded());
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,
650 /*Offset=*/0x0,
651 /*Length=*/0xff);
653 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
654 /*Offset=*/0x3333abcdabcd,
655 /*Length=*/0x4444abcdabcd,
656 /*CIEPointer=*/0x1111abcdabcd,
657 /*InitialLocation=*/0x1000,
658 /*AddressRange=*/0x1000,
659 /*Cie=*/&TestCIE,
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
665 // error back.
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
672 // cause an error.
673 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}),
674 Succeeded());
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,
685 /*Offset=*/0x0,
686 /*Length=*/0xff);
688 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
689 /*Offset=*/0x3333abcdabcd,
690 /*Length=*/0x4444abcdabcd,
691 /*CIEPointer=*/0x1111abcdabcd,
692 /*InitialLocation=*/0x1000,
693 /*AddressRange=*/0x1000,
694 /*Cie=*/&TestCIE,
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
707 // cause an error.
708 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}),
709 Succeeded());
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,
720 /*Offset=*/0x0,
721 /*Length=*/0xff);
723 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
724 /*Offset=*/0x3333abcdabcd,
725 /*Length=*/0x4444abcdabcd,
726 /*CIEPointer=*/0x1111abcdabcd,
727 /*InitialLocation=*/0x1000,
728 /*AddressRange=*/0x1000,
729 /*Cie=*/&TestCIE,
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}),
738 Succeeded());
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,
760 /*Offset=*/0x0,
761 /*Length=*/0xff);
763 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
764 /*Offset=*/0x3333abcdabcd,
765 /*Length=*/0x4444abcdabcd,
766 /*CIEPointer=*/0x1111abcdabcd,
767 /*InitialLocation=*/0x1000,
768 /*AddressRange=*/0x1000,
769 /*Cie=*/&TestCIE,
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}),
782 Succeeded());
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
790 // from the CIE.
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,
803 0x14,
804 0x10,
810 0}),
811 Succeeded());
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
846 // machine.
847 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
848 /*Offset=*/0x0,
849 /*Length=*/0xff);
851 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
852 /*Offset=*/0x3333abcdabcd,
853 /*Length=*/0x4444abcdabcd,
854 /*CIEPointer=*/0x1111abcdabcd,
855 /*InitialLocation=*/0x1000,
856 /*AddressRange=*/0x1000,
857 /*Cie=*/&TestCIE,
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}),
871 Succeeded());
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
876 // two rows:
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}),
882 Succeeded());
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
909 // machine.
910 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
911 /*Offset=*/0x0,
912 /*Length=*/0xff);
914 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
915 /*Offset=*/0x3333abcdabcd,
916 /*Length=*/0x4444abcdabcd,
917 /*CIEPointer=*/0x1111abcdabcd,
918 /*InitialLocation=*/0x1000,
919 /*AddressRange=*/0x1000,
920 /*Cie=*/&TestCIE,
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}),
934 Succeeded());
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}),
945 Succeeded());
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
973 // machine.
974 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
975 /*Offset=*/0x0,
976 /*Length=*/0xff);
978 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
979 /*Offset=*/0x3333abcdabcd,
980 /*Length=*/0x4444abcdabcd,
981 /*CIEPointer=*/0x1111abcdabcd,
982 /*InitialLocation=*/0x1000,
983 /*AddressRange=*/0x1000,
984 /*Cie=*/&TestCIE,
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}),
991 Succeeded());
993 // Make a FDE with DWARF call frame instruction opcodes that changes the
994 // unwind rules for the follwing registers:
995 // Reg1 = [CFA-8]
996 // Reg2 = [CFA-16]
997 // Reg3 = [CFA+8]
998 constexpr uint8_t Reg1 = 14;
999 constexpr uint8_t Reg2 = 15;
1000 constexpr uint8_t Reg3 = 16;
1001 constexpr uint8_t Neg1SLEB = 0x7f;
1002 EXPECT_THAT_ERROR(
1003 parseCFI(TestFDE,
1004 {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended,
1005 Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}),
1006 Succeeded());
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,
1031 /*Offset=*/0x0,
1032 /*Length=*/0xff);
1034 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1035 /*Offset=*/0x3333abcdabcd,
1036 /*Length=*/0x4444abcdabcd,
1037 /*CIEPointer=*/0x1111abcdabcd,
1038 /*InitialLocation=*/0x1000,
1039 /*AddressRange=*/0x1000,
1040 /*Cie=*/&TestCIE,
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}),
1047 Succeeded());
1049 // Make a FDE with DWARF call frame instruction opcodes that changes the
1050 // unwind rules for the follwing registers:
1051 // Reg1 = [CFA-8]
1052 // Reg2 = [CFA-16]
1053 // Reg3 = [CFA+8]
1054 constexpr uint8_t Reg1 = 14;
1055 constexpr uint8_t Reg2 = 15;
1056 constexpr uint8_t Neg1SLEB = 0x7f;
1057 EXPECT_THAT_ERROR(
1058 parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1,
1059 dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}),
1060 Succeeded());
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,
1082 /*Offset=*/0x0,
1083 /*Length=*/0xff);
1085 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1086 /*Offset=*/0x3333abcdabcd,
1087 /*Length=*/0x4444abcdabcd,
1088 /*CIEPointer=*/0x1111abcdabcd,
1089 /*InitialLocation=*/0x1000,
1090 /*AddressRange=*/0x1000,
1091 /*Cie=*/&TestCIE,
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}),
1098 Succeeded());
1100 // Make a FDE with DWARF call frame instruction opcodes that changes the
1101 // unwind rules for the follwing registers:
1102 // Reg1 = [CFA-8]
1103 // The opcodes for setting Reg1 are preceded by a DW_CFA_nop.
1104 constexpr uint8_t Reg1 = 14;
1105 EXPECT_THAT_ERROR(
1106 parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}),
1107 Succeeded());
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,
1128 /*Offset=*/0x0,
1129 /*Length=*/0xff);
1131 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1132 /*Offset=*/0x3333abcdabcd,
1133 /*Length=*/0x4444abcdabcd,
1134 /*CIEPointer=*/0x1111abcdabcd,
1135 /*InitialLocation=*/0x1000,
1136 /*AddressRange=*/0x1000,
1137 /*Cie=*/&TestCIE,
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}),
1150 Succeeded());
1152 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1153 // follwing rows:
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.
1174 EXPECT_THAT_ERROR(
1175 parseCFI(TestFDE,
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}),
1183 Succeeded());
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
1238 // machine.
1239 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1240 /*Offset=*/0x0,
1241 /*Length=*/0xff);
1243 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1244 /*Offset=*/0x3333abcdabcd,
1245 /*Length=*/0x4444abcdabcd,
1246 /*CIEPointer=*/0x1111abcdabcd,
1247 /*InitialLocation=*/0x1000,
1248 /*AddressRange=*/0x1000,
1249 /*Cie=*/&TestCIE,
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}),
1256 Succeeded());
1258 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1259 // follwing rows:
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}),
1264 Succeeded());
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
1283 // machine.
1284 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1285 /*Offset=*/0x0,
1286 /*Length=*/0xff);
1288 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1289 /*Offset=*/0x3333abcdabcd,
1290 /*Length=*/0x4444abcdabcd,
1291 /*CIEPointer=*/0x1111abcdabcd,
1292 /*InitialLocation=*/0x1000,
1293 /*AddressRange=*/0x1000,
1294 /*Cie=*/&TestCIE,
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}),
1301 Succeeded());
1303 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1304 // follwing rows:
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}),
1309 Succeeded());
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
1327 // machine.
1328 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1329 /*Offset=*/0x0,
1330 /*Length=*/0xff);
1332 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1333 /*Offset=*/0x3333abcdabcd,
1334 /*Length=*/0x4444abcdabcd,
1335 /*CIEPointer=*/0x1111abcdabcd,
1336 /*InitialLocation=*/0x1000,
1337 /*AddressRange=*/0x1000,
1338 /*Cie=*/&TestCIE,
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}),
1345 Succeeded());
1347 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1348 // follwing rows:
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}),
1354 Succeeded());
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
1373 // machine.
1374 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1375 /*Offset=*/0x0,
1376 /*Length=*/0xff);
1378 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1379 /*Offset=*/0x3333abcdabcd,
1380 /*Length=*/0x4444abcdabcd,
1381 /*CIEPointer=*/0x1111abcdabcd,
1382 /*InitialLocation=*/0x1000,
1383 /*AddressRange=*/0x1000,
1384 /*Cie=*/&TestCIE,
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}),
1391 Succeeded());
1393 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1394 // follwing rows:
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
1425 // machine.
1426 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1427 /*Offset=*/0x0,
1428 /*Length=*/0xff);
1430 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1431 /*Offset=*/0x3333abcdabcd,
1432 /*Length=*/0x4444abcdabcd,
1433 /*CIEPointer=*/0x1111abcdabcd,
1434 /*InitialLocation=*/0x1000,
1435 /*AddressRange=*/0x1000,
1436 /*Cie=*/&TestCIE,
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}),
1443 Succeeded());
1445 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1446 // follwing rows:
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,
1480 /*Offset=*/0x0,
1481 /*Length=*/0xff);
1483 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1484 /*Offset=*/0x3333abcdabcd,
1485 /*Length=*/0x4444abcdabcd,
1486 /*CIEPointer=*/0x1111abcdabcd,
1487 /*InitialLocation=*/0x1000,
1488 /*AddressRange=*/0x1000,
1489 /*Cie=*/&TestCIE,
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}),
1504 Succeeded());
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.
1509 EXPECT_THAT_ERROR(
1510 parseCFI(
1511 TestFDE,
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)
1521 Succeeded());
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);
1535 EXPECT_EQ(
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);
1542 EXPECT_EQ(
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);
1549 EXPECT_EQ(
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);
1556 EXPECT_EQ(
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);
1563 EXPECT_EQ(
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
1574 // machine.
1575 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1576 /*Offset=*/0x0,
1577 /*Length=*/0xff);
1579 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1580 /*Offset=*/0x3333abcdabcd,
1581 /*Length=*/0x4444abcdabcd,
1582 /*CIEPointer=*/0x1111abcdabcd,
1583 /*InitialLocation=*/0x1000,
1584 /*AddressRange=*/0x1000,
1585 /*Cie=*/&TestCIE,
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;
1599 EXPECT_THAT_ERROR(
1600 parseCFI(TestCIE, {dwarf::DW_CFA_LLVM_def_aspace_cfa, CFAReg1, CFAOff1,
1601 AddrSpace, dwarf::DW_CFA_register, Reg, InReg}),
1602 Succeeded());
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.
1607 EXPECT_THAT_ERROR(
1608 parseCFI(
1609 TestFDE,
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)
1619 Succeeded());
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,
1635 AddrSpace));
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,
1642 AddrSpace));
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,
1649 AddrSpace));
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,
1656 AddrSpace));
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,
1663 AddrSpace));
1664 EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
1665 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
1668 } // end anonymous namespace