[docs] Fix build-docs.sh
[llvm-project.git] / llvm / unittests / DebugInfo / DWARF / DWARFDebugFrameTest.cpp
blobdbc54e7bdb8ef13a76825094c5ac342fe7f011f8
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=*/None,
36 /*PersonalityEnc=*/None,
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 TestCIE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH);
45 OS.flush();
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) {
52 std::string Output;
53 raw_string_ostream OS(Output);
54 TestFDE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH);
55 OS.flush();
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,
77 /*Offset=*/0x1000,
78 /*Length=*/0x20);
79 expectDumpResult(TestCIE, /*IsEH=*/true, "00001000 00000020 00000000 CIE");
82 TEST(DWARFDebugFrame, DumpEH64CIE) {
83 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
84 /*Offset=*/0x1000,
85 /*Length=*/0x20);
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,
100 /*Cie=*/&TestCIE,
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,
111 /*Length=*/0x20);
112 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
113 /*Offset=*/0x1111abcdabcd,
114 /*Length=*/0x2222abcdabcd,
115 /*CIEPointer=*/0x33abcd,
116 /*InitialLocation=*/0x4444abcdabcd,
117 /*AddressRange=*/0x111111111111,
118 /*Cie=*/&TestCIE,
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,
129 /*AddressSize=*/8);
130 uint64_t Offset = 0;
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,
137 /*AddressSize=*/8);
138 uint64_t Offset = 0;
139 return FDE.cfis().parse(Data, &Offset, Instructions.size());
142 TEST(DWARFDebugFrame, InvalidCFIOpcodesTest) {
143 llvm::DenseSet<uint8_t> ValidExtendedOpcodes = {
144 dwarf::DW_CFA_nop,
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,
178 /*Offset=*/0x0,
179 /*Length=*/0xff);
181 // See DWARF standard v3, section 7.23: low 6 bits are used to encode an
182 // extended opcode.
183 for (uint8_t Code = 0; Code <= 63; ++Code) {
184 if (ValidExtendedOpcodes.count(Code))
185 continue;
187 EXPECT_THAT_ERROR(parseCFI(TestCIE, Code),
188 FailedWithMessage(("invalid extended CFI opcode 0x" +
189 Twine::utohexstr(Code))
190 .str()
191 .c_str()));
195 // Here we test how truncated Call Frame Instructions are parsed.
196 TEST(DWARFDebugFrame, ParseTruncatedCFITest) {
197 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
198 /*Offset=*/0x0,
199 /*Length=*/0xff);
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.
206 EXPECT_THAT_ERROR(
207 parseCFI(TestCIE, {}, /*Size=*/1),
208 FailedWithMessage(
209 "unexpected end of data at offset 0x0 while reading [0x0, 0x1)"));
211 // Unable to read a truncated DW_CFA_offset instruction.
212 EXPECT_THAT_ERROR(
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.
218 EXPECT_THAT_ERROR(
219 parseCFI(TestCIE, {dwarf::DW_CFA_set_loc}),
220 FailedWithMessage(
221 "unexpected end of data at offset 0x1 while reading [0x1, 0x9)"));
223 // Unable to read a truncated DW_CFA_advance_loc1 instruction.
224 EXPECT_THAT_ERROR(
225 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}),
226 FailedWithMessage(
227 "unexpected end of data at offset 0x1 while reading [0x1, 0x2)"));
229 // Unable to read a truncated DW_CFA_advance_loc2 instruction.
230 EXPECT_THAT_ERROR(
231 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}),
232 FailedWithMessage(
233 "unexpected end of data at offset 0x1 while reading [0x1, 0x3)"));
235 // Unable to read a truncated DW_CFA_advance_loc4 instruction.
236 EXPECT_THAT_ERROR(
237 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}),
238 FailedWithMessage(
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) {
243 EXPECT_THAT_ERROR(
244 parseCFI(TestCIE, Inst),
245 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
246 "malformed uleb128, extends past end"));
249 for (uint8_t Inst :
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.
256 EXPECT_THAT_ERROR(
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) {
263 EXPECT_THAT_ERROR(
264 parseCFI(TestCIE, Inst),
265 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
266 "malformed uleb128, extends past end"));
268 EXPECT_THAT_ERROR(
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) {
281 EXPECT_THAT_ERROR(
282 parseCFI(TestCIE, Inst),
283 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
284 "malformed uleb128, extends past end"));
286 EXPECT_THAT_ERROR(
287 parseCFI(TestCIE, {Inst, /*Op1=*/0}),
288 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
289 "malformed sleb128, extends past end"));
292 for (uint8_t Inst :
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.
298 EXPECT_THAT_ERROR(
299 parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}),
300 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
301 "malformed uleb128, extends past end"));
302 EXPECT_THAT_ERROR(
303 parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
304 /*expression length=*/0x1}),
305 FailedWithMessage(
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,
309 /*ExprLen=*/0}),
310 Succeeded());
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) {
315 EXPECT_THAT_ERROR(
316 parseCFI(TestCIE, {Inst}),
317 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
318 "malformed uleb128, extends past end"));
319 EXPECT_THAT_ERROR(
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}),
326 Succeeded());
327 EXPECT_THAT_ERROR(
328 parseCFI(TestCIE, {Inst,
329 /*Op1=*/0, /*ExprLen=*/1}),
330 FailedWithMessage(
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) {
340 std::string Output;
341 raw_string_ostream OS(Output);
342 OS << Loc;
343 OS.flush();
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),
357 "CFA+8");
358 expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff),
359 "CFA-8");
360 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff),
361 "[CFA+8]");
362 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff),
363 "[CFA-8]");
365 expectDumpResult(
366 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, PlusOff),
367 "reg12+8");
368 expectDumpResult(
369 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, MinusOff),
370 "reg12-8");
371 expectDumpResult(
372 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, PlusOff),
373 "[reg12+8]");
374 expectDumpResult(
375 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, MinusOff),
376 "[reg12-8]");
377 expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12");
378 expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32");
381 void expectDumpResult(const dwarf::RegisterLocations &Locs,
382 StringRef ExpectedFirstLine) {
383 std::string Output;
384 raw_string_ostream OS(Output);
385 OS << Locs;
386 OS.flush();
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
397 // correctly.
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
409 // is removed.
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,
460 /*Offset=*/0x0,
461 /*Length=*/0xff);
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,
480 /*Cie=*/&TestCIE,
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,
499 /*Offset=*/0x0,
500 /*Length=*/0xff);
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,
519 /*Cie=*/&TestCIE,
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,
536 /*Offset=*/0x0,
537 /*Length=*/0xff);
539 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
540 /*Offset=*/0x3333abcdabcd,
541 /*Length=*/0x4444abcdabcd,
542 /*CIEPointer=*/0x1111abcdabcd,
543 /*InitialLocation=*/0x1000,
544 /*AddressRange=*/0x1000,
545 /*Cie=*/&TestCIE,
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}),
553 Succeeded());
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.
563 EXPECT_THAT_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}),
566 Succeeded());
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 "
573 "address 0x1100"));
576 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) {
577 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
578 /*Offset=*/0x0,
579 /*Length=*/0xff);
581 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
582 /*Offset=*/0x3333abcdabcd,
583 /*Length=*/0x4444abcdabcd,
584 /*CIEPointer=*/0x1111abcdabcd,
585 /*InitialLocation=*/0x1000,
586 /*AddressRange=*/0x1000,
587 /*Cie=*/&TestCIE,
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}),
595 Succeeded());
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}),
602 Succeeded());
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,
613 /*Offset=*/0x0,
614 /*Length=*/0xff);
616 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
617 /*Offset=*/0x3333abcdabcd,
618 /*Length=*/0x4444abcdabcd,
619 /*CIEPointer=*/0x1111abcdabcd,
620 /*InitialLocation=*/0x1000,
621 /*AddressRange=*/0x1000,
622 /*Cie=*/&TestCIE,
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}),
630 Succeeded());
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
636 // searching.
637 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}),
638 Succeeded());
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,
649 /*Offset=*/0x0,
650 /*Length=*/0xff);
652 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
653 /*Offset=*/0x3333abcdabcd,
654 /*Length=*/0x4444abcdabcd,
655 /*CIEPointer=*/0x1111abcdabcd,
656 /*InitialLocation=*/0x1000,
657 /*AddressRange=*/0x1000,
658 /*Cie=*/&TestCIE,
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
664 // error back.
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
671 // cause an error.
672 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}),
673 Succeeded());
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,
684 /*Offset=*/0x0,
685 /*Length=*/0xff);
687 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
688 /*Offset=*/0x3333abcdabcd,
689 /*Length=*/0x4444abcdabcd,
690 /*CIEPointer=*/0x1111abcdabcd,
691 /*InitialLocation=*/0x1000,
692 /*AddressRange=*/0x1000,
693 /*Cie=*/&TestCIE,
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
706 // cause an error.
707 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}),
708 Succeeded());
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,
719 /*Offset=*/0x0,
720 /*Length=*/0xff);
722 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
723 /*Offset=*/0x3333abcdabcd,
724 /*Length=*/0x4444abcdabcd,
725 /*CIEPointer=*/0x1111abcdabcd,
726 /*InitialLocation=*/0x1000,
727 /*AddressRange=*/0x1000,
728 /*Cie=*/&TestCIE,
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}),
737 Succeeded());
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,
759 /*Offset=*/0x0,
760 /*Length=*/0xff);
762 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
763 /*Offset=*/0x3333abcdabcd,
764 /*Length=*/0x4444abcdabcd,
765 /*CIEPointer=*/0x1111abcdabcd,
766 /*InitialLocation=*/0x1000,
767 /*AddressRange=*/0x1000,
768 /*Cie=*/&TestCIE,
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}),
781 Succeeded());
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
789 // from the CIE.
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,
802 0x14,
803 0x10,
809 0}),
810 Succeeded());
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
845 // machine.
846 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
847 /*Offset=*/0x0,
848 /*Length=*/0xff);
850 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
851 /*Offset=*/0x3333abcdabcd,
852 /*Length=*/0x4444abcdabcd,
853 /*CIEPointer=*/0x1111abcdabcd,
854 /*InitialLocation=*/0x1000,
855 /*AddressRange=*/0x1000,
856 /*Cie=*/&TestCIE,
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}),
870 Succeeded());
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
875 // two rows:
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}),
881 Succeeded());
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
908 // machine.
909 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
910 /*Offset=*/0x0,
911 /*Length=*/0xff);
913 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
914 /*Offset=*/0x3333abcdabcd,
915 /*Length=*/0x4444abcdabcd,
916 /*CIEPointer=*/0x1111abcdabcd,
917 /*InitialLocation=*/0x1000,
918 /*AddressRange=*/0x1000,
919 /*Cie=*/&TestCIE,
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}),
933 Succeeded());
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}),
944 Succeeded());
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
972 // machine.
973 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
974 /*Offset=*/0x0,
975 /*Length=*/0xff);
977 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
978 /*Offset=*/0x3333abcdabcd,
979 /*Length=*/0x4444abcdabcd,
980 /*CIEPointer=*/0x1111abcdabcd,
981 /*InitialLocation=*/0x1000,
982 /*AddressRange=*/0x1000,
983 /*Cie=*/&TestCIE,
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}),
990 Succeeded());
992 // Make a FDE with DWARF call frame instruction opcodes that changes the
993 // unwind rules for the follwing registers:
994 // Reg1 = [CFA-8]
995 // Reg2 = [CFA-16]
996 // Reg3 = [CFA+8]
997 constexpr uint8_t Reg1 = 14;
998 constexpr uint8_t Reg2 = 15;
999 constexpr uint8_t Reg3 = 16;
1000 constexpr uint8_t Neg1SLEB = 0x7f;
1001 EXPECT_THAT_ERROR(
1002 parseCFI(TestFDE,
1003 {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended,
1004 Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}),
1005 Succeeded());
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,
1030 /*Offset=*/0x0,
1031 /*Length=*/0xff);
1033 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1034 /*Offset=*/0x3333abcdabcd,
1035 /*Length=*/0x4444abcdabcd,
1036 /*CIEPointer=*/0x1111abcdabcd,
1037 /*InitialLocation=*/0x1000,
1038 /*AddressRange=*/0x1000,
1039 /*Cie=*/&TestCIE,
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}),
1046 Succeeded());
1048 // Make a FDE with DWARF call frame instruction opcodes that changes the
1049 // unwind rules for the follwing registers:
1050 // Reg1 = [CFA-8]
1051 // Reg2 = [CFA-16]
1052 // Reg3 = [CFA+8]
1053 constexpr uint8_t Reg1 = 14;
1054 constexpr uint8_t Reg2 = 15;
1055 constexpr uint8_t Neg1SLEB = 0x7f;
1056 EXPECT_THAT_ERROR(
1057 parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1,
1058 dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}),
1059 Succeeded());
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,
1081 /*Offset=*/0x0,
1082 /*Length=*/0xff);
1084 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1085 /*Offset=*/0x3333abcdabcd,
1086 /*Length=*/0x4444abcdabcd,
1087 /*CIEPointer=*/0x1111abcdabcd,
1088 /*InitialLocation=*/0x1000,
1089 /*AddressRange=*/0x1000,
1090 /*Cie=*/&TestCIE,
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}),
1097 Succeeded());
1099 // Make a FDE with DWARF call frame instruction opcodes that changes the
1100 // unwind rules for the follwing registers:
1101 // Reg1 = [CFA-8]
1102 // The opcodes for setting Reg1 are preceded by a DW_CFA_nop.
1103 constexpr uint8_t Reg1 = 14;
1104 EXPECT_THAT_ERROR(
1105 parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}),
1106 Succeeded());
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,
1127 /*Offset=*/0x0,
1128 /*Length=*/0xff);
1130 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1131 /*Offset=*/0x3333abcdabcd,
1132 /*Length=*/0x4444abcdabcd,
1133 /*CIEPointer=*/0x1111abcdabcd,
1134 /*InitialLocation=*/0x1000,
1135 /*AddressRange=*/0x1000,
1136 /*Cie=*/&TestCIE,
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}),
1143 Succeeded());
1145 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1146 // follwing rows:
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;
1169 EXPECT_THAT_ERROR(
1170 parseCFI(TestFDE,
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}),
1177 Succeeded());
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
1222 // machine.
1223 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1224 /*Offset=*/0x0,
1225 /*Length=*/0xff);
1227 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1228 /*Offset=*/0x3333abcdabcd,
1229 /*Length=*/0x4444abcdabcd,
1230 /*CIEPointer=*/0x1111abcdabcd,
1231 /*InitialLocation=*/0x1000,
1232 /*AddressRange=*/0x1000,
1233 /*Cie=*/&TestCIE,
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}),
1240 Succeeded());
1242 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1243 // follwing rows:
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}),
1248 Succeeded());
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
1267 // machine.
1268 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1269 /*Offset=*/0x0,
1270 /*Length=*/0xff);
1272 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1273 /*Offset=*/0x3333abcdabcd,
1274 /*Length=*/0x4444abcdabcd,
1275 /*CIEPointer=*/0x1111abcdabcd,
1276 /*InitialLocation=*/0x1000,
1277 /*AddressRange=*/0x1000,
1278 /*Cie=*/&TestCIE,
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}),
1285 Succeeded());
1287 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1288 // follwing rows:
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}),
1293 Succeeded());
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
1311 // machine.
1312 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1313 /*Offset=*/0x0,
1314 /*Length=*/0xff);
1316 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1317 /*Offset=*/0x3333abcdabcd,
1318 /*Length=*/0x4444abcdabcd,
1319 /*CIEPointer=*/0x1111abcdabcd,
1320 /*InitialLocation=*/0x1000,
1321 /*AddressRange=*/0x1000,
1322 /*Cie=*/&TestCIE,
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}),
1329 Succeeded());
1331 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1332 // follwing rows:
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}),
1338 Succeeded());
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
1357 // machine.
1358 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1359 /*Offset=*/0x0,
1360 /*Length=*/0xff);
1362 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1363 /*Offset=*/0x3333abcdabcd,
1364 /*Length=*/0x4444abcdabcd,
1365 /*CIEPointer=*/0x1111abcdabcd,
1366 /*InitialLocation=*/0x1000,
1367 /*AddressRange=*/0x1000,
1368 /*Cie=*/&TestCIE,
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}),
1375 Succeeded());
1377 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1378 // follwing rows:
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
1409 // machine.
1410 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1411 /*Offset=*/0x0,
1412 /*Length=*/0xff);
1414 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1415 /*Offset=*/0x3333abcdabcd,
1416 /*Length=*/0x4444abcdabcd,
1417 /*CIEPointer=*/0x1111abcdabcd,
1418 /*InitialLocation=*/0x1000,
1419 /*AddressRange=*/0x1000,
1420 /*Cie=*/&TestCIE,
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}),
1427 Succeeded());
1429 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1430 // follwing rows:
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,
1464 /*Offset=*/0x0,
1465 /*Length=*/0xff);
1467 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1468 /*Offset=*/0x3333abcdabcd,
1469 /*Length=*/0x4444abcdabcd,
1470 /*CIEPointer=*/0x1111abcdabcd,
1471 /*InitialLocation=*/0x1000,
1472 /*AddressRange=*/0x1000,
1473 /*Cie=*/&TestCIE,
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}),
1488 Succeeded());
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.
1493 EXPECT_THAT_ERROR(
1494 parseCFI(
1495 TestFDE,
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)
1505 Succeeded());
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);
1519 EXPECT_EQ(
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);
1526 EXPECT_EQ(
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);
1533 EXPECT_EQ(
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);
1540 EXPECT_EQ(
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);
1547 EXPECT_EQ(
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
1558 // machine.
1559 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1560 /*Offset=*/0x0,
1561 /*Length=*/0xff);
1563 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1564 /*Offset=*/0x3333abcdabcd,
1565 /*Length=*/0x4444abcdabcd,
1566 /*CIEPointer=*/0x1111abcdabcd,
1567 /*InitialLocation=*/0x1000,
1568 /*AddressRange=*/0x1000,
1569 /*Cie=*/&TestCIE,
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;
1583 EXPECT_THAT_ERROR(
1584 parseCFI(TestCIE, {dwarf::DW_CFA_LLVM_def_aspace_cfa, CFAReg1, CFAOff1,
1585 AddrSpace, dwarf::DW_CFA_register, Reg, InReg}),
1586 Succeeded());
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.
1591 EXPECT_THAT_ERROR(
1592 parseCFI(
1593 TestFDE,
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)
1603 Succeeded());
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,
1619 AddrSpace));
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,
1626 AddrSpace));
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,
1633 AddrSpace));
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,
1640 AddrSpace));
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,
1647 AddrSpace));
1648 EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
1649 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
1652 } // end anonymous namespace