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