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( 65 C.takeError(), 66 FailedWithMessage( 67 "unexpected end of data at offset 0x6 while reading [0x4, 0x8)")); 68 } 69 70 TEST(DWARFDataExtractorTest, getInitialLength) { 71 auto GetWithError = [](ArrayRef<uint8_t> Bytes) 72 -> Expected<std::tuple<uint64_t, dwarf::DwarfFormat, uint64_t>> { 73 DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8); 74 DWARFDataExtractor::Cursor C(0); 75 uint64_t Length; 76 dwarf::DwarfFormat Format; 77 std::tie(Length, Format) = Data.getInitialLength(C); 78 if (C) 79 return std::make_tuple(Length, Format, C.tell()); 80 81 EXPECT_EQ(Length, 0u); 82 EXPECT_EQ(Format, dwarf::DWARF32); 83 EXPECT_EQ(C.tell(), 0u); 84 return C.takeError(); 85 }; 86 auto GetWithoutError = [](ArrayRef<uint8_t> Bytes) { 87 DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8); 88 uint64_t Offset = 0; 89 uint64_t Length; 90 dwarf::DwarfFormat Format; 91 std::tie(Length, Format) = Data.getInitialLength(&Offset); 92 return std::make_tuple(Length, Format, Offset); 93 }; 94 auto ErrorResult = std::make_tuple(0, dwarf::DWARF32, 0); 95 96 // Empty data. 97 EXPECT_THAT_EXPECTED( 98 GetWithError({}), 99 FailedWithMessage( 100 "unexpected end of data at offset 0x0 while reading [0x0, 0x4)")); 101 EXPECT_EQ(GetWithoutError({}), ErrorResult); 102 103 // Not long enough for the U32 field. 104 EXPECT_THAT_EXPECTED( 105 GetWithError({0x00, 0x01, 0x02}), 106 FailedWithMessage( 107 "unexpected end of data at offset 0x3 while reading [0x0, 0x4)")); 108 EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02}), ErrorResult); 109 110 EXPECT_THAT_EXPECTED( 111 GetWithError({0x00, 0x01, 0x02, 0x03}), 112 HasValue(std::make_tuple(0x00010203, dwarf::DWARF32, 4))); 113 EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02, 0x03}), 114 std::make_tuple(0x00010203, dwarf::DWARF32, 4)); 115 116 // Zeroes are not an error, but without the Error object it is hard to tell 117 // them apart from a failed read. 118 EXPECT_THAT_EXPECTED( 119 GetWithError({0x00, 0x00, 0x00, 0x00}), 120 HasValue(std::make_tuple(0x00000000, dwarf::DWARF32, 4))); 121 EXPECT_EQ(GetWithoutError({0x00, 0x00, 0x00, 0x00}), 122 std::make_tuple(0x00000000, dwarf::DWARF32, 4)); 123 124 // Smallest invalid value. 125 EXPECT_THAT_EXPECTED( 126 GetWithError({0xff, 0xff, 0xff, 0xf0}), 127 FailedWithMessage( 128 "unsupported reserved unit length of value 0xfffffff0")); 129 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xf0}), ErrorResult); 130 131 // DWARF64 marker without the subsequent length field. 132 EXPECT_THAT_EXPECTED( 133 GetWithError({0xff, 0xff, 0xff, 0xff}), 134 FailedWithMessage( 135 "unexpected end of data at offset 0x4 while reading [0x4, 0xc)")); 136 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff}), ErrorResult); 137 138 // Not enough data for the U64 length. 139 EXPECT_THAT_EXPECTED( 140 GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}), 141 FailedWithMessage( 142 "unexpected end of data at offset 0x8 while reading [0x4, 0xc)")); 143 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}), 144 ErrorResult); 145 146 EXPECT_THAT_EXPECTED( 147 GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 148 0x06, 0x07}), 149 HasValue(std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12))); 150 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 151 0x04, 0x05, 0x06, 0x07}), 152 std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12)); 153 } 154 155 TEST(DWARFDataExtractorTest, Truncation) { 156 StringRef Yaml = R"( 157 !ELF 158 FileHeader: 159 Class: ELFCLASS32 160 Data: ELFDATA2LSB 161 Type: ET_REL 162 Machine: EM_386 163 Sections: 164 - Name: .text 165 Type: SHT_PROGBITS 166 Size: 0x80 167 - Name: .debug_line 168 Type: SHT_PROGBITS 169 Content: '616263640000000065666768' 170 - Name: .rel.debug_line 171 Type: SHT_REL 172 Info: .debug_line 173 Relocations: 174 - Offset: 4 175 Symbol: f 176 Type: R_386_32 177 Symbols: 178 - Name: f 179 Type: STT_SECTION 180 Section: .text 181 Value: 0x42 182 )"; 183 SmallString<0> Storage; 184 std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile( 185 Storage, Yaml, [](const Twine &Err) { errs() << Err; }); 186 ASSERT_TRUE(Obj); 187 std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj); 188 const DWARFObject &DObj = Ctx->getDWARFObj(); 189 ASSERT_EQ(12u, DObj.getLineSection().Data.size()); 190 191 DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(), 192 Obj->getBytesInAddress()); 193 DataExtractor::Cursor C(0); 194 EXPECT_EQ(0x64636261u, Data.getRelocatedAddress(C)); 195 EXPECT_EQ(0x42u, Data.getRelocatedAddress(C)); 196 EXPECT_EQ(0x68676665u, Data.getRelocatedAddress(C)); 197 EXPECT_THAT_ERROR(C.takeError(), Succeeded()); 198 199 C = DataExtractor::Cursor{0}; 200 DWARFDataExtractor Truncated8(Data, 8); 201 EXPECT_EQ(0x64636261u, Truncated8.getRelocatedAddress(C)); 202 EXPECT_EQ(0x42u, Truncated8.getRelocatedAddress(C)); 203 EXPECT_EQ(0x0u, Truncated8.getRelocatedAddress(C)); 204 EXPECT_THAT_ERROR( 205 C.takeError(), 206 FailedWithMessage( 207 "unexpected end of data at offset 0x8 while reading [0x8, 0xc)")); 208 209 C = DataExtractor::Cursor{0}; 210 DWARFDataExtractor Truncated6(Data, 6); 211 EXPECT_EQ(0x64636261u, Truncated6.getRelocatedAddress(C)); 212 EXPECT_EQ(0x0u, Truncated6.getRelocatedAddress(C)); 213 EXPECT_THAT_ERROR( 214 C.takeError(), 215 FailedWithMessage( 216 "unexpected end of data at offset 0x6 while reading [0x4, 0x8)")); 217 218 C = DataExtractor::Cursor{0}; 219 DWARFDataExtractor Truncated2(Data, 2); 220 EXPECT_EQ(0x0u, Truncated2.getRelocatedAddress(C)); 221 EXPECT_THAT_ERROR( 222 C.takeError(), 223 FailedWithMessage( 224 "unexpected end of data at offset 0x2 while reading [0x0, 0x4)")); 225 } 226 227 } // namespace 228