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 
9cada5b88SIgor Kudrin #include "llvm/ADT/SmallVector.h"
10cada5b88SIgor Kudrin #include "llvm/ADT/StringRef.h"
11cada5b88SIgor Kudrin #include "llvm/BinaryFormat/Dwarf.h"
12cada5b88SIgor Kudrin #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
13*1e820e82SGeorgii Rymar #include "llvm/Testing/Support/Error.h"
14cada5b88SIgor Kudrin #include "gtest/gtest.h"
15cada5b88SIgor Kudrin 
16cada5b88SIgor Kudrin using namespace llvm;
17cada5b88SIgor Kudrin 
18cada5b88SIgor Kudrin namespace {
19cada5b88SIgor Kudrin 
20cada5b88SIgor Kudrin dwarf::CIE createCIE(bool IsDWARF64, uint64_t Offset, uint64_t Length) {
21cada5b88SIgor Kudrin   return dwarf::CIE(IsDWARF64, Offset, Length,
22cada5b88SIgor Kudrin                     /*Version=*/3,
23cada5b88SIgor Kudrin                     /*Augmentation=*/StringRef(),
24cada5b88SIgor Kudrin                     /*AddressSize=*/8,
25cada5b88SIgor Kudrin                     /*SegmentDescriptorSize=*/0,
26cada5b88SIgor Kudrin                     /*CodeAlignmentFactor=*/1,
27cada5b88SIgor Kudrin                     /*DataAlignmentFactor=*/-8,
28cada5b88SIgor Kudrin                     /*ReturnAddressRegister=*/16,
29cada5b88SIgor Kudrin                     /*AugmentationData=*/StringRef(),
30cada5b88SIgor Kudrin                     /*FDEPointerEncoding=*/dwarf::DW_EH_PE_absptr,
31cada5b88SIgor Kudrin                     /*LSDAPointerEncoding=*/dwarf::DW_EH_PE_omit,
32cada5b88SIgor Kudrin                     /*Personality=*/None,
33cada5b88SIgor Kudrin                     /*PersonalityEnc=*/None,
34cada5b88SIgor Kudrin                     /*Arch=*/Triple::x86_64);
35cada5b88SIgor Kudrin }
36cada5b88SIgor Kudrin 
37cada5b88SIgor Kudrin void expectDumpResult(const dwarf::CIE &TestCIE, bool IsEH,
38cada5b88SIgor Kudrin                       StringRef ExpectedFirstLine) {
39cada5b88SIgor Kudrin   std::string Output;
40cada5b88SIgor Kudrin   raw_string_ostream OS(Output);
41cada5b88SIgor Kudrin   TestCIE.dump(OS, /*MRI=*/nullptr, IsEH);
42cada5b88SIgor Kudrin   OS.flush();
43cada5b88SIgor Kudrin   StringRef FirstLine = StringRef(Output).split('\n').first;
44cada5b88SIgor Kudrin   EXPECT_EQ(FirstLine, ExpectedFirstLine);
45cada5b88SIgor Kudrin }
46cada5b88SIgor Kudrin 
47cada5b88SIgor Kudrin void expectDumpResult(const dwarf::FDE &TestFDE, bool IsEH,
48cada5b88SIgor Kudrin                       StringRef ExpectedFirstLine) {
49cada5b88SIgor Kudrin   std::string Output;
50cada5b88SIgor Kudrin   raw_string_ostream OS(Output);
51cada5b88SIgor Kudrin   TestFDE.dump(OS, /*MRI=*/nullptr, IsEH);
52cada5b88SIgor Kudrin   OS.flush();
53cada5b88SIgor Kudrin   StringRef FirstLine = StringRef(Output).split('\n').first;
54cada5b88SIgor Kudrin   EXPECT_EQ(FirstLine, ExpectedFirstLine);
55cada5b88SIgor Kudrin }
56cada5b88SIgor Kudrin 
57cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF32CIE) {
58cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
59cada5b88SIgor Kudrin                                  /*Offset=*/0x1111abcd,
60cada5b88SIgor Kudrin                                  /*Length=*/0x2222abcd);
61cada5b88SIgor Kudrin   expectDumpResult(TestCIE, /*IsEH=*/false, "1111abcd 2222abcd ffffffff CIE");
62cada5b88SIgor Kudrin }
63cada5b88SIgor Kudrin 
64cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF64CIE) {
65cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
66cada5b88SIgor Kudrin                                  /*Offset=*/0x1111abcdabcd,
67cada5b88SIgor Kudrin                                  /*Length=*/0x2222abcdabcd);
68cada5b88SIgor Kudrin   expectDumpResult(TestCIE, /*IsEH=*/false,
69cada5b88SIgor Kudrin                    "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE");
70cada5b88SIgor Kudrin }
71cada5b88SIgor Kudrin 
72cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEHCIE) {
73cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
74cada5b88SIgor Kudrin                                  /*Offset=*/0x1000,
75cada5b88SIgor Kudrin                                  /*Length=*/0x20);
76cada5b88SIgor Kudrin   expectDumpResult(TestCIE, /*IsEH=*/true, "00001000 00000020 00000000 CIE");
77cada5b88SIgor Kudrin }
78cada5b88SIgor Kudrin 
79cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEH64CIE) {
80cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
81cada5b88SIgor Kudrin                                  /*Offset=*/0x1000,
82cada5b88SIgor Kudrin                                  /*Length=*/0x20);
83cada5b88SIgor Kudrin   expectDumpResult(TestCIE, /*IsEH=*/true,
84cada5b88SIgor Kudrin                    "00001000 0000000000000020 00000000 CIE");
85cada5b88SIgor Kudrin }
86cada5b88SIgor Kudrin 
87cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF64FDE) {
88cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
89cada5b88SIgor Kudrin                                  /*Offset=*/0x1111abcdabcd,
90cada5b88SIgor Kudrin                                  /*Length=*/0x2222abcdabcd);
91cada5b88SIgor Kudrin   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
92cada5b88SIgor Kudrin                      /*Offset=*/0x3333abcdabcd,
93cada5b88SIgor Kudrin                      /*Length=*/0x4444abcdabcd,
94cada5b88SIgor Kudrin                      /*CIEPointer=*/0x1111abcdabcd,
95cada5b88SIgor Kudrin                      /*InitialLocation=*/0x5555abcdabcd,
96cada5b88SIgor Kudrin                      /*AddressRange=*/0x111111111111,
97cada5b88SIgor Kudrin                      /*Cie=*/&TestCIE,
98cada5b88SIgor Kudrin                      /*LSDAAddress=*/None,
99cada5b88SIgor Kudrin                      /*Arch=*/Triple::x86_64);
100cada5b88SIgor Kudrin   expectDumpResult(TestFDE, /*IsEH=*/false,
101cada5b88SIgor Kudrin                    "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE "
102cada5b88SIgor Kudrin                    "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde");
103cada5b88SIgor Kudrin }
104cada5b88SIgor Kudrin 
105cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEH64FDE) {
106cada5b88SIgor Kudrin   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true,
107cada5b88SIgor Kudrin                                  /*Offset=*/0x1111ab9a000c,
108cada5b88SIgor Kudrin                                  /*Length=*/0x20);
109cada5b88SIgor Kudrin   dwarf::FDE TestFDE(/*IsDWARF64=*/true,
110cada5b88SIgor Kudrin                      /*Offset=*/0x1111abcdabcd,
111cada5b88SIgor Kudrin                      /*Length=*/0x2222abcdabcd,
112cada5b88SIgor Kudrin                      /*CIEPointer=*/0x33abcd,
113cada5b88SIgor Kudrin                      /*InitialLocation=*/0x4444abcdabcd,
114cada5b88SIgor Kudrin                      /*AddressRange=*/0x111111111111,
115cada5b88SIgor Kudrin                      /*Cie=*/&TestCIE,
116cada5b88SIgor Kudrin                      /*LSDAAddress=*/None,
117cada5b88SIgor Kudrin                      /*Arch=*/Triple::x86_64);
118cada5b88SIgor Kudrin   expectDumpResult(TestFDE, /*IsEH=*/true,
119cada5b88SIgor Kudrin                    "1111abcdabcd 00002222abcdabcd 0033abcd FDE "
120cada5b88SIgor Kudrin                    "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde");
121cada5b88SIgor Kudrin }
122cada5b88SIgor Kudrin 
123*1e820e82SGeorgii Rymar // Here we test how truncated Call Frame Instructions are parsed.
124*1e820e82SGeorgii Rymar TEST(DWARFDebugFrame, ParseTruncatedCFITest) {
125*1e820e82SGeorgii Rymar   auto ParseCFI = [](dwarf::CIE &C, ArrayRef<uint8_t> Instructions,
126*1e820e82SGeorgii Rymar                      Optional<uint64_t> Size = None) {
127*1e820e82SGeorgii Rymar     DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true,
128*1e820e82SGeorgii Rymar                             /*AddressSize=*/8);
129*1e820e82SGeorgii Rymar     uint64_t Offset = 0;
130*1e820e82SGeorgii Rymar     const uint64_t EndOffset = Size ? *Size : (uint64_t)Instructions.size();
131*1e820e82SGeorgii Rymar     return C.cfis().parse(Data, &Offset, EndOffset);
132*1e820e82SGeorgii Rymar   };
133*1e820e82SGeorgii Rymar 
134*1e820e82SGeorgii Rymar   dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false,
135*1e820e82SGeorgii Rymar                                  /*Offset=*/0x0,
136*1e820e82SGeorgii Rymar                                  /*Length=*/0xff);
137*1e820e82SGeorgii Rymar 
138*1e820e82SGeorgii Rymar   // Having an empty instructions list is fine.
139*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(ParseCFI(TestCIE, {}), Succeeded());
140*1e820e82SGeorgii Rymar 
141*1e820e82SGeorgii Rymar   // Unable to read an opcode, because the instructions list is empty, but we
142*1e820e82SGeorgii Rymar   // say to the parser that it is not.
143*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
144*1e820e82SGeorgii Rymar       ParseCFI(TestCIE, {}, /*Size=*/1),
145*1e820e82SGeorgii Rymar       FailedWithMessage(
146*1e820e82SGeorgii Rymar           "unexpected end of data at offset 0x0 while reading [0x0, 0x1)"));
147*1e820e82SGeorgii Rymar 
148*1e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_offset instruction.
149*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
150*1e820e82SGeorgii Rymar       ParseCFI(TestCIE, {dwarf::DW_CFA_offset}),
151*1e820e82SGeorgii Rymar       FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
152*1e820e82SGeorgii Rymar                         "malformed uleb128, extends past end"));
153*1e820e82SGeorgii Rymar 
154*1e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_set_loc instruction.
155*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
156*1e820e82SGeorgii Rymar       ParseCFI(TestCIE, {dwarf::DW_CFA_set_loc}),
157*1e820e82SGeorgii Rymar       FailedWithMessage(
158*1e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x9)"));
159*1e820e82SGeorgii Rymar 
160*1e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_advance_loc1 instruction.
161*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
162*1e820e82SGeorgii Rymar       ParseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}),
163*1e820e82SGeorgii Rymar       FailedWithMessage(
164*1e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x2)"));
165*1e820e82SGeorgii Rymar 
166*1e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_advance_loc2 instruction.
167*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
168*1e820e82SGeorgii Rymar       ParseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}),
169*1e820e82SGeorgii Rymar       FailedWithMessage(
170*1e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x3)"));
171*1e820e82SGeorgii Rymar 
172*1e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_advance_loc4 instruction.
173*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
174*1e820e82SGeorgii Rymar       ParseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}),
175*1e820e82SGeorgii Rymar       FailedWithMessage(
176*1e820e82SGeorgii Rymar           "unexpected end of data at offset 0x1 while reading [0x1, 0x5)"));
177*1e820e82SGeorgii Rymar 
178*1e820e82SGeorgii Rymar   // A test for an instruction with a single ULEB128 operand.
179*1e820e82SGeorgii Rymar   auto CheckOp_ULEB128 = [&](uint8_t Inst) {
180*1e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
181*1e820e82SGeorgii Rymar         ParseCFI(TestCIE, Inst),
182*1e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
183*1e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
184*1e820e82SGeorgii Rymar   };
185*1e820e82SGeorgii Rymar 
186*1e820e82SGeorgii Rymar   for (uint8_t Inst :
187*1e820e82SGeorgii Rymar        {dwarf::DW_CFA_restore_extended, dwarf::DW_CFA_undefined,
188*1e820e82SGeorgii Rymar         dwarf::DW_CFA_same_value, dwarf::DW_CFA_def_cfa_register,
189*1e820e82SGeorgii Rymar         dwarf::DW_CFA_def_cfa_offset, dwarf::DW_CFA_GNU_args_size})
190*1e820e82SGeorgii Rymar     CheckOp_ULEB128(Inst);
191*1e820e82SGeorgii Rymar 
192*1e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction.
193*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
194*1e820e82SGeorgii Rymar       ParseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_offset_sf}),
195*1e820e82SGeorgii Rymar       FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
196*1e820e82SGeorgii Rymar                         "malformed sleb128, extends past end"));
197*1e820e82SGeorgii Rymar 
198*1e820e82SGeorgii Rymar   // A test for an instruction with two ULEB128 operands.
199*1e820e82SGeorgii Rymar   auto CheckOp_ULEB128_ULEB128 = [&](uint8_t Inst) {
200*1e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
201*1e820e82SGeorgii Rymar         ParseCFI(TestCIE, Inst),
202*1e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
203*1e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
204*1e820e82SGeorgii Rymar 
205*1e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
206*1e820e82SGeorgii Rymar         ParseCFI(TestCIE, {Inst, /*Op1=*/0}),
207*1e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
208*1e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
209*1e820e82SGeorgii Rymar   };
210*1e820e82SGeorgii Rymar 
211*1e820e82SGeorgii Rymar   for (uint8_t Inst : {dwarf::DW_CFA_offset_extended, dwarf::DW_CFA_register,
212*1e820e82SGeorgii Rymar                        dwarf::DW_CFA_def_cfa, dwarf::DW_CFA_val_offset})
213*1e820e82SGeorgii Rymar     CheckOp_ULEB128_ULEB128(Inst);
214*1e820e82SGeorgii Rymar 
215*1e820e82SGeorgii Rymar   // A test for an instruction with two operands: ULEB128, SLEB128.
216*1e820e82SGeorgii Rymar   auto CheckOp_ULEB128_SLEB128 = [&](uint8_t Inst) {
217*1e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
218*1e820e82SGeorgii Rymar         ParseCFI(TestCIE, Inst),
219*1e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
220*1e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
221*1e820e82SGeorgii Rymar 
222*1e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
223*1e820e82SGeorgii Rymar         ParseCFI(TestCIE, {Inst, /*Op1=*/0}),
224*1e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
225*1e820e82SGeorgii Rymar                           "malformed sleb128, extends past end"));
226*1e820e82SGeorgii Rymar   };
227*1e820e82SGeorgii Rymar 
228*1e820e82SGeorgii Rymar   for (uint8_t Inst : {dwarf::DW_CFA_offset_extended_sf,
229*1e820e82SGeorgii Rymar                        dwarf::DW_CFA_def_cfa_sf, dwarf::DW_CFA_val_offset_sf})
230*1e820e82SGeorgii Rymar     CheckOp_ULEB128_SLEB128(Inst);
231*1e820e82SGeorgii Rymar 
232*1e820e82SGeorgii Rymar   // Unable to read a truncated DW_CFA_def_cfa_expression instruction.
233*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
234*1e820e82SGeorgii Rymar       ParseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}),
235*1e820e82SGeorgii Rymar       FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
236*1e820e82SGeorgii Rymar                         "malformed uleb128, extends past end"));
237*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(
238*1e820e82SGeorgii Rymar       ParseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
239*1e820e82SGeorgii Rymar                          /*expression length=*/0x1}),
240*1e820e82SGeorgii Rymar       FailedWithMessage(
241*1e820e82SGeorgii Rymar           "unexpected end of data at offset 0x2 while reading [0x2, 0x3)"));
242*1e820e82SGeorgii Rymar   // The DW_CFA_def_cfa_expression can contain a zero length expression.
243*1e820e82SGeorgii Rymar   EXPECT_THAT_ERROR(ParseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
244*1e820e82SGeorgii Rymar                                        /*ExprLen=*/0}),
245*1e820e82SGeorgii Rymar                     Succeeded());
246*1e820e82SGeorgii Rymar 
247*1e820e82SGeorgii Rymar   // A test for an instruction with three operands: ULEB128, expression length
248*1e820e82SGeorgii Rymar   // (ULEB128) and expression bytes.
249*1e820e82SGeorgii Rymar   auto CheckOp_ULEB128_Expr = [&](uint8_t Inst) {
250*1e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
251*1e820e82SGeorgii Rymar         ParseCFI(TestCIE, {Inst}),
252*1e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
253*1e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
254*1e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
255*1e820e82SGeorgii Rymar         ParseCFI(TestCIE, {Inst, /*Op1=*/0}),
256*1e820e82SGeorgii Rymar         FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
257*1e820e82SGeorgii Rymar                           "malformed uleb128, extends past end"));
258*1e820e82SGeorgii Rymar     // A zero length expression is fine
259*1e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(ParseCFI(TestCIE, {Inst,
260*1e820e82SGeorgii Rymar                                          /*Op1=*/0, /*ExprLen=*/0}),
261*1e820e82SGeorgii Rymar                       Succeeded());
262*1e820e82SGeorgii Rymar     EXPECT_THAT_ERROR(
263*1e820e82SGeorgii Rymar         ParseCFI(TestCIE, {Inst,
264*1e820e82SGeorgii Rymar                            /*Op1=*/0, /*ExprLen=*/1}),
265*1e820e82SGeorgii Rymar         FailedWithMessage(
266*1e820e82SGeorgii Rymar             "unexpected end of data at offset 0x3 while reading [0x3, 0x4)"));
267*1e820e82SGeorgii Rymar   };
268*1e820e82SGeorgii Rymar 
269*1e820e82SGeorgii Rymar   for (uint8_t Inst : {dwarf::DW_CFA_expression, dwarf::DW_CFA_val_expression})
270*1e820e82SGeorgii Rymar     CheckOp_ULEB128_Expr(Inst);
271*1e820e82SGeorgii Rymar }
272*1e820e82SGeorgii Rymar 
273cada5b88SIgor Kudrin } // end anonymous namespace
274