1 //===- DWARFDataExtractorTest.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/DebugInfo/DWARF/DWARFDataExtractor.h" 10 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 11 #include "llvm/Object/ObjectFile.h" 12 #include "llvm/ObjectYAML/yaml2obj.h" 13 #include "llvm/Testing/Support/Error.h" 14 #include "gtest/gtest.h" 15 16 using namespace llvm; 17 18 namespace { 19 20 TEST(DWARFDataExtractorTest, getRelocatedValue) { 21 StringRef Yaml = R"( 22 !ELF 23 FileHeader: 24 Class: ELFCLASS32 25 Data: ELFDATA2LSB 26 Type: ET_REL 27 Machine: EM_386 28 Sections: 29 - Name: .text 30 Type: SHT_PROGBITS 31 Size: 0x80 32 - Name: .debug_line 33 Type: SHT_PROGBITS 34 Content: '000000000000' 35 - Name: .rel.debug_line 36 Type: SHT_REL 37 Info: .debug_line 38 Relocations: 39 - Offset: 0 40 Symbol: f 41 Type: R_386_32 42 - Offset: 4 43 Symbol: f 44 Type: R_386_32 45 Symbols: 46 - Name: f 47 Type: STT_SECTION 48 Section: .text 49 Value: 0x42 50 )"; 51 SmallString<0> Storage; 52 std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile( 53 Storage, Yaml, [](const Twine &Err) { errs() << Err; }); 54 ASSERT_TRUE(Obj); 55 std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj); 56 const DWARFObject &DObj = Ctx->getDWARFObj(); 57 ASSERT_EQ(6u, DObj.getLineSection().Data.size()); 58 59 DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(), 60 Obj->getBytesInAddress()); 61 DataExtractor::Cursor C(0); 62 EXPECT_EQ(0x42u, Data.getRelocatedAddress(C)); 63 EXPECT_EQ(0u, Data.getRelocatedAddress(C)); 64 EXPECT_THAT_ERROR(C.takeError(), 65 FailedWithMessage("unexpected end of data at offset 0x4")); 66 } 67 68 TEST(DWARFDataExtractorTest, getInitialLength) { 69 auto GetWithError = [](ArrayRef<uint8_t> Bytes) 70 -> Expected<std::tuple<uint64_t, dwarf::DwarfFormat, uint64_t>> { 71 DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8); 72 DWARFDataExtractor::Cursor C(0); 73 uint64_t Length; 74 dwarf::DwarfFormat Format; 75 std::tie(Length, Format) = Data.getInitialLength(C); 76 if (C) 77 return std::make_tuple(Length, Format, C.tell()); 78 79 EXPECT_EQ(Length, 0u); 80 EXPECT_EQ(Format, dwarf::DWARF32); 81 EXPECT_EQ(C.tell(), 0u); 82 return C.takeError(); 83 }; 84 auto GetWithoutError = [](ArrayRef<uint8_t> Bytes) { 85 DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8); 86 uint64_t Offset = 0; 87 uint64_t Length; 88 dwarf::DwarfFormat Format; 89 std::tie(Length, Format) = Data.getInitialLength(&Offset); 90 return std::make_tuple(Length, Format, Offset); 91 }; 92 auto ErrorResult = std::make_tuple(0, dwarf::DWARF32, 0); 93 94 // Empty data. 95 EXPECT_THAT_EXPECTED( 96 GetWithError({}), 97 FailedWithMessage("unexpected end of data at offset 0x0")); 98 EXPECT_EQ(GetWithoutError({}), ErrorResult); 99 100 // Not long enough for the U32 field. 101 EXPECT_THAT_EXPECTED( 102 GetWithError({0x00, 0x01, 0x02}), 103 FailedWithMessage("unexpected end of data at offset 0x0")); 104 EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02}), ErrorResult); 105 106 EXPECT_THAT_EXPECTED( 107 GetWithError({0x00, 0x01, 0x02, 0x03}), 108 HasValue(std::make_tuple(0x00010203, dwarf::DWARF32, 4))); 109 EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02, 0x03}), 110 std::make_tuple(0x00010203, dwarf::DWARF32, 4)); 111 112 // Zeroes are not an error, but without the Error object it is hard to tell 113 // them apart from a failed read. 114 EXPECT_THAT_EXPECTED( 115 GetWithError({0x00, 0x00, 0x00, 0x00}), 116 HasValue(std::make_tuple(0x00000000, dwarf::DWARF32, 4))); 117 EXPECT_EQ(GetWithoutError({0x00, 0x00, 0x00, 0x00}), 118 std::make_tuple(0x00000000, dwarf::DWARF32, 4)); 119 120 // Smallest invalid value. 121 EXPECT_THAT_EXPECTED( 122 GetWithError({0xff, 0xff, 0xff, 0xf0}), 123 FailedWithMessage( 124 "unsupported reserved unit length of value 0xfffffff0")); 125 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xf0}), ErrorResult); 126 127 // DWARF64 marker without the subsequent length field. 128 EXPECT_THAT_EXPECTED( 129 GetWithError({0xff, 0xff, 0xff, 0xff}), 130 FailedWithMessage("unexpected end of data at offset 0x4")); 131 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff}), ErrorResult); 132 133 // Not enough data for the U64 length. 134 EXPECT_THAT_EXPECTED( 135 GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}), 136 FailedWithMessage("unexpected end of data at offset 0x4")); 137 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}), 138 ErrorResult); 139 140 EXPECT_THAT_EXPECTED( 141 GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 142 0x06, 0x07}), 143 HasValue(std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12))); 144 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 145 0x04, 0x05, 0x06, 0x07}), 146 std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12)); 147 } 148 149 TEST(DWARFDataExtractorTest, Truncation) { 150 StringRef Yaml = R"( 151 !ELF 152 FileHeader: 153 Class: ELFCLASS32 154 Data: ELFDATA2LSB 155 Type: ET_REL 156 Machine: EM_386 157 Sections: 158 - Name: .text 159 Type: SHT_PROGBITS 160 Size: 0x80 161 - Name: .debug_line 162 Type: SHT_PROGBITS 163 Content: '616263640000000065666768' 164 - Name: .rel.debug_line 165 Type: SHT_REL 166 Info: .debug_line 167 Relocations: 168 - Offset: 4 169 Symbol: f 170 Type: R_386_32 171 Symbols: 172 - Name: f 173 Type: STT_SECTION 174 Section: .text 175 Value: 0x42 176 )"; 177 SmallString<0> Storage; 178 std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile( 179 Storage, Yaml, [](const Twine &Err) { errs() << Err; }); 180 ASSERT_TRUE(Obj); 181 std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj); 182 const DWARFObject &DObj = Ctx->getDWARFObj(); 183 ASSERT_EQ(12u, DObj.getLineSection().Data.size()); 184 185 DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(), 186 Obj->getBytesInAddress()); 187 DataExtractor::Cursor C(0); 188 EXPECT_EQ(0x64636261u, Data.getRelocatedAddress(C)); 189 EXPECT_EQ(0x42u, Data.getRelocatedAddress(C)); 190 EXPECT_EQ(0x68676665u, Data.getRelocatedAddress(C)); 191 EXPECT_THAT_ERROR(C.takeError(), Succeeded()); 192 193 C = DataExtractor::Cursor{0}; 194 DWARFDataExtractor Truncated8(Data, 8); 195 EXPECT_EQ(0x64636261u, Truncated8.getRelocatedAddress(C)); 196 EXPECT_EQ(0x42u, Truncated8.getRelocatedAddress(C)); 197 EXPECT_EQ(0x0u, Truncated8.getRelocatedAddress(C)); 198 EXPECT_THAT_ERROR(C.takeError(), 199 FailedWithMessage("unexpected end of data at offset 0x8")); 200 201 C = DataExtractor::Cursor{0}; 202 DWARFDataExtractor Truncated6(Data, 6); 203 EXPECT_EQ(0x64636261u, Truncated6.getRelocatedAddress(C)); 204 EXPECT_EQ(0x0u, Truncated6.getRelocatedAddress(C)); 205 EXPECT_THAT_ERROR(C.takeError(), 206 FailedWithMessage("unexpected end of data at offset 0x4")); 207 208 C = DataExtractor::Cursor{0}; 209 DWARFDataExtractor Truncated2(Data, 2); 210 EXPECT_EQ(0x0u, Truncated2.getRelocatedAddress(C)); 211 EXPECT_THAT_ERROR(C.takeError(), 212 FailedWithMessage("unexpected end of data at offset 0x0")); 213 } 214 215 } // namespace 216