xref: /llvm-project/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp (revision 86f76c3b171f95fd0560339f2ad0f4449277cf8d)
1cada5b88SIgor Kudrin //===- llvm/unittest/DebugInfo/DWARFDebugFrameTest.cpp --------------------===//
2cada5b88SIgor Kudrin //
3cada5b88SIgor Kudrin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4cada5b88SIgor Kudrin // See https://llvm.org/LICENSE.txt for license information.
5cada5b88SIgor Kudrin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cada5b88SIgor Kudrin //
7cada5b88SIgor Kudrin //===----------------------------------------------------------------------===//
8cada5b88SIgor Kudrin 
9290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
10bee8cdcaSGeorgii Rymar #include "llvm/ADT/DenseSet.h"
11cada5b88SIgor Kudrin #include "llvm/ADT/SmallVector.h"
12cada5b88SIgor Kudrin #include "llvm/ADT/StringRef.h"
13cada5b88SIgor Kudrin #include "llvm/BinaryFormat/Dwarf.h"
14290e4823Sserge-sans-paille #include "llvm/DebugInfo/DIContext.h"
15290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
161e820e82SGeorgii Rymar #include "llvm/Testing/Support/Error.h"
17cada5b88SIgor Kudrin #include "gtest/gtest.h"
18cada5b88SIgor Kudrin 
19cada5b88SIgor Kudrin using namespace llvm;
20cada5b88SIgor Kudrin 
21cada5b88SIgor Kudrin namespace {
22cada5b88SIgor Kudrin 
23cada5b88SIgor Kudrin dwarf::CIE createCIE(bool IsDWARF64, uint64_t Offset, uint64_t Length) {
24cada5b88SIgor Kudrin   return dwarf::CIE(IsDWARF64, Offset, Length,
25cada5b88SIgor Kudrin                     /*Version=*/3,
26cada5b88SIgor Kudrin                     /*Augmentation=*/StringRef(),
27cada5b88SIgor Kudrin                     /*AddressSize=*/8,
28cada5b88SIgor Kudrin                     /*SegmentDescriptorSize=*/0,
29cada5b88SIgor Kudrin                     /*CodeAlignmentFactor=*/1,
30cada5b88SIgor Kudrin                     /*DataAlignmentFactor=*/-8,
31cada5b88SIgor Kudrin                     /*ReturnAddressRegister=*/16,
32cada5b88SIgor Kudrin                     /*AugmentationData=*/StringRef(),
33cada5b88SIgor Kudrin                     /*FDEPointerEncoding=*/dwarf::DW_EH_PE_absptr,
34cada5b88SIgor Kudrin                     /*LSDAPointerEncoding=*/dwarf::DW_EH_PE_omit,
35b6a01caaSKazu Hirata                     /*Personality=*/std::nullopt,
36b6a01caaSKazu Hirata                     /*PersonalityEnc=*/std::nullopt,
37cada5b88SIgor Kudrin                     /*Arch=*/Triple::x86_64);
38cada5b88SIgor Kudrin }
39cada5b88SIgor Kudrin 
40cada5b88SIgor Kudrin void expectDumpResult(const dwarf::CIE &TestCIE, bool IsEH,
41cada5b88SIgor Kudrin                       StringRef ExpectedFirstLine) {
42cada5b88SIgor Kudrin   std::string Output;
43cada5b88SIgor Kudrin   raw_string_ostream OS(Output);
44617ed4f0SShubham Sandeep Rastogi   auto DumpOpts = DIDumpOptions();
45617ed4f0SShubham Sandeep Rastogi   DumpOpts.IsEH = IsEH;
46617ed4f0SShubham Sandeep Rastogi   TestCIE.dump(OS, DumpOpts);
47cada5b88SIgor Kudrin   StringRef FirstLine = StringRef(Output).split('\n').first;
48cada5b88SIgor Kudrin   EXPECT_EQ(FirstLine, ExpectedFirstLine);
49cada5b88SIgor Kudrin }
50cada5b88SIgor Kudrin 
51cada5b88SIgor Kudrin void expectDumpResult(const dwarf::FDE &TestFDE, bool IsEH,
52cada5b88SIgor Kudrin                       StringRef ExpectedFirstLine) {
53cada5b88SIgor Kudrin   std::string Output;
54cada5b88SIgor Kudrin   raw_string_ostream OS(Output);
55617ed4f0SShubham Sandeep Rastogi   auto DumpOpts = DIDumpOptions();
56617ed4f0SShubham Sandeep Rastogi   DumpOpts.IsEH = IsEH;
57617ed4f0SShubham Sandeep Rastogi   TestFDE.dump(OS, DumpOpts);
58cada5b88SIgor Kudrin   StringRef FirstLine = StringRef(Output).split('\n').first;
59cada5b88SIgor Kudrin   EXPECT_EQ(FirstLine, ExpectedFirstLine);
60cada5b88SIgor Kudrin }
61cada5b88SIgor Kudrin 
62cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF32CIE) {
63cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
64cada5b88SIgor Kudrin                                  /*Offset=*/0x1111abcd,
65cada5b88SIgor Kudrin                                  /*Length=*/0x2222abcd);
66cada5b88SIgor Kudrin   expectDumpResult(TestCIE, /*IsEH=*/false, "1111abcd 2222abcd ffffffff CIE");
67cada5b88SIgor Kudrin }
68cada5b88SIgor Kudrin 
69cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF64CIE) {
70cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
71cada5b88SIgor Kudrin                                  /*Offset=*/0x1111abcdabcd,
72cada5b88SIgor Kudrin                                  /*Length=*/0x2222abcdabcd);
73cada5b88SIgor Kudrin   expectDumpResult(TestCIE, /*IsEH=*/false,
74cada5b88SIgor Kudrin                    "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE");
75cada5b88SIgor Kudrin }
76cada5b88SIgor Kudrin 
77cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEHCIE) {
78cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
79cada5b88SIgor Kudrin                                  /*Offset=*/0x1000,
80cada5b88SIgor Kudrin                                  /*Length=*/0x20);
81cada5b88SIgor Kudrin   expectDumpResult(TestCIE, /*IsEH=*/true, "00001000 00000020 00000000 CIE");
82cada5b88SIgor Kudrin }
83cada5b88SIgor Kudrin 
84cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEH64CIE) {
85cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
86cada5b88SIgor Kudrin                                  /*Offset=*/0x1000,
87cada5b88SIgor Kudrin                                  /*Length=*/0x20);
88cada5b88SIgor Kudrin   expectDumpResult(TestCIE, /*IsEH=*/true,
89cada5b88SIgor Kudrin                    "00001000 0000000000000020 00000000 CIE");
90cada5b88SIgor Kudrin }
91cada5b88SIgor Kudrin 
92cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF64FDE) {
93cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
94cada5b88SIgor Kudrin                                  /*Offset=*/0x1111abcdabcd,
95cada5b88SIgor Kudrin                                  /*Length=*/0x2222abcdabcd);
96cada5b88SIgor Kudrin   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
97cada5b88SIgor Kudrin                      /*Offset=*/0x3333abcdabcd,
98cada5b88SIgor Kudrin                      /*Length=*/0x4444abcdabcd,
99cada5b88SIgor Kudrin                      /*CIEPointer=*/0x1111abcdabcd,
100cada5b88SIgor Kudrin                      /*InitialLocation=*/0x5555abcdabcd,
101cada5b88SIgor Kudrin                      /*AddressRange=*/0x111111111111,
102cada5b88SIgor Kudrin                      /*Cie=*/&TestCIE,
103b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
104cada5b88SIgor Kudrin                      /*Arch=*/Triple::x86_64);
105cada5b88SIgor Kudrin   expectDumpResult(TestFDE, /*IsEH=*/false,
106cada5b88SIgor Kudrin                    "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE "
107cada5b88SIgor Kudrin                    "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde");
108cada5b88SIgor Kudrin }
109cada5b88SIgor Kudrin 
110cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEH64FDE) {
111cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
112cada5b88SIgor Kudrin                                  /*Offset=*/0x1111ab9a000c,
113cada5b88SIgor Kudrin                                  /*Length=*/0x20);
114cada5b88SIgor Kudrin   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
115cada5b88SIgor Kudrin                      /*Offset=*/0x1111abcdabcd,
116cada5b88SIgor Kudrin                      /*Length=*/0x2222abcdabcd,
117cada5b88SIgor Kudrin                      /*CIEPointer=*/0x33abcd,
118cada5b88SIgor Kudrin                      /*InitialLocation=*/0x4444abcdabcd,
119cada5b88SIgor Kudrin                      /*AddressRange=*/0x111111111111,
120cada5b88SIgor Kudrin                      /*Cie=*/&TestCIE,
121b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
122cada5b88SIgor Kudrin                      /*Arch=*/Triple::x86_64);
123cada5b88SIgor Kudrin   expectDumpResult(TestFDE, /*IsEH=*/true,
124cada5b88SIgor Kudrin                    "1111abcdabcd 00002222abcdabcd 0033abcd FDE "
125cada5b88SIgor Kudrin                    "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde");
126cada5b88SIgor Kudrin }
127cada5b88SIgor Kudrin 
128bee8cdcaSGeorgii Rymar static Error parseCFI(dwarf::CIE &C, ArrayRef<uint8_t> Instructions,
12977c90c8cSKazu Hirata                       std::optional<uint64_t> Size = std::nullopt) {
1301e820e82SGeorgii Rymar   DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true,
1311e820e82SGeorgii Rymar                           /*AddressSize=*/8);
1321e820e82SGeorgii Rymar   uint64_t Offset = 0;
1331e820e82SGeorgii Rymar   const uint64_t EndOffset = Size ? *Size : (uint64_t)Instructions.size();
1341e820e82SGeorgii Rymar   return C.cfis().parse(Data, &Offset, EndOffset);
135bee8cdcaSGeorgii Rymar }
136bee8cdcaSGeorgii Rymar 
137f8122d35SGreg Clayton static Error parseCFI(dwarf::FDE &FDE, ArrayRef<uint8_t> Instructions) {
138f8122d35SGreg Clayton   DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true,
139f8122d35SGreg Clayton                           /*AddressSize=*/8);
140f8122d35SGreg Clayton   uint64_t Offset = 0;
141f8122d35SGreg Clayton   return FDE.cfis().parse(Data, &Offset, Instructions.size());
142f8122d35SGreg Clayton }
143f8122d35SGreg Clayton 
144bee8cdcaSGeorgii Rymar TEST(DWARFDebugFrame, InvalidCFIOpcodesTest) {
145bee8cdcaSGeorgii Rymar   llvm::DenseSet<uint8_t> ValidExtendedOpcodes = {
146bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_nop,
147bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_advance_loc,
148bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_offset,
149bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_restore,
150bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_set_loc,
151bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_advance_loc1,
152bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_advance_loc2,
153bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_advance_loc4,
154bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_offset_extended,
155bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_restore_extended,
156bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_undefined,
157bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_same_value,
158bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_register,
159bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_remember_state,
160bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_restore_state,
161bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_def_cfa,
162bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_def_cfa_register,
163bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_def_cfa_offset,
164bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_def_cfa_expression,
165bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_expression,
166bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_offset_extended_sf,
167bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_def_cfa_sf,
168bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_def_cfa_offset_sf,
169167e7afcSRamNalamothu       dwarf::DW_CFA_LLVM_def_aspace_cfa,
170167e7afcSRamNalamothu       dwarf::DW_CFA_LLVM_def_aspace_cfa_sf,
171bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_val_offset,
172bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_val_offset_sf,
173bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_val_expression,
174bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_MIPS_advance_loc8,
175bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_GNU_window_save,
176bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_AARCH64_negate_ra_state,
177*86f76c3bSJack Styles       dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc,
178bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_GNU_args_size};
1791e820e82SGeorgii Rymar 
1801e820e82SGeorgii Rymar   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1811e820e82SGeorgii Rymar                                  /*Offset=*/0x0,
1821e820e82SGeorgii Rymar                                  /*Length=*/0xff);
1831e820e82SGeorgii Rymar 
184bee8cdcaSGeorgii Rymar   // See DWARF standard v3, section 7.23: low 6 bits are used to encode an
185bee8cdcaSGeorgii Rymar   // extended opcode.
186bee8cdcaSGeorgii Rymar   for (uint8_t Code = 0; Code <= 63; ++Code) {
187bee8cdcaSGeorgii Rymar     if (ValidExtendedOpcodes.count(Code))
188bee8cdcaSGeorgii Rymar       continue;
189bee8cdcaSGeorgii Rymar 
190bee8cdcaSGeorgii Rymar     EXPECT_THAT_ERROR(parseCFI(TestCIE, Code),
191bee8cdcaSGeorgii Rymar                       FailedWithMessage(("invalid extended CFI opcode 0x" +
192bee8cdcaSGeorgii Rymar                                          Twine::utohexstr(Code))
193bee8cdcaSGeorgii Rymar                                             .str()
194bee8cdcaSGeorgii Rymar                                             .c_str()));
195bee8cdcaSGeorgii Rymar   }
196bee8cdcaSGeorgii Rymar }
197bee8cdcaSGeorgii Rymar 
198bee8cdcaSGeorgii Rymar // Here we test how truncated Call Frame Instructions are parsed.
199bee8cdcaSGeorgii Rymar TEST(DWARFDebugFrame, ParseTruncatedCFITest) {
200bee8cdcaSGeorgii Rymar   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
201bee8cdcaSGeorgii Rymar                                  /*Offset=*/0x0,
202bee8cdcaSGeorgii Rymar                                  /*Length=*/0xff);
203bee8cdcaSGeorgii Rymar 
2041e820e82SGeorgii Rymar   // Having an empty instructions list is fine.
205bee8cdcaSGeorgii Rymar   EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
2061e820e82SGeorgii Rymar 
2071e820e82SGeorgii Rymar   // Unable to read an opcode, because the instructions list is empty, but we
2081e820e82SGeorgii Rymar   // say to the parser that it is not.
2091e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
210bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {}, /*Size=*/1),
2111e820e82SGeorgii Rymar       FailedWithMessage(
2121e820e82SGeorgii Rymar           "unexpected end of data at offset 0x0 while reading [0x0, 0x1)"));
2131e820e82SGeorgii Rymar 
2141e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_offset instruction.
2151e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
216bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_offset}),
2171e820e82SGeorgii Rymar       FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2181e820e82SGeorgii Rymar                         "malformed uleb128, extends past end"));
2191e820e82SGeorgii Rymar 
2201e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_set_loc instruction.
2211e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
222bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_set_loc}),
2231e820e82SGeorgii Rymar       FailedWithMessage(
2241e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x9)"));
2251e820e82SGeorgii Rymar 
2261e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_advance_loc1 instruction.
2271e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
228bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}),
2291e820e82SGeorgii Rymar       FailedWithMessage(
2301e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x2)"));
2311e820e82SGeorgii Rymar 
2321e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_advance_loc2 instruction.
2331e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
234bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}),
2351e820e82SGeorgii Rymar       FailedWithMessage(
2361e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x3)"));
2371e820e82SGeorgii Rymar 
2381e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_advance_loc4 instruction.
2391e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
240bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}),
2411e820e82SGeorgii Rymar       FailedWithMessage(
2421e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x5)"));
2431e820e82SGeorgii Rymar 
2441e820e82SGeorgii Rymar   // A test for an instruction with a single ULEB128 operand.
2451e820e82SGeorgii Rymar   auto CheckOp_ULEB128 = [&](uint8_t Inst) {
2461e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
247bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, Inst),
2481e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2491e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
2501e820e82SGeorgii Rymar   };
2511e820e82SGeorgii Rymar 
2521e820e82SGeorgii Rymar   for (uint8_t Inst :
2531e820e82SGeorgii Rymar        {dwarf::DW_CFA_restore_extended, dwarf::DW_CFA_undefined,
2541e820e82SGeorgii Rymar         dwarf::DW_CFA_same_value, dwarf::DW_CFA_def_cfa_register,
2551e820e82SGeorgii Rymar         dwarf::DW_CFA_def_cfa_offset, dwarf::DW_CFA_GNU_args_size})
2561e820e82SGeorgii Rymar     CheckOp_ULEB128(Inst);
2571e820e82SGeorgii Rymar 
2581e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction.
2591e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
260bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_offset_sf}),
2611e820e82SGeorgii Rymar       FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2621e820e82SGeorgii Rymar                         "malformed sleb128, extends past end"));
2631e820e82SGeorgii Rymar 
2641e820e82SGeorgii Rymar   // A test for an instruction with two ULEB128 operands.
2651e820e82SGeorgii Rymar   auto CheckOp_ULEB128_ULEB128 = [&](uint8_t Inst) {
2661e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
267bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, Inst),
2681e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2691e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
2701e820e82SGeorgii Rymar 
2711e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
272bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, {Inst, /*Op1=*/0}),
2731e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
2741e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
2751e820e82SGeorgii Rymar   };
2761e820e82SGeorgii Rymar 
2771e820e82SGeorgii Rymar   for (uint8_t Inst : {dwarf::DW_CFA_offset_extended, dwarf::DW_CFA_register,
278167e7afcSRamNalamothu                        dwarf::DW_CFA_def_cfa, dwarf::DW_CFA_LLVM_def_aspace_cfa,
279167e7afcSRamNalamothu                        dwarf::DW_CFA_val_offset})
2801e820e82SGeorgii Rymar     CheckOp_ULEB128_ULEB128(Inst);
2811e820e82SGeorgii Rymar 
2821e820e82SGeorgii Rymar   // A test for an instruction with two operands: ULEB128, SLEB128.
2831e820e82SGeorgii Rymar   auto CheckOp_ULEB128_SLEB128 = [&](uint8_t Inst) {
2841e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
285bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, Inst),
2861e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2871e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
2881e820e82SGeorgii Rymar 
2891e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
290bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, {Inst, /*Op1=*/0}),
2911e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
2921e820e82SGeorgii Rymar                           "malformed sleb128, extends past end"));
2931e820e82SGeorgii Rymar   };
2941e820e82SGeorgii Rymar 
295167e7afcSRamNalamothu   for (uint8_t Inst :
296167e7afcSRamNalamothu        {dwarf::DW_CFA_offset_extended_sf, dwarf::DW_CFA_def_cfa_sf,
297167e7afcSRamNalamothu         dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, dwarf::DW_CFA_val_offset_sf})
2981e820e82SGeorgii Rymar     CheckOp_ULEB128_SLEB128(Inst);
2991e820e82SGeorgii Rymar 
3001e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_def_cfa_expression instruction.
3011e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
302bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}),
3031e820e82SGeorgii Rymar       FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
3041e820e82SGeorgii Rymar                         "malformed uleb128, extends past end"));
3051e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
306bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
3071e820e82SGeorgii Rymar                          /*expression length=*/0x1}),
3081e820e82SGeorgii Rymar       FailedWithMessage(
3091e820e82SGeorgii Rymar           "unexpected end of data at offset 0x2 while reading [0x2, 0x3)"));
3101e820e82SGeorgii Rymar   // The DW_CFA_def_cfa_expression can contain a zero length expression.
311bee8cdcaSGeorgii Rymar   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
3121e820e82SGeorgii Rymar                                        /*ExprLen=*/0}),
3131e820e82SGeorgii Rymar                     Succeeded());
3141e820e82SGeorgii Rymar 
3151e820e82SGeorgii Rymar   // A test for an instruction with three operands: ULEB128, expression length
3161e820e82SGeorgii Rymar   // (ULEB128) and expression bytes.
3171e820e82SGeorgii Rymar   auto CheckOp_ULEB128_Expr = [&](uint8_t Inst) {
3181e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
319bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, {Inst}),
3201e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
3211e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
3221e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
323bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, {Inst, /*Op1=*/0}),
3241e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
3251e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
3261e820e82SGeorgii Rymar     // A zero length expression is fine
327bee8cdcaSGeorgii Rymar     EXPECT_THAT_ERROR(parseCFI(TestCIE, {Inst,
3281e820e82SGeorgii Rymar                                          /*Op1=*/0, /*ExprLen=*/0}),
3291e820e82SGeorgii Rymar                       Succeeded());
3301e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
331bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, {Inst,
3321e820e82SGeorgii Rymar                            /*Op1=*/0, /*ExprLen=*/1}),
3331e820e82SGeorgii Rymar         FailedWithMessage(
3341e820e82SGeorgii Rymar             "unexpected end of data at offset 0x3 while reading [0x3, 0x4)"));
3351e820e82SGeorgii Rymar   };
3361e820e82SGeorgii Rymar 
3371e820e82SGeorgii Rymar   for (uint8_t Inst : {dwarf::DW_CFA_expression, dwarf::DW_CFA_val_expression})
3381e820e82SGeorgii Rymar     CheckOp_ULEB128_Expr(Inst);
3391e820e82SGeorgii Rymar }
3401e820e82SGeorgii Rymar 
341f8122d35SGreg Clayton void expectDumpResult(const dwarf::UnwindLocation &Loc,
342f8122d35SGreg Clayton                       StringRef ExpectedFirstLine) {
343f8122d35SGreg Clayton   std::string Output;
344f8122d35SGreg Clayton   raw_string_ostream OS(Output);
345f8122d35SGreg Clayton   OS << Loc;
346f8122d35SGreg Clayton   StringRef FirstLine = StringRef(Output).split('\n').first;
347f8122d35SGreg Clayton   EXPECT_EQ(FirstLine, ExpectedFirstLine);
348f8122d35SGreg Clayton }
349f8122d35SGreg Clayton 
350f8122d35SGreg Clayton TEST(DWARFDebugFrame, DumpUnwindLocations) {
351f8122d35SGreg Clayton   // Test constructing unwind locations and dumping each kind.
352f8122d35SGreg Clayton   constexpr int32_t PlusOff = 8;
353f8122d35SGreg Clayton   constexpr int32_t MinusOff = -8;
354a1a3fdcdSGreg Clayton   constexpr uint8_t RegNum = 12;
355f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createUnspecified(), "unspecified");
356f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createUndefined(), "undefined");
357f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createSame(), "same");
358f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(PlusOff),
359f8122d35SGreg Clayton                    "CFA+8");
360f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff),
361f8122d35SGreg Clayton                    "CFA-8");
362f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff),
363f8122d35SGreg Clayton                    "[CFA+8]");
364f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff),
365f8122d35SGreg Clayton                    "[CFA-8]");
366f8122d35SGreg Clayton 
367f8122d35SGreg Clayton   expectDumpResult(
368f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, PlusOff),
369f8122d35SGreg Clayton       "reg12+8");
370f8122d35SGreg Clayton   expectDumpResult(
371f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, MinusOff),
372f8122d35SGreg Clayton       "reg12-8");
373f8122d35SGreg Clayton   expectDumpResult(
374f8122d35SGreg Clayton       dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, PlusOff),
375f8122d35SGreg Clayton       "[reg12+8]");
376f8122d35SGreg Clayton   expectDumpResult(
377f8122d35SGreg Clayton       dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, MinusOff),
378f8122d35SGreg Clayton       "[reg12-8]");
379f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12");
380f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32");
381f8122d35SGreg Clayton }
382f8122d35SGreg Clayton 
383f8122d35SGreg Clayton void expectDumpResult(const dwarf::RegisterLocations &Locs,
384f8122d35SGreg Clayton                       StringRef ExpectedFirstLine) {
385f8122d35SGreg Clayton   std::string Output;
386f8122d35SGreg Clayton   raw_string_ostream OS(Output);
387f8122d35SGreg Clayton   OS << Locs;
388f8122d35SGreg Clayton   StringRef FirstLine = StringRef(Output).split('\n').first;
389f8122d35SGreg Clayton   EXPECT_EQ(FirstLine, ExpectedFirstLine);
390f8122d35SGreg Clayton }
391f8122d35SGreg Clayton 
392f8122d35SGreg Clayton TEST(DWARFDebugFrame, RegisterLocations) {
393f8122d35SGreg Clayton   // Test the functionality of the RegisterLocations class.
394f8122d35SGreg Clayton   dwarf::RegisterLocations Locs;
395f8122d35SGreg Clayton   expectDumpResult(Locs, "");
396f8122d35SGreg Clayton   EXPECT_FALSE(Locs.hasLocations());
397f8122d35SGreg Clayton   // Set a register location for reg12 to unspecified and verify it dumps
398f8122d35SGreg Clayton   // correctly.
399f8122d35SGreg Clayton   Locs.setRegisterLocation(12, dwarf::UnwindLocation::createUnspecified());
400f8122d35SGreg Clayton   EXPECT_TRUE(Locs.hasLocations());
401f8122d35SGreg Clayton   expectDumpResult(Locs, "reg12=unspecified");
402f8122d35SGreg Clayton 
403f8122d35SGreg Clayton   // Replace the register location for reg12 to "same" and verify it dumps
404f8122d35SGreg Clayton   // correctly after it is modified
405f8122d35SGreg Clayton   Locs.setRegisterLocation(12, dwarf::UnwindLocation::createSame());
406f8122d35SGreg Clayton   EXPECT_TRUE(Locs.hasLocations());
407f8122d35SGreg Clayton   expectDumpResult(Locs, "reg12=same");
408f8122d35SGreg Clayton 
409f8122d35SGreg Clayton   // Remove the register location for reg12 verify it dumps correctly after it
410f8122d35SGreg Clayton   // is removed.
411f8122d35SGreg Clayton   Locs.removeRegisterLocation(12);
412f8122d35SGreg Clayton   EXPECT_FALSE(Locs.hasLocations());
413f8122d35SGreg Clayton   expectDumpResult(Locs, "");
414f8122d35SGreg Clayton 
415f8122d35SGreg Clayton   // Verify multiple registers added to the list dump correctly.
416f8122d35SGreg Clayton   auto Reg12Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(4);
417f8122d35SGreg Clayton   auto Reg13Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(8);
418f8122d35SGreg Clayton   auto Reg14Loc = dwarf::UnwindLocation::createSame();
419f8122d35SGreg Clayton   Locs.setRegisterLocation(12, Reg12Loc);
420f8122d35SGreg Clayton   Locs.setRegisterLocation(13, Reg13Loc);
421f8122d35SGreg Clayton   Locs.setRegisterLocation(14, Reg14Loc);
422f8122d35SGreg Clayton   EXPECT_TRUE(Locs.hasLocations());
423f8122d35SGreg Clayton   expectDumpResult(Locs, "reg12=[CFA+4], reg13=[CFA+8], reg14=same");
424f8122d35SGreg Clayton 
425f8122d35SGreg Clayton   // Verify RegisterLocations::getRegisterLocation() works as expected.
42689fab98eSFangrui Song   std::optional<dwarf::UnwindLocation> OptionalLoc;
427f8122d35SGreg Clayton   OptionalLoc = Locs.getRegisterLocation(0);
4283361a364SKazu Hirata   EXPECT_FALSE(OptionalLoc.has_value());
429f8122d35SGreg Clayton 
430f8122d35SGreg Clayton   OptionalLoc = Locs.getRegisterLocation(12);
4313361a364SKazu Hirata   EXPECT_TRUE(OptionalLoc.has_value());
432f8122d35SGreg Clayton   EXPECT_EQ(*OptionalLoc, Reg12Loc);
433f8122d35SGreg Clayton 
434f8122d35SGreg Clayton   OptionalLoc = Locs.getRegisterLocation(13);
4353361a364SKazu Hirata   EXPECT_TRUE(OptionalLoc.has_value());
436f8122d35SGreg Clayton   EXPECT_EQ(*OptionalLoc, Reg13Loc);
437f8122d35SGreg Clayton 
438f8122d35SGreg Clayton   OptionalLoc = Locs.getRegisterLocation(14);
4393361a364SKazu Hirata   EXPECT_TRUE(OptionalLoc.has_value());
440f8122d35SGreg Clayton   EXPECT_EQ(*OptionalLoc, Reg14Loc);
441f8122d35SGreg Clayton 
442f8122d35SGreg Clayton   // Verify registers are correctly removed when multiple exist in the list.
443f8122d35SGreg Clayton   Locs.removeRegisterLocation(13);
4443361a364SKazu Hirata   EXPECT_FALSE(Locs.getRegisterLocation(13).has_value());
445f8122d35SGreg Clayton   EXPECT_TRUE(Locs.hasLocations());
446f8122d35SGreg Clayton   expectDumpResult(Locs, "reg12=[CFA+4], reg14=same");
447f8122d35SGreg Clayton   Locs.removeRegisterLocation(14);
4483361a364SKazu Hirata   EXPECT_FALSE(Locs.getRegisterLocation(14).has_value());
449f8122d35SGreg Clayton   EXPECT_TRUE(Locs.hasLocations());
450f8122d35SGreg Clayton   expectDumpResult(Locs, "reg12=[CFA+4]");
451f8122d35SGreg Clayton   Locs.removeRegisterLocation(12);
4523361a364SKazu Hirata   EXPECT_FALSE(Locs.getRegisterLocation(12).has_value());
453f8122d35SGreg Clayton   EXPECT_FALSE(Locs.hasLocations());
454f8122d35SGreg Clayton   expectDumpResult(Locs, "");
455f8122d35SGreg Clayton }
456f8122d35SGreg Clayton 
457223852d7SRamNalamothu // Test that empty rows are not added to UnwindTable when
458223852d7SRamNalamothu // dwarf::CIE::CFIs or dwarf::FDE::CFIs is empty.
459223852d7SRamNalamothu TEST(DWARFDebugFrame, UnwindTableEmptyRows) {
460223852d7SRamNalamothu   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
461223852d7SRamNalamothu                                  /*Offset=*/0x0,
462223852d7SRamNalamothu                                  /*Length=*/0xff);
463223852d7SRamNalamothu 
464223852d7SRamNalamothu   // Having an empty instructions list is fine.
465223852d7SRamNalamothu   EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
466223852d7SRamNalamothu   EXPECT_TRUE(TestCIE.cfis().empty());
467223852d7SRamNalamothu 
468223852d7SRamNalamothu   // Verify dwarf::UnwindTable::create() won't result in errors and
469223852d7SRamNalamothu   // and empty rows are not added to CIE UnwindTable.
470223852d7SRamNalamothu   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE);
471223852d7SRamNalamothu   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
472223852d7SRamNalamothu   const size_t ExpectedNumOfRows = 0;
473223852d7SRamNalamothu   EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
474223852d7SRamNalamothu 
475223852d7SRamNalamothu   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
476223852d7SRamNalamothu                      /*Offset=*/0x3333abcdabcd,
477223852d7SRamNalamothu                      /*Length=*/0x4444abcdabcd,
478223852d7SRamNalamothu                      /*CIEPointer=*/0x1111abcdabcd,
479223852d7SRamNalamothu                      /*InitialLocation=*/0x1000,
480223852d7SRamNalamothu                      /*AddressRange=*/0x1000,
481223852d7SRamNalamothu                      /*Cie=*/&TestCIE,
482b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
483223852d7SRamNalamothu                      /*Arch=*/Triple::x86_64);
484223852d7SRamNalamothu 
485223852d7SRamNalamothu   // Having an empty instructions list is fine.
486223852d7SRamNalamothu   EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
487223852d7SRamNalamothu   EXPECT_TRUE(TestFDE.cfis().empty());
488223852d7SRamNalamothu 
489223852d7SRamNalamothu   // Verify dwarf::UnwindTable::create() won't result in errors and
490223852d7SRamNalamothu   // and empty rows are not added to FDE UnwindTable.
491223852d7SRamNalamothu   RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
492223852d7SRamNalamothu   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
493223852d7SRamNalamothu   EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
494223852d7SRamNalamothu }
495223852d7SRamNalamothu 
496223852d7SRamNalamothu // Test that empty rows are not added to UnwindTable when dwarf::CIE::CFIs
497223852d7SRamNalamothu // or dwarf::FDE::CFIs is not empty but has only DW_CFA_nop instructions.
498223852d7SRamNalamothu TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) {
499223852d7SRamNalamothu   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
500223852d7SRamNalamothu                                  /*Offset=*/0x0,
501223852d7SRamNalamothu                                  /*Length=*/0xff);
502223852d7SRamNalamothu 
503223852d7SRamNalamothu   // Make a CIE that has only DW_CFA_nop instructions.
504223852d7SRamNalamothu   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_nop}), Succeeded());
505223852d7SRamNalamothu   EXPECT_TRUE(!TestCIE.cfis().empty());
506223852d7SRamNalamothu 
507223852d7SRamNalamothu   // Verify dwarf::UnwindTable::create() won't result in errors and
508223852d7SRamNalamothu   // and empty rows are not added to CIE UnwindTable.
509223852d7SRamNalamothu   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE);
510223852d7SRamNalamothu   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
511223852d7SRamNalamothu   const size_t ExpectedNumOfRows = 0;
512223852d7SRamNalamothu   EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
513223852d7SRamNalamothu 
514223852d7SRamNalamothu   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
515223852d7SRamNalamothu                      /*Offset=*/0x3333abcdabcd,
516223852d7SRamNalamothu                      /*Length=*/0x4444abcdabcd,
517223852d7SRamNalamothu                      /*CIEPointer=*/0x1111abcdabcd,
518223852d7SRamNalamothu                      /*InitialLocation=*/0x1000,
519223852d7SRamNalamothu                      /*AddressRange=*/0x1000,
520223852d7SRamNalamothu                      /*Cie=*/&TestCIE,
521b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
522223852d7SRamNalamothu                      /*Arch=*/Triple::x86_64);
523223852d7SRamNalamothu 
524223852d7SRamNalamothu   // Make an FDE that has only DW_CFA_nop instructions.
525223852d7SRamNalamothu   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_nop}), Succeeded());
526223852d7SRamNalamothu   EXPECT_TRUE(!TestFDE.cfis().empty());
527223852d7SRamNalamothu 
528223852d7SRamNalamothu   // Verify dwarf::UnwindTable::create() won't result in errors and
529223852d7SRamNalamothu   // and empty rows are not added to FDE UnwindTable.
530223852d7SRamNalamothu   RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
531223852d7SRamNalamothu   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
532223852d7SRamNalamothu   EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
533223852d7SRamNalamothu }
534223852d7SRamNalamothu 
535f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) {
536f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
537f8122d35SGreg Clayton                                  /*Offset=*/0x0,
538f8122d35SGreg Clayton                                  /*Length=*/0xff);
539f8122d35SGreg Clayton 
540f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
541f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
542f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
543f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
544f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
545f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
546f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
547b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
548f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
549f8122d35SGreg Clayton 
550f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition.
551f8122d35SGreg Clayton   constexpr uint8_t Reg = 12;
552f8122d35SGreg Clayton   constexpr uint8_t Offset = 32;
553f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
554f8122d35SGreg Clayton                     Succeeded());
555f8122d35SGreg Clayton 
556f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
557f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
558f8122d35SGreg Clayton   // Here we encode two DW_CFA_set_loc opcodes:
559f8122d35SGreg Clayton   //   DW_CFA_set_loc(0x1100)
560f8122d35SGreg Clayton   //   DW_CFA_set_loc(0x1000)
561f8122d35SGreg Clayton   // These opcodes cause a new row to be appended to the rows in a UnwindTable
562f8122d35SGreg Clayton   // and the resulting rows are not in ascending address order and should cause
563f8122d35SGreg Clayton   // a state machine error.
564f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
565f8122d35SGreg Clayton       parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0,
566f8122d35SGreg Clayton                          dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}),
567f8122d35SGreg Clayton       Succeeded());
568f8122d35SGreg Clayton 
569f8122d35SGreg Clayton   // Verify we catch state machine error.
570f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
571f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
572f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which"
573f8122d35SGreg Clayton                                       " must be greater than the current row "
574f8122d35SGreg Clayton                                       "address 0x1100"));
575f8122d35SGreg Clayton }
576f8122d35SGreg Clayton 
577f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) {
578f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
579f8122d35SGreg Clayton                                  /*Offset=*/0x0,
580f8122d35SGreg Clayton                                  /*Length=*/0xff);
581f8122d35SGreg Clayton 
582f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
583f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
584f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
585f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
586f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
587f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
588f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
589b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
590f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
591f8122d35SGreg Clayton 
592f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition.
593f8122d35SGreg Clayton   constexpr uint8_t Reg = 12;
594f8122d35SGreg Clayton   constexpr uint8_t Offset = 32;
595f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
596f8122d35SGreg Clayton                     Succeeded());
597f8122d35SGreg Clayton 
598f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
599f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
600f8122d35SGreg Clayton   // Here we encode a DW_CFA_restore_state opcode that was not preceded by a
601f8122d35SGreg Clayton   // DW_CFA_remember_state, and an error should be returned.
602f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}),
603f8122d35SGreg Clayton                     Succeeded());
604f8122d35SGreg Clayton 
605f8122d35SGreg Clayton   // Verify we catch state machine error.
606f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
607f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
608f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_restore_state without a matching "
609f8122d35SGreg Clayton                                       "previous DW_CFA_remember_state"));
610f8122d35SGreg Clayton }
611f8122d35SGreg Clayton 
612f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) {
613f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
614f8122d35SGreg Clayton                                  /*Offset=*/0x0,
615f8122d35SGreg Clayton                                  /*Length=*/0xff);
616f8122d35SGreg Clayton 
617f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
618f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
619f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
620f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
621f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
622f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
623f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
624b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
625f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
626f8122d35SGreg Clayton 
627f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition.
628f8122d35SGreg Clayton   constexpr uint8_t Reg = 12;
629f8122d35SGreg Clayton   constexpr uint8_t Offset = 32;
630f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
631f8122d35SGreg Clayton                     Succeeded());
632f8122d35SGreg Clayton 
633f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
634f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
635f8122d35SGreg Clayton   // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not
636f8122d35SGreg Clayton   // found any documentation that describes what this does after some brief
637f8122d35SGreg Clayton   // searching.
638f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}),
639f8122d35SGreg Clayton                     Succeeded());
640f8122d35SGreg Clayton 
641f8122d35SGreg Clayton   // Verify we catch state machine error.
642f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
643f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
644f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA opcode 0x2d is not supported for "
645f8122d35SGreg Clayton                                       "architecture x86_64"));
646f8122d35SGreg Clayton }
647f8122d35SGreg Clayton 
648f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) {
649f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
650f8122d35SGreg Clayton                                  /*Offset=*/0x0,
651f8122d35SGreg Clayton                                  /*Length=*/0xff);
652f8122d35SGreg Clayton 
653f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
654f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
655f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
656f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
657f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
658f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
659f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
660b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
661f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
662f8122d35SGreg Clayton 
663f8122d35SGreg Clayton   // Make a CIE that has an invalid CFA definition. We do this so we can try
664f8122d35SGreg Clayton   // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate
665f8122d35SGreg Clayton   // error back.
666f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
667f8122d35SGreg Clayton 
668f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
669f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
670f8122d35SGreg Clayton   // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE
671f8122d35SGreg Clayton   // didn't define the CFA in terms of a register plus offset, so this should
672f8122d35SGreg Clayton   // cause an error.
673f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}),
674f8122d35SGreg Clayton                     Succeeded());
675f8122d35SGreg Clayton 
676f8122d35SGreg Clayton   // Verify we catch state machine error.
677f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
678f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
679f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_def_cfa_offset found when CFA "
680f8122d35SGreg Clayton                                       "rule was not RegPlusOffset"));
681f8122d35SGreg Clayton }
682f8122d35SGreg Clayton 
683f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) {
684f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
685f8122d35SGreg Clayton                                  /*Offset=*/0x0,
686f8122d35SGreg Clayton                                  /*Length=*/0xff);
687f8122d35SGreg Clayton 
688f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
689f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
690f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
691f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
692f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
693f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
694f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
695b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
696f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
697f8122d35SGreg Clayton 
698f8122d35SGreg Clayton   // Make a CIE that has an invalid CFA definition. We do this so we can try
699f8122d35SGreg Clayton   // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an
700f8122d35SGreg Clayton   // appropriate error back.
701f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
702f8122d35SGreg Clayton 
703f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
704f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
705f8122d35SGreg Clayton   // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE
706f8122d35SGreg Clayton   // didn't define the CFA in terms of a register plus offset, so this should
707f8122d35SGreg Clayton   // cause an error.
708f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}),
709f8122d35SGreg Clayton                     Succeeded());
710f8122d35SGreg Clayton 
711f8122d35SGreg Clayton   // Verify we catch state machine error.
712f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
713f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
714f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA "
715f8122d35SGreg Clayton                                       "rule was not RegPlusOffset"));
716f8122d35SGreg Clayton }
717f8122d35SGreg Clayton 
718f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) {
719f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
720f8122d35SGreg Clayton                                  /*Offset=*/0x0,
721f8122d35SGreg Clayton                                  /*Length=*/0xff);
722f8122d35SGreg Clayton 
723f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
724f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
725f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
726f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
727f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
728f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
729f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
730b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
731f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
732f8122d35SGreg Clayton 
733f8122d35SGreg Clayton   // Make a CIE that has only defines the CFA register with no offset. Some
734f8122d35SGreg Clayton   // architectures do this and we must ensure that we set the CFA value to be
735f8122d35SGreg Clayton   // equal to that register with no offset.
736f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
737f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}),
738f8122d35SGreg Clayton                     Succeeded());
739f8122d35SGreg Clayton 
740f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
741f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
742f8122d35SGreg Clayton   // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but
743f8122d35SGreg Clayton   // our CIE didn't define the CFA in terms of a register plus offset, so this
744f8122d35SGreg Clayton   // should cause an error.
745f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
746f8122d35SGreg Clayton 
747f8122d35SGreg Clayton   // Verify we catch state machine error.
748f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
749f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
750f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
751f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
752f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
753f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getCFAValue(),
754f8122d35SGreg Clayton             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0));
755f8122d35SGreg Clayton }
756f8122d35SGreg Clayton 
757f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) {
758f8122d35SGreg Clayton   // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable.
759f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
760f8122d35SGreg Clayton                                  /*Offset=*/0x0,
761f8122d35SGreg Clayton                                  /*Length=*/0xff);
762f8122d35SGreg Clayton 
763f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
764f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
765f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
766f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
767f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
768f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
769f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
770b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
771f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
772f8122d35SGreg Clayton 
773f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
774f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
775f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
776f8122d35SGreg Clayton   constexpr uint8_t CFAOffset = 32;
777f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
778f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
779f8122d35SGreg Clayton 
780f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
781f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
782f8122d35SGreg Clayton                     Succeeded());
783f8122d35SGreg Clayton 
784f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that use all of the
785f8122d35SGreg Clayton   // row pushing opcodes. This will verify that all opcodes that should create
786f8122d35SGreg Clayton   // a row are correctly working. Each opcode will push a row prior to
787f8122d35SGreg Clayton   // advancing the address, and then a row will be automatically pushed at the
788f8122d35SGreg Clayton   // end of the parsing, so we should end up with 6 rows starting at address
789f8122d35SGreg Clayton   // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor
790f8122d35SGreg Clayton   // from the CIE.
791f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4,
792f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc1,
793f8122d35SGreg Clayton                                        4,
794f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc2,
795f8122d35SGreg Clayton                                        4,
796f8122d35SGreg Clayton                                        0,
797f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc4,
798f8122d35SGreg Clayton                                        4,
799f8122d35SGreg Clayton                                        0,
800f8122d35SGreg Clayton                                        0,
801f8122d35SGreg Clayton                                        0,
802f8122d35SGreg Clayton                                        dwarf::DW_CFA_set_loc,
803f8122d35SGreg Clayton                                        0x14,
804f8122d35SGreg Clayton                                        0x10,
805f8122d35SGreg Clayton                                        0,
806f8122d35SGreg Clayton                                        0,
807f8122d35SGreg Clayton                                        0,
808f8122d35SGreg Clayton                                        0,
809f8122d35SGreg Clayton                                        0,
810f8122d35SGreg Clayton                                        0}),
811f8122d35SGreg Clayton                     Succeeded());
812f8122d35SGreg Clayton 
813f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
814f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
815f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
816f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
817f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
818f8122d35SGreg Clayton 
819f8122d35SGreg Clayton   // Verify we catch state machine error.
820f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
821f8122d35SGreg Clayton   ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
822f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
823f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 6u);
824f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
825f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
826f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
827f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
828f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
829f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
830f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
831f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
832f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
833f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
834f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
835f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
836f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
837f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
838f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
839f8122d35SGreg Clayton   EXPECT_EQ(Rows[5].getAddress(), 0x1014u);
840f8122d35SGreg Clayton   EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u);
841f8122d35SGreg Clayton   EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs);
842f8122d35SGreg Clayton }
843f8122d35SGreg Clayton 
844f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) {
845f8122d35SGreg Clayton   // Test that DW_CFA_restore works as expected when parsed in the state
846f8122d35SGreg Clayton   // machine.
847f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
848f8122d35SGreg Clayton                                  /*Offset=*/0x0,
849f8122d35SGreg Clayton                                  /*Length=*/0xff);
850f8122d35SGreg Clayton 
851f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
852f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
853f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
854f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
855f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
856f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
857f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
858b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
859f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
860f8122d35SGreg Clayton 
861f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
862f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
863f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
864f8122d35SGreg Clayton   constexpr uint8_t CFAOffset = 32;
865f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
866f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
867f8122d35SGreg Clayton   constexpr int32_t RegCFAOffset = -8;
868f8122d35SGreg Clayton 
869f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
870f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
871f8122d35SGreg Clayton                     Succeeded());
872f8122d35SGreg Clayton 
873f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the rule
874f8122d35SGreg Clayton   // for register "Reg" to be [CFA-8], then push a row, and then restore the
875f8122d35SGreg Clayton   // register unwind rule for "Reg" using DW_CFA_restore. We should end up with
876f8122d35SGreg Clayton   // two rows:
877f8122d35SGreg Clayton   //   - one with Reg = [CFA-8]
878f8122d35SGreg Clayton   //   - one with Reg = InReg
879f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1,
880f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc | 4,
881f8122d35SGreg Clayton                                        dwarf::DW_CFA_restore | Reg}),
882f8122d35SGreg Clayton                     Succeeded());
883f8122d35SGreg Clayton 
884f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
885f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
886f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs1;
887f8122d35SGreg Clayton   VerifyLocs1.setRegisterLocation(
888f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset));
889f8122d35SGreg Clayton 
890f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs2;
891f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
892f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
893f8122d35SGreg Clayton 
894f8122d35SGreg Clayton   // Verify we catch state machine error.
895f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
896f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
897f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
898f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 2u);
899f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
900f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
901f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
902f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
903f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
904f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
905f8122d35SGreg Clayton }
906f8122d35SGreg Clayton 
907f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) {
908f8122d35SGreg Clayton   // Test that DW_CFA_restore works as expected when parsed in the state
909f8122d35SGreg Clayton   // machine.
910f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
911f8122d35SGreg Clayton                                  /*Offset=*/0x0,
912f8122d35SGreg Clayton                                  /*Length=*/0xff);
913f8122d35SGreg Clayton 
914f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
915f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
916f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
917f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
918f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
919f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
920f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
921b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
922f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
923f8122d35SGreg Clayton 
924f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
925f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
926f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
927f8122d35SGreg Clayton   constexpr uint8_t CFAOffset = 32;
928f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
929f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
930f8122d35SGreg Clayton   constexpr int32_t RegCFAOffset = -8;
931f8122d35SGreg Clayton 
932f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
933f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
934f8122d35SGreg Clayton                     Succeeded());
935f8122d35SGreg Clayton 
936f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the rule
937f8122d35SGreg Clayton   // for register "Reg" to be [CFA-8], then push a row, and then restore the
938f8122d35SGreg Clayton   // register unwind rule for "Reg" using DW_CFA_restore_extended. We should
939f8122d35SGreg Clayton   // end up with two rows:
940f8122d35SGreg Clayton   //   - one with Reg = [CFA-8]
941f8122d35SGreg Clayton   //   - one with Reg = InReg
942f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1,
943f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc | 4,
944f8122d35SGreg Clayton                                        dwarf::DW_CFA_restore_extended, Reg}),
945f8122d35SGreg Clayton                     Succeeded());
946f8122d35SGreg Clayton 
947f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
948f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
949f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs1;
950f8122d35SGreg Clayton   VerifyLocs1.setRegisterLocation(
951f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset));
952f8122d35SGreg Clayton 
953f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs2;
954f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
955f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
956f8122d35SGreg Clayton 
957f8122d35SGreg Clayton   // Verify we catch state machine error.
958f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
959f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
960f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
961f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 2u);
962f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
963f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
964f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
965f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
966f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
967f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
968f8122d35SGreg Clayton }
969f8122d35SGreg Clayton 
970f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) {
971f8122d35SGreg Clayton   // Test that DW_CFA_offset, DW_CFA_offset_extended and
972f8122d35SGreg Clayton   // DW_CFA_offset_extended_sf work as expected when parsed in the state
973f8122d35SGreg Clayton   // machine.
974f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
975f8122d35SGreg Clayton                                  /*Offset=*/0x0,
976f8122d35SGreg Clayton                                  /*Length=*/0xff);
977f8122d35SGreg Clayton 
978f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
979f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
980f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
981f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
982f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
983f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
984f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
985b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
986f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
987f8122d35SGreg Clayton 
988f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
989f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
990f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
991f8122d35SGreg Clayton                     Succeeded());
992f8122d35SGreg Clayton 
993f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the
994f8122d35SGreg Clayton   // unwind rules for the follwing registers:
995f8122d35SGreg Clayton   //   Reg1 = [CFA-8]
996f8122d35SGreg Clayton   //   Reg2 = [CFA-16]
997f8122d35SGreg Clayton   //   Reg3 = [CFA+8]
998a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
999a1a3fdcdSGreg Clayton   constexpr uint8_t Reg2 = 15;
1000a1a3fdcdSGreg Clayton   constexpr uint8_t Reg3 = 16;
1001f8122d35SGreg Clayton   constexpr uint8_t Neg1SLEB = 0x7f;
1002f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1003f8122d35SGreg Clayton       parseCFI(TestFDE,
1004f8122d35SGreg Clayton                {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended,
1005f8122d35SGreg Clayton                 Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}),
1006f8122d35SGreg Clayton       Succeeded());
1007f8122d35SGreg Clayton 
1008f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1009f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1010f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1011f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1012f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1013f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1014f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1015f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1016f8122d35SGreg Clayton       Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8));
1017f8122d35SGreg Clayton 
1018f8122d35SGreg Clayton   // Verify we catch state machine error.
1019f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1020f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1021f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1022f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1023f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1024f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1025f8122d35SGreg Clayton }
1026f8122d35SGreg Clayton 
1027f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) {
1028f8122d35SGreg Clayton   // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when
1029f8122d35SGreg Clayton   // parsed in the state machine.
1030f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1031f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1032f8122d35SGreg Clayton                                  /*Length=*/0xff);
1033f8122d35SGreg Clayton 
1034f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1035f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1036f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1037f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1038f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1039f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1040f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1041b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
1042f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1043f8122d35SGreg Clayton 
1044f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1045f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1046f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1047f8122d35SGreg Clayton                     Succeeded());
1048f8122d35SGreg Clayton 
1049f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the
1050f8122d35SGreg Clayton   // unwind rules for the follwing registers:
1051f8122d35SGreg Clayton   //   Reg1 = [CFA-8]
1052f8122d35SGreg Clayton   //   Reg2 = [CFA-16]
1053f8122d35SGreg Clayton   //   Reg3 = [CFA+8]
1054a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1055a1a3fdcdSGreg Clayton   constexpr uint8_t Reg2 = 15;
1056f8122d35SGreg Clayton   constexpr uint8_t Neg1SLEB = 0x7f;
1057f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1058f8122d35SGreg Clayton       parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1,
1059f8122d35SGreg Clayton                          dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}),
1060f8122d35SGreg Clayton       Succeeded());
1061f8122d35SGreg Clayton 
1062f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1063f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1064f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1065f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1066f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8));
1067f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1068f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8));
1069f8122d35SGreg Clayton 
1070f8122d35SGreg Clayton   // Verify we catch state machine error.
1071f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1072f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1073f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1074f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1075f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1076f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1077f8122d35SGreg Clayton }
1078f8122d35SGreg Clayton 
1079f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) {
1080f8122d35SGreg Clayton   // Test that DW_CFA_nop works as expected when parsed in the state machine.
1081f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1082f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1083f8122d35SGreg Clayton                                  /*Length=*/0xff);
1084f8122d35SGreg Clayton 
1085f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1086f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1087f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1088f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1089f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1090f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1091f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1092b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
1093f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1094f8122d35SGreg Clayton 
1095f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1096f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1097f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1098f8122d35SGreg Clayton                     Succeeded());
1099f8122d35SGreg Clayton 
1100f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the
1101f8122d35SGreg Clayton   // unwind rules for the follwing registers:
1102f8122d35SGreg Clayton   //   Reg1 = [CFA-8]
1103f8122d35SGreg Clayton   // The opcodes for setting Reg1 are preceded by a DW_CFA_nop.
1104a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1105f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1106f8122d35SGreg Clayton       parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}),
1107f8122d35SGreg Clayton       Succeeded());
1108f8122d35SGreg Clayton 
1109f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1110f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1111f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1112f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1113f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1114f8122d35SGreg Clayton 
1115f8122d35SGreg Clayton   // Verify we catch state machine error.
1116f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1117f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1118f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1119f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1120f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1121f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1122f8122d35SGreg Clayton }
1123f8122d35SGreg Clayton 
1124f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) {
1125f8122d35SGreg Clayton   // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected
1126f8122d35SGreg Clayton   // when parsed in the state machine.
1127f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1128f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1129f8122d35SGreg Clayton                                  /*Length=*/0xff);
1130f8122d35SGreg Clayton 
1131f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1132f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1133f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1134f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1135f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1136f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1137f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1138b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
1139f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1140f8122d35SGreg Clayton 
1141f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1142f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
11437cf99347SAlexis Engelke   constexpr uint8_t CFAOff1 = 32;
11447cf99347SAlexis Engelke   constexpr uint8_t CFAOff2 = 16;
11457cf99347SAlexis Engelke   constexpr uint8_t Reg1 = 14;
11467cf99347SAlexis Engelke   constexpr uint8_t Reg2 = 15;
11477cf99347SAlexis Engelke   constexpr uint8_t Reg3 = 16;
11487cf99347SAlexis Engelke 
11497cf99347SAlexis Engelke   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, CFAOff1}),
1150f8122d35SGreg Clayton                     Succeeded());
1151f8122d35SGreg Clayton 
1152f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1153f8122d35SGreg Clayton   // follwing rows:
11547cf99347SAlexis Engelke   // 0x1000: CFA=reg12+CFAOff1: Reg1=[CFA-8]
11557cf99347SAlexis Engelke   // 0x1004: CFA=reg12+CFAOff1: Reg1=[CFA-8] Reg2=[CFA-16]
11567cf99347SAlexis Engelke   // 0x1008: CFA=reg12+CFAOff2: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24]
11577cf99347SAlexis Engelke   // 0x100C: CFA=reg12+CFAOff1: Reg1=[CFA-8] Reg2=[CFA-16]
11587cf99347SAlexis Engelke   // 0x1010: CFA=reg12+CFAOff1: Reg1=[CFA-8]
1159f8122d35SGreg Clayton   // This state machine will:
1160f8122d35SGreg Clayton   //  - set Reg1 location
1161f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1162f8122d35SGreg Clayton   //  - remember the state
1163f8122d35SGreg Clayton   //  - set Reg2 location
1164f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1165f8122d35SGreg Clayton   //  - remember the state
11667cf99347SAlexis Engelke   //  - set CFA offset to CFAOff2
1167f8122d35SGreg Clayton   //  - set Reg3 location
1168f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1169f8122d35SGreg Clayton   //  - remember the state where Reg1 and Reg2 were set
1170f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1171f8122d35SGreg Clayton   //  - remember the state where only Reg1 was set
1172f8122d35SGreg Clayton   //  - push a row (automatically at the end of instruction parsing)
1173f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1174f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1175f8122d35SGreg Clayton       parseCFI(TestFDE,
1176f8122d35SGreg Clayton                {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4,
1177f8122d35SGreg Clayton                 dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2,
1178f8122d35SGreg Clayton                 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state,
11797cf99347SAlexis Engelke                 dwarf::DW_CFA_def_cfa_offset, CFAOff2,
1180f8122d35SGreg Clayton                 dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4,
1181f8122d35SGreg Clayton                 dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4,
1182f8122d35SGreg Clayton                 dwarf::DW_CFA_restore_state}),
1183f8122d35SGreg Clayton       Succeeded());
1184f8122d35SGreg Clayton 
1185f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1186f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1187f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs1;
1188f8122d35SGreg Clayton   VerifyLocs1.setRegisterLocation(
1189f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1190f8122d35SGreg Clayton 
1191f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs2;
1192f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
1193f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1194f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
1195f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1196f8122d35SGreg Clayton 
1197f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs3;
1198f8122d35SGreg Clayton   VerifyLocs3.setRegisterLocation(
1199f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1200f8122d35SGreg Clayton   VerifyLocs3.setRegisterLocation(
1201f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1202f8122d35SGreg Clayton   VerifyLocs3.setRegisterLocation(
1203f8122d35SGreg Clayton       Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24));
1204f8122d35SGreg Clayton 
1205f8122d35SGreg Clayton   // Verify we catch state machine error.
1206f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1207f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1208f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1209f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 5u);
1210f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
12117cf99347SAlexis Engelke   EXPECT_EQ(Rows[0].getCFAValue(),
12127cf99347SAlexis Engelke             dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1));
1213f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
1214f8122d35SGreg Clayton 
1215f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
12167cf99347SAlexis Engelke   EXPECT_EQ(Rows[1].getCFAValue(),
12177cf99347SAlexis Engelke             dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1));
1218f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
1219f8122d35SGreg Clayton 
1220f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
12217cf99347SAlexis Engelke   EXPECT_EQ(Rows[2].getCFAValue(),
12227cf99347SAlexis Engelke             dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff2));
1223f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3);
1224f8122d35SGreg Clayton 
1225f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getAddress(), 0x100Cu);
12267cf99347SAlexis Engelke   EXPECT_EQ(Rows[3].getCFAValue(),
12277cf99347SAlexis Engelke             dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1));
1228f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2);
1229f8122d35SGreg Clayton 
1230f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
12317cf99347SAlexis Engelke   EXPECT_EQ(Rows[4].getCFAValue(),
12327cf99347SAlexis Engelke             dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1));
1233f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1);
1234f8122d35SGreg Clayton }
1235f8122d35SGreg Clayton 
1236f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) {
1237f8122d35SGreg Clayton   // Test that DW_CFA_undefined works as expected when parsed in the state
1238f8122d35SGreg Clayton   // machine.
1239f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1240f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1241f8122d35SGreg Clayton                                  /*Length=*/0xff);
1242f8122d35SGreg Clayton 
1243f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1244f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1245f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1246f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1247f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1248f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1249f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1250b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
1251f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1252f8122d35SGreg Clayton 
1253f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1254f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1255f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1256f8122d35SGreg Clayton                     Succeeded());
1257f8122d35SGreg Clayton 
1258f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1259f8122d35SGreg Clayton   // follwing rows:
1260f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=undefined
1261f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1262a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1263f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}),
1264f8122d35SGreg Clayton                     Succeeded());
1265f8122d35SGreg Clayton 
1266f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1267f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1268f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1269f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(Reg1,
1270f8122d35SGreg Clayton                                  dwarf::UnwindLocation::createUndefined());
1271f8122d35SGreg Clayton 
1272f8122d35SGreg Clayton   // Verify we catch state machine error.
1273f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1274f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1275f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1276f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1277f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1278f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1279f8122d35SGreg Clayton }
1280f8122d35SGreg Clayton 
1281f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) {
1282f8122d35SGreg Clayton   // Test that DW_CFA_same_value works as expected when parsed in the state
1283f8122d35SGreg Clayton   // machine.
1284f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1285f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1286f8122d35SGreg Clayton                                  /*Length=*/0xff);
1287f8122d35SGreg Clayton 
1288f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1289f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1290f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1291f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1292f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1293f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1294f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1295b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
1296f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1297f8122d35SGreg Clayton 
1298f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1299f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1300f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1301f8122d35SGreg Clayton                     Succeeded());
1302f8122d35SGreg Clayton 
1303f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1304f8122d35SGreg Clayton   // follwing rows:
1305f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=same
1306f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1307a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1308f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}),
1309f8122d35SGreg Clayton                     Succeeded());
1310f8122d35SGreg Clayton 
1311f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1312f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1313f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1314f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame());
1315f8122d35SGreg Clayton 
1316f8122d35SGreg Clayton   // Verify we catch state machine error.
1317f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1318f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1319f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1320f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1321f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1322f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1323f8122d35SGreg Clayton }
1324f8122d35SGreg Clayton 
1325f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) {
1326f8122d35SGreg Clayton   // Test that DW_CFA_register works as expected when parsed in the state
1327f8122d35SGreg Clayton   // machine.
1328f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1329f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1330f8122d35SGreg Clayton                                  /*Length=*/0xff);
1331f8122d35SGreg Clayton 
1332f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1333f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1334f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1335f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1336f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1337f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1338f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1339b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
1340f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1341f8122d35SGreg Clayton 
1342f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1343f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1344f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1345f8122d35SGreg Clayton                     Succeeded());
1346f8122d35SGreg Clayton 
1347f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1348f8122d35SGreg Clayton   // follwing rows:
1349f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=same
1350f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1351f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1352f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
1353f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}),
1354f8122d35SGreg Clayton                     Succeeded());
1355f8122d35SGreg Clayton 
1356f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1357f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1358f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1359f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1360f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1361f8122d35SGreg Clayton 
1362f8122d35SGreg Clayton   // Verify we catch state machine error.
1363f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1364f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1365f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1366f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1367f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1368f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1369f8122d35SGreg Clayton }
1370f8122d35SGreg Clayton 
1371f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) {
1372f8122d35SGreg Clayton   // Test that DW_CFA_expression works as expected when parsed in the state
1373f8122d35SGreg Clayton   // machine.
1374f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1375f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1376f8122d35SGreg Clayton                                  /*Length=*/0xff);
1377f8122d35SGreg Clayton 
1378f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1379f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1380f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1381f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1382f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1383f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1384f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1385b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
1386f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1387f8122d35SGreg Clayton 
1388f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1389f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1390f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1391f8122d35SGreg Clayton                     Succeeded());
1392f8122d35SGreg Clayton 
1393f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1394f8122d35SGreg Clayton   // follwing rows:
1395f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1396f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1397f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1398f8122d35SGreg Clayton   constexpr uint8_t AddrSize = 8;
1399f8122d35SGreg Clayton   std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1,
1400f8122d35SGreg Clayton                                    dwarf::DW_OP_reg12};
1401f8122d35SGreg Clayton 
1402f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded());
1403f8122d35SGreg Clayton 
1404f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1405f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1406f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1407f8122d35SGreg Clayton 
1408f8122d35SGreg Clayton   std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12};
1409f8122d35SGreg Clayton   DataExtractor ExprData(ExprBytes, true, AddrSize);
1410f8122d35SGreg Clayton   DWARFExpression Expr(ExprData, AddrSize);
1411f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1412f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr));
1413f8122d35SGreg Clayton 
1414f8122d35SGreg Clayton   // Verify we catch state machine error.
1415f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1416f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1417f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1418f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1419f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1420f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1421f8122d35SGreg Clayton }
1422f8122d35SGreg Clayton 
1423f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) {
1424f8122d35SGreg Clayton   // Test that DW_CFA_val_expression works as expected when parsed in the state
1425f8122d35SGreg Clayton   // machine.
1426f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1427f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1428f8122d35SGreg Clayton                                  /*Length=*/0xff);
1429f8122d35SGreg Clayton 
1430f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1431f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1432f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1433f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1434f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1435f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1436f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1437b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
1438f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1439f8122d35SGreg Clayton 
1440f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1441f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1442f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1443f8122d35SGreg Clayton                     Succeeded());
1444f8122d35SGreg Clayton 
1445f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1446f8122d35SGreg Clayton   // follwing rows:
1447f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1448f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1449f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1450f8122d35SGreg Clayton   constexpr uint8_t AddrSize = 8;
1451f8122d35SGreg Clayton   std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1,
1452f8122d35SGreg Clayton                                    dwarf::DW_OP_reg12};
1453f8122d35SGreg Clayton 
1454f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded());
1455f8122d35SGreg Clayton 
1456f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1457f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1458f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1459f8122d35SGreg Clayton 
1460f8122d35SGreg Clayton   std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12};
1461f8122d35SGreg Clayton   DataExtractor ExprData(ExprBytes, true, AddrSize);
1462f8122d35SGreg Clayton   DWARFExpression Expr(ExprData, AddrSize);
1463f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1464f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr));
1465f8122d35SGreg Clayton 
1466f8122d35SGreg Clayton   // Verify we catch state machine error.
1467f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1468f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1469f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1470f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1471f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1472f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1473f8122d35SGreg Clayton }
1474f8122d35SGreg Clayton 
1475f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) {
1476f8122d35SGreg Clayton   // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register,
1477f8122d35SGreg Clayton   // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when
1478f8122d35SGreg Clayton   // parsed in the state machine.
1479f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1480f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1481f8122d35SGreg Clayton                                  /*Length=*/0xff);
1482f8122d35SGreg Clayton 
1483f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1484f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1485f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1486f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1487f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1488f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1489f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1490b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
1491f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1492f8122d35SGreg Clayton 
1493f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1494f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1495f8122d35SGreg Clayton   constexpr uint8_t CFAReg1 = 12;
1496f8122d35SGreg Clayton   constexpr uint8_t CFAOff1 = 32;
1497f8122d35SGreg Clayton   constexpr uint8_t CFAReg2 = 13;
1498f8122d35SGreg Clayton   constexpr uint8_t CFAOff2 = 48;
1499f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1500f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
1501f8122d35SGreg Clayton 
1502f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1,
1503f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
1504f8122d35SGreg Clayton                     Succeeded());
1505f8122d35SGreg Clayton 
1506f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that use all of the
1507f8122d35SGreg Clayton   // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1508f8122d35SGreg Clayton   // create a row are correctly working.
1509f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1510f8122d35SGreg Clayton       parseCFI(
1511f8122d35SGreg Clayton           TestFDE,
1512f8122d35SGreg Clayton           {
1513f8122d35SGreg Clayton               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register,
1514f8122d35SGreg Clayton               CFAReg2, dwarf::DW_CFA_advance_loc | 4,
1515f8122d35SGreg Clayton               dwarf::DW_CFA_def_cfa_offset, CFAOff2,
1516f8122d35SGreg Clayton               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf,
1517f8122d35SGreg Clayton               0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1518f8122d35SGreg Clayton               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1,
1519f8122d35SGreg Clayton               0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1520f8122d35SGreg Clayton           }),
1521f8122d35SGreg Clayton       Succeeded());
1522f8122d35SGreg Clayton 
1523f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1524f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1525f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1526f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1527f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1528f8122d35SGreg Clayton 
1529f8122d35SGreg Clayton   // Verify we catch state machine error.
1530f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1531f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1532f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1533f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 5u);
1534f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1535f8122d35SGreg Clayton   EXPECT_EQ(
1536f8122d35SGreg Clayton       Rows[0].getCFAValue(),
1537f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1));
1538f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
1539f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1540f8122d35SGreg Clayton 
1541f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
1542f8122d35SGreg Clayton   EXPECT_EQ(
1543f8122d35SGreg Clayton       Rows[1].getCFAValue(),
1544f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1));
1545f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
1546f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
1547f8122d35SGreg Clayton 
1548f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
1549f8122d35SGreg Clayton   EXPECT_EQ(
1550f8122d35SGreg Clayton       Rows[2].getCFAValue(),
1551f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2));
1552f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
1553f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
1554f8122d35SGreg Clayton 
1555f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
1556f8122d35SGreg Clayton   EXPECT_EQ(
1557f8122d35SGreg Clayton       Rows[3].getCFAValue(),
1558f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1));
1559f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
1560f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
1561f8122d35SGreg Clayton 
1562f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
1563f8122d35SGreg Clayton   EXPECT_EQ(
1564f8122d35SGreg Clayton       Rows[4].getCFAValue(),
1565f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2));
1566f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
1567f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
1568f8122d35SGreg Clayton }
1569f8122d35SGreg Clayton 
1570167e7afcSRamNalamothu TEST(DWARFDebugFrame, UnwindTable_DW_CFA_LLVM_def_aspace_cfa) {
1571167e7afcSRamNalamothu   // Test that DW_CFA_LLVM_def_aspace_cfa, DW_CFA_LLVM_def_aspace_cfa_sf,
1572167e7afcSRamNalamothu   // DW_CFA_def_cfa_register, DW_CFA_def_cfa_offset, and
1573167e7afcSRamNalamothu   // DW_CFA_def_cfa_offset_sf works as expected when parsed in the state
1574167e7afcSRamNalamothu   // machine.
1575167e7afcSRamNalamothu   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1576167e7afcSRamNalamothu                                  /*Offset=*/0x0,
1577167e7afcSRamNalamothu                                  /*Length=*/0xff);
1578167e7afcSRamNalamothu 
1579167e7afcSRamNalamothu   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1580167e7afcSRamNalamothu                      /*Offset=*/0x3333abcdabcd,
1581167e7afcSRamNalamothu                      /*Length=*/0x4444abcdabcd,
1582167e7afcSRamNalamothu                      /*CIEPointer=*/0x1111abcdabcd,
1583167e7afcSRamNalamothu                      /*InitialLocation=*/0x1000,
1584167e7afcSRamNalamothu                      /*AddressRange=*/0x1000,
1585167e7afcSRamNalamothu                      /*Cie=*/&TestCIE,
1586b6a01caaSKazu Hirata                      /*LSDAAddress=*/std::nullopt,
1587167e7afcSRamNalamothu                      /*Arch=*/Triple::x86_64);
1588167e7afcSRamNalamothu 
1589167e7afcSRamNalamothu   // Make a CIE that has a valid CFA definition and a single register unwind
1590167e7afcSRamNalamothu   // rule for register that we will verify is in all of the pushed rows.
1591167e7afcSRamNalamothu   constexpr uint8_t CFAReg1 = 12;
1592167e7afcSRamNalamothu   constexpr uint8_t CFAOff1 = 32;
1593167e7afcSRamNalamothu   constexpr uint8_t CFAReg2 = 13;
1594167e7afcSRamNalamothu   constexpr uint8_t CFAOff2 = 48;
1595167e7afcSRamNalamothu   constexpr uint8_t Reg = 13;
1596167e7afcSRamNalamothu   constexpr uint8_t InReg = 14;
1597167e7afcSRamNalamothu   constexpr uint8_t AddrSpace = 2;
1598167e7afcSRamNalamothu 
1599167e7afcSRamNalamothu   EXPECT_THAT_ERROR(
1600167e7afcSRamNalamothu       parseCFI(TestCIE, {dwarf::DW_CFA_LLVM_def_aspace_cfa, CFAReg1, CFAOff1,
1601167e7afcSRamNalamothu                          AddrSpace, dwarf::DW_CFA_register, Reg, InReg}),
1602167e7afcSRamNalamothu       Succeeded());
1603167e7afcSRamNalamothu 
1604167e7afcSRamNalamothu   // Make a FDE with DWARF call frame instruction opcodes that use all of the
1605167e7afcSRamNalamothu   // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1606167e7afcSRamNalamothu   // create a row are correctly working.
1607167e7afcSRamNalamothu   EXPECT_THAT_ERROR(
1608167e7afcSRamNalamothu       parseCFI(
1609167e7afcSRamNalamothu           TestFDE,
1610167e7afcSRamNalamothu           {
1611167e7afcSRamNalamothu               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register,
1612167e7afcSRamNalamothu               CFAReg2, dwarf::DW_CFA_advance_loc | 4,
1613167e7afcSRamNalamothu               dwarf::DW_CFA_def_cfa_offset, CFAOff2,
1614167e7afcSRamNalamothu               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf,
1615167e7afcSRamNalamothu               0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1616167e7afcSRamNalamothu               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1,
1617167e7afcSRamNalamothu               0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1618167e7afcSRamNalamothu           }),
1619167e7afcSRamNalamothu       Succeeded());
1620167e7afcSRamNalamothu 
1621167e7afcSRamNalamothu   // Create locations that we expect the UnwindRow objects to contain after
1622167e7afcSRamNalamothu   // parsing the DWARF call frame instructions.
1623167e7afcSRamNalamothu   dwarf::RegisterLocations VerifyLocs;
1624167e7afcSRamNalamothu   VerifyLocs.setRegisterLocation(
1625167e7afcSRamNalamothu       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1626167e7afcSRamNalamothu 
1627167e7afcSRamNalamothu   // Verify we catch state machine error.
1628167e7afcSRamNalamothu   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1629167e7afcSRamNalamothu   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1630167e7afcSRamNalamothu   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1631167e7afcSRamNalamothu   EXPECT_EQ(Rows.size(), 5u);
1632167e7afcSRamNalamothu   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1633167e7afcSRamNalamothu   EXPECT_EQ(Rows[0].getCFAValue(),
1634167e7afcSRamNalamothu             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1,
1635167e7afcSRamNalamothu                                                               AddrSpace));
1636167e7afcSRamNalamothu   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
1637167e7afcSRamNalamothu   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1638167e7afcSRamNalamothu 
1639167e7afcSRamNalamothu   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
1640167e7afcSRamNalamothu   EXPECT_EQ(Rows[1].getCFAValue(),
1641167e7afcSRamNalamothu             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1,
1642167e7afcSRamNalamothu                                                               AddrSpace));
1643167e7afcSRamNalamothu   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
1644167e7afcSRamNalamothu   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
1645167e7afcSRamNalamothu 
1646167e7afcSRamNalamothu   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
1647167e7afcSRamNalamothu   EXPECT_EQ(Rows[2].getCFAValue(),
1648167e7afcSRamNalamothu             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2,
1649167e7afcSRamNalamothu                                                               AddrSpace));
1650167e7afcSRamNalamothu   EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
1651167e7afcSRamNalamothu   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
1652167e7afcSRamNalamothu 
1653167e7afcSRamNalamothu   EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
1654167e7afcSRamNalamothu   EXPECT_EQ(Rows[3].getCFAValue(),
1655167e7afcSRamNalamothu             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1,
1656167e7afcSRamNalamothu                                                               AddrSpace));
1657167e7afcSRamNalamothu   EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
1658167e7afcSRamNalamothu   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
1659167e7afcSRamNalamothu 
1660167e7afcSRamNalamothu   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
1661167e7afcSRamNalamothu   EXPECT_EQ(Rows[4].getCFAValue(),
1662167e7afcSRamNalamothu             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2,
1663167e7afcSRamNalamothu                                                               AddrSpace));
1664167e7afcSRamNalamothu   EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
1665167e7afcSRamNalamothu   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
1666167e7afcSRamNalamothu }
1667167e7afcSRamNalamothu 
1668cada5b88SIgor Kudrin } // end anonymous namespace
1669