xref: /llvm-project/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp (revision a1a3fdcdba52c9d0a045af5f68365c273467b127)
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;
346*a1a3fdcdSGreg 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 
450f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) {
451f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
452f8122d35SGreg Clayton                                  /*Offset=*/0x0,
453f8122d35SGreg Clayton                                  /*Length=*/0xff);
454f8122d35SGreg Clayton 
455f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
456f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
457f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
458f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
459f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
460f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
461f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
462f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
463f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
464f8122d35SGreg Clayton 
465f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition.
466f8122d35SGreg Clayton   constexpr uint8_t Reg = 12;
467f8122d35SGreg Clayton   constexpr uint8_t Offset = 32;
468f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
469f8122d35SGreg Clayton                     Succeeded());
470f8122d35SGreg Clayton 
471f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
472f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
473f8122d35SGreg Clayton   // Here we encode two DW_CFA_set_loc opcodes:
474f8122d35SGreg Clayton   //   DW_CFA_set_loc(0x1100)
475f8122d35SGreg Clayton   //   DW_CFA_set_loc(0x1000)
476f8122d35SGreg Clayton   // These opcodes cause a new row to be appended to the rows in a UnwindTable
477f8122d35SGreg Clayton   // and the resulting rows are not in ascending address order and should cause
478f8122d35SGreg Clayton   // a state machine error.
479f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
480f8122d35SGreg Clayton       parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0,
481f8122d35SGreg Clayton                          dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}),
482f8122d35SGreg Clayton       Succeeded());
483f8122d35SGreg Clayton 
484f8122d35SGreg Clayton   // Verify we catch state machine error.
485f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
486f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
487f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which"
488f8122d35SGreg Clayton                                       " must be greater than the current row "
489f8122d35SGreg Clayton                                       "address 0x1100"));
490f8122d35SGreg Clayton }
491f8122d35SGreg Clayton 
492f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) {
493f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
494f8122d35SGreg Clayton                                  /*Offset=*/0x0,
495f8122d35SGreg Clayton                                  /*Length=*/0xff);
496f8122d35SGreg Clayton 
497f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
498f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
499f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
500f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
501f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
502f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
503f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
504f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
505f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
506f8122d35SGreg Clayton 
507f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition.
508f8122d35SGreg Clayton   constexpr uint8_t Reg = 12;
509f8122d35SGreg Clayton   constexpr uint8_t Offset = 32;
510f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
511f8122d35SGreg Clayton                     Succeeded());
512f8122d35SGreg Clayton 
513f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
514f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
515f8122d35SGreg Clayton   // Here we encode a DW_CFA_restore_state opcode that was not preceded by a
516f8122d35SGreg Clayton   // DW_CFA_remember_state, and an error should be returned.
517f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}),
518f8122d35SGreg Clayton                     Succeeded());
519f8122d35SGreg Clayton 
520f8122d35SGreg Clayton   // Verify we catch state machine error.
521f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
522f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
523f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_restore_state without a matching "
524f8122d35SGreg Clayton                                       "previous DW_CFA_remember_state"));
525f8122d35SGreg Clayton }
526f8122d35SGreg Clayton 
527f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) {
528f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
529f8122d35SGreg Clayton                                  /*Offset=*/0x0,
530f8122d35SGreg Clayton                                  /*Length=*/0xff);
531f8122d35SGreg Clayton 
532f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
533f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
534f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
535f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
536f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
537f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
538f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
539f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
540f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
541f8122d35SGreg Clayton 
542f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition.
543f8122d35SGreg Clayton   constexpr uint8_t Reg = 12;
544f8122d35SGreg Clayton   constexpr uint8_t Offset = 32;
545f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
546f8122d35SGreg Clayton                     Succeeded());
547f8122d35SGreg Clayton 
548f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
549f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
550f8122d35SGreg Clayton   // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not
551f8122d35SGreg Clayton   // found any documentation that describes what this does after some brief
552f8122d35SGreg Clayton   // searching.
553f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}),
554f8122d35SGreg Clayton                     Succeeded());
555f8122d35SGreg Clayton 
556f8122d35SGreg Clayton   // Verify we catch state machine error.
557f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
558f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
559f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA opcode 0x2d is not supported for "
560f8122d35SGreg Clayton                                       "architecture x86_64"));
561f8122d35SGreg Clayton }
562f8122d35SGreg Clayton 
563f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) {
564f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
565f8122d35SGreg Clayton                                  /*Offset=*/0x0,
566f8122d35SGreg Clayton                                  /*Length=*/0xff);
567f8122d35SGreg Clayton 
568f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
569f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
570f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
571f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
572f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
573f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
574f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
575f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
576f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
577f8122d35SGreg Clayton 
578f8122d35SGreg Clayton   // Make a CIE that has an invalid CFA definition. We do this so we can try
579f8122d35SGreg Clayton   // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate
580f8122d35SGreg Clayton   // error back.
581f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
582f8122d35SGreg Clayton 
583f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
584f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
585f8122d35SGreg Clayton   // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE
586f8122d35SGreg Clayton   // didn't define the CFA in terms of a register plus offset, so this should
587f8122d35SGreg Clayton   // cause an error.
588f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}),
589f8122d35SGreg Clayton                     Succeeded());
590f8122d35SGreg Clayton 
591f8122d35SGreg Clayton   // Verify we catch state machine error.
592f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
593f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
594f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_def_cfa_offset found when CFA "
595f8122d35SGreg Clayton                                       "rule was not RegPlusOffset"));
596f8122d35SGreg Clayton }
597f8122d35SGreg Clayton 
598f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) {
599f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
600f8122d35SGreg Clayton                                  /*Offset=*/0x0,
601f8122d35SGreg Clayton                                  /*Length=*/0xff);
602f8122d35SGreg Clayton 
603f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
604f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
605f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
606f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
607f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
608f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
609f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
610f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
611f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
612f8122d35SGreg Clayton 
613f8122d35SGreg Clayton   // Make a CIE that has an invalid CFA definition. We do this so we can try
614f8122d35SGreg Clayton   // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an
615f8122d35SGreg Clayton   // appropriate error back.
616f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
617f8122d35SGreg Clayton 
618f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
619f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
620f8122d35SGreg Clayton   // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE
621f8122d35SGreg Clayton   // didn't define the CFA in terms of a register plus offset, so this should
622f8122d35SGreg Clayton   // cause an error.
623f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}),
624f8122d35SGreg Clayton                     Succeeded());
625f8122d35SGreg Clayton 
626f8122d35SGreg Clayton   // Verify we catch state machine error.
627f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
628f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
629f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA "
630f8122d35SGreg Clayton                                       "rule was not RegPlusOffset"));
631f8122d35SGreg Clayton }
632f8122d35SGreg Clayton 
633f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) {
634f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
635f8122d35SGreg Clayton                                  /*Offset=*/0x0,
636f8122d35SGreg Clayton                                  /*Length=*/0xff);
637f8122d35SGreg Clayton 
638f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
639f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
640f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
641f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
642f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
643f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
644f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
645f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
646f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
647f8122d35SGreg Clayton 
648f8122d35SGreg Clayton   // Make a CIE that has only defines the CFA register with no offset. Some
649f8122d35SGreg Clayton   // architectures do this and we must ensure that we set the CFA value to be
650f8122d35SGreg Clayton   // equal to that register with no offset.
651f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
652f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}),
653f8122d35SGreg Clayton                     Succeeded());
654f8122d35SGreg Clayton 
655f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
656f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
657f8122d35SGreg Clayton   // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but
658f8122d35SGreg Clayton   // our CIE didn't define the CFA in terms of a register plus offset, so this
659f8122d35SGreg Clayton   // should cause an error.
660f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
661f8122d35SGreg Clayton 
662f8122d35SGreg Clayton   // Verify we catch state machine error.
663f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
664f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
665f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
666f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
667f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
668f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getCFAValue(),
669f8122d35SGreg Clayton             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0));
670f8122d35SGreg Clayton }
671f8122d35SGreg Clayton 
672f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) {
673f8122d35SGreg Clayton   // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable.
674f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
675f8122d35SGreg Clayton                                  /*Offset=*/0x0,
676f8122d35SGreg Clayton                                  /*Length=*/0xff);
677f8122d35SGreg Clayton 
678f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
679f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
680f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
681f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
682f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
683f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
684f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
685f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
686f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
687f8122d35SGreg Clayton 
688f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
689f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
690f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
691f8122d35SGreg Clayton   constexpr uint8_t CFAOffset = 32;
692f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
693f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
694f8122d35SGreg Clayton 
695f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
696f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
697f8122d35SGreg Clayton                     Succeeded());
698f8122d35SGreg Clayton 
699f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that use all of the
700f8122d35SGreg Clayton   // row pushing opcodes. This will verify that all opcodes that should create
701f8122d35SGreg Clayton   // a row are correctly working. Each opcode will push a row prior to
702f8122d35SGreg Clayton   // advancing the address, and then a row will be automatically pushed at the
703f8122d35SGreg Clayton   // end of the parsing, so we should end up with 6 rows starting at address
704f8122d35SGreg Clayton   // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor
705f8122d35SGreg Clayton   // from the CIE.
706f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4,
707f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc1,
708f8122d35SGreg Clayton                                        4,
709f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc2,
710f8122d35SGreg Clayton                                        4,
711f8122d35SGreg Clayton                                        0,
712f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc4,
713f8122d35SGreg Clayton                                        4,
714f8122d35SGreg Clayton                                        0,
715f8122d35SGreg Clayton                                        0,
716f8122d35SGreg Clayton                                        0,
717f8122d35SGreg Clayton                                        dwarf::DW_CFA_set_loc,
718f8122d35SGreg Clayton                                        0x14,
719f8122d35SGreg Clayton                                        0x10,
720f8122d35SGreg Clayton                                        0,
721f8122d35SGreg Clayton                                        0,
722f8122d35SGreg Clayton                                        0,
723f8122d35SGreg Clayton                                        0,
724f8122d35SGreg Clayton                                        0,
725f8122d35SGreg Clayton                                        0}),
726f8122d35SGreg Clayton                     Succeeded());
727f8122d35SGreg Clayton 
728f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
729f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
730f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
731f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
732f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
733f8122d35SGreg Clayton 
734f8122d35SGreg Clayton   // Verify we catch state machine error.
735f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
736f8122d35SGreg Clayton   ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
737f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
738f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 6u);
739f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
740f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
741f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
742f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
743f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
744f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
745f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
746f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
747f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
748f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
749f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
750f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
751f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
752f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
753f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
754f8122d35SGreg Clayton   EXPECT_EQ(Rows[5].getAddress(), 0x1014u);
755f8122d35SGreg Clayton   EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u);
756f8122d35SGreg Clayton   EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs);
757f8122d35SGreg Clayton }
758f8122d35SGreg Clayton 
759f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) {
760f8122d35SGreg Clayton   // Test that DW_CFA_restore works as expected when parsed in the state
761f8122d35SGreg Clayton   // machine.
762f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
763f8122d35SGreg Clayton                                  /*Offset=*/0x0,
764f8122d35SGreg Clayton                                  /*Length=*/0xff);
765f8122d35SGreg Clayton 
766f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
767f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
768f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
769f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
770f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
771f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
772f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
773f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
774f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
775f8122d35SGreg Clayton 
776f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
777f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
778f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
779f8122d35SGreg Clayton   constexpr uint8_t CFAOffset = 32;
780f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
781f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
782f8122d35SGreg Clayton   constexpr int32_t RegCFAOffset = -8;
783f8122d35SGreg Clayton 
784f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
785f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
786f8122d35SGreg Clayton                     Succeeded());
787f8122d35SGreg Clayton 
788f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the rule
789f8122d35SGreg Clayton   // for register "Reg" to be [CFA-8], then push a row, and then restore the
790f8122d35SGreg Clayton   // register unwind rule for "Reg" using DW_CFA_restore. We should end up with
791f8122d35SGreg Clayton   // two rows:
792f8122d35SGreg Clayton   //   - one with Reg = [CFA-8]
793f8122d35SGreg Clayton   //   - one with Reg = InReg
794f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1,
795f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc | 4,
796f8122d35SGreg Clayton                                        dwarf::DW_CFA_restore | Reg}),
797f8122d35SGreg Clayton                     Succeeded());
798f8122d35SGreg Clayton 
799f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
800f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
801f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs1;
802f8122d35SGreg Clayton   VerifyLocs1.setRegisterLocation(
803f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset));
804f8122d35SGreg Clayton 
805f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs2;
806f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
807f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
808f8122d35SGreg Clayton 
809f8122d35SGreg Clayton   // Verify we catch state machine error.
810f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
811f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
812f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
813f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 2u);
814f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
815f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
816f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
817f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
818f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
819f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
820f8122d35SGreg Clayton }
821f8122d35SGreg Clayton 
822f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) {
823f8122d35SGreg Clayton   // Test that DW_CFA_restore works as expected when parsed in the state
824f8122d35SGreg Clayton   // machine.
825f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
826f8122d35SGreg Clayton                                  /*Offset=*/0x0,
827f8122d35SGreg Clayton                                  /*Length=*/0xff);
828f8122d35SGreg Clayton 
829f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
830f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
831f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
832f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
833f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
834f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
835f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
836f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
837f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
838f8122d35SGreg Clayton 
839f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
840f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
841f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
842f8122d35SGreg Clayton   constexpr uint8_t CFAOffset = 32;
843f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
844f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
845f8122d35SGreg Clayton   constexpr int32_t RegCFAOffset = -8;
846f8122d35SGreg Clayton 
847f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
848f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
849f8122d35SGreg Clayton                     Succeeded());
850f8122d35SGreg Clayton 
851f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the rule
852f8122d35SGreg Clayton   // for register "Reg" to be [CFA-8], then push a row, and then restore the
853f8122d35SGreg Clayton   // register unwind rule for "Reg" using DW_CFA_restore_extended. We should
854f8122d35SGreg Clayton   // end up with two rows:
855f8122d35SGreg Clayton   //   - one with Reg = [CFA-8]
856f8122d35SGreg Clayton   //   - one with Reg = InReg
857f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1,
858f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc | 4,
859f8122d35SGreg Clayton                                        dwarf::DW_CFA_restore_extended, Reg}),
860f8122d35SGreg Clayton                     Succeeded());
861f8122d35SGreg Clayton 
862f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
863f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
864f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs1;
865f8122d35SGreg Clayton   VerifyLocs1.setRegisterLocation(
866f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset));
867f8122d35SGreg Clayton 
868f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs2;
869f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
870f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
871f8122d35SGreg Clayton 
872f8122d35SGreg Clayton   // Verify we catch state machine error.
873f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
874f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
875f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
876f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 2u);
877f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
878f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
879f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
880f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
881f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
882f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
883f8122d35SGreg Clayton }
884f8122d35SGreg Clayton 
885f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) {
886f8122d35SGreg Clayton   // Test that DW_CFA_offset, DW_CFA_offset_extended and
887f8122d35SGreg Clayton   // DW_CFA_offset_extended_sf work as expected when parsed in the state
888f8122d35SGreg Clayton   // machine.
889f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
890f8122d35SGreg Clayton                                  /*Offset=*/0x0,
891f8122d35SGreg Clayton                                  /*Length=*/0xff);
892f8122d35SGreg Clayton 
893f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
894f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
895f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
896f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
897f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
898f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
899f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
900f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
901f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
902f8122d35SGreg Clayton 
903f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
904f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
905f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
906f8122d35SGreg Clayton                     Succeeded());
907f8122d35SGreg Clayton 
908f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the
909f8122d35SGreg Clayton   // unwind rules for the follwing registers:
910f8122d35SGreg Clayton   //   Reg1 = [CFA-8]
911f8122d35SGreg Clayton   //   Reg2 = [CFA-16]
912f8122d35SGreg Clayton   //   Reg3 = [CFA+8]
913*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
914*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg2 = 15;
915*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg3 = 16;
916f8122d35SGreg Clayton   constexpr uint8_t Neg1SLEB = 0x7f;
917f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
918f8122d35SGreg Clayton       parseCFI(TestFDE,
919f8122d35SGreg Clayton                {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended,
920f8122d35SGreg Clayton                 Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}),
921f8122d35SGreg Clayton       Succeeded());
922f8122d35SGreg Clayton 
923f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
924f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
925f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
926f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
927f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
928f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
929f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
930f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
931f8122d35SGreg Clayton       Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8));
932f8122d35SGreg Clayton 
933f8122d35SGreg Clayton   // Verify we catch state machine error.
934f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
935f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
936f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
937f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
938f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
939f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
940f8122d35SGreg Clayton }
941f8122d35SGreg Clayton 
942f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) {
943f8122d35SGreg Clayton   // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when
944f8122d35SGreg Clayton   // parsed in the state machine.
945f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
946f8122d35SGreg Clayton                                  /*Offset=*/0x0,
947f8122d35SGreg Clayton                                  /*Length=*/0xff);
948f8122d35SGreg Clayton 
949f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
950f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
951f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
952f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
953f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
954f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
955f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
956f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
957f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
958f8122d35SGreg Clayton 
959f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
960f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
961f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
962f8122d35SGreg Clayton                     Succeeded());
963f8122d35SGreg Clayton 
964f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the
965f8122d35SGreg Clayton   // unwind rules for the follwing registers:
966f8122d35SGreg Clayton   //   Reg1 = [CFA-8]
967f8122d35SGreg Clayton   //   Reg2 = [CFA-16]
968f8122d35SGreg Clayton   //   Reg3 = [CFA+8]
969*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
970*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg2 = 15;
971f8122d35SGreg Clayton   constexpr uint8_t Neg1SLEB = 0x7f;
972f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
973f8122d35SGreg Clayton       parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1,
974f8122d35SGreg Clayton                          dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}),
975f8122d35SGreg Clayton       Succeeded());
976f8122d35SGreg Clayton 
977f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
978f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
979f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
980f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
981f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8));
982f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
983f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8));
984f8122d35SGreg Clayton 
985f8122d35SGreg Clayton   // Verify we catch state machine error.
986f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
987f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
988f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
989f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
990f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
991f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
992f8122d35SGreg Clayton }
993f8122d35SGreg Clayton 
994f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) {
995f8122d35SGreg Clayton   // Test that DW_CFA_nop works as expected when parsed in the state machine.
996f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
997f8122d35SGreg Clayton                                  /*Offset=*/0x0,
998f8122d35SGreg Clayton                                  /*Length=*/0xff);
999f8122d35SGreg Clayton 
1000f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1001f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1002f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1003f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1004f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1005f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1006f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1007f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1008f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1009f8122d35SGreg Clayton 
1010f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1011f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1012f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1013f8122d35SGreg Clayton                     Succeeded());
1014f8122d35SGreg Clayton 
1015f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the
1016f8122d35SGreg Clayton   // unwind rules for the follwing registers:
1017f8122d35SGreg Clayton   //   Reg1 = [CFA-8]
1018f8122d35SGreg Clayton   // The opcodes for setting Reg1 are preceded by a DW_CFA_nop.
1019*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1020f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1021f8122d35SGreg Clayton       parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}),
1022f8122d35SGreg Clayton       Succeeded());
1023f8122d35SGreg Clayton 
1024f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1025f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1026f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1027f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1028f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1029f8122d35SGreg Clayton 
1030f8122d35SGreg Clayton   // Verify we catch state machine error.
1031f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1032f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1033f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1034f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1035f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1036f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1037f8122d35SGreg Clayton }
1038f8122d35SGreg Clayton 
1039f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) {
1040f8122d35SGreg Clayton   // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected
1041f8122d35SGreg Clayton   // when parsed in the state machine.
1042f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1043f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1044f8122d35SGreg Clayton                                  /*Length=*/0xff);
1045f8122d35SGreg Clayton 
1046f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1047f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1048f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1049f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1050f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1051f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1052f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1053f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1054f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1055f8122d35SGreg Clayton 
1056f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1057f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1058f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1059f8122d35SGreg Clayton                     Succeeded());
1060f8122d35SGreg Clayton 
1061f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1062f8122d35SGreg Clayton   // follwing rows:
1063f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=[CFA-8]
1064f8122d35SGreg Clayton   // 0x1004: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16]
1065f8122d35SGreg Clayton   // 0x1008: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24]
1066f8122d35SGreg Clayton   // 0x100C: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16]
1067f8122d35SGreg Clayton   // 0x1010: CFA=reg12+32: Reg1=[CFA-8]
1068f8122d35SGreg Clayton   // This state machine will:
1069f8122d35SGreg Clayton   //  - set Reg1 location
1070f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1071f8122d35SGreg Clayton   //  - remember the state
1072f8122d35SGreg Clayton   //  - set Reg2 location
1073f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1074f8122d35SGreg Clayton   //  - remember the state
1075f8122d35SGreg Clayton   //  - set Reg3 location
1076f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1077f8122d35SGreg Clayton   //  - remember the state where Reg1 and Reg2 were set
1078f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1079f8122d35SGreg Clayton   //  - remember the state where only Reg1 was set
1080f8122d35SGreg Clayton   //  - push a row (automatically at the end of instruction parsing)
1081f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1082*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1083*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg2 = 15;
1084*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg3 = 16;
1085f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1086f8122d35SGreg Clayton       parseCFI(TestFDE,
1087f8122d35SGreg Clayton                {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4,
1088f8122d35SGreg Clayton                 dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2,
1089f8122d35SGreg Clayton                 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state,
1090f8122d35SGreg Clayton                 dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4,
1091f8122d35SGreg Clayton                 dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4,
1092f8122d35SGreg Clayton                 dwarf::DW_CFA_restore_state}),
1093f8122d35SGreg Clayton       Succeeded());
1094f8122d35SGreg Clayton 
1095f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1096f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1097f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs1;
1098f8122d35SGreg Clayton   VerifyLocs1.setRegisterLocation(
1099f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1100f8122d35SGreg Clayton 
1101f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs2;
1102f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
1103f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1104f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
1105f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1106f8122d35SGreg Clayton 
1107f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs3;
1108f8122d35SGreg Clayton   VerifyLocs3.setRegisterLocation(
1109f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1110f8122d35SGreg Clayton   VerifyLocs3.setRegisterLocation(
1111f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1112f8122d35SGreg Clayton   VerifyLocs3.setRegisterLocation(
1113f8122d35SGreg Clayton       Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24));
1114f8122d35SGreg Clayton 
1115f8122d35SGreg Clayton   // Verify we catch state machine error.
1116f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1117f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1118f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1119f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 5u);
1120f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1121f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
1122f8122d35SGreg Clayton 
1123f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
1124f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
1125f8122d35SGreg Clayton 
1126f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
1127f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3);
1128f8122d35SGreg Clayton 
1129f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getAddress(), 0x100Cu);
1130f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2);
1131f8122d35SGreg Clayton 
1132f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
1133f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1);
1134f8122d35SGreg Clayton }
1135f8122d35SGreg Clayton 
1136f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) {
1137f8122d35SGreg Clayton   // Test that DW_CFA_undefined works as expected when parsed in the state
1138f8122d35SGreg Clayton   // machine.
1139f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1140f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1141f8122d35SGreg Clayton                                  /*Length=*/0xff);
1142f8122d35SGreg Clayton 
1143f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1144f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1145f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1146f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1147f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1148f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1149f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1150f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1151f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1152f8122d35SGreg Clayton 
1153f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1154f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1155f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1156f8122d35SGreg Clayton                     Succeeded());
1157f8122d35SGreg Clayton 
1158f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1159f8122d35SGreg Clayton   // follwing rows:
1160f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=undefined
1161f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1162*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1163f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}),
1164f8122d35SGreg Clayton                     Succeeded());
1165f8122d35SGreg Clayton 
1166f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1167f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1168f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1169f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(Reg1,
1170f8122d35SGreg Clayton                                  dwarf::UnwindLocation::createUndefined());
1171f8122d35SGreg Clayton 
1172f8122d35SGreg Clayton   // Verify we catch state machine error.
1173f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1174f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1175f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1176f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1177f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1178f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1179f8122d35SGreg Clayton }
1180f8122d35SGreg Clayton 
1181f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) {
1182f8122d35SGreg Clayton   // Test that DW_CFA_same_value works as expected when parsed in the state
1183f8122d35SGreg Clayton   // machine.
1184f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1185f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1186f8122d35SGreg Clayton                                  /*Length=*/0xff);
1187f8122d35SGreg Clayton 
1188f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1189f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1190f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1191f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1192f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1193f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1194f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1195f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1196f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1197f8122d35SGreg Clayton 
1198f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1199f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1200f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1201f8122d35SGreg Clayton                     Succeeded());
1202f8122d35SGreg Clayton 
1203f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1204f8122d35SGreg Clayton   // follwing rows:
1205f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=same
1206f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1207*a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1208f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}),
1209f8122d35SGreg Clayton                     Succeeded());
1210f8122d35SGreg Clayton 
1211f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1212f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1213f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1214f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame());
1215f8122d35SGreg Clayton 
1216f8122d35SGreg Clayton   // Verify we catch state machine error.
1217f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1218f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1219f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1220f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1221f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1222f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1223f8122d35SGreg Clayton }
1224f8122d35SGreg Clayton 
1225f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) {
1226f8122d35SGreg Clayton   // Test that DW_CFA_register works as expected when parsed in the state
1227f8122d35SGreg Clayton   // machine.
1228f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1229f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1230f8122d35SGreg Clayton                                  /*Length=*/0xff);
1231f8122d35SGreg Clayton 
1232f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1233f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1234f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1235f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1236f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1237f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1238f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1239f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1240f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1241f8122d35SGreg Clayton 
1242f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1243f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1244f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1245f8122d35SGreg Clayton                     Succeeded());
1246f8122d35SGreg Clayton 
1247f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1248f8122d35SGreg Clayton   // follwing rows:
1249f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=same
1250f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1251f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1252f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
1253f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}),
1254f8122d35SGreg Clayton                     Succeeded());
1255f8122d35SGreg Clayton 
1256f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1257f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1258f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1259f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1260f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1261f8122d35SGreg Clayton 
1262f8122d35SGreg Clayton   // Verify we catch state machine error.
1263f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1264f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1265f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1266f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1267f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1268f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1269f8122d35SGreg Clayton }
1270f8122d35SGreg Clayton 
1271f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) {
1272f8122d35SGreg Clayton   // Test that DW_CFA_expression works as expected when parsed in the state
1273f8122d35SGreg Clayton   // machine.
1274f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1275f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1276f8122d35SGreg Clayton                                  /*Length=*/0xff);
1277f8122d35SGreg Clayton 
1278f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1279f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1280f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1281f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1282f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1283f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1284f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1285f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1286f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1287f8122d35SGreg Clayton 
1288f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1289f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1290f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1291f8122d35SGreg Clayton                     Succeeded());
1292f8122d35SGreg Clayton 
1293f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1294f8122d35SGreg Clayton   // follwing rows:
1295f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1296f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1297f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1298f8122d35SGreg Clayton   constexpr uint8_t AddrSize = 8;
1299f8122d35SGreg Clayton   std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1,
1300f8122d35SGreg Clayton                                    dwarf::DW_OP_reg12};
1301f8122d35SGreg Clayton 
1302f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded());
1303f8122d35SGreg Clayton 
1304f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1305f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1306f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1307f8122d35SGreg Clayton 
1308f8122d35SGreg Clayton   std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12};
1309f8122d35SGreg Clayton   DataExtractor ExprData(ExprBytes, true, AddrSize);
1310f8122d35SGreg Clayton   DWARFExpression Expr(ExprData, AddrSize);
1311f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1312f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr));
1313f8122d35SGreg Clayton 
1314f8122d35SGreg Clayton   // Verify we catch state machine error.
1315f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1316f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1317f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1318f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1319f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1320f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1321f8122d35SGreg Clayton }
1322f8122d35SGreg Clayton 
1323f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) {
1324f8122d35SGreg Clayton   // Test that DW_CFA_val_expression works as expected when parsed in the state
1325f8122d35SGreg Clayton   // machine.
1326f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1327f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1328f8122d35SGreg Clayton                                  /*Length=*/0xff);
1329f8122d35SGreg Clayton 
1330f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1331f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1332f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1333f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1334f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1335f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1336f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1337f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1338f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1339f8122d35SGreg Clayton 
1340f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1341f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1342f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1343f8122d35SGreg Clayton                     Succeeded());
1344f8122d35SGreg Clayton 
1345f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1346f8122d35SGreg Clayton   // follwing rows:
1347f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1348f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1349f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1350f8122d35SGreg Clayton   constexpr uint8_t AddrSize = 8;
1351f8122d35SGreg Clayton   std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1,
1352f8122d35SGreg Clayton                                    dwarf::DW_OP_reg12};
1353f8122d35SGreg Clayton 
1354f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded());
1355f8122d35SGreg Clayton 
1356f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1357f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1358f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1359f8122d35SGreg Clayton 
1360f8122d35SGreg Clayton   std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12};
1361f8122d35SGreg Clayton   DataExtractor ExprData(ExprBytes, true, AddrSize);
1362f8122d35SGreg Clayton   DWARFExpression Expr(ExprData, AddrSize);
1363f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1364f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr));
1365f8122d35SGreg Clayton 
1366f8122d35SGreg Clayton   // Verify we catch state machine error.
1367f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1368f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1369f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1370f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1371f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1372f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1373f8122d35SGreg Clayton }
1374f8122d35SGreg Clayton 
1375f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) {
1376f8122d35SGreg Clayton   // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register,
1377f8122d35SGreg Clayton   // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when
1378f8122d35SGreg Clayton   // parsed in the state machine.
1379f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1380f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1381f8122d35SGreg Clayton                                  /*Length=*/0xff);
1382f8122d35SGreg Clayton 
1383f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1384f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1385f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1386f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1387f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1388f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1389f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1390f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1391f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1392f8122d35SGreg Clayton 
1393f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1394f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1395f8122d35SGreg Clayton   constexpr uint8_t CFAReg1 = 12;
1396f8122d35SGreg Clayton   constexpr uint8_t CFAOff1 = 32;
1397f8122d35SGreg Clayton   constexpr uint8_t CFAReg2 = 13;
1398f8122d35SGreg Clayton   constexpr uint8_t CFAOff2 = 48;
1399f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1400f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
1401f8122d35SGreg Clayton 
1402f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1,
1403f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
1404f8122d35SGreg Clayton                     Succeeded());
1405f8122d35SGreg Clayton 
1406f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that use all of the
1407f8122d35SGreg Clayton   // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1408f8122d35SGreg Clayton   // create a row are correctly working.
1409f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1410f8122d35SGreg Clayton       parseCFI(
1411f8122d35SGreg Clayton           TestFDE,
1412f8122d35SGreg Clayton           {
1413f8122d35SGreg Clayton               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register,
1414f8122d35SGreg Clayton               CFAReg2, dwarf::DW_CFA_advance_loc | 4,
1415f8122d35SGreg Clayton               dwarf::DW_CFA_def_cfa_offset, CFAOff2,
1416f8122d35SGreg Clayton               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf,
1417f8122d35SGreg Clayton               0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1418f8122d35SGreg Clayton               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1,
1419f8122d35SGreg Clayton               0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1420f8122d35SGreg Clayton           }),
1421f8122d35SGreg Clayton       Succeeded());
1422f8122d35SGreg Clayton 
1423f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1424f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1425f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1426f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1427f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1428f8122d35SGreg Clayton 
1429f8122d35SGreg Clayton   // Verify we catch state machine error.
1430f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1431f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1432f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1433f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 5u);
1434f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1435f8122d35SGreg Clayton   EXPECT_EQ(
1436f8122d35SGreg Clayton       Rows[0].getCFAValue(),
1437f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1));
1438f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
1439f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1440f8122d35SGreg Clayton 
1441f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
1442f8122d35SGreg Clayton   EXPECT_EQ(
1443f8122d35SGreg Clayton       Rows[1].getCFAValue(),
1444f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1));
1445f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
1446f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
1447f8122d35SGreg Clayton 
1448f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
1449f8122d35SGreg Clayton   EXPECT_EQ(
1450f8122d35SGreg Clayton       Rows[2].getCFAValue(),
1451f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2));
1452f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
1453f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
1454f8122d35SGreg Clayton 
1455f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
1456f8122d35SGreg Clayton   EXPECT_EQ(
1457f8122d35SGreg Clayton       Rows[3].getCFAValue(),
1458f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1));
1459f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
1460f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
1461f8122d35SGreg Clayton 
1462f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
1463f8122d35SGreg Clayton   EXPECT_EQ(
1464f8122d35SGreg Clayton       Rows[4].getCFAValue(),
1465f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2));
1466f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
1467f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
1468f8122d35SGreg Clayton }
1469f8122d35SGreg Clayton 
1470cada5b88SIgor Kudrin } // end anonymous namespace
1471