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