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,
165*167e7afcSRamNalamothu       dwarf::DW_CFA_LLVM_def_aspace_cfa,
166*167e7afcSRamNalamothu       dwarf::DW_CFA_LLVM_def_aspace_cfa_sf,
167bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_val_offset,
168bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_val_offset_sf,
169bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_val_expression,
170bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_MIPS_advance_loc8,
171bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_GNU_window_save,
172bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_AARCH64_negate_ra_state,
173bee8cdcaSGeorgii Rymar       dwarf::DW_CFA_GNU_args_size};
1741e820e82SGeorgii Rymar 
1751e820e82SGeorgii Rymar   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1761e820e82SGeorgii Rymar                                  /*Offset=*/0x0,
1771e820e82SGeorgii Rymar                                  /*Length=*/0xff);
1781e820e82SGeorgii Rymar 
179bee8cdcaSGeorgii Rymar   // See DWARF standard v3, section 7.23: low 6 bits are used to encode an
180bee8cdcaSGeorgii Rymar   // extended opcode.
181bee8cdcaSGeorgii Rymar   for (uint8_t Code = 0; Code <= 63; ++Code) {
182bee8cdcaSGeorgii Rymar     if (ValidExtendedOpcodes.count(Code))
183bee8cdcaSGeorgii Rymar       continue;
184bee8cdcaSGeorgii Rymar 
185bee8cdcaSGeorgii Rymar     EXPECT_THAT_ERROR(parseCFI(TestCIE, Code),
186bee8cdcaSGeorgii Rymar                       FailedWithMessage(("invalid extended CFI opcode 0x" +
187bee8cdcaSGeorgii Rymar                                          Twine::utohexstr(Code))
188bee8cdcaSGeorgii Rymar                                             .str()
189bee8cdcaSGeorgii Rymar                                             .c_str()));
190bee8cdcaSGeorgii Rymar   }
191bee8cdcaSGeorgii Rymar }
192bee8cdcaSGeorgii Rymar 
193bee8cdcaSGeorgii Rymar // Here we test how truncated Call Frame Instructions are parsed.
194bee8cdcaSGeorgii Rymar TEST(DWARFDebugFrame, ParseTruncatedCFITest) {
195bee8cdcaSGeorgii Rymar   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
196bee8cdcaSGeorgii Rymar                                  /*Offset=*/0x0,
197bee8cdcaSGeorgii Rymar                                  /*Length=*/0xff);
198bee8cdcaSGeorgii Rymar 
1991e820e82SGeorgii Rymar   // Having an empty instructions list is fine.
200bee8cdcaSGeorgii Rymar   EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
2011e820e82SGeorgii Rymar 
2021e820e82SGeorgii Rymar   // Unable to read an opcode, because the instructions list is empty, but we
2031e820e82SGeorgii Rymar   // say to the parser that it is not.
2041e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
205bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {}, /*Size=*/1),
2061e820e82SGeorgii Rymar       FailedWithMessage(
2071e820e82SGeorgii Rymar           "unexpected end of data at offset 0x0 while reading [0x0, 0x1)"));
2081e820e82SGeorgii Rymar 
2091e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_offset instruction.
2101e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
211bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_offset}),
2121e820e82SGeorgii Rymar       FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2131e820e82SGeorgii Rymar                         "malformed uleb128, extends past end"));
2141e820e82SGeorgii Rymar 
2151e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_set_loc instruction.
2161e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
217bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_set_loc}),
2181e820e82SGeorgii Rymar       FailedWithMessage(
2191e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x9)"));
2201e820e82SGeorgii Rymar 
2211e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_advance_loc1 instruction.
2221e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
223bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}),
2241e820e82SGeorgii Rymar       FailedWithMessage(
2251e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x2)"));
2261e820e82SGeorgii Rymar 
2271e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_advance_loc2 instruction.
2281e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
229bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}),
2301e820e82SGeorgii Rymar       FailedWithMessage(
2311e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x3)"));
2321e820e82SGeorgii Rymar 
2331e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_advance_loc4 instruction.
2341e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
235bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}),
2361e820e82SGeorgii Rymar       FailedWithMessage(
2371e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x5)"));
2381e820e82SGeorgii Rymar 
2391e820e82SGeorgii Rymar   // A test for an instruction with a single ULEB128 operand.
2401e820e82SGeorgii Rymar   auto CheckOp_ULEB128 = [&](uint8_t Inst) {
2411e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
242bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, Inst),
2431e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2441e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
2451e820e82SGeorgii Rymar   };
2461e820e82SGeorgii Rymar 
2471e820e82SGeorgii Rymar   for (uint8_t Inst :
2481e820e82SGeorgii Rymar        {dwarf::DW_CFA_restore_extended, dwarf::DW_CFA_undefined,
2491e820e82SGeorgii Rymar         dwarf::DW_CFA_same_value, dwarf::DW_CFA_def_cfa_register,
2501e820e82SGeorgii Rymar         dwarf::DW_CFA_def_cfa_offset, dwarf::DW_CFA_GNU_args_size})
2511e820e82SGeorgii Rymar     CheckOp_ULEB128(Inst);
2521e820e82SGeorgii Rymar 
2531e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction.
2541e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
255bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_offset_sf}),
2561e820e82SGeorgii Rymar       FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2571e820e82SGeorgii Rymar                         "malformed sleb128, extends past end"));
2581e820e82SGeorgii Rymar 
2591e820e82SGeorgii Rymar   // A test for an instruction with two ULEB128 operands.
2601e820e82SGeorgii Rymar   auto CheckOp_ULEB128_ULEB128 = [&](uint8_t Inst) {
2611e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
262bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, Inst),
2631e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2641e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
2651e820e82SGeorgii Rymar 
2661e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
267bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, {Inst, /*Op1=*/0}),
2681e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
2691e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
2701e820e82SGeorgii Rymar   };
2711e820e82SGeorgii Rymar 
2721e820e82SGeorgii Rymar   for (uint8_t Inst : {dwarf::DW_CFA_offset_extended, dwarf::DW_CFA_register,
273*167e7afcSRamNalamothu                        dwarf::DW_CFA_def_cfa, dwarf::DW_CFA_LLVM_def_aspace_cfa,
274*167e7afcSRamNalamothu                        dwarf::DW_CFA_val_offset})
2751e820e82SGeorgii Rymar     CheckOp_ULEB128_ULEB128(Inst);
2761e820e82SGeorgii Rymar 
2771e820e82SGeorgii Rymar   // A test for an instruction with two operands: ULEB128, SLEB128.
2781e820e82SGeorgii Rymar   auto CheckOp_ULEB128_SLEB128 = [&](uint8_t Inst) {
2791e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
280bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, Inst),
2811e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2821e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
2831e820e82SGeorgii Rymar 
2841e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
285bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, {Inst, /*Op1=*/0}),
2861e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
2871e820e82SGeorgii Rymar                           "malformed sleb128, extends past end"));
2881e820e82SGeorgii Rymar   };
2891e820e82SGeorgii Rymar 
290*167e7afcSRamNalamothu   for (uint8_t Inst :
291*167e7afcSRamNalamothu        {dwarf::DW_CFA_offset_extended_sf, dwarf::DW_CFA_def_cfa_sf,
292*167e7afcSRamNalamothu         dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, dwarf::DW_CFA_val_offset_sf})
2931e820e82SGeorgii Rymar     CheckOp_ULEB128_SLEB128(Inst);
2941e820e82SGeorgii Rymar 
2951e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_def_cfa_expression instruction.
2961e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
297bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}),
2981e820e82SGeorgii Rymar       FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
2991e820e82SGeorgii Rymar                         "malformed uleb128, extends past end"));
3001e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
301bee8cdcaSGeorgii Rymar       parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
3021e820e82SGeorgii Rymar                          /*expression length=*/0x1}),
3031e820e82SGeorgii Rymar       FailedWithMessage(
3041e820e82SGeorgii Rymar           "unexpected end of data at offset 0x2 while reading [0x2, 0x3)"));
3051e820e82SGeorgii Rymar   // The DW_CFA_def_cfa_expression can contain a zero length expression.
306bee8cdcaSGeorgii Rymar   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
3071e820e82SGeorgii Rymar                                        /*ExprLen=*/0}),
3081e820e82SGeorgii Rymar                     Succeeded());
3091e820e82SGeorgii Rymar 
3101e820e82SGeorgii Rymar   // A test for an instruction with three operands: ULEB128, expression length
3111e820e82SGeorgii Rymar   // (ULEB128) and expression bytes.
3121e820e82SGeorgii Rymar   auto CheckOp_ULEB128_Expr = [&](uint8_t Inst) {
3131e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
314bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, {Inst}),
3151e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
3161e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
3171e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
318bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, {Inst, /*Op1=*/0}),
3191e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
3201e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
3211e820e82SGeorgii Rymar     // A zero length expression is fine
322bee8cdcaSGeorgii Rymar     EXPECT_THAT_ERROR(parseCFI(TestCIE, {Inst,
3231e820e82SGeorgii Rymar                                          /*Op1=*/0, /*ExprLen=*/0}),
3241e820e82SGeorgii Rymar                       Succeeded());
3251e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
326bee8cdcaSGeorgii Rymar         parseCFI(TestCIE, {Inst,
3271e820e82SGeorgii Rymar                            /*Op1=*/0, /*ExprLen=*/1}),
3281e820e82SGeorgii Rymar         FailedWithMessage(
3291e820e82SGeorgii Rymar             "unexpected end of data at offset 0x3 while reading [0x3, 0x4)"));
3301e820e82SGeorgii Rymar   };
3311e820e82SGeorgii Rymar 
3321e820e82SGeorgii Rymar   for (uint8_t Inst : {dwarf::DW_CFA_expression, dwarf::DW_CFA_val_expression})
3331e820e82SGeorgii Rymar     CheckOp_ULEB128_Expr(Inst);
3341e820e82SGeorgii Rymar }
3351e820e82SGeorgii Rymar 
336f8122d35SGreg Clayton void expectDumpResult(const dwarf::UnwindLocation &Loc,
337f8122d35SGreg Clayton                       StringRef ExpectedFirstLine) {
338f8122d35SGreg Clayton   std::string Output;
339f8122d35SGreg Clayton   raw_string_ostream OS(Output);
340f8122d35SGreg Clayton   OS << Loc;
341f8122d35SGreg Clayton   OS.flush();
342f8122d35SGreg Clayton   StringRef FirstLine = StringRef(Output).split('\n').first;
343f8122d35SGreg Clayton   EXPECT_EQ(FirstLine, ExpectedFirstLine);
344f8122d35SGreg Clayton }
345f8122d35SGreg Clayton 
346f8122d35SGreg Clayton TEST(DWARFDebugFrame, DumpUnwindLocations) {
347f8122d35SGreg Clayton   // Test constructing unwind locations and dumping each kind.
348f8122d35SGreg Clayton   constexpr int32_t PlusOff = 8;
349f8122d35SGreg Clayton   constexpr int32_t MinusOff = -8;
350a1a3fdcdSGreg Clayton   constexpr uint8_t RegNum = 12;
351f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createUnspecified(), "unspecified");
352f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createUndefined(), "undefined");
353f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createSame(), "same");
354f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(PlusOff),
355f8122d35SGreg Clayton                    "CFA+8");
356f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff),
357f8122d35SGreg Clayton                    "CFA-8");
358f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff),
359f8122d35SGreg Clayton                    "[CFA+8]");
360f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff),
361f8122d35SGreg Clayton                    "[CFA-8]");
362f8122d35SGreg Clayton 
363f8122d35SGreg Clayton   expectDumpResult(
364f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, PlusOff),
365f8122d35SGreg Clayton       "reg12+8");
366f8122d35SGreg Clayton   expectDumpResult(
367f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, MinusOff),
368f8122d35SGreg Clayton       "reg12-8");
369f8122d35SGreg Clayton   expectDumpResult(
370f8122d35SGreg Clayton       dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, PlusOff),
371f8122d35SGreg Clayton       "[reg12+8]");
372f8122d35SGreg Clayton   expectDumpResult(
373f8122d35SGreg Clayton       dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, MinusOff),
374f8122d35SGreg Clayton       "[reg12-8]");
375f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12");
376f8122d35SGreg Clayton   expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32");
377f8122d35SGreg Clayton }
378f8122d35SGreg Clayton 
379f8122d35SGreg Clayton void expectDumpResult(const dwarf::RegisterLocations &Locs,
380f8122d35SGreg Clayton                       StringRef ExpectedFirstLine) {
381f8122d35SGreg Clayton   std::string Output;
382f8122d35SGreg Clayton   raw_string_ostream OS(Output);
383f8122d35SGreg Clayton   OS << Locs;
384f8122d35SGreg Clayton   OS.flush();
385f8122d35SGreg Clayton   StringRef FirstLine = StringRef(Output).split('\n').first;
386f8122d35SGreg Clayton   EXPECT_EQ(FirstLine, ExpectedFirstLine);
387f8122d35SGreg Clayton }
388f8122d35SGreg Clayton 
389f8122d35SGreg Clayton TEST(DWARFDebugFrame, RegisterLocations) {
390f8122d35SGreg Clayton   // Test the functionality of the RegisterLocations class.
391f8122d35SGreg Clayton   dwarf::RegisterLocations Locs;
392f8122d35SGreg Clayton   expectDumpResult(Locs, "");
393f8122d35SGreg Clayton   EXPECT_FALSE(Locs.hasLocations());
394f8122d35SGreg Clayton   // Set a register location for reg12 to unspecified and verify it dumps
395f8122d35SGreg Clayton   // correctly.
396f8122d35SGreg Clayton   Locs.setRegisterLocation(12, dwarf::UnwindLocation::createUnspecified());
397f8122d35SGreg Clayton   EXPECT_TRUE(Locs.hasLocations());
398f8122d35SGreg Clayton   expectDumpResult(Locs, "reg12=unspecified");
399f8122d35SGreg Clayton 
400f8122d35SGreg Clayton   // Replace the register location for reg12 to "same" and verify it dumps
401f8122d35SGreg Clayton   // correctly after it is modified
402f8122d35SGreg Clayton   Locs.setRegisterLocation(12, dwarf::UnwindLocation::createSame());
403f8122d35SGreg Clayton   EXPECT_TRUE(Locs.hasLocations());
404f8122d35SGreg Clayton   expectDumpResult(Locs, "reg12=same");
405f8122d35SGreg Clayton 
406f8122d35SGreg Clayton   // Remove the register location for reg12 verify it dumps correctly after it
407f8122d35SGreg Clayton   // is removed.
408f8122d35SGreg Clayton   Locs.removeRegisterLocation(12);
409f8122d35SGreg Clayton   EXPECT_FALSE(Locs.hasLocations());
410f8122d35SGreg Clayton   expectDumpResult(Locs, "");
411f8122d35SGreg Clayton 
412f8122d35SGreg Clayton   // Verify multiple registers added to the list dump correctly.
413f8122d35SGreg Clayton   auto Reg12Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(4);
414f8122d35SGreg Clayton   auto Reg13Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(8);
415f8122d35SGreg Clayton   auto Reg14Loc = dwarf::UnwindLocation::createSame();
416f8122d35SGreg Clayton   Locs.setRegisterLocation(12, Reg12Loc);
417f8122d35SGreg Clayton   Locs.setRegisterLocation(13, Reg13Loc);
418f8122d35SGreg Clayton   Locs.setRegisterLocation(14, Reg14Loc);
419f8122d35SGreg Clayton   EXPECT_TRUE(Locs.hasLocations());
420f8122d35SGreg Clayton   expectDumpResult(Locs, "reg12=[CFA+4], reg13=[CFA+8], reg14=same");
421f8122d35SGreg Clayton 
422f8122d35SGreg Clayton   // Verify RegisterLocations::getRegisterLocation() works as expected.
423f8122d35SGreg Clayton   Optional<dwarf::UnwindLocation> OptionalLoc;
424f8122d35SGreg Clayton   OptionalLoc = Locs.getRegisterLocation(0);
425f8122d35SGreg Clayton   EXPECT_FALSE(OptionalLoc.hasValue());
426f8122d35SGreg Clayton 
427f8122d35SGreg Clayton   OptionalLoc = Locs.getRegisterLocation(12);
428f8122d35SGreg Clayton   EXPECT_TRUE(OptionalLoc.hasValue());
429f8122d35SGreg Clayton   EXPECT_EQ(*OptionalLoc, Reg12Loc);
430f8122d35SGreg Clayton 
431f8122d35SGreg Clayton   OptionalLoc = Locs.getRegisterLocation(13);
432f8122d35SGreg Clayton   EXPECT_TRUE(OptionalLoc.hasValue());
433f8122d35SGreg Clayton   EXPECT_EQ(*OptionalLoc, Reg13Loc);
434f8122d35SGreg Clayton 
435f8122d35SGreg Clayton   OptionalLoc = Locs.getRegisterLocation(14);
436f8122d35SGreg Clayton   EXPECT_TRUE(OptionalLoc.hasValue());
437f8122d35SGreg Clayton   EXPECT_EQ(*OptionalLoc, Reg14Loc);
438f8122d35SGreg Clayton 
439f8122d35SGreg Clayton   // Verify registers are correctly removed when multiple exist in the list.
440f8122d35SGreg Clayton   Locs.removeRegisterLocation(13);
441f8122d35SGreg Clayton   EXPECT_FALSE(Locs.getRegisterLocation(13).hasValue());
442f8122d35SGreg Clayton   EXPECT_TRUE(Locs.hasLocations());
443f8122d35SGreg Clayton   expectDumpResult(Locs, "reg12=[CFA+4], reg14=same");
444f8122d35SGreg Clayton   Locs.removeRegisterLocation(14);
445f8122d35SGreg Clayton   EXPECT_FALSE(Locs.getRegisterLocation(14).hasValue());
446f8122d35SGreg Clayton   EXPECT_TRUE(Locs.hasLocations());
447f8122d35SGreg Clayton   expectDumpResult(Locs, "reg12=[CFA+4]");
448f8122d35SGreg Clayton   Locs.removeRegisterLocation(12);
449f8122d35SGreg Clayton   EXPECT_FALSE(Locs.getRegisterLocation(12).hasValue());
450f8122d35SGreg Clayton   EXPECT_FALSE(Locs.hasLocations());
451f8122d35SGreg Clayton   expectDumpResult(Locs, "");
452f8122d35SGreg Clayton }
453f8122d35SGreg Clayton 
454223852d7SRamNalamothu // Test that empty rows are not added to UnwindTable when
455223852d7SRamNalamothu // dwarf::CIE::CFIs or dwarf::FDE::CFIs is empty.
456223852d7SRamNalamothu TEST(DWARFDebugFrame, UnwindTableEmptyRows) {
457223852d7SRamNalamothu   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
458223852d7SRamNalamothu                                  /*Offset=*/0x0,
459223852d7SRamNalamothu                                  /*Length=*/0xff);
460223852d7SRamNalamothu 
461223852d7SRamNalamothu   // Having an empty instructions list is fine.
462223852d7SRamNalamothu   EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
463223852d7SRamNalamothu   EXPECT_TRUE(TestCIE.cfis().empty());
464223852d7SRamNalamothu 
465223852d7SRamNalamothu   // Verify dwarf::UnwindTable::create() won't result in errors and
466223852d7SRamNalamothu   // and empty rows are not added to CIE UnwindTable.
467223852d7SRamNalamothu   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE);
468223852d7SRamNalamothu   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
469223852d7SRamNalamothu   const size_t ExpectedNumOfRows = 0;
470223852d7SRamNalamothu   EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
471223852d7SRamNalamothu 
472223852d7SRamNalamothu   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
473223852d7SRamNalamothu                      /*Offset=*/0x3333abcdabcd,
474223852d7SRamNalamothu                      /*Length=*/0x4444abcdabcd,
475223852d7SRamNalamothu                      /*CIEPointer=*/0x1111abcdabcd,
476223852d7SRamNalamothu                      /*InitialLocation=*/0x1000,
477223852d7SRamNalamothu                      /*AddressRange=*/0x1000,
478223852d7SRamNalamothu                      /*Cie=*/&TestCIE,
479223852d7SRamNalamothu                      /*LSDAAddress=*/None,
480223852d7SRamNalamothu                      /*Arch=*/Triple::x86_64);
481223852d7SRamNalamothu 
482223852d7SRamNalamothu   // Having an empty instructions list is fine.
483223852d7SRamNalamothu   EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
484223852d7SRamNalamothu   EXPECT_TRUE(TestFDE.cfis().empty());
485223852d7SRamNalamothu 
486223852d7SRamNalamothu   // Verify dwarf::UnwindTable::create() won't result in errors and
487223852d7SRamNalamothu   // and empty rows are not added to FDE UnwindTable.
488223852d7SRamNalamothu   RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
489223852d7SRamNalamothu   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
490223852d7SRamNalamothu   EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
491223852d7SRamNalamothu }
492223852d7SRamNalamothu 
493223852d7SRamNalamothu // Test that empty rows are not added to UnwindTable when dwarf::CIE::CFIs
494223852d7SRamNalamothu // or dwarf::FDE::CFIs is not empty but has only DW_CFA_nop instructions.
495223852d7SRamNalamothu TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) {
496223852d7SRamNalamothu   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
497223852d7SRamNalamothu                                  /*Offset=*/0x0,
498223852d7SRamNalamothu                                  /*Length=*/0xff);
499223852d7SRamNalamothu 
500223852d7SRamNalamothu   // Make a CIE that has only DW_CFA_nop instructions.
501223852d7SRamNalamothu   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_nop}), Succeeded());
502223852d7SRamNalamothu   EXPECT_TRUE(!TestCIE.cfis().empty());
503223852d7SRamNalamothu 
504223852d7SRamNalamothu   // Verify dwarf::UnwindTable::create() won't result in errors and
505223852d7SRamNalamothu   // and empty rows are not added to CIE UnwindTable.
506223852d7SRamNalamothu   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE);
507223852d7SRamNalamothu   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
508223852d7SRamNalamothu   const size_t ExpectedNumOfRows = 0;
509223852d7SRamNalamothu   EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
510223852d7SRamNalamothu 
511223852d7SRamNalamothu   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
512223852d7SRamNalamothu                      /*Offset=*/0x3333abcdabcd,
513223852d7SRamNalamothu                      /*Length=*/0x4444abcdabcd,
514223852d7SRamNalamothu                      /*CIEPointer=*/0x1111abcdabcd,
515223852d7SRamNalamothu                      /*InitialLocation=*/0x1000,
516223852d7SRamNalamothu                      /*AddressRange=*/0x1000,
517223852d7SRamNalamothu                      /*Cie=*/&TestCIE,
518223852d7SRamNalamothu                      /*LSDAAddress=*/None,
519223852d7SRamNalamothu                      /*Arch=*/Triple::x86_64);
520223852d7SRamNalamothu 
521223852d7SRamNalamothu   // Make an FDE that has only DW_CFA_nop instructions.
522223852d7SRamNalamothu   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_nop}), Succeeded());
523223852d7SRamNalamothu   EXPECT_TRUE(!TestFDE.cfis().empty());
524223852d7SRamNalamothu 
525223852d7SRamNalamothu   // Verify dwarf::UnwindTable::create() won't result in errors and
526223852d7SRamNalamothu   // and empty rows are not added to FDE UnwindTable.
527223852d7SRamNalamothu   RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
528223852d7SRamNalamothu   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
529223852d7SRamNalamothu   EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
530223852d7SRamNalamothu }
531223852d7SRamNalamothu 
532f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) {
533f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
534f8122d35SGreg Clayton                                  /*Offset=*/0x0,
535f8122d35SGreg Clayton                                  /*Length=*/0xff);
536f8122d35SGreg Clayton 
537f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
538f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
539f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
540f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
541f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
542f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
543f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
544f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
545f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
546f8122d35SGreg Clayton 
547f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition.
548f8122d35SGreg Clayton   constexpr uint8_t Reg = 12;
549f8122d35SGreg Clayton   constexpr uint8_t Offset = 32;
550f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
551f8122d35SGreg Clayton                     Succeeded());
552f8122d35SGreg Clayton 
553f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
554f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
555f8122d35SGreg Clayton   // Here we encode two DW_CFA_set_loc opcodes:
556f8122d35SGreg Clayton   //   DW_CFA_set_loc(0x1100)
557f8122d35SGreg Clayton   //   DW_CFA_set_loc(0x1000)
558f8122d35SGreg Clayton   // These opcodes cause a new row to be appended to the rows in a UnwindTable
559f8122d35SGreg Clayton   // and the resulting rows are not in ascending address order and should cause
560f8122d35SGreg Clayton   // a state machine error.
561f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
562f8122d35SGreg Clayton       parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0,
563f8122d35SGreg Clayton                          dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}),
564f8122d35SGreg Clayton       Succeeded());
565f8122d35SGreg Clayton 
566f8122d35SGreg Clayton   // Verify we catch state machine error.
567f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
568f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
569f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which"
570f8122d35SGreg Clayton                                       " must be greater than the current row "
571f8122d35SGreg Clayton                                       "address 0x1100"));
572f8122d35SGreg Clayton }
573f8122d35SGreg Clayton 
574f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) {
575f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
576f8122d35SGreg Clayton                                  /*Offset=*/0x0,
577f8122d35SGreg Clayton                                  /*Length=*/0xff);
578f8122d35SGreg Clayton 
579f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
580f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
581f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
582f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
583f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
584f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
585f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
586f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
587f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
588f8122d35SGreg Clayton 
589f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition.
590f8122d35SGreg Clayton   constexpr uint8_t Reg = 12;
591f8122d35SGreg Clayton   constexpr uint8_t Offset = 32;
592f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
593f8122d35SGreg Clayton                     Succeeded());
594f8122d35SGreg Clayton 
595f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
596f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
597f8122d35SGreg Clayton   // Here we encode a DW_CFA_restore_state opcode that was not preceded by a
598f8122d35SGreg Clayton   // DW_CFA_remember_state, and an error should be returned.
599f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}),
600f8122d35SGreg Clayton                     Succeeded());
601f8122d35SGreg Clayton 
602f8122d35SGreg Clayton   // Verify we catch state machine error.
603f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
604f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
605f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_restore_state without a matching "
606f8122d35SGreg Clayton                                       "previous DW_CFA_remember_state"));
607f8122d35SGreg Clayton }
608f8122d35SGreg Clayton 
609f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) {
610f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
611f8122d35SGreg Clayton                                  /*Offset=*/0x0,
612f8122d35SGreg Clayton                                  /*Length=*/0xff);
613f8122d35SGreg Clayton 
614f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
615f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
616f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
617f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
618f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
619f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
620f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
621f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
622f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
623f8122d35SGreg Clayton 
624f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition.
625f8122d35SGreg Clayton   constexpr uint8_t Reg = 12;
626f8122d35SGreg Clayton   constexpr uint8_t Offset = 32;
627f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
628f8122d35SGreg Clayton                     Succeeded());
629f8122d35SGreg Clayton 
630f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
631f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
632f8122d35SGreg Clayton   // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not
633f8122d35SGreg Clayton   // found any documentation that describes what this does after some brief
634f8122d35SGreg Clayton   // searching.
635f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}),
636f8122d35SGreg Clayton                     Succeeded());
637f8122d35SGreg Clayton 
638f8122d35SGreg Clayton   // Verify we catch state machine error.
639f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
640f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
641f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA opcode 0x2d is not supported for "
642f8122d35SGreg Clayton                                       "architecture x86_64"));
643f8122d35SGreg Clayton }
644f8122d35SGreg Clayton 
645f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) {
646f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
647f8122d35SGreg Clayton                                  /*Offset=*/0x0,
648f8122d35SGreg Clayton                                  /*Length=*/0xff);
649f8122d35SGreg Clayton 
650f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
651f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
652f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
653f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
654f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
655f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
656f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
657f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
658f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
659f8122d35SGreg Clayton 
660f8122d35SGreg Clayton   // Make a CIE that has an invalid CFA definition. We do this so we can try
661f8122d35SGreg Clayton   // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate
662f8122d35SGreg Clayton   // error back.
663f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
664f8122d35SGreg Clayton 
665f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
666f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
667f8122d35SGreg Clayton   // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE
668f8122d35SGreg Clayton   // didn't define the CFA in terms of a register plus offset, so this should
669f8122d35SGreg Clayton   // cause an error.
670f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}),
671f8122d35SGreg Clayton                     Succeeded());
672f8122d35SGreg Clayton 
673f8122d35SGreg Clayton   // Verify we catch state machine error.
674f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
675f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
676f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_def_cfa_offset found when CFA "
677f8122d35SGreg Clayton                                       "rule was not RegPlusOffset"));
678f8122d35SGreg Clayton }
679f8122d35SGreg Clayton 
680f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) {
681f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
682f8122d35SGreg Clayton                                  /*Offset=*/0x0,
683f8122d35SGreg Clayton                                  /*Length=*/0xff);
684f8122d35SGreg Clayton 
685f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
686f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
687f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
688f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
689f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
690f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
691f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
692f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
693f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
694f8122d35SGreg Clayton 
695f8122d35SGreg Clayton   // Make a CIE that has an invalid CFA definition. We do this so we can try
696f8122d35SGreg Clayton   // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an
697f8122d35SGreg Clayton   // appropriate error back.
698f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
699f8122d35SGreg Clayton 
700f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
701f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
702f8122d35SGreg Clayton   // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE
703f8122d35SGreg Clayton   // didn't define the CFA in terms of a register plus offset, so this should
704f8122d35SGreg Clayton   // cause an error.
705f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}),
706f8122d35SGreg Clayton                     Succeeded());
707f8122d35SGreg Clayton 
708f8122d35SGreg Clayton   // Verify we catch state machine error.
709f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
710f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(),
711f8122d35SGreg Clayton                     FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA "
712f8122d35SGreg Clayton                                       "rule was not RegPlusOffset"));
713f8122d35SGreg Clayton }
714f8122d35SGreg Clayton 
715f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) {
716f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
717f8122d35SGreg Clayton                                  /*Offset=*/0x0,
718f8122d35SGreg Clayton                                  /*Length=*/0xff);
719f8122d35SGreg Clayton 
720f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
721f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
722f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
723f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
724f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
725f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
726f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
727f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
728f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
729f8122d35SGreg Clayton 
730f8122d35SGreg Clayton   // Make a CIE that has only defines the CFA register with no offset. Some
731f8122d35SGreg Clayton   // architectures do this and we must ensure that we set the CFA value to be
732f8122d35SGreg Clayton   // equal to that register with no offset.
733f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
734f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}),
735f8122d35SGreg Clayton                     Succeeded());
736f8122d35SGreg Clayton 
737f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that have valid
738f8122d35SGreg Clayton   // syntax, but will cause an error when we parse them into a UnwindTable.
739f8122d35SGreg Clayton   // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but
740f8122d35SGreg Clayton   // our CIE didn't define the CFA in terms of a register plus offset, so this
741f8122d35SGreg Clayton   // should cause an error.
742f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
743f8122d35SGreg Clayton 
744f8122d35SGreg Clayton   // Verify we catch state machine error.
745f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
746f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
747f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
748f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
749f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
750f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getCFAValue(),
751f8122d35SGreg Clayton             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0));
752f8122d35SGreg Clayton }
753f8122d35SGreg Clayton 
754f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) {
755f8122d35SGreg Clayton   // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable.
756f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
757f8122d35SGreg Clayton                                  /*Offset=*/0x0,
758f8122d35SGreg Clayton                                  /*Length=*/0xff);
759f8122d35SGreg Clayton 
760f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
761f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
762f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
763f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
764f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
765f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
766f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
767f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
768f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
769f8122d35SGreg Clayton 
770f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
771f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
772f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
773f8122d35SGreg Clayton   constexpr uint8_t CFAOffset = 32;
774f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
775f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
776f8122d35SGreg Clayton 
777f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
778f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
779f8122d35SGreg Clayton                     Succeeded());
780f8122d35SGreg Clayton 
781f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that use all of the
782f8122d35SGreg Clayton   // row pushing opcodes. This will verify that all opcodes that should create
783f8122d35SGreg Clayton   // a row are correctly working. Each opcode will push a row prior to
784f8122d35SGreg Clayton   // advancing the address, and then a row will be automatically pushed at the
785f8122d35SGreg Clayton   // end of the parsing, so we should end up with 6 rows starting at address
786f8122d35SGreg Clayton   // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor
787f8122d35SGreg Clayton   // from the CIE.
788f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4,
789f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc1,
790f8122d35SGreg Clayton                                        4,
791f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc2,
792f8122d35SGreg Clayton                                        4,
793f8122d35SGreg Clayton                                        0,
794f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc4,
795f8122d35SGreg Clayton                                        4,
796f8122d35SGreg Clayton                                        0,
797f8122d35SGreg Clayton                                        0,
798f8122d35SGreg Clayton                                        0,
799f8122d35SGreg Clayton                                        dwarf::DW_CFA_set_loc,
800f8122d35SGreg Clayton                                        0x14,
801f8122d35SGreg Clayton                                        0x10,
802f8122d35SGreg Clayton                                        0,
803f8122d35SGreg Clayton                                        0,
804f8122d35SGreg Clayton                                        0,
805f8122d35SGreg Clayton                                        0,
806f8122d35SGreg Clayton                                        0,
807f8122d35SGreg Clayton                                        0}),
808f8122d35SGreg Clayton                     Succeeded());
809f8122d35SGreg Clayton 
810f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
811f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
812f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
813f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
814f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
815f8122d35SGreg Clayton 
816f8122d35SGreg Clayton   // Verify we catch state machine error.
817f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
818f8122d35SGreg Clayton   ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
819f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
820f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 6u);
821f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
822f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
823f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
824f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
825f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
826f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
827f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
828f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
829f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
830f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
831f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
832f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
833f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
834f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
835f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
836f8122d35SGreg Clayton   EXPECT_EQ(Rows[5].getAddress(), 0x1014u);
837f8122d35SGreg Clayton   EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u);
838f8122d35SGreg Clayton   EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs);
839f8122d35SGreg Clayton }
840f8122d35SGreg Clayton 
841f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) {
842f8122d35SGreg Clayton   // Test that DW_CFA_restore works as expected when parsed in the state
843f8122d35SGreg Clayton   // machine.
844f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
845f8122d35SGreg Clayton                                  /*Offset=*/0x0,
846f8122d35SGreg Clayton                                  /*Length=*/0xff);
847f8122d35SGreg Clayton 
848f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
849f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
850f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
851f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
852f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
853f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
854f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
855f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
856f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
857f8122d35SGreg Clayton 
858f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
859f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
860f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
861f8122d35SGreg Clayton   constexpr uint8_t CFAOffset = 32;
862f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
863f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
864f8122d35SGreg Clayton   constexpr int32_t RegCFAOffset = -8;
865f8122d35SGreg Clayton 
866f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
867f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
868f8122d35SGreg Clayton                     Succeeded());
869f8122d35SGreg Clayton 
870f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the rule
871f8122d35SGreg Clayton   // for register "Reg" to be [CFA-8], then push a row, and then restore the
872f8122d35SGreg Clayton   // register unwind rule for "Reg" using DW_CFA_restore. We should end up with
873f8122d35SGreg Clayton   // two rows:
874f8122d35SGreg Clayton   //   - one with Reg = [CFA-8]
875f8122d35SGreg Clayton   //   - one with Reg = InReg
876f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1,
877f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc | 4,
878f8122d35SGreg Clayton                                        dwarf::DW_CFA_restore | Reg}),
879f8122d35SGreg Clayton                     Succeeded());
880f8122d35SGreg Clayton 
881f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
882f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
883f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs1;
884f8122d35SGreg Clayton   VerifyLocs1.setRegisterLocation(
885f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset));
886f8122d35SGreg Clayton 
887f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs2;
888f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
889f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
890f8122d35SGreg Clayton 
891f8122d35SGreg Clayton   // Verify we catch state machine error.
892f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
893f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
894f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
895f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 2u);
896f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
897f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
898f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
899f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
900f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
901f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
902f8122d35SGreg Clayton }
903f8122d35SGreg Clayton 
904f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) {
905f8122d35SGreg Clayton   // Test that DW_CFA_restore works as expected when parsed in the state
906f8122d35SGreg Clayton   // machine.
907f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
908f8122d35SGreg Clayton                                  /*Offset=*/0x0,
909f8122d35SGreg Clayton                                  /*Length=*/0xff);
910f8122d35SGreg Clayton 
911f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
912f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
913f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
914f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
915f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
916f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
917f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
918f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
919f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
920f8122d35SGreg Clayton 
921f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
922f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
923f8122d35SGreg Clayton   constexpr uint8_t CFAReg = 12;
924f8122d35SGreg Clayton   constexpr uint8_t CFAOffset = 32;
925f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
926f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
927f8122d35SGreg Clayton   constexpr int32_t RegCFAOffset = -8;
928f8122d35SGreg Clayton 
929f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
930f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
931f8122d35SGreg Clayton                     Succeeded());
932f8122d35SGreg Clayton 
933f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the rule
934f8122d35SGreg Clayton   // for register "Reg" to be [CFA-8], then push a row, and then restore the
935f8122d35SGreg Clayton   // register unwind rule for "Reg" using DW_CFA_restore_extended. We should
936f8122d35SGreg Clayton   // end up with two rows:
937f8122d35SGreg Clayton   //   - one with Reg = [CFA-8]
938f8122d35SGreg Clayton   //   - one with Reg = InReg
939f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1,
940f8122d35SGreg Clayton                                        dwarf::DW_CFA_advance_loc | 4,
941f8122d35SGreg Clayton                                        dwarf::DW_CFA_restore_extended, Reg}),
942f8122d35SGreg Clayton                     Succeeded());
943f8122d35SGreg Clayton 
944f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
945f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
946f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs1;
947f8122d35SGreg Clayton   VerifyLocs1.setRegisterLocation(
948f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset));
949f8122d35SGreg Clayton 
950f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs2;
951f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
952f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
953f8122d35SGreg Clayton 
954f8122d35SGreg Clayton   // Verify we catch state machine error.
955f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
956f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
957f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
958f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 2u);
959f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
960f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
961f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
962f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
963f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
964f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
965f8122d35SGreg Clayton }
966f8122d35SGreg Clayton 
967f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) {
968f8122d35SGreg Clayton   // Test that DW_CFA_offset, DW_CFA_offset_extended and
969f8122d35SGreg Clayton   // DW_CFA_offset_extended_sf work as expected when parsed in the state
970f8122d35SGreg Clayton   // machine.
971f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
972f8122d35SGreg Clayton                                  /*Offset=*/0x0,
973f8122d35SGreg Clayton                                  /*Length=*/0xff);
974f8122d35SGreg Clayton 
975f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
976f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
977f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
978f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
979f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
980f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
981f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
982f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
983f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
984f8122d35SGreg Clayton 
985f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
986f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
987f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
988f8122d35SGreg Clayton                     Succeeded());
989f8122d35SGreg Clayton 
990f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the
991f8122d35SGreg Clayton   // unwind rules for the follwing registers:
992f8122d35SGreg Clayton   //   Reg1 = [CFA-8]
993f8122d35SGreg Clayton   //   Reg2 = [CFA-16]
994f8122d35SGreg Clayton   //   Reg3 = [CFA+8]
995a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
996a1a3fdcdSGreg Clayton   constexpr uint8_t Reg2 = 15;
997a1a3fdcdSGreg Clayton   constexpr uint8_t Reg3 = 16;
998f8122d35SGreg Clayton   constexpr uint8_t Neg1SLEB = 0x7f;
999f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1000f8122d35SGreg Clayton       parseCFI(TestFDE,
1001f8122d35SGreg Clayton                {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended,
1002f8122d35SGreg Clayton                 Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}),
1003f8122d35SGreg Clayton       Succeeded());
1004f8122d35SGreg Clayton 
1005f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1006f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1007f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1008f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1009f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1010f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1011f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1012f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1013f8122d35SGreg Clayton       Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8));
1014f8122d35SGreg Clayton 
1015f8122d35SGreg Clayton   // Verify we catch state machine error.
1016f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1017f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1018f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1019f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1020f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1021f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1022f8122d35SGreg Clayton }
1023f8122d35SGreg Clayton 
1024f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) {
1025f8122d35SGreg Clayton   // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when
1026f8122d35SGreg Clayton   // parsed in the state machine.
1027f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1028f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1029f8122d35SGreg Clayton                                  /*Length=*/0xff);
1030f8122d35SGreg Clayton 
1031f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1032f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1033f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1034f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1035f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1036f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1037f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1038f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1039f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1040f8122d35SGreg Clayton 
1041f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1042f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1043f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1044f8122d35SGreg Clayton                     Succeeded());
1045f8122d35SGreg Clayton 
1046f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the
1047f8122d35SGreg Clayton   // unwind rules for the follwing registers:
1048f8122d35SGreg Clayton   //   Reg1 = [CFA-8]
1049f8122d35SGreg Clayton   //   Reg2 = [CFA-16]
1050f8122d35SGreg Clayton   //   Reg3 = [CFA+8]
1051a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1052a1a3fdcdSGreg Clayton   constexpr uint8_t Reg2 = 15;
1053f8122d35SGreg Clayton   constexpr uint8_t Neg1SLEB = 0x7f;
1054f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1055f8122d35SGreg Clayton       parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1,
1056f8122d35SGreg Clayton                          dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}),
1057f8122d35SGreg Clayton       Succeeded());
1058f8122d35SGreg Clayton 
1059f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1060f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1061f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1062f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1063f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8));
1064f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1065f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8));
1066f8122d35SGreg Clayton 
1067f8122d35SGreg Clayton   // Verify we catch state machine error.
1068f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1069f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1070f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1071f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1072f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1073f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1074f8122d35SGreg Clayton }
1075f8122d35SGreg Clayton 
1076f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) {
1077f8122d35SGreg Clayton   // Test that DW_CFA_nop works as expected when parsed in the state machine.
1078f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1079f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1080f8122d35SGreg Clayton                                  /*Length=*/0xff);
1081f8122d35SGreg Clayton 
1082f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1083f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1084f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1085f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1086f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1087f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1088f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1089f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1090f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1091f8122d35SGreg Clayton 
1092f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1093f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1094f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1095f8122d35SGreg Clayton                     Succeeded());
1096f8122d35SGreg Clayton 
1097f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that changes the
1098f8122d35SGreg Clayton   // unwind rules for the follwing registers:
1099f8122d35SGreg Clayton   //   Reg1 = [CFA-8]
1100f8122d35SGreg Clayton   // The opcodes for setting Reg1 are preceded by a DW_CFA_nop.
1101a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1102f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1103f8122d35SGreg Clayton       parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}),
1104f8122d35SGreg Clayton       Succeeded());
1105f8122d35SGreg Clayton 
1106f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1107f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1108f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1109f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1110f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1111f8122d35SGreg Clayton 
1112f8122d35SGreg Clayton   // Verify we catch state machine error.
1113f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1114f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1115f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1116f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1117f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1118f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1119f8122d35SGreg Clayton }
1120f8122d35SGreg Clayton 
1121f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) {
1122f8122d35SGreg Clayton   // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected
1123f8122d35SGreg Clayton   // when parsed in the state machine.
1124f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1125f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1126f8122d35SGreg Clayton                                  /*Length=*/0xff);
1127f8122d35SGreg Clayton 
1128f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1129f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1130f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1131f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1132f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1133f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1134f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1135f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1136f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1137f8122d35SGreg Clayton 
1138f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1139f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1140f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1141f8122d35SGreg Clayton                     Succeeded());
1142f8122d35SGreg Clayton 
1143f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1144f8122d35SGreg Clayton   // follwing rows:
1145f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=[CFA-8]
1146f8122d35SGreg Clayton   // 0x1004: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16]
1147f8122d35SGreg Clayton   // 0x1008: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24]
1148f8122d35SGreg Clayton   // 0x100C: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16]
1149f8122d35SGreg Clayton   // 0x1010: CFA=reg12+32: Reg1=[CFA-8]
1150f8122d35SGreg Clayton   // This state machine will:
1151f8122d35SGreg Clayton   //  - set Reg1 location
1152f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1153f8122d35SGreg Clayton   //  - remember the state
1154f8122d35SGreg Clayton   //  - set Reg2 location
1155f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1156f8122d35SGreg Clayton   //  - remember the state
1157f8122d35SGreg Clayton   //  - set Reg3 location
1158f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1159f8122d35SGreg Clayton   //  - remember the state where Reg1 and Reg2 were set
1160f8122d35SGreg Clayton   //  - push a row (from DW_CFA_advance_loc)
1161f8122d35SGreg Clayton   //  - remember the state where only Reg1 was set
1162f8122d35SGreg Clayton   //  - push a row (automatically at the end of instruction parsing)
1163f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1164a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1165a1a3fdcdSGreg Clayton   constexpr uint8_t Reg2 = 15;
1166a1a3fdcdSGreg Clayton   constexpr uint8_t Reg3 = 16;
1167f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1168f8122d35SGreg Clayton       parseCFI(TestFDE,
1169f8122d35SGreg Clayton                {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4,
1170f8122d35SGreg Clayton                 dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2,
1171f8122d35SGreg Clayton                 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state,
1172f8122d35SGreg Clayton                 dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4,
1173f8122d35SGreg Clayton                 dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4,
1174f8122d35SGreg Clayton                 dwarf::DW_CFA_restore_state}),
1175f8122d35SGreg Clayton       Succeeded());
1176f8122d35SGreg Clayton 
1177f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1178f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1179f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs1;
1180f8122d35SGreg Clayton   VerifyLocs1.setRegisterLocation(
1181f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1182f8122d35SGreg Clayton 
1183f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs2;
1184f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
1185f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1186f8122d35SGreg Clayton   VerifyLocs2.setRegisterLocation(
1187f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1188f8122d35SGreg Clayton 
1189f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs3;
1190f8122d35SGreg Clayton   VerifyLocs3.setRegisterLocation(
1191f8122d35SGreg Clayton       Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
1192f8122d35SGreg Clayton   VerifyLocs3.setRegisterLocation(
1193f8122d35SGreg Clayton       Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
1194f8122d35SGreg Clayton   VerifyLocs3.setRegisterLocation(
1195f8122d35SGreg Clayton       Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24));
1196f8122d35SGreg Clayton 
1197f8122d35SGreg Clayton   // Verify we catch state machine error.
1198f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1199f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1200f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1201f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 5u);
1202f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1203f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
1204f8122d35SGreg Clayton 
1205f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
1206f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
1207f8122d35SGreg Clayton 
1208f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
1209f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3);
1210f8122d35SGreg Clayton 
1211f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getAddress(), 0x100Cu);
1212f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2);
1213f8122d35SGreg Clayton 
1214f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
1215f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1);
1216f8122d35SGreg Clayton }
1217f8122d35SGreg Clayton 
1218f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) {
1219f8122d35SGreg Clayton   // Test that DW_CFA_undefined works as expected when parsed in the state
1220f8122d35SGreg Clayton   // machine.
1221f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1222f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1223f8122d35SGreg Clayton                                  /*Length=*/0xff);
1224f8122d35SGreg Clayton 
1225f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1226f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1227f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1228f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1229f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1230f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1231f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1232f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1233f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1234f8122d35SGreg Clayton 
1235f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1236f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1237f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1238f8122d35SGreg Clayton                     Succeeded());
1239f8122d35SGreg Clayton 
1240f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1241f8122d35SGreg Clayton   // follwing rows:
1242f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=undefined
1243f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1244a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1245f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}),
1246f8122d35SGreg Clayton                     Succeeded());
1247f8122d35SGreg Clayton 
1248f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1249f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1250f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1251f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(Reg1,
1252f8122d35SGreg Clayton                                  dwarf::UnwindLocation::createUndefined());
1253f8122d35SGreg Clayton 
1254f8122d35SGreg Clayton   // Verify we catch state machine error.
1255f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1256f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1257f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1258f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1259f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1260f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1261f8122d35SGreg Clayton }
1262f8122d35SGreg Clayton 
1263f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) {
1264f8122d35SGreg Clayton   // Test that DW_CFA_same_value works as expected when parsed in the state
1265f8122d35SGreg Clayton   // machine.
1266f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1267f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1268f8122d35SGreg Clayton                                  /*Length=*/0xff);
1269f8122d35SGreg Clayton 
1270f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1271f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1272f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1273f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1274f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1275f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1276f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1277f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1278f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1279f8122d35SGreg Clayton 
1280f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1281f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1282f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1283f8122d35SGreg Clayton                     Succeeded());
1284f8122d35SGreg Clayton 
1285f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1286f8122d35SGreg Clayton   // follwing rows:
1287f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=same
1288f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1289a1a3fdcdSGreg Clayton   constexpr uint8_t Reg1 = 14;
1290f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}),
1291f8122d35SGreg Clayton                     Succeeded());
1292f8122d35SGreg Clayton 
1293f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1294f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1295f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1296f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame());
1297f8122d35SGreg Clayton 
1298f8122d35SGreg Clayton   // Verify we catch state machine error.
1299f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1300f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1301f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1302f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1303f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1304f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1305f8122d35SGreg Clayton }
1306f8122d35SGreg Clayton 
1307f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) {
1308f8122d35SGreg Clayton   // Test that DW_CFA_register works as expected when parsed in the state
1309f8122d35SGreg Clayton   // machine.
1310f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1311f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1312f8122d35SGreg Clayton                                  /*Length=*/0xff);
1313f8122d35SGreg Clayton 
1314f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1315f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1316f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1317f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1318f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1319f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1320f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1321f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1322f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1323f8122d35SGreg Clayton 
1324f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1325f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1326f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1327f8122d35SGreg Clayton                     Succeeded());
1328f8122d35SGreg Clayton 
1329f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1330f8122d35SGreg Clayton   // follwing rows:
1331f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=same
1332f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1333f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1334f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
1335f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}),
1336f8122d35SGreg Clayton                     Succeeded());
1337f8122d35SGreg Clayton 
1338f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1339f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1340f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1341f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1342f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1343f8122d35SGreg Clayton 
1344f8122d35SGreg Clayton   // Verify we catch state machine error.
1345f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1346f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1347f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1348f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1349f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1350f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1351f8122d35SGreg Clayton }
1352f8122d35SGreg Clayton 
1353f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) {
1354f8122d35SGreg Clayton   // Test that DW_CFA_expression works as expected when parsed in the state
1355f8122d35SGreg Clayton   // machine.
1356f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1357f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1358f8122d35SGreg Clayton                                  /*Length=*/0xff);
1359f8122d35SGreg Clayton 
1360f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1361f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1362f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1363f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1364f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1365f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1366f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1367f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1368f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1369f8122d35SGreg Clayton 
1370f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1371f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1372f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1373f8122d35SGreg Clayton                     Succeeded());
1374f8122d35SGreg Clayton 
1375f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1376f8122d35SGreg Clayton   // follwing rows:
1377f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1378f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1379f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1380f8122d35SGreg Clayton   constexpr uint8_t AddrSize = 8;
1381f8122d35SGreg Clayton   std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1,
1382f8122d35SGreg Clayton                                    dwarf::DW_OP_reg12};
1383f8122d35SGreg Clayton 
1384f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded());
1385f8122d35SGreg Clayton 
1386f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1387f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1388f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1389f8122d35SGreg Clayton 
1390f8122d35SGreg Clayton   std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12};
1391f8122d35SGreg Clayton   DataExtractor ExprData(ExprBytes, true, AddrSize);
1392f8122d35SGreg Clayton   DWARFExpression Expr(ExprData, AddrSize);
1393f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1394f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr));
1395f8122d35SGreg Clayton 
1396f8122d35SGreg Clayton   // Verify we catch state machine error.
1397f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1398f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1399f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1400f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1401f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1402f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1403f8122d35SGreg Clayton }
1404f8122d35SGreg Clayton 
1405f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) {
1406f8122d35SGreg Clayton   // Test that DW_CFA_val_expression works as expected when parsed in the state
1407f8122d35SGreg Clayton   // machine.
1408f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1409f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1410f8122d35SGreg Clayton                                  /*Length=*/0xff);
1411f8122d35SGreg Clayton 
1412f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1413f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1414f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1415f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1416f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1417f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1418f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1419f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1420f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1421f8122d35SGreg Clayton 
1422f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1423f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1424f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
1425f8122d35SGreg Clayton                     Succeeded());
1426f8122d35SGreg Clayton 
1427f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that encodes the
1428f8122d35SGreg Clayton   // follwing rows:
1429f8122d35SGreg Clayton   // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12)
1430f8122d35SGreg Clayton   // Then we verify that all registers are correct in all generated rows.
1431f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1432f8122d35SGreg Clayton   constexpr uint8_t AddrSize = 8;
1433f8122d35SGreg Clayton   std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1,
1434f8122d35SGreg Clayton                                    dwarf::DW_OP_reg12};
1435f8122d35SGreg Clayton 
1436f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded());
1437f8122d35SGreg Clayton 
1438f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1439f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1440f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1441f8122d35SGreg Clayton 
1442f8122d35SGreg Clayton   std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12};
1443f8122d35SGreg Clayton   DataExtractor ExprData(ExprBytes, true, AddrSize);
1444f8122d35SGreg Clayton   DWARFExpression Expr(ExprData, AddrSize);
1445f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1446f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr));
1447f8122d35SGreg Clayton 
1448f8122d35SGreg Clayton   // Verify we catch state machine error.
1449f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1450f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1451f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1452f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 1u);
1453f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1454f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1455f8122d35SGreg Clayton }
1456f8122d35SGreg Clayton 
1457f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) {
1458f8122d35SGreg Clayton   // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register,
1459f8122d35SGreg Clayton   // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when
1460f8122d35SGreg Clayton   // parsed in the state machine.
1461f8122d35SGreg Clayton   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1462f8122d35SGreg Clayton                                  /*Offset=*/0x0,
1463f8122d35SGreg Clayton                                  /*Length=*/0xff);
1464f8122d35SGreg Clayton 
1465f8122d35SGreg Clayton   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1466f8122d35SGreg Clayton                      /*Offset=*/0x3333abcdabcd,
1467f8122d35SGreg Clayton                      /*Length=*/0x4444abcdabcd,
1468f8122d35SGreg Clayton                      /*CIEPointer=*/0x1111abcdabcd,
1469f8122d35SGreg Clayton                      /*InitialLocation=*/0x1000,
1470f8122d35SGreg Clayton                      /*AddressRange=*/0x1000,
1471f8122d35SGreg Clayton                      /*Cie=*/&TestCIE,
1472f8122d35SGreg Clayton                      /*LSDAAddress=*/None,
1473f8122d35SGreg Clayton                      /*Arch=*/Triple::x86_64);
1474f8122d35SGreg Clayton 
1475f8122d35SGreg Clayton   // Make a CIE that has a valid CFA definition and a single register unwind
1476f8122d35SGreg Clayton   // rule for register that we will verify is in all of the pushed rows.
1477f8122d35SGreg Clayton   constexpr uint8_t CFAReg1 = 12;
1478f8122d35SGreg Clayton   constexpr uint8_t CFAOff1 = 32;
1479f8122d35SGreg Clayton   constexpr uint8_t CFAReg2 = 13;
1480f8122d35SGreg Clayton   constexpr uint8_t CFAOff2 = 48;
1481f8122d35SGreg Clayton   constexpr uint8_t Reg = 13;
1482f8122d35SGreg Clayton   constexpr uint8_t InReg = 14;
1483f8122d35SGreg Clayton 
1484f8122d35SGreg Clayton   EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1,
1485f8122d35SGreg Clayton                                        dwarf::DW_CFA_register, Reg, InReg}),
1486f8122d35SGreg Clayton                     Succeeded());
1487f8122d35SGreg Clayton 
1488f8122d35SGreg Clayton   // Make a FDE with DWARF call frame instruction opcodes that use all of the
1489f8122d35SGreg Clayton   // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1490f8122d35SGreg Clayton   // create a row are correctly working.
1491f8122d35SGreg Clayton   EXPECT_THAT_ERROR(
1492f8122d35SGreg Clayton       parseCFI(
1493f8122d35SGreg Clayton           TestFDE,
1494f8122d35SGreg Clayton           {
1495f8122d35SGreg Clayton               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register,
1496f8122d35SGreg Clayton               CFAReg2, dwarf::DW_CFA_advance_loc | 4,
1497f8122d35SGreg Clayton               dwarf::DW_CFA_def_cfa_offset, CFAOff2,
1498f8122d35SGreg Clayton               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf,
1499f8122d35SGreg Clayton               0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1500f8122d35SGreg Clayton               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1,
1501f8122d35SGreg Clayton               0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1502f8122d35SGreg Clayton           }),
1503f8122d35SGreg Clayton       Succeeded());
1504f8122d35SGreg Clayton 
1505f8122d35SGreg Clayton   // Create locations that we expect the UnwindRow objects to contain after
1506f8122d35SGreg Clayton   // parsing the DWARF call frame instructions.
1507f8122d35SGreg Clayton   dwarf::RegisterLocations VerifyLocs;
1508f8122d35SGreg Clayton   VerifyLocs.setRegisterLocation(
1509f8122d35SGreg Clayton       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1510f8122d35SGreg Clayton 
1511f8122d35SGreg Clayton   // Verify we catch state machine error.
1512f8122d35SGreg Clayton   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1513f8122d35SGreg Clayton   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1514f8122d35SGreg Clayton   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1515f8122d35SGreg Clayton   EXPECT_EQ(Rows.size(), 5u);
1516f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1517f8122d35SGreg Clayton   EXPECT_EQ(
1518f8122d35SGreg Clayton       Rows[0].getCFAValue(),
1519f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1));
1520f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
1521f8122d35SGreg Clayton   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1522f8122d35SGreg Clayton 
1523f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
1524f8122d35SGreg Clayton   EXPECT_EQ(
1525f8122d35SGreg Clayton       Rows[1].getCFAValue(),
1526f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1));
1527f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
1528f8122d35SGreg Clayton   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
1529f8122d35SGreg Clayton 
1530f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
1531f8122d35SGreg Clayton   EXPECT_EQ(
1532f8122d35SGreg Clayton       Rows[2].getCFAValue(),
1533f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2));
1534f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
1535f8122d35SGreg Clayton   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
1536f8122d35SGreg Clayton 
1537f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
1538f8122d35SGreg Clayton   EXPECT_EQ(
1539f8122d35SGreg Clayton       Rows[3].getCFAValue(),
1540f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1));
1541f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
1542f8122d35SGreg Clayton   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
1543f8122d35SGreg Clayton 
1544f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
1545f8122d35SGreg Clayton   EXPECT_EQ(
1546f8122d35SGreg Clayton       Rows[4].getCFAValue(),
1547f8122d35SGreg Clayton       dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2));
1548f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
1549f8122d35SGreg Clayton   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
1550f8122d35SGreg Clayton }
1551f8122d35SGreg Clayton 
1552*167e7afcSRamNalamothu TEST(DWARFDebugFrame, UnwindTable_DW_CFA_LLVM_def_aspace_cfa) {
1553*167e7afcSRamNalamothu   // Test that DW_CFA_LLVM_def_aspace_cfa, DW_CFA_LLVM_def_aspace_cfa_sf,
1554*167e7afcSRamNalamothu   // DW_CFA_def_cfa_register, DW_CFA_def_cfa_offset, and
1555*167e7afcSRamNalamothu   // DW_CFA_def_cfa_offset_sf works as expected when parsed in the state
1556*167e7afcSRamNalamothu   // machine.
1557*167e7afcSRamNalamothu   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
1558*167e7afcSRamNalamothu                                  /*Offset=*/0x0,
1559*167e7afcSRamNalamothu                                  /*Length=*/0xff);
1560*167e7afcSRamNalamothu 
1561*167e7afcSRamNalamothu   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
1562*167e7afcSRamNalamothu                      /*Offset=*/0x3333abcdabcd,
1563*167e7afcSRamNalamothu                      /*Length=*/0x4444abcdabcd,
1564*167e7afcSRamNalamothu                      /*CIEPointer=*/0x1111abcdabcd,
1565*167e7afcSRamNalamothu                      /*InitialLocation=*/0x1000,
1566*167e7afcSRamNalamothu                      /*AddressRange=*/0x1000,
1567*167e7afcSRamNalamothu                      /*Cie=*/&TestCIE,
1568*167e7afcSRamNalamothu                      /*LSDAAddress=*/None,
1569*167e7afcSRamNalamothu                      /*Arch=*/Triple::x86_64);
1570*167e7afcSRamNalamothu 
1571*167e7afcSRamNalamothu   // Make a CIE that has a valid CFA definition and a single register unwind
1572*167e7afcSRamNalamothu   // rule for register that we will verify is in all of the pushed rows.
1573*167e7afcSRamNalamothu   constexpr uint8_t CFAReg1 = 12;
1574*167e7afcSRamNalamothu   constexpr uint8_t CFAOff1 = 32;
1575*167e7afcSRamNalamothu   constexpr uint8_t CFAReg2 = 13;
1576*167e7afcSRamNalamothu   constexpr uint8_t CFAOff2 = 48;
1577*167e7afcSRamNalamothu   constexpr uint8_t Reg = 13;
1578*167e7afcSRamNalamothu   constexpr uint8_t InReg = 14;
1579*167e7afcSRamNalamothu   constexpr uint8_t AddrSpace = 2;
1580*167e7afcSRamNalamothu 
1581*167e7afcSRamNalamothu   EXPECT_THAT_ERROR(
1582*167e7afcSRamNalamothu       parseCFI(TestCIE, {dwarf::DW_CFA_LLVM_def_aspace_cfa, CFAReg1, CFAOff1,
1583*167e7afcSRamNalamothu                          AddrSpace, dwarf::DW_CFA_register, Reg, InReg}),
1584*167e7afcSRamNalamothu       Succeeded());
1585*167e7afcSRamNalamothu 
1586*167e7afcSRamNalamothu   // Make a FDE with DWARF call frame instruction opcodes that use all of the
1587*167e7afcSRamNalamothu   // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should
1588*167e7afcSRamNalamothu   // create a row are correctly working.
1589*167e7afcSRamNalamothu   EXPECT_THAT_ERROR(
1590*167e7afcSRamNalamothu       parseCFI(
1591*167e7afcSRamNalamothu           TestFDE,
1592*167e7afcSRamNalamothu           {
1593*167e7afcSRamNalamothu               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register,
1594*167e7afcSRamNalamothu               CFAReg2, dwarf::DW_CFA_advance_loc | 4,
1595*167e7afcSRamNalamothu               dwarf::DW_CFA_def_cfa_offset, CFAOff2,
1596*167e7afcSRamNalamothu               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf,
1597*167e7afcSRamNalamothu               0x7c, // -4 SLEB to make offset = 32 (CFAOff1)
1598*167e7afcSRamNalamothu               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1,
1599*167e7afcSRamNalamothu               0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2)
1600*167e7afcSRamNalamothu           }),
1601*167e7afcSRamNalamothu       Succeeded());
1602*167e7afcSRamNalamothu 
1603*167e7afcSRamNalamothu   // Create locations that we expect the UnwindRow objects to contain after
1604*167e7afcSRamNalamothu   // parsing the DWARF call frame instructions.
1605*167e7afcSRamNalamothu   dwarf::RegisterLocations VerifyLocs;
1606*167e7afcSRamNalamothu   VerifyLocs.setRegisterLocation(
1607*167e7afcSRamNalamothu       Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
1608*167e7afcSRamNalamothu 
1609*167e7afcSRamNalamothu   // Verify we catch state machine error.
1610*167e7afcSRamNalamothu   Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
1611*167e7afcSRamNalamothu   EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
1612*167e7afcSRamNalamothu   const dwarf::UnwindTable &Rows = RowsOrErr.get();
1613*167e7afcSRamNalamothu   EXPECT_EQ(Rows.size(), 5u);
1614*167e7afcSRamNalamothu   EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
1615*167e7afcSRamNalamothu   EXPECT_EQ(Rows[0].getCFAValue(),
1616*167e7afcSRamNalamothu             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1,
1617*167e7afcSRamNalamothu                                                               AddrSpace));
1618*167e7afcSRamNalamothu   EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
1619*167e7afcSRamNalamothu   EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
1620*167e7afcSRamNalamothu 
1621*167e7afcSRamNalamothu   EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
1622*167e7afcSRamNalamothu   EXPECT_EQ(Rows[1].getCFAValue(),
1623*167e7afcSRamNalamothu             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1,
1624*167e7afcSRamNalamothu                                                               AddrSpace));
1625*167e7afcSRamNalamothu   EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
1626*167e7afcSRamNalamothu   EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
1627*167e7afcSRamNalamothu 
1628*167e7afcSRamNalamothu   EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
1629*167e7afcSRamNalamothu   EXPECT_EQ(Rows[2].getCFAValue(),
1630*167e7afcSRamNalamothu             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2,
1631*167e7afcSRamNalamothu                                                               AddrSpace));
1632*167e7afcSRamNalamothu   EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
1633*167e7afcSRamNalamothu   EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
1634*167e7afcSRamNalamothu 
1635*167e7afcSRamNalamothu   EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
1636*167e7afcSRamNalamothu   EXPECT_EQ(Rows[3].getCFAValue(),
1637*167e7afcSRamNalamothu             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1,
1638*167e7afcSRamNalamothu                                                               AddrSpace));
1639*167e7afcSRamNalamothu   EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
1640*167e7afcSRamNalamothu   EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
1641*167e7afcSRamNalamothu 
1642*167e7afcSRamNalamothu   EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
1643*167e7afcSRamNalamothu   EXPECT_EQ(Rows[4].getCFAValue(),
1644*167e7afcSRamNalamothu             dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2,
1645*167e7afcSRamNalamothu                                                               AddrSpace));
1646*167e7afcSRamNalamothu   EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
1647*167e7afcSRamNalamothu   EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
1648*167e7afcSRamNalamothu }
1649*167e7afcSRamNalamothu 
1650cada5b88SIgor Kudrin } // end anonymous namespace
1651