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