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