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 //===----------------------------------------------------------------------===//
8
9 #include "llvm/ADT/DenseSet.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/BinaryFormat/Dwarf.h"
13 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
14 #include "llvm/Testing/Support/Error.h"
15 #include "gtest/gtest.h"
16
17 using namespace llvm;
18
19 namespace {
20
createCIE(bool IsDWARF64,uint64_t Offset,uint64_t Length)21 dwarf::CIE createCIE(bool IsDWARF64, uint64_t Offset, uint64_t Length) {
22 return dwarf::CIE(IsDWARF64, Offset, Length,
23 /*Version=*/3,
24 /*Augmentation=*/StringRef(),
25 /*AddressSize=*/8,
26 /*SegmentDescriptorSize=*/0,
27 /*CodeAlignmentFactor=*/1,
28 /*DataAlignmentFactor=*/-8,
29 /*ReturnAddressRegister=*/16,
30 /*AugmentationData=*/StringRef(),
31 /*FDEPointerEncoding=*/dwarf::DW_EH_PE_absptr,
32 /*LSDAPointerEncoding=*/dwarf::DW_EH_PE_omit,
33 /*Personality=*/None,
34 /*PersonalityEnc=*/None,
35 /*Arch=*/Triple::x86_64);
36 }
37
expectDumpResult(const dwarf::CIE & TestCIE,bool IsEH,StringRef ExpectedFirstLine)38 void expectDumpResult(const dwarf::CIE &TestCIE, bool IsEH,
39 StringRef ExpectedFirstLine) {
40 std::string Output;
41 raw_string_ostream OS(Output);
42 TestCIE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH);
43 OS.flush();
44 StringRef FirstLine = StringRef(Output).split('\n').first;
45 EXPECT_EQ(FirstLine, ExpectedFirstLine);
46 }
47
expectDumpResult(const dwarf::FDE & TestFDE,bool IsEH,StringRef ExpectedFirstLine)48 void expectDumpResult(const dwarf::FDE &TestFDE, bool IsEH,
49 StringRef ExpectedFirstLine) {
50 std::string Output;
51 raw_string_ostream OS(Output);
52 TestFDE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH);
53 OS.flush();
54 StringRef FirstLine = StringRef(Output).split('\n').first;
55 EXPECT_EQ(FirstLine, ExpectedFirstLine);
56 }
57
TEST(DWARFDebugFrame,DumpDWARF32CIE)58 TEST(DWARFDebugFrame, DumpDWARF32CIE) {
59 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
60 /*Offset=*/0x1111abcd,
61 /*Length=*/0x2222abcd);
62 expectDumpResult(TestCIE, /*IsEH=*/false, "1111abcd 2222abcd ffffffff CIE");
63 }
64
TEST(DWARFDebugFrame,DumpDWARF64CIE)65 TEST(DWARFDebugFrame, DumpDWARF64CIE) {
66 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
67 /*Offset=*/0x1111abcdabcd,
68 /*Length=*/0x2222abcdabcd);
69 expectDumpResult(TestCIE, /*IsEH=*/false,
70 "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE");
71 }
72
TEST(DWARFDebugFrame,DumpEHCIE)73 TEST(DWARFDebugFrame, DumpEHCIE) {
74 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
75 /*Offset=*/0x1000,
76 /*Length=*/0x20);
77 expectDumpResult(TestCIE, /*IsEH=*/true, "00001000 00000020 00000000 CIE");
78 }
79
TEST(DWARFDebugFrame,DumpEH64CIE)80 TEST(DWARFDebugFrame, DumpEH64CIE) {
81 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
82 /*Offset=*/0x1000,
83 /*Length=*/0x20);
84 expectDumpResult(TestCIE, /*IsEH=*/true,
85 "00001000 0000000000000020 00000000 CIE");
86 }
87
TEST(DWARFDebugFrame,DumpDWARF64FDE)88 TEST(DWARFDebugFrame, DumpDWARF64FDE) {
89 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
90 /*Offset=*/0x1111abcdabcd,
91 /*Length=*/0x2222abcdabcd);
92 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
93 /*Offset=*/0x3333abcdabcd,
94 /*Length=*/0x4444abcdabcd,
95 /*CIEPointer=*/0x1111abcdabcd,
96 /*InitialLocation=*/0x5555abcdabcd,
97 /*AddressRange=*/0x111111111111,
98 /*Cie=*/&TestCIE,
99 /*LSDAAddress=*/None,
100 /*Arch=*/Triple::x86_64);
101 expectDumpResult(TestFDE, /*IsEH=*/false,
102 "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE "
103 "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde");
104 }
105
TEST(DWARFDebugFrame,DumpEH64FDE)106 TEST(DWARFDebugFrame, DumpEH64FDE) {
107 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
108 /*Offset=*/0x1111ab9a000c,
109 /*Length=*/0x20);
110 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
111 /*Offset=*/0x1111abcdabcd,
112 /*Length=*/0x2222abcdabcd,
113 /*CIEPointer=*/0x33abcd,
114 /*InitialLocation=*/0x4444abcdabcd,
115 /*AddressRange=*/0x111111111111,
116 /*Cie=*/&TestCIE,
117 /*LSDAAddress=*/None,
118 /*Arch=*/Triple::x86_64);
119 expectDumpResult(TestFDE, /*IsEH=*/true,
120 "1111abcdabcd 00002222abcdabcd 0033abcd FDE "
121 "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde");
122 }
123
parseCFI(dwarf::CIE & C,ArrayRef<uint8_t> Instructions,Optional<uint64_t> Size=None)124 static Error parseCFI(dwarf::CIE &C, ArrayRef<uint8_t> Instructions,
125 Optional<uint64_t> Size = None) {
126 DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true,
127 /*AddressSize=*/8);
128 uint64_t Offset = 0;
129 const uint64_t EndOffset = Size ? *Size : (uint64_t)Instructions.size();
130 return C.cfis().parse(Data, &Offset, EndOffset);
131 }
132
parseCFI(dwarf::FDE & FDE,ArrayRef<uint8_t> Instructions)133 static Error parseCFI(dwarf::FDE &FDE, ArrayRef<uint8_t> Instructions) {
134 DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true,
135 /*AddressSize=*/8);
136 uint64_t Offset = 0;
137 return FDE.cfis().parse(Data, &Offset, Instructions.size());
138 }
139
TEST(DWARFDebugFrame,InvalidCFIOpcodesTest)140 TEST(DWARFDebugFrame, InvalidCFIOpcodesTest) {
141 llvm::DenseSet<uint8_t> ValidExtendedOpcodes = {
142 dwarf::DW_CFA_nop,
143 dwarf::DW_CFA_advance_loc,
144 dwarf::DW_CFA_offset,
145 dwarf::DW_CFA_restore,
146 dwarf::DW_CFA_set_loc,
147 dwarf::DW_CFA_advance_loc1,
148 dwarf::DW_CFA_advance_loc2,
149 dwarf::DW_CFA_advance_loc4,
150 dwarf::DW_CFA_offset_extended,
151 dwarf::DW_CFA_restore_extended,
152 dwarf::DW_CFA_undefined,
153 dwarf::DW_CFA_same_value,
154 dwarf::DW_CFA_register,
155 dwarf::DW_CFA_remember_state,
156 dwarf::DW_CFA_restore_state,
157 dwarf::DW_CFA_def_cfa,
158 dwarf::DW_CFA_def_cfa_register,
159 dwarf::DW_CFA_def_cfa_offset,
160 dwarf::DW_CFA_def_cfa_expression,
161 dwarf::DW_CFA_expression,
162 dwarf::DW_CFA_offset_extended_sf,
163 dwarf::DW_CFA_def_cfa_sf,
164 dwarf::DW_CFA_def_cfa_offset_sf,
165 dwarf::DW_CFA_LLVM_def_aspace_cfa,
166 dwarf::DW_CFA_LLVM_def_aspace_cfa_sf,
167 dwarf::DW_CFA_val_offset,
168 dwarf::DW_CFA_val_offset_sf,
169 dwarf::DW_CFA_val_expression,
170 dwarf::DW_CFA_MIPS_advance_loc8,
171 dwarf::DW_CFA_GNU_window_save,
172 dwarf::DW_CFA_AARCH64_negate_ra_state,
173 dwarf::DW_CFA_GNU_args_size};
174
175 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
176 /*Offset=*/0x0,
177 /*Length=*/0xff);
178
179 // See DWARF standard v3, section 7.23: low 6 bits are used to encode an
180 // extended opcode.
181 for (uint8_t Code = 0; Code <= 63; ++Code) {
182 if (ValidExtendedOpcodes.count(Code))
183 continue;
184
185 EXPECT_THAT_ERROR(parseCFI(TestCIE, Code),
186 FailedWithMessage(("invalid extended CFI opcode 0x" +
187 Twine::utohexstr(Code))
188 .str()
189 .c_str()));
190 }
191 }
192
193 // Here we test how truncated Call Frame Instructions are parsed.
TEST(DWARFDebugFrame,ParseTruncatedCFITest)194 TEST(DWARFDebugFrame, ParseTruncatedCFITest) {
195 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
196 /*Offset=*/0x0,
197 /*Length=*/0xff);
198
199 // Having an empty instructions list is fine.
200 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
201
202 // Unable to read an opcode, because the instructions list is empty, but we
203 // say to the parser that it is not.
204 EXPECT_THAT_ERROR(
205 parseCFI(TestCIE, {}, /*Size=*/1),
206 FailedWithMessage(
207 "unexpected end of data at offset 0x0 while reading [0x0, 0x1)"));
208
209 // Unable to read a truncated DW_CFA_offset instruction.
210 EXPECT_THAT_ERROR(
211 parseCFI(TestCIE, {dwarf::DW_CFA_offset}),
212 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
213 "malformed uleb128, extends past end"));
214
215 // Unable to read a truncated DW_CFA_set_loc instruction.
216 EXPECT_THAT_ERROR(
217 parseCFI(TestCIE, {dwarf::DW_CFA_set_loc}),
218 FailedWithMessage(
219 "unexpected end of data at offset 0x1 while reading [0x1, 0x9)"));
220
221 // Unable to read a truncated DW_CFA_advance_loc1 instruction.
222 EXPECT_THAT_ERROR(
223 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}),
224 FailedWithMessage(
225 "unexpected end of data at offset 0x1 while reading [0x1, 0x2)"));
226
227 // Unable to read a truncated DW_CFA_advance_loc2 instruction.
228 EXPECT_THAT_ERROR(
229 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}),
230 FailedWithMessage(
231 "unexpected end of data at offset 0x1 while reading [0x1, 0x3)"));
232
233 // Unable to read a truncated DW_CFA_advance_loc4 instruction.
234 EXPECT_THAT_ERROR(
235 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}),
236 FailedWithMessage(
237 "unexpected end of data at offset 0x1 while reading [0x1, 0x5)"));
238
239 // A test for an instruction with a single ULEB128 operand.
240 auto CheckOp_ULEB128 = [&](uint8_t Inst) {
241 EXPECT_THAT_ERROR(
242 parseCFI(TestCIE, Inst),
243 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
244 "malformed uleb128, extends past end"));
245 };
246
247 for (uint8_t Inst :
248 {dwarf::DW_CFA_restore_extended, dwarf::DW_CFA_undefined,
249 dwarf::DW_CFA_same_value, dwarf::DW_CFA_def_cfa_register,
250 dwarf::DW_CFA_def_cfa_offset, dwarf::DW_CFA_GNU_args_size})
251 CheckOp_ULEB128(Inst);
252
253 // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction.
254 EXPECT_THAT_ERROR(
255 parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_offset_sf}),
256 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
257 "malformed sleb128, extends past end"));
258
259 // A test for an instruction with two ULEB128 operands.
260 auto CheckOp_ULEB128_ULEB128 = [&](uint8_t Inst) {
261 EXPECT_THAT_ERROR(
262 parseCFI(TestCIE, Inst),
263 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
264 "malformed uleb128, extends past end"));
265
266 EXPECT_THAT_ERROR(
267 parseCFI(TestCIE, {Inst, /*Op1=*/0}),
268 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
269 "malformed uleb128, extends past end"));
270 };
271
272 for (uint8_t Inst : {dwarf::DW_CFA_offset_extended, dwarf::DW_CFA_register,
273 dwarf::DW_CFA_def_cfa, dwarf::DW_CFA_LLVM_def_aspace_cfa,
274 dwarf::DW_CFA_val_offset})
275 CheckOp_ULEB128_ULEB128(Inst);
276
277 // A test for an instruction with two operands: ULEB128, SLEB128.
278 auto CheckOp_ULEB128_SLEB128 = [&](uint8_t Inst) {
279 EXPECT_THAT_ERROR(
280 parseCFI(TestCIE, Inst),
281 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
282 "malformed uleb128, extends past end"));
283
284 EXPECT_THAT_ERROR(
285 parseCFI(TestCIE, {Inst, /*Op1=*/0}),
286 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
287 "malformed sleb128, extends past end"));
288 };
289
290 for (uint8_t Inst :
291 {dwarf::DW_CFA_offset_extended_sf, dwarf::DW_CFA_def_cfa_sf,
292 dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, dwarf::DW_CFA_val_offset_sf})
293 CheckOp_ULEB128_SLEB128(Inst);
294
295 // Unable to read a truncated DW_CFA_def_cfa_expression instruction.
296 EXPECT_THAT_ERROR(
297 parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}),
298 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
299 "malformed uleb128, extends past end"));
300 EXPECT_THAT_ERROR(
301 parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
302 /*expression length=*/0x1}),
303 FailedWithMessage(
304 "unexpected end of data at offset 0x2 while reading [0x2, 0x3)"));
305 // The DW_CFA_def_cfa_expression can contain a zero length expression.
306 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
307 /*ExprLen=*/0}),
308 Succeeded());
309
310 // A test for an instruction with three operands: ULEB128, expression length
311 // (ULEB128) and expression bytes.
312 auto CheckOp_ULEB128_Expr = [&](uint8_t Inst) {
313 EXPECT_THAT_ERROR(
314 parseCFI(TestCIE, {Inst}),
315 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
316 "malformed uleb128, extends past end"));
317 EXPECT_THAT_ERROR(
318 parseCFI(TestCIE, {Inst, /*Op1=*/0}),
319 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
320 "malformed uleb128, extends past end"));
321 // A zero length expression is fine
322 EXPECT_THAT_ERROR(parseCFI(TestCIE, {Inst,
323 /*Op1=*/0, /*ExprLen=*/0}),
324 Succeeded());
325 EXPECT_THAT_ERROR(
326 parseCFI(TestCIE, {Inst,
327 /*Op1=*/0, /*ExprLen=*/1}),
328 FailedWithMessage(
329 "unexpected end of data at offset 0x3 while reading [0x3, 0x4)"));
330 };
331
332 for (uint8_t Inst : {dwarf::DW_CFA_expression, dwarf::DW_CFA_val_expression})
333 CheckOp_ULEB128_Expr(Inst);
334 }
335
expectDumpResult(const dwarf::UnwindLocation & Loc,StringRef ExpectedFirstLine)336 void expectDumpResult(const dwarf::UnwindLocation &Loc,
337 StringRef ExpectedFirstLine) {
338 std::string Output;
339 raw_string_ostream OS(Output);
340 OS << Loc;
341 OS.flush();
342 StringRef FirstLine = StringRef(Output).split('\n').first;
343 EXPECT_EQ(FirstLine, ExpectedFirstLine);
344 }
345
TEST(DWARFDebugFrame,DumpUnwindLocations)346 TEST(DWARFDebugFrame, DumpUnwindLocations) {
347 // Test constructing unwind locations and dumping each kind.
348 constexpr int32_t PlusOff = 8;
349 constexpr int32_t MinusOff = -8;
350 constexpr uint8_t RegNum = 12;
351 expectDumpResult(dwarf::UnwindLocation::createUnspecified(), "unspecified");
352 expectDumpResult(dwarf::UnwindLocation::createUndefined(), "undefined");
353 expectDumpResult(dwarf::UnwindLocation::createSame(), "same");
354 expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(PlusOff),
355 "CFA+8");
356 expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff),
357 "CFA-8");
358 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff),
359 "[CFA+8]");
360 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff),
361 "[CFA-8]");
362
363 expectDumpResult(
364 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, PlusOff),
365 "reg12+8");
366 expectDumpResult(
367 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, MinusOff),
368 "reg12-8");
369 expectDumpResult(
370 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, PlusOff),
371 "[reg12+8]");
372 expectDumpResult(
373 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, MinusOff),
374 "[reg12-8]");
375 expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12");
376 expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32");
377 }
378
expectDumpResult(const dwarf::RegisterLocations & Locs,StringRef ExpectedFirstLine)379 void expectDumpResult(const dwarf::RegisterLocations &Locs,
380 StringRef ExpectedFirstLine) {
381 std::string Output;
382 raw_string_ostream OS(Output);
383 OS << Locs;
384 OS.flush();
385 StringRef FirstLine = StringRef(Output).split('\n').first;
386 EXPECT_EQ(FirstLine, ExpectedFirstLine);
387 }
388
TEST(DWARFDebugFrame,RegisterLocations)389 TEST(DWARFDebugFrame, RegisterLocations) {
390 // Test the functionality of the RegisterLocations class.
391 dwarf::RegisterLocations Locs;
392 expectDumpResult(Locs, "");
393 EXPECT_FALSE(Locs.hasLocations());
394 // Set a register location for reg12 to unspecified and verify it dumps
395 // correctly.
396 Locs.setRegisterLocation(12, dwarf::UnwindLocation::createUnspecified());
397 EXPECT_TRUE(Locs.hasLocations());
398 expectDumpResult(Locs, "reg12=unspecified");
399
400 // Replace the register location for reg12 to "same" and verify it dumps
401 // correctly after it is modified
402 Locs.setRegisterLocation(12, dwarf::UnwindLocation::createSame());
403 EXPECT_TRUE(Locs.hasLocations());
404 expectDumpResult(Locs, "reg12=same");
405
406 // Remove the register location for reg12 verify it dumps correctly after it
407 // is removed.
408 Locs.removeRegisterLocation(12);
409 EXPECT_FALSE(Locs.hasLocations());
410 expectDumpResult(Locs, "");
411
412 // Verify multiple registers added to the list dump correctly.
413 auto Reg12Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(4);
414 auto Reg13Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(8);
415 auto Reg14Loc = dwarf::UnwindLocation::createSame();
416 Locs.setRegisterLocation(12, Reg12Loc);
417 Locs.setRegisterLocation(13, Reg13Loc);
418 Locs.setRegisterLocation(14, Reg14Loc);
419 EXPECT_TRUE(Locs.hasLocations());
420 expectDumpResult(Locs, "reg12=[CFA+4], reg13=[CFA+8], reg14=same");
421
422 // Verify RegisterLocations::getRegisterLocation() works as expected.
423 Optional<dwarf::UnwindLocation> OptionalLoc;
424 OptionalLoc = Locs.getRegisterLocation(0);
425 EXPECT_FALSE(OptionalLoc.hasValue());
426
427 OptionalLoc = Locs.getRegisterLocation(12);
428 EXPECT_TRUE(OptionalLoc.hasValue());
429 EXPECT_EQ(*OptionalLoc, Reg12Loc);
430
431 OptionalLoc = Locs.getRegisterLocation(13);
432 EXPECT_TRUE(OptionalLoc.hasValue());
433 EXPECT_EQ(*OptionalLoc, Reg13Loc);
434
435 OptionalLoc = Locs.getRegisterLocation(14);
436 EXPECT_TRUE(OptionalLoc.hasValue());
437 EXPECT_EQ(*OptionalLoc, Reg14Loc);
438
439 // Verify registers are correctly removed when multiple exist in the list.
440 Locs.removeRegisterLocation(13);
441 EXPECT_FALSE(Locs.getRegisterLocation(13).hasValue());
442 EXPECT_TRUE(Locs.hasLocations());
443 expectDumpResult(Locs, "reg12=[CFA+4], reg14=same");
444 Locs.removeRegisterLocation(14);
445 EXPECT_FALSE(Locs.getRegisterLocation(14).hasValue());
446 EXPECT_TRUE(Locs.hasLocations());
447 expectDumpResult(Locs, "reg12=[CFA+4]");
448 Locs.removeRegisterLocation(12);
449 EXPECT_FALSE(Locs.getRegisterLocation(12).hasValue());
450 EXPECT_FALSE(Locs.hasLocations());
451 expectDumpResult(Locs, "");
452 }
453
454 // Test that empty rows are not added to UnwindTable when
455 // dwarf::CIE::CFIs or dwarf::FDE::CFIs is empty.
TEST(DWARFDebugFrame,UnwindTableEmptyRows)456 TEST(DWARFDebugFrame, UnwindTableEmptyRows) {
457 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
458 /*Offset=*/0x0,
459 /*Length=*/0xff);
460
461 // Having an empty instructions list is fine.
462 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
463 EXPECT_TRUE(TestCIE.cfis().empty());
464
465 // Verify dwarf::UnwindTable::create() won't result in errors and
466 // and empty rows are not added to CIE UnwindTable.
467 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE);
468 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
469 const size_t ExpectedNumOfRows = 0;
470 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
471
472 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
473 /*Offset=*/0x3333abcdabcd,
474 /*Length=*/0x4444abcdabcd,
475 /*CIEPointer=*/0x1111abcdabcd,
476 /*InitialLocation=*/0x1000,
477 /*AddressRange=*/0x1000,
478 /*Cie=*/&TestCIE,
479 /*LSDAAddress=*/None,
480 /*Arch=*/Triple::x86_64);
481
482 // Having an empty instructions list is fine.
483 EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
484 EXPECT_TRUE(TestFDE.cfis().empty());
485
486 // Verify dwarf::UnwindTable::create() won't result in errors and
487 // and empty rows are not added to FDE UnwindTable.
488 RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
489 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
490 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
491 }
492
493 // Test that empty rows are not added to UnwindTable when dwarf::CIE::CFIs
494 // or dwarf::FDE::CFIs is not empty but has only DW_CFA_nop instructions.
TEST(DWARFDebugFrame,UnwindTableEmptyRows_NOPs)495 TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) {
496 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
497 /*Offset=*/0x0,
498 /*Length=*/0xff);
499
500 // Make a CIE that has only DW_CFA_nop instructions.
501 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_nop}), Succeeded());
502 EXPECT_TRUE(!TestCIE.cfis().empty());
503
504 // Verify dwarf::UnwindTable::create() won't result in errors and
505 // and empty rows are not added to CIE UnwindTable.
506 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE);
507 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
508 const size_t ExpectedNumOfRows = 0;
509 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
510
511 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
512 /*Offset=*/0x3333abcdabcd,
513 /*Length=*/0x4444abcdabcd,
514 /*CIEPointer=*/0x1111abcdabcd,
515 /*InitialLocation=*/0x1000,
516 /*AddressRange=*/0x1000,
517 /*Cie=*/&TestCIE,
518 /*LSDAAddress=*/None,
519 /*Arch=*/Triple::x86_64);
520
521 // Make an FDE that has only DW_CFA_nop instructions.
522 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_nop}), Succeeded());
523 EXPECT_TRUE(!TestFDE.cfis().empty());
524
525 // Verify dwarf::UnwindTable::create() won't result in errors and
526 // and empty rows are not added to FDE UnwindTable.
527 RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
528 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
529 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
530 }
531
TEST(DWARFDebugFrame,UnwindTableErrorNonAscendingFDERows)532 TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) {
533 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
534 /*Offset=*/0x0,
535 /*Length=*/0xff);
536
537 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
538 /*Offset=*/0x3333abcdabcd,
539 /*Length=*/0x4444abcdabcd,
540 /*CIEPointer=*/0x1111abcdabcd,
541 /*InitialLocation=*/0x1000,
542 /*AddressRange=*/0x1000,
543 /*Cie=*/&TestCIE,
544 /*LSDAAddress=*/None,
545 /*Arch=*/Triple::x86_64);
546
547 // Make a CIE that has a valid CFA definition.
548 constexpr uint8_t Reg = 12;
549 constexpr uint8_t Offset = 32;
550 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
551 Succeeded());
552
553 // Make a FDE with DWARF call frame instruction opcodes that have valid
554 // syntax, but will cause an error when we parse them into a UnwindTable.
555 // Here we encode two DW_CFA_set_loc opcodes:
556 // DW_CFA_set_loc(0x1100)
557 // DW_CFA_set_loc(0x1000)
558 // These opcodes cause a new row to be appended to the rows in a UnwindTable
559 // and the resulting rows are not in ascending address order and should cause
560 // a state machine error.
561 EXPECT_THAT_ERROR(
562 parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0,
563 dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}),
564 Succeeded());
565
566 // Verify we catch state machine error.
567 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
568 EXPECT_THAT_ERROR(RowsOrErr.takeError(),
569 FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which"
570 " must be greater than the current row "
571 "address 0x1100"));
572 }
573
TEST(DWARFDebugFrame,UnwindTableError_DW_CFA_restore_state)574 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) {
575 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
576 /*Offset=*/0x0,
577 /*Length=*/0xff);
578
579 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
580 /*Offset=*/0x3333abcdabcd,
581 /*Length=*/0x4444abcdabcd,
582 /*CIEPointer=*/0x1111abcdabcd,
583 /*InitialLocation=*/0x1000,
584 /*AddressRange=*/0x1000,
585 /*Cie=*/&TestCIE,
586 /*LSDAAddress=*/None,
587 /*Arch=*/Triple::x86_64);
588
589 // Make a CIE that has a valid CFA definition.
590 constexpr uint8_t Reg = 12;
591 constexpr uint8_t Offset = 32;
592 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
593 Succeeded());
594
595 // Make a FDE with DWARF call frame instruction opcodes that have valid
596 // syntax, but will cause an error when we parse them into a UnwindTable.
597 // Here we encode a DW_CFA_restore_state opcode that was not preceded by a
598 // DW_CFA_remember_state, and an error should be returned.
599 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}),
600 Succeeded());
601
602 // Verify we catch state machine error.
603 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
604 EXPECT_THAT_ERROR(RowsOrErr.takeError(),
605 FailedWithMessage("DW_CFA_restore_state without a matching "
606 "previous DW_CFA_remember_state"));
607 }
608
TEST(DWARFDebugFrame,UnwindTableError_DW_CFA_GNU_window_save)609 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) {
610 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
611 /*Offset=*/0x0,
612 /*Length=*/0xff);
613
614 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
615 /*Offset=*/0x3333abcdabcd,
616 /*Length=*/0x4444abcdabcd,
617 /*CIEPointer=*/0x1111abcdabcd,
618 /*InitialLocation=*/0x1000,
619 /*AddressRange=*/0x1000,
620 /*Cie=*/&TestCIE,
621 /*LSDAAddress=*/None,
622 /*Arch=*/Triple::x86_64);
623
624 // Make a CIE that has a valid CFA definition.
625 constexpr uint8_t Reg = 12;
626 constexpr uint8_t Offset = 32;
627 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
628 Succeeded());
629
630 // Make a FDE with DWARF call frame instruction opcodes that have valid
631 // syntax, but will cause an error when we parse them into a UnwindTable.
632 // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not
633 // found any documentation that describes what this does after some brief
634 // searching.
635 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}),
636 Succeeded());
637
638 // Verify we catch state machine error.
639 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
640 EXPECT_THAT_ERROR(RowsOrErr.takeError(),
641 FailedWithMessage("DW_CFA opcode 0x2d is not supported for "
642 "architecture x86_64"));
643 }
644
TEST(DWARFDebugFrame,UnwindTableError_DW_CFA_def_cfa_offset)645 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) {
646 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
647 /*Offset=*/0x0,
648 /*Length=*/0xff);
649
650 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
651 /*Offset=*/0x3333abcdabcd,
652 /*Length=*/0x4444abcdabcd,
653 /*CIEPointer=*/0x1111abcdabcd,
654 /*InitialLocation=*/0x1000,
655 /*AddressRange=*/0x1000,
656 /*Cie=*/&TestCIE,
657 /*LSDAAddress=*/None,
658 /*Arch=*/Triple::x86_64);
659
660 // Make a CIE that has an invalid CFA definition. We do this so we can try
661 // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate
662 // error back.
663 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
664
665 // Make a FDE with DWARF call frame instruction opcodes that have valid
666 // syntax, but will cause an error when we parse them into a UnwindTable.
667 // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE
668 // didn't define the CFA in terms of a register plus offset, so this should
669 // cause an error.
670 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}),
671 Succeeded());
672
673 // Verify we catch state machine error.
674 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
675 EXPECT_THAT_ERROR(RowsOrErr.takeError(),
676 FailedWithMessage("DW_CFA_def_cfa_offset found when CFA "
677 "rule was not RegPlusOffset"));
678 }
679
TEST(DWARFDebugFrame,UnwindTableDefCFAOffsetSFCFAError)680 TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) {
681 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
682 /*Offset=*/0x0,
683 /*Length=*/0xff);
684
685 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
686 /*Offset=*/0x3333abcdabcd,
687 /*Length=*/0x4444abcdabcd,
688 /*CIEPointer=*/0x1111abcdabcd,
689 /*InitialLocation=*/0x1000,
690 /*AddressRange=*/0x1000,
691 /*Cie=*/&TestCIE,
692 /*LSDAAddress=*/None,
693 /*Arch=*/Triple::x86_64);
694
695 // Make a CIE that has an invalid CFA definition. We do this so we can try
696 // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an
697 // appropriate error back.
698 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
699
700 // Make a FDE with DWARF call frame instruction opcodes that have valid
701 // syntax, but will cause an error when we parse them into a UnwindTable.
702 // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE
703 // didn't define the CFA in terms of a register plus offset, so this should
704 // cause an error.
705 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}),
706 Succeeded());
707
708 // Verify we catch state machine error.
709 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
710 EXPECT_THAT_ERROR(RowsOrErr.takeError(),
711 FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA "
712 "rule was not RegPlusOffset"));
713 }
714
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_def_cfa_register)715 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) {
716 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
717 /*Offset=*/0x0,
718 /*Length=*/0xff);
719
720 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
721 /*Offset=*/0x3333abcdabcd,
722 /*Length=*/0x4444abcdabcd,
723 /*CIEPointer=*/0x1111abcdabcd,
724 /*InitialLocation=*/0x1000,
725 /*AddressRange=*/0x1000,
726 /*Cie=*/&TestCIE,
727 /*LSDAAddress=*/None,
728 /*Arch=*/Triple::x86_64);
729
730 // Make a CIE that has only defines the CFA register with no offset. Some
731 // architectures do this and we must ensure that we set the CFA value to be
732 // equal to that register with no offset.
733 constexpr uint8_t CFAReg = 12;
734 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}),
735 Succeeded());
736
737 // Make a FDE with DWARF call frame instruction opcodes that have valid
738 // syntax, but will cause an error when we parse them into a UnwindTable.
739 // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but
740 // our CIE didn't define the CFA in terms of a register plus offset, so this
741 // should cause an error.
742 EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
743
744 // Verify we catch state machine error.
745 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
746 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
747 const dwarf::UnwindTable &Rows = RowsOrErr.get();
748 EXPECT_EQ(Rows.size(), 1u);
749 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
750 EXPECT_EQ(Rows[0].getCFAValue(),
751 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0));
752 }
753
TEST(DWARFDebugFrame,UnwindTableRowPushingOpcodes)754 TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) {
755 // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable.
756 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
757 /*Offset=*/0x0,
758 /*Length=*/0xff);
759
760 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
761 /*Offset=*/0x3333abcdabcd,
762 /*Length=*/0x4444abcdabcd,
763 /*CIEPointer=*/0x1111abcdabcd,
764 /*InitialLocation=*/0x1000,
765 /*AddressRange=*/0x1000,
766 /*Cie=*/&TestCIE,
767 /*LSDAAddress=*/None,
768 /*Arch=*/Triple::x86_64);
769
770 // Make a CIE that has a valid CFA definition and a single register unwind
771 // rule for register that we will verify is in all of the pushed rows.
772 constexpr uint8_t CFAReg = 12;
773 constexpr uint8_t CFAOffset = 32;
774 constexpr uint8_t Reg = 13;
775 constexpr uint8_t InReg = 14;
776
777 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
778 dwarf::DW_CFA_register, Reg, InReg}),
779 Succeeded());
780
781 // Make a FDE with DWARF call frame instruction opcodes that use all of the
782 // row pushing opcodes. This will verify that all opcodes that should create
783 // a row are correctly working. Each opcode will push a row prior to
784 // advancing the address, and then a row will be automatically pushed at the
785 // end of the parsing, so we should end up with 6 rows starting at address
786 // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor
787 // from the CIE.
788 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4,
789 dwarf::DW_CFA_advance_loc1,
790 4,
791 dwarf::DW_CFA_advance_loc2,
792 4,
793 0,
794 dwarf::DW_CFA_advance_loc4,
795 4,
796 0,
797 0,
798 0,
799 dwarf::DW_CFA_set_loc,
800 0x14,
801 0x10,
802 0,
803 0,
804 0,
805 0,
806 0,
807 0}),
808 Succeeded());
809
810 // Create locations that we expect the UnwindRow objects to contain after
811 // parsing the DWARF call frame instructions.
812 dwarf::RegisterLocations VerifyLocs;
813 VerifyLocs.setRegisterLocation(
814 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
815
816 // Verify we catch state machine error.
817 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
818 ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
819 const dwarf::UnwindTable &Rows = RowsOrErr.get();
820 EXPECT_EQ(Rows.size(), 6u);
821 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
822 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
823 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
824 EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
825 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
826 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
827 EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
828 EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
829 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
830 EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
831 EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
832 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
833 EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
834 EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
835 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
836 EXPECT_EQ(Rows[5].getAddress(), 0x1014u);
837 EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u);
838 EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs);
839 }
840
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_restore)841 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) {
842 // Test that DW_CFA_restore works as expected when parsed in the state
843 // machine.
844 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
845 /*Offset=*/0x0,
846 /*Length=*/0xff);
847
848 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
849 /*Offset=*/0x3333abcdabcd,
850 /*Length=*/0x4444abcdabcd,
851 /*CIEPointer=*/0x1111abcdabcd,
852 /*InitialLocation=*/0x1000,
853 /*AddressRange=*/0x1000,
854 /*Cie=*/&TestCIE,
855 /*LSDAAddress=*/None,
856 /*Arch=*/Triple::x86_64);
857
858 // Make a CIE that has a valid CFA definition and a single register unwind
859 // rule for register that we will verify is in all of the pushed rows.
860 constexpr uint8_t CFAReg = 12;
861 constexpr uint8_t CFAOffset = 32;
862 constexpr uint8_t Reg = 13;
863 constexpr uint8_t InReg = 14;
864 constexpr int32_t RegCFAOffset = -8;
865
866 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
867 dwarf::DW_CFA_register, Reg, InReg}),
868 Succeeded());
869
870 // Make a FDE with DWARF call frame instruction opcodes that changes the rule
871 // for register "Reg" to be [CFA-8], then push a row, and then restore the
872 // register unwind rule for "Reg" using DW_CFA_restore. We should end up with
873 // two rows:
874 // - one with Reg = [CFA-8]
875 // - one with Reg = InReg
876 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1,
877 dwarf::DW_CFA_advance_loc | 4,
878 dwarf::DW_CFA_restore | Reg}),
879 Succeeded());
880
881 // Create locations that we expect the UnwindRow objects to contain after
882 // parsing the DWARF call frame instructions.
883 dwarf::RegisterLocations VerifyLocs1;
884 VerifyLocs1.setRegisterLocation(
885 Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset));
886
887 dwarf::RegisterLocations VerifyLocs2;
888 VerifyLocs2.setRegisterLocation(
889 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
890
891 // Verify we catch state machine error.
892 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
893 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
894 const dwarf::UnwindTable &Rows = RowsOrErr.get();
895 EXPECT_EQ(Rows.size(), 2u);
896 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
897 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
898 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
899 EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
900 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
901 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
902 }
903
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_restore_extended)904 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) {
905 // Test that DW_CFA_restore works as expected when parsed in the state
906 // machine.
907 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
908 /*Offset=*/0x0,
909 /*Length=*/0xff);
910
911 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
912 /*Offset=*/0x3333abcdabcd,
913 /*Length=*/0x4444abcdabcd,
914 /*CIEPointer=*/0x1111abcdabcd,
915 /*InitialLocation=*/0x1000,
916 /*AddressRange=*/0x1000,
917 /*Cie=*/&TestCIE,
918 /*LSDAAddress=*/None,
919 /*Arch=*/Triple::x86_64);
920
921 // Make a CIE that has a valid CFA definition and a single register unwind
922 // rule for register that we will verify is in all of the pushed rows.
923 constexpr uint8_t CFAReg = 12;
924 constexpr uint8_t CFAOffset = 32;
925 constexpr uint8_t Reg = 13;
926 constexpr uint8_t InReg = 14;
927 constexpr int32_t RegCFAOffset = -8;
928
929 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
930 dwarf::DW_CFA_register, Reg, InReg}),
931 Succeeded());
932
933 // Make a FDE with DWARF call frame instruction opcodes that changes the rule
934 // for register "Reg" to be [CFA-8], then push a row, and then restore the
935 // register unwind rule for "Reg" using DW_CFA_restore_extended. We should
936 // end up with two rows:
937 // - one with Reg = [CFA-8]
938 // - one with Reg = InReg
939 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1,
940 dwarf::DW_CFA_advance_loc | 4,
941 dwarf::DW_CFA_restore_extended, Reg}),
942 Succeeded());
943
944 // Create locations that we expect the UnwindRow objects to contain after
945 // parsing the DWARF call frame instructions.
946 dwarf::RegisterLocations VerifyLocs1;
947 VerifyLocs1.setRegisterLocation(
948 Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset));
949
950 dwarf::RegisterLocations VerifyLocs2;
951 VerifyLocs2.setRegisterLocation(
952 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
953
954 // Verify we catch state machine error.
955 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
956 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
957 const dwarf::UnwindTable &Rows = RowsOrErr.get();
958 EXPECT_EQ(Rows.size(), 2u);
959 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
960 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
961 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
962 EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
963 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
964 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
965 }
966
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_offset)967 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) {
968 // Test that DW_CFA_offset, DW_CFA_offset_extended and
969 // DW_CFA_offset_extended_sf work as expected when parsed in the state
970 // machine.
971 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
972 /*Offset=*/0x0,
973 /*Length=*/0xff);
974
975 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
976 /*Offset=*/0x3333abcdabcd,
977 /*Length=*/0x4444abcdabcd,
978 /*CIEPointer=*/0x1111abcdabcd,
979 /*InitialLocation=*/0x1000,
980 /*AddressRange=*/0x1000,
981 /*Cie=*/&TestCIE,
982 /*LSDAAddress=*/None,
983 /*Arch=*/Triple::x86_64);
984
985 // Make a CIE that has a valid CFA definition and a single register unwind
986 // rule for register that we will verify is in all of the pushed rows.
987 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
988 Succeeded());
989
990 // Make a FDE with DWARF call frame instruction opcodes that changes the
991 // unwind rules for the follwing registers:
992 // Reg1 = [CFA-8]
993 // Reg2 = [CFA-16]
994 // Reg3 = [CFA+8]
995 constexpr uint8_t Reg1 = 14;
996 constexpr uint8_t Reg2 = 15;
997 constexpr uint8_t Reg3 = 16;
998 constexpr uint8_t Neg1SLEB = 0x7f;
999 EXPECT_THAT_ERROR(
1000 parseCFI(TestFDE,
1001 {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended,
1002 Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}),
1003 Succeeded());
1004
1005 // Create locations that we expect the UnwindRow objects to contain after
1006 // parsing the DWARF call frame instructions.
1007 dwarf::RegisterLocations VerifyLocs;
1008 VerifyLocs.setRegisterLocation(
1009 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1010 VerifyLocs.setRegisterLocation(
1011 Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1012 VerifyLocs.setRegisterLocation(
1013 Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8));
1014
1015 // Verify we catch state machine error.
1016 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1017 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1018 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1019 EXPECT_EQ(Rows.size(), 1u);
1020 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1021 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1022 }
1023
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_val_offset)1024 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) {
1025 // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when
1026 // parsed in the state machine.
1027 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1028 /*Offset=*/0x0,
1029 /*Length=*/0xff);
1030
1031 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1032 /*Offset=*/0x3333abcdabcd,
1033 /*Length=*/0x4444abcdabcd,
1034 /*CIEPointer=*/0x1111abcdabcd,
1035 /*InitialLocation=*/0x1000,
1036 /*AddressRange=*/0x1000,
1037 /*Cie=*/&TestCIE,
1038 /*LSDAAddress=*/None,
1039 /*Arch=*/Triple::x86_64);
1040
1041 // Make a CIE that has a valid CFA definition and a single register unwind
1042 // rule for register that we will verify is in all of the pushed rows.
1043 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1044 Succeeded());
1045
1046 // Make a FDE with DWARF call frame instruction opcodes that changes the
1047 // unwind rules for the follwing registers:
1048 // Reg1 = [CFA-8]
1049 // Reg2 = [CFA-16]
1050 // Reg3 = [CFA+8]
1051 constexpr uint8_t Reg1 = 14;
1052 constexpr uint8_t Reg2 = 15;
1053 constexpr uint8_t Neg1SLEB = 0x7f;
1054 EXPECT_THAT_ERROR(
1055 parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1,
1056 dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}),
1057 Succeeded());
1058
1059 // Create locations that we expect the UnwindRow objects to contain after
1060 // parsing the DWARF call frame instructions.
1061 dwarf::RegisterLocations VerifyLocs;
1062 VerifyLocs.setRegisterLocation(
1063 Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8));
1064 VerifyLocs.setRegisterLocation(
1065 Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8));
1066
1067 // Verify we catch state machine error.
1068 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1069 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1070 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1071 EXPECT_EQ(Rows.size(), 1u);
1072 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1073 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1074 }
1075
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_nop)1076 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) {
1077 // Test that DW_CFA_nop works as expected when parsed in the state machine.
1078 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1079 /*Offset=*/0x0,
1080 /*Length=*/0xff);
1081
1082 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1083 /*Offset=*/0x3333abcdabcd,
1084 /*Length=*/0x4444abcdabcd,
1085 /*CIEPointer=*/0x1111abcdabcd,
1086 /*InitialLocation=*/0x1000,
1087 /*AddressRange=*/0x1000,
1088 /*Cie=*/&TestCIE,
1089 /*LSDAAddress=*/None,
1090 /*Arch=*/Triple::x86_64);
1091
1092 // Make a CIE that has a valid CFA definition and a single register unwind
1093 // rule for register that we will verify is in all of the pushed rows.
1094 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1095 Succeeded());
1096
1097 // Make a FDE with DWARF call frame instruction opcodes that changes the
1098 // unwind rules for the follwing registers:
1099 // Reg1 = [CFA-8]
1100 // The opcodes for setting Reg1 are preceded by a DW_CFA_nop.
1101 constexpr uint8_t Reg1 = 14;
1102 EXPECT_THAT_ERROR(
1103 parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}),
1104 Succeeded());
1105
1106 // Create locations that we expect the UnwindRow objects to contain after
1107 // parsing the DWARF call frame instructions.
1108 dwarf::RegisterLocations VerifyLocs;
1109 VerifyLocs.setRegisterLocation(
1110 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1111
1112 // Verify we catch state machine error.
1113 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1114 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1115 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1116 EXPECT_EQ(Rows.size(), 1u);
1117 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1118 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1119 }
1120
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_remember_state)1121 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) {
1122 // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected
1123 // when parsed in the state machine.
1124 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1125 /*Offset=*/0x0,
1126 /*Length=*/0xff);
1127
1128 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1129 /*Offset=*/0x3333abcdabcd,
1130 /*Length=*/0x4444abcdabcd,
1131 /*CIEPointer=*/0x1111abcdabcd,
1132 /*InitialLocation=*/0x1000,
1133 /*AddressRange=*/0x1000,
1134 /*Cie=*/&TestCIE,
1135 /*LSDAAddress=*/None,
1136 /*Arch=*/Triple::x86_64);
1137
1138 // Make a CIE that has a valid CFA definition and a single register unwind
1139 // rule for register that we will verify is in all of the pushed rows.
1140 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1141 Succeeded());
1142
1143 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1144 // follwing rows:
1145 // 0x1000: CFA=reg12+32: Reg1=[CFA-8]
1146 // 0x1004: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16]
1147 // 0x1008: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24]
1148 // 0x100C: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16]
1149 // 0x1010: CFA=reg12+32: Reg1=[CFA-8]
1150 // This state machine will:
1151 // - set Reg1 location
1152 // - push a row (from DW_CFA_advance_loc)
1153 // - remember the state
1154 // - set Reg2 location
1155 // - push a row (from DW_CFA_advance_loc)
1156 // - remember the state
1157 // - set Reg3 location
1158 // - push a row (from DW_CFA_advance_loc)
1159 // - remember the state where Reg1 and Reg2 were set
1160 // - push a row (from DW_CFA_advance_loc)
1161 // - remember the state where only Reg1 was set
1162 // - push a row (automatically at the end of instruction parsing)
1163 // Then we verify that all registers are correct in all generated rows.
1164 constexpr uint8_t Reg1 = 14;
1165 constexpr uint8_t Reg2 = 15;
1166 constexpr uint8_t Reg3 = 16;
1167 EXPECT_THAT_ERROR(
1168 parseCFI(TestFDE,
1169 {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4,
1170 dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2,
1171 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state,
1172 dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4,
1173 dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4,
1174 dwarf::DW_CFA_restore_state}),
1175 Succeeded());
1176
1177 // Create locations that we expect the UnwindRow objects to contain after
1178 // parsing the DWARF call frame instructions.
1179 dwarf::RegisterLocations VerifyLocs1;
1180 VerifyLocs1.setRegisterLocation(
1181 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1182
1183 dwarf::RegisterLocations VerifyLocs2;
1184 VerifyLocs2.setRegisterLocation(
1185 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1186 VerifyLocs2.setRegisterLocation(
1187 Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1188
1189 dwarf::RegisterLocations VerifyLocs3;
1190 VerifyLocs3.setRegisterLocation(
1191 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1192 VerifyLocs3.setRegisterLocation(
1193 Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1194 VerifyLocs3.setRegisterLocation(
1195 Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24));
1196
1197 // Verify we catch state machine error.
1198 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1199 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1200 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1201 EXPECT_EQ(Rows.size(), 5u);
1202 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1203 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
1204
1205 EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
1206 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
1207
1208 EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
1209 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3);
1210
1211 EXPECT_EQ(Rows[3].getAddress(), 0x100Cu);
1212 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2);
1213
1214 EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
1215 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1);
1216 }
1217
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_undefined)1218 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) {
1219 // Test that DW_CFA_undefined works as expected when parsed in the state
1220 // machine.
1221 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1222 /*Offset=*/0x0,
1223 /*Length=*/0xff);
1224
1225 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1226 /*Offset=*/0x3333abcdabcd,
1227 /*Length=*/0x4444abcdabcd,
1228 /*CIEPointer=*/0x1111abcdabcd,
1229 /*InitialLocation=*/0x1000,
1230 /*AddressRange=*/0x1000,
1231 /*Cie=*/&TestCIE,
1232 /*LSDAAddress=*/None,
1233 /*Arch=*/Triple::x86_64);
1234
1235 // Make a CIE that has a valid CFA definition and a single register unwind
1236 // rule for register that we will verify is in all of the pushed rows.
1237 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1238 Succeeded());
1239
1240 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1241 // follwing rows:
1242 // 0x1000: CFA=reg12+32: Reg1=undefined
1243 // Then we verify that all registers are correct in all generated rows.
1244 constexpr uint8_t Reg1 = 14;
1245 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}),
1246 Succeeded());
1247
1248 // Create locations that we expect the UnwindRow objects to contain after
1249 // parsing the DWARF call frame instructions.
1250 dwarf::RegisterLocations VerifyLocs;
1251 VerifyLocs.setRegisterLocation(Reg1,
1252 dwarf::UnwindLocation::createUndefined());
1253
1254 // Verify we catch state machine error.
1255 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1256 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1257 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1258 EXPECT_EQ(Rows.size(), 1u);
1259 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1260 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1261 }
1262
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_same_value)1263 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) {
1264 // Test that DW_CFA_same_value works as expected when parsed in the state
1265 // machine.
1266 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1267 /*Offset=*/0x0,
1268 /*Length=*/0xff);
1269
1270 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1271 /*Offset=*/0x3333abcdabcd,
1272 /*Length=*/0x4444abcdabcd,
1273 /*CIEPointer=*/0x1111abcdabcd,
1274 /*InitialLocation=*/0x1000,
1275 /*AddressRange=*/0x1000,
1276 /*Cie=*/&TestCIE,
1277 /*LSDAAddress=*/None,
1278 /*Arch=*/Triple::x86_64);
1279
1280 // Make a CIE that has a valid CFA definition and a single register unwind
1281 // rule for register that we will verify is in all of the pushed rows.
1282 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1283 Succeeded());
1284
1285 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1286 // follwing rows:
1287 // 0x1000: CFA=reg12+32: Reg1=same
1288 // Then we verify that all registers are correct in all generated rows.
1289 constexpr uint8_t Reg1 = 14;
1290 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}),
1291 Succeeded());
1292
1293 // Create locations that we expect the UnwindRow objects to contain after
1294 // parsing the DWARF call frame instructions.
1295 dwarf::RegisterLocations VerifyLocs;
1296 VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame());
1297
1298 // Verify we catch state machine error.
1299 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1300 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1301 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1302 EXPECT_EQ(Rows.size(), 1u);
1303 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1304 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1305 }
1306
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_register)1307 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) {
1308 // Test that DW_CFA_register works as expected when parsed in the state
1309 // machine.
1310 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1311 /*Offset=*/0x0,
1312 /*Length=*/0xff);
1313
1314 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1315 /*Offset=*/0x3333abcdabcd,
1316 /*Length=*/0x4444abcdabcd,
1317 /*CIEPointer=*/0x1111abcdabcd,
1318 /*InitialLocation=*/0x1000,
1319 /*AddressRange=*/0x1000,
1320 /*Cie=*/&TestCIE,
1321 /*LSDAAddress=*/None,
1322 /*Arch=*/Triple::x86_64);
1323
1324 // Make a CIE that has a valid CFA definition and a single register unwind
1325 // rule for register that we will verify is in all of the pushed rows.
1326 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1327 Succeeded());
1328
1329 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1330 // follwing rows:
1331 // 0x1000: CFA=reg12+32: Reg1=same
1332 // Then we verify that all registers are correct in all generated rows.
1333 constexpr uint8_t Reg = 13;
1334 constexpr uint8_t InReg = 14;
1335 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}),
1336 Succeeded());
1337
1338 // Create locations that we expect the UnwindRow objects to contain after
1339 // parsing the DWARF call frame instructions.
1340 dwarf::RegisterLocations VerifyLocs;
1341 VerifyLocs.setRegisterLocation(
1342 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1343
1344 // Verify we catch state machine error.
1345 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1346 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1347 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1348 EXPECT_EQ(Rows.size(), 1u);
1349 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1350 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1351 }
1352
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_expression)1353 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) {
1354 // Test that DW_CFA_expression works as expected when parsed in the state
1355 // machine.
1356 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1357 /*Offset=*/0x0,
1358 /*Length=*/0xff);
1359
1360 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1361 /*Offset=*/0x3333abcdabcd,
1362 /*Length=*/0x4444abcdabcd,
1363 /*CIEPointer=*/0x1111abcdabcd,
1364 /*InitialLocation=*/0x1000,
1365 /*AddressRange=*/0x1000,
1366 /*Cie=*/&TestCIE,
1367 /*LSDAAddress=*/None,
1368 /*Arch=*/Triple::x86_64);
1369
1370 // Make a CIE that has a valid CFA definition and a single register unwind
1371 // rule for register that we will verify is in all of the pushed rows.
1372 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1373 Succeeded());
1374
1375 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1376 // follwing rows:
1377 // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1378 // Then we verify that all registers are correct in all generated rows.
1379 constexpr uint8_t Reg = 13;
1380 constexpr uint8_t AddrSize = 8;
1381 std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1,
1382 dwarf::DW_OP_reg12};
1383
1384 EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded());
1385
1386 // Create locations that we expect the UnwindRow objects to contain after
1387 // parsing the DWARF call frame instructions.
1388 dwarf::RegisterLocations VerifyLocs;
1389
1390 std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12};
1391 DataExtractor ExprData(ExprBytes, true, AddrSize);
1392 DWARFExpression Expr(ExprData, AddrSize);
1393 VerifyLocs.setRegisterLocation(
1394 Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr));
1395
1396 // Verify we catch state machine error.
1397 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1398 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1399 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1400 EXPECT_EQ(Rows.size(), 1u);
1401 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1402 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1403 }
1404
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_val_expression)1405 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) {
1406 // Test that DW_CFA_val_expression works as expected when parsed in the state
1407 // machine.
1408 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1409 /*Offset=*/0x0,
1410 /*Length=*/0xff);
1411
1412 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1413 /*Offset=*/0x3333abcdabcd,
1414 /*Length=*/0x4444abcdabcd,
1415 /*CIEPointer=*/0x1111abcdabcd,
1416 /*InitialLocation=*/0x1000,
1417 /*AddressRange=*/0x1000,
1418 /*Cie=*/&TestCIE,
1419 /*LSDAAddress=*/None,
1420 /*Arch=*/Triple::x86_64);
1421
1422 // Make a CIE that has a valid CFA definition and a single register unwind
1423 // rule for register that we will verify is in all of the pushed rows.
1424 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1425 Succeeded());
1426
1427 // Make a FDE with DWARF call frame instruction opcodes that encodes the
1428 // follwing rows:
1429 // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1430 // Then we verify that all registers are correct in all generated rows.
1431 constexpr uint8_t Reg = 13;
1432 constexpr uint8_t AddrSize = 8;
1433 std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1,
1434 dwarf::DW_OP_reg12};
1435
1436 EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded());
1437
1438 // Create locations that we expect the UnwindRow objects to contain after
1439 // parsing the DWARF call frame instructions.
1440 dwarf::RegisterLocations VerifyLocs;
1441
1442 std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12};
1443 DataExtractor ExprData(ExprBytes, true, AddrSize);
1444 DWARFExpression Expr(ExprData, AddrSize);
1445 VerifyLocs.setRegisterLocation(
1446 Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr));
1447
1448 // Verify we catch state machine error.
1449 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1450 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1451 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1452 EXPECT_EQ(Rows.size(), 1u);
1453 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1454 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1455 }
1456
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_def_cfa)1457 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) {
1458 // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register,
1459 // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when
1460 // parsed in the state machine.
1461 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1462 /*Offset=*/0x0,
1463 /*Length=*/0xff);
1464
1465 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1466 /*Offset=*/0x3333abcdabcd,
1467 /*Length=*/0x4444abcdabcd,
1468 /*CIEPointer=*/0x1111abcdabcd,
1469 /*InitialLocation=*/0x1000,
1470 /*AddressRange=*/0x1000,
1471 /*Cie=*/&TestCIE,
1472 /*LSDAAddress=*/None,
1473 /*Arch=*/Triple::x86_64);
1474
1475 // Make a CIE that has a valid CFA definition and a single register unwind
1476 // rule for register that we will verify is in all of the pushed rows.
1477 constexpr uint8_t CFAReg1 = 12;
1478 constexpr uint8_t CFAOff1 = 32;
1479 constexpr uint8_t CFAReg2 = 13;
1480 constexpr uint8_t CFAOff2 = 48;
1481 constexpr uint8_t Reg = 13;
1482 constexpr uint8_t InReg = 14;
1483
1484 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1,
1485 dwarf::DW_CFA_register, Reg, InReg}),
1486 Succeeded());
1487
1488 // Make a FDE with DWARF call frame instruction opcodes that use all of the
1489 // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1490 // create a row are correctly working.
1491 EXPECT_THAT_ERROR(
1492 parseCFI(
1493 TestFDE,
1494 {
1495 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register,
1496 CFAReg2, dwarf::DW_CFA_advance_loc | 4,
1497 dwarf::DW_CFA_def_cfa_offset, CFAOff2,
1498 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf,
1499 0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1500 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1,
1501 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1502 }),
1503 Succeeded());
1504
1505 // Create locations that we expect the UnwindRow objects to contain after
1506 // parsing the DWARF call frame instructions.
1507 dwarf::RegisterLocations VerifyLocs;
1508 VerifyLocs.setRegisterLocation(
1509 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1510
1511 // Verify we catch state machine error.
1512 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1513 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1514 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1515 EXPECT_EQ(Rows.size(), 5u);
1516 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1517 EXPECT_EQ(
1518 Rows[0].getCFAValue(),
1519 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1));
1520 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
1521 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1522
1523 EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
1524 EXPECT_EQ(
1525 Rows[1].getCFAValue(),
1526 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1));
1527 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
1528 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
1529
1530 EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
1531 EXPECT_EQ(
1532 Rows[2].getCFAValue(),
1533 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2));
1534 EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
1535 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
1536
1537 EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
1538 EXPECT_EQ(
1539 Rows[3].getCFAValue(),
1540 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1));
1541 EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
1542 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
1543
1544 EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
1545 EXPECT_EQ(
1546 Rows[4].getCFAValue(),
1547 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2));
1548 EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
1549 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
1550 }
1551
TEST(DWARFDebugFrame,UnwindTable_DW_CFA_LLVM_def_aspace_cfa)1552 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_LLVM_def_aspace_cfa) {
1553 // Test that DW_CFA_LLVM_def_aspace_cfa, DW_CFA_LLVM_def_aspace_cfa_sf,
1554 // DW_CFA_def_cfa_register, DW_CFA_def_cfa_offset, and
1555 // DW_CFA_def_cfa_offset_sf works as expected when parsed in the state
1556 // machine.
1557 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1558 /*Offset=*/0x0,
1559 /*Length=*/0xff);
1560
1561 dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1562 /*Offset=*/0x3333abcdabcd,
1563 /*Length=*/0x4444abcdabcd,
1564 /*CIEPointer=*/0x1111abcdabcd,
1565 /*InitialLocation=*/0x1000,
1566 /*AddressRange=*/0x1000,
1567 /*Cie=*/&TestCIE,
1568 /*LSDAAddress=*/None,
1569 /*Arch=*/Triple::x86_64);
1570
1571 // Make a CIE that has a valid CFA definition and a single register unwind
1572 // rule for register that we will verify is in all of the pushed rows.
1573 constexpr uint8_t CFAReg1 = 12;
1574 constexpr uint8_t CFAOff1 = 32;
1575 constexpr uint8_t CFAReg2 = 13;
1576 constexpr uint8_t CFAOff2 = 48;
1577 constexpr uint8_t Reg = 13;
1578 constexpr uint8_t InReg = 14;
1579 constexpr uint8_t AddrSpace = 2;
1580
1581 EXPECT_THAT_ERROR(
1582 parseCFI(TestCIE, {dwarf::DW_CFA_LLVM_def_aspace_cfa, CFAReg1, CFAOff1,
1583 AddrSpace, dwarf::DW_CFA_register, Reg, InReg}),
1584 Succeeded());
1585
1586 // Make a FDE with DWARF call frame instruction opcodes that use all of the
1587 // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1588 // create a row are correctly working.
1589 EXPECT_THAT_ERROR(
1590 parseCFI(
1591 TestFDE,
1592 {
1593 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register,
1594 CFAReg2, dwarf::DW_CFA_advance_loc | 4,
1595 dwarf::DW_CFA_def_cfa_offset, CFAOff2,
1596 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf,
1597 0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1598 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1,
1599 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1600 }),
1601 Succeeded());
1602
1603 // Create locations that we expect the UnwindRow objects to contain after
1604 // parsing the DWARF call frame instructions.
1605 dwarf::RegisterLocations VerifyLocs;
1606 VerifyLocs.setRegisterLocation(
1607 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1608
1609 // Verify we catch state machine error.
1610 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1611 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1612 const dwarf::UnwindTable &Rows = RowsOrErr.get();
1613 EXPECT_EQ(Rows.size(), 5u);
1614 EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1615 EXPECT_EQ(Rows[0].getCFAValue(),
1616 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1,
1617 AddrSpace));
1618 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
1619 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1620
1621 EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
1622 EXPECT_EQ(Rows[1].getCFAValue(),
1623 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1,
1624 AddrSpace));
1625 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
1626 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
1627
1628 EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
1629 EXPECT_EQ(Rows[2].getCFAValue(),
1630 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2,
1631 AddrSpace));
1632 EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
1633 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
1634
1635 EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
1636 EXPECT_EQ(Rows[3].getCFAValue(),
1637 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1,
1638 AddrSpace));
1639 EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
1640 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
1641
1642 EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
1643 EXPECT_EQ(Rows[4].getCFAValue(),
1644 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2,
1645 AddrSpace));
1646 EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
1647 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
1648 }
1649
1650 } // end anonymous namespace
1651