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 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 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 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 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 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 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 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 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 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 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 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. 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