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