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