Pavel Labath | 3c36d8d | 2020-02-13 16:47:31 +0100 | [diff] [blame] | 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" |
Pavel Labath | 122c50d | 2020-04-14 17:06:04 +0200 | [diff] [blame] | 10 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
| 11 | #include "llvm/Object/ObjectFile.h" |
| 12 | #include "llvm/ObjectYAML/yaml2obj.h" |
Pavel Labath | 3c36d8d | 2020-02-13 16:47:31 +0100 | [diff] [blame] | 13 | #include "llvm/Testing/Support/Error.h" |
| 14 | #include "gtest/gtest.h" |
| 15 | |
| 16 | using namespace llvm; |
| 17 | |
| 18 | namespace { |
| 19 | |
Pavel Labath | 122c50d | 2020-04-14 17:06:04 +0200 | [diff] [blame] | 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)); |
Pavel Labath | 04aea76 | 2020-04-20 17:28:15 +0200 | [diff] [blame] | 64 | EXPECT_THAT_ERROR( |
| 65 | C.takeError(), |
| 66 | FailedWithMessage( |
| 67 | "unexpected end of data at offset 0x6 while reading [0x4, 0x8)")); |
Pavel Labath | 122c50d | 2020-04-14 17:06:04 +0200 | [diff] [blame] | 68 | } |
| 69 | |
Pavel Labath | 3c36d8d | 2020-02-13 16:47:31 +0100 | [diff] [blame] | 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. |
Pavel Labath | 5754a61 | 2020-02-27 16:22:12 +0100 | [diff] [blame] | 97 | EXPECT_THAT_EXPECTED( |
| 98 | GetWithError({}), |
Pavel Labath | 04aea76 | 2020-04-20 17:28:15 +0200 | [diff] [blame] | 99 | FailedWithMessage( |
| 100 | "unexpected end of data at offset 0x0 while reading [0x0, 0x4)")); |
Pavel Labath | 3c36d8d | 2020-02-13 16:47:31 +0100 | [diff] [blame] | 101 | EXPECT_EQ(GetWithoutError({}), ErrorResult); |
| 102 | |
| 103 | // Not long enough for the U32 field. |
Pavel Labath | 5754a61 | 2020-02-27 16:22:12 +0100 | [diff] [blame] | 104 | EXPECT_THAT_EXPECTED( |
| 105 | GetWithError({0x00, 0x01, 0x02}), |
Pavel Labath | 04aea76 | 2020-04-20 17:28:15 +0200 | [diff] [blame] | 106 | FailedWithMessage( |
| 107 | "unexpected end of data at offset 0x3 while reading [0x0, 0x4)")); |
Pavel Labath | 3c36d8d | 2020-02-13 16:47:31 +0100 | [diff] [blame] | 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. |
Pavel Labath | 5754a61 | 2020-02-27 16:22:12 +0100 | [diff] [blame] | 132 | EXPECT_THAT_EXPECTED( |
| 133 | GetWithError({0xff, 0xff, 0xff, 0xff}), |
Pavel Labath | 04aea76 | 2020-04-20 17:28:15 +0200 | [diff] [blame] | 134 | FailedWithMessage( |
| 135 | "unexpected end of data at offset 0x4 while reading [0x4, 0xc)")); |
Pavel Labath | 3c36d8d | 2020-02-13 16:47:31 +0100 | [diff] [blame] | 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}), |
Pavel Labath | 04aea76 | 2020-04-20 17:28:15 +0200 | [diff] [blame] | 141 | FailedWithMessage( |
| 142 | "unexpected end of data at offset 0x8 while reading [0x4, 0xc)")); |
Pavel Labath | 3c36d8d | 2020-02-13 16:47:31 +0100 | [diff] [blame] | 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 | |
Pavel Labath | cc0acda | 2020-03-23 14:20:08 +0100 | [diff] [blame] | 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)); |
Pavel Labath | 04aea76 | 2020-04-20 17:28:15 +0200 | [diff] [blame] | 204 | EXPECT_THAT_ERROR( |
| 205 | C.takeError(), |
| 206 | FailedWithMessage( |
| 207 | "unexpected end of data at offset 0x8 while reading [0x8, 0xc)")); |
Pavel Labath | cc0acda | 2020-03-23 14:20:08 +0100 | [diff] [blame] | 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)); |
Pavel Labath | 04aea76 | 2020-04-20 17:28:15 +0200 | [diff] [blame] | 213 | EXPECT_THAT_ERROR( |
| 214 | C.takeError(), |
| 215 | FailedWithMessage( |
| 216 | "unexpected end of data at offset 0x6 while reading [0x4, 0x8)")); |
Pavel Labath | cc0acda | 2020-03-23 14:20:08 +0100 | [diff] [blame] | 217 | |
| 218 | C = DataExtractor::Cursor{0}; |
| 219 | DWARFDataExtractor Truncated2(Data, 2); |
| 220 | EXPECT_EQ(0x0u, Truncated2.getRelocatedAddress(C)); |
Pavel Labath | 04aea76 | 2020-04-20 17:28:15 +0200 | [diff] [blame] | 221 | EXPECT_THAT_ERROR( |
| 222 | C.takeError(), |
| 223 | FailedWithMessage( |
| 224 | "unexpected end of data at offset 0x2 while reading [0x0, 0x4)")); |
Pavel Labath | cc0acda | 2020-03-23 14:20:08 +0100 | [diff] [blame] | 225 | } |
| 226 | |
Pavel Labath | 3c36d8d | 2020-02-13 16:47:31 +0100 | [diff] [blame] | 227 | } // namespace |