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