1 //===- llvm/unittest/DebugInfo/DWARFDebugArangeSetTest.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/DWARFDebugArangeSet.h" 10 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 11 #include "llvm/Testing/Support/Error.h" 12 #include "gtest/gtest.h" 13 14 using namespace llvm; 15 16 namespace { 17 18 struct WarningHandler { 19 ~WarningHandler() { EXPECT_THAT_ERROR(std::move(Err), Succeeded()); } 20 21 void operator()(Error E) { Err = joinErrors(std::move(Err), std::move(E)); } 22 23 Error getWarning() { return std::move(Err); } 24 25 Error Err = Error::success(); 26 }; 27 28 template <size_t SecSize> 29 void ExpectExtractError(const char (&SecDataRaw)[SecSize], 30 const char *ErrorMessage) { 31 DWARFDataExtractor Extractor(StringRef(SecDataRaw, SecSize - 1), 32 /* IsLittleEndian = */ true, 33 /* AddressSize = */ 4); 34 DWARFDebugArangeSet Set; 35 uint64_t Offset = 0; 36 WarningHandler Warnings; 37 Error E = Set.extract(Extractor, &Offset, Warnings); 38 ASSERT_TRUE(E.operator bool()); 39 EXPECT_STREQ(ErrorMessage, toString(std::move(E)).c_str()); 40 } 41 42 TEST(DWARFDebugArangeSet, LengthExceedsSectionSize) { 43 static const char DebugArangesSecRaw[] = 44 "\x15\x00\x00\x00" // The length exceeds the section boundaries 45 "\x02\x00" // Version 46 "\x00\x00\x00\x00" // Debug Info Offset 47 "\x04" // Address Size 48 "\x00" // Segment Selector Size 49 "\x00\x00\x00\x00" // Padding 50 "\x00\x00\x00\x00" // Termination tuple 51 "\x00\x00\x00\x00"; 52 ExpectExtractError( 53 DebugArangesSecRaw, 54 "the length of address range table at offset 0x0 exceeds section size"); 55 } 56 57 TEST(DWARFDebugArangeSet, LengthExceedsSectionSizeDWARF64) { 58 static const char DebugArangesSecRaw[] = 59 "\xff\xff\xff\xff" // DWARF64 mark 60 "\x15\x00\x00\x00\x00\x00\x00\x00" // The length exceeds the section 61 // boundaries 62 "\x02\x00" // Version 63 "\x00\x00\x00\x00\x00\x00\x00\x00" // Debug Info Offset 64 "\x04" // Address Size 65 "\x00" // Segment Selector Size 66 // No padding 67 "\x00\x00\x00\x00" // Termination tuple 68 "\x00\x00\x00\x00"; 69 ExpectExtractError( 70 DebugArangesSecRaw, 71 "the length of address range table at offset 0x0 exceeds section size"); 72 } 73 74 TEST(DWARFDebugArangeSet, UnsupportedAddressSize) { 75 static const char DebugArangesSecRaw[] = 76 "\x0c\x00\x00\x00" // Length 77 "\x02\x00" // Version 78 "\x00\x00\x00\x00" // Debug Info Offset 79 "\x03" // Address Size (not supported) 80 "\x00" // Segment Selector Size 81 // No padding 82 "\x00\x00\x00\x00"; // Termination tuple 83 ExpectExtractError( 84 DebugArangesSecRaw, 85 "address range table at offset 0x0 has unsupported address size: 3 " 86 "(supported are 2, 4, 8)"); 87 } 88 89 TEST(DWARFDebugArangeSet, UnsupportedSegmentSelectorSize) { 90 static const char DebugArangesSecRaw[] = 91 "\x14\x00\x00\x00" // Length 92 "\x02\x00" // Version 93 "\x00\x00\x00\x00" // Debug Info Offset 94 "\x04" // Address Size 95 "\x04" // Segment Selector Size (not supported) 96 // No padding 97 "\x00\x00\x00\x00" // Termination tuple 98 "\x00\x00\x00\x00" 99 "\x00\x00\x00\x00"; 100 ExpectExtractError( 101 DebugArangesSecRaw, 102 "non-zero segment selector size in address range table at offset 0x0 " 103 "is not supported"); 104 } 105 106 TEST(DWARFDebugArangeSet, NoTerminationEntry) { 107 static const char DebugArangesSecRaw[] = 108 "\x14\x00\x00\x00" // Length 109 "\x02\x00" // Version 110 "\x00\x00\x00\x00" // Debug Info Offset 111 "\x04" // Address Size 112 "\x00" // Segment Selector Size 113 "\x00\x00\x00\x00" // Padding 114 "\x00\x00\x00\x00" // Entry: Address 115 "\x01\x00\x00\x00" // Length 116 ; // No termination tuple 117 ExpectExtractError( 118 DebugArangesSecRaw, 119 "address range table at offset 0x0 is not terminated by null entry"); 120 } 121 122 TEST(DWARFDebugArangeSet, ReservedUnitLength) { 123 // Note: 12 is the minimum length to pass the basic check for the size of 124 // the section. 1 will be automatically subtracted in ExpectExtractError(). 125 static const char DebugArangesSecRaw[12 + 1] = 126 "\xf0\xff\xff\xff"; // Reserved unit length value 127 ExpectExtractError(DebugArangesSecRaw, 128 "parsing address ranges table at offset 0x0: unsupported " 129 "reserved unit length of value 0xfffffff0"); 130 } 131 132 TEST(DWARFDebugArangeSet, SectionTooShort) { 133 // Note: 1 will be automatically subtracted in ExpectExtractError(). 134 static const char DebugArangesSecRaw[11 + 1] = {0}; 135 ExpectExtractError(DebugArangesSecRaw, 136 "parsing address ranges table at offset 0x0: unexpected " 137 "end of data at offset 0xb while reading [0xb, 0xc)"); 138 } 139 140 TEST(DWARFDebugArangeSet, SectionTooShortDWARF64) { 141 // Note: 1 will be automatically subtracted in ExpectExtractError(). 142 static const char DebugArangesSecRaw[23 + 1] = 143 "\xff\xff\xff\xff"; // DWARF64 mark 144 ExpectExtractError(DebugArangesSecRaw, 145 "parsing address ranges table at offset 0x0: unexpected " 146 "end of data at offset 0x17 while reading [0x17, 0x18)"); 147 } 148 149 TEST(DWARFDebugArangeSet, NoSpaceForEntries) { 150 static const char DebugArangesSecRaw[] = 151 "\x0c\x00\x00\x00" // Length 152 "\x02\x00" // Version 153 "\x00\x00\x00\x00" // Debug Info Offset 154 "\x04" // Address Size 155 "\x00" // Segment Selector Size 156 "\x00\x00\x00\x00" // Padding 157 ; // No entries 158 ExpectExtractError( 159 DebugArangesSecRaw, 160 "address range table at offset 0x0 has an insufficient length " 161 "to contain any entries"); 162 } 163 164 TEST(DWARFDebugArangeSet, UnevenLength) { 165 static const char DebugArangesSecRaw[] = 166 "\x1b\x00\x00\x00" // Length (not a multiple of tuple size) 167 "\x02\x00" // Version 168 "\x00\x00\x00\x00" // Debug Info Offset 169 "\x04" // Address Size 170 "\x00" // Segment Selector Size 171 "\x00\x00\x00\x00" // Padding 172 "\x00\x00\x00\x00" // Entry: Address 173 "\x01\x00\x00\x00" // Length 174 "\x00\x00\x00\x00" // Termination tuple 175 "\x00\x00\x00\x00"; 176 ExpectExtractError( 177 DebugArangesSecRaw, 178 "address range table at offset 0x0 has length that is not a multiple " 179 "of the tuple size"); 180 } 181 182 TEST(DWARFDebugArangeSet, ZeroAddressEntry) { 183 static const char DebugArangesSecRaw[] = 184 "\x1c\x00\x00\x00" // Length 185 "\x02\x00" // Version 186 "\x00\x00\x00\x00" // Debug Info Offset 187 "\x04" // Address Size 188 "\x00" // Segment Selector Size 189 "\x00\x00\x00\x00" // Padding 190 "\x00\x00\x00\x00" // Entry1: Address 191 "\x01\x00\x00\x00" // Length 192 "\x00\x00\x00\x00" // Termination tuple 193 "\x00\x00\x00\x00"; 194 DWARFDataExtractor Extractor( 195 StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1), 196 /*IsLittleEndian=*/true, 197 /*AddressSize=*/4); 198 DWARFDebugArangeSet Set; 199 uint64_t Offset = 0; 200 ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, WarningHandler()), 201 Succeeded()); 202 auto Range = Set.descriptors(); 203 auto Iter = Range.begin(); 204 ASSERT_EQ(std::distance(Iter, Range.end()), 1); 205 EXPECT_EQ(Iter->Address, 0u); 206 EXPECT_EQ(Iter->Length, 1u); 207 } 208 209 TEST(DWARFDebugArangeSet, ZeroLengthEntry) { 210 static const char DebugArangesSecRaw[] = 211 "\x1c\x00\x00\x00" // Length 212 "\x02\x00" // Version 213 "\x00\x00\x00\x00" // Debug Info Offset 214 "\x04" // Address Size 215 "\x00" // Segment Selector Size 216 "\x00\x00\x00\x00" // Padding 217 "\x01\x00\x00\x00" // Entry1: Address 218 "\x00\x00\x00\x00" // Length 219 "\x00\x00\x00\x00" // Termination tuple 220 "\x00\x00\x00\x00"; 221 DWARFDataExtractor Extractor( 222 StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1), 223 /*IsLittleEndian=*/true, 224 /*AddressSize=*/4); 225 DWARFDebugArangeSet Set; 226 uint64_t Offset = 0; 227 ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, WarningHandler()), 228 Succeeded()); 229 auto Range = Set.descriptors(); 230 auto Iter = Range.begin(); 231 ASSERT_EQ(std::distance(Iter, Range.end()), 1); 232 EXPECT_EQ(Iter->Address, 1u); 233 EXPECT_EQ(Iter->Length, 0u); 234 } 235 236 TEST(DWARFDebugArangesSet, PrematureTerminator) { 237 static const char DebugArangesSecRaw[] = 238 "\x24\x00\x00\x00" // Length 239 "\x02\x00" // Version 240 "\x00\x00\x00\x00" // Debug Info Offset 241 "\x04" // Address Size 242 "\x00" // Segment Selector Size 243 "\x00\x00\x00\x00" // Padding 244 "\x00\x00\x00\x00" // Entry1: Premature 245 "\x00\x00\x00\x00" // terminator 246 "\x01\x00\x00\x00" // Entry2: Address 247 "\x01\x00\x00\x00" // Length 248 "\x00\x00\x00\x00" // Termination tuple 249 "\x00\x00\x00\x00"; 250 DWARFDataExtractor Extractor( 251 StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1), 252 /*IsLittleEndian=*/true, 253 /*AddressSize=*/4); 254 DWARFDebugArangeSet Set; 255 uint64_t Offset = 0; 256 WarningHandler Warnings; 257 ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, Warnings), Succeeded()); 258 auto Range = Set.descriptors(); 259 auto Iter = Range.begin(); 260 ASSERT_EQ(std::distance(Iter, Range.end()), 2); 261 EXPECT_EQ(Iter->Address, 0u); 262 EXPECT_EQ(Iter->Length, 0u); 263 ++Iter; 264 EXPECT_EQ(Iter->Address, 1u); 265 EXPECT_EQ(Iter->Length, 1u); 266 EXPECT_THAT_ERROR( 267 Warnings.getWarning(), 268 FailedWithMessage("address range table at offset 0x0 has a premature " 269 "terminator entry at offset 0x10")); 270 } 271 272 } // end anonymous namespace 273