1 //===-- SymbolFileDWARFTests.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 "gtest/gtest.h" 10 11 #include "llvm/ADT/STLExtras.h" 12 #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" 13 #include "llvm/DebugInfo/PDB/PDBSymbolData.h" 14 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 15 #include "llvm/Support/FileSystem.h" 16 #include "llvm/Support/Path.h" 17 18 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" 19 #include "Plugins/SymbolFile/DWARF/DWARFDataExtractor.h" 20 #include "Plugins/SymbolFile/DWARF/DWARFDebugAranges.h" 21 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" 22 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h" 23 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 24 #include "TestingSupport/SubsystemRAII.h" 25 #include "TestingSupport/TestUtilities.h" 26 #include "lldb/Core/Address.h" 27 #include "lldb/Core/Module.h" 28 #include "lldb/Core/ModuleSpec.h" 29 #include "lldb/Host/FileSystem.h" 30 #include "lldb/Host/HostInfo.h" 31 #include "lldb/Symbol/CompileUnit.h" 32 #include "lldb/Symbol/LineTable.h" 33 #include "lldb/Utility/ArchSpec.h" 34 #include "lldb/Utility/DataEncoder.h" 35 #include "lldb/Utility/FileSpec.h" 36 #include "lldb/Utility/StreamString.h" 37 38 using namespace lldb; 39 using namespace lldb_private; 40 using namespace lldb_private::dwarf; 41 using namespace lldb_private::plugin::dwarf; 42 using llvm::DWARFDebugArangeSet; 43 44 class SymbolFileDWARFTests : public testing::Test { 45 SubsystemRAII<FileSystem, HostInfo, ObjectFilePECOFF, SymbolFileDWARF, 46 TypeSystemClang, SymbolFilePDB> 47 subsystems; 48 49 public: 50 void SetUp() override { 51 m_dwarf_test_exe = GetInputFilePath("test-dwarf.exe"); 52 } 53 54 protected: 55 std::string m_dwarf_test_exe; 56 }; 57 58 TEST_F(SymbolFileDWARFTests, TestAbilitiesForDWARF) { 59 // Test that when we have Dwarf debug info, SymbolFileDWARF is used. 60 FileSpec fspec(m_dwarf_test_exe); 61 ArchSpec aspec("i686-pc-windows"); 62 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 63 64 SymbolFile *symfile = module->GetSymbolFile(); 65 ASSERT_NE(nullptr, symfile); 66 EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic()); 67 68 uint32_t expected_abilities = SymbolFile::kAllAbilities; 69 EXPECT_EQ(expected_abilities, symfile->CalculateAbilities()); 70 } 71 72 TEST_F(SymbolFileDWARFTests, ParseArangesNonzeroSegmentSize) { 73 // This `.debug_aranges` table header is a valid 32bit big-endian section 74 // according to the DWARFv5 spec:6.2.1, but contains segment selectors which 75 // are not supported by lldb, and should be gracefully rejected 76 const unsigned char binary_data[] = { 77 0, 0, 0, 41, // unit_length (length field not including this field itself) 78 0, 2, // DWARF version number (half) 79 0, 0, 0, 0, // offset into the .debug_info_table (ignored for the purposes 80 // of this test 81 4, // address size 82 1, // segment size 83 // alignment for the first tuple which "begins at an offset that is a 84 // multiple of the size of a single tuple". Tuples are nine bytes in this 85 // example. 86 0, 0, 0, 0, 0, 0, 87 // BEGIN TUPLES 88 1, 0, 0, 0, 4, 0, 0, 0, 89 1, // a 1byte object starting at address 4 in segment 1 90 0, 0, 0, 0, 4, 0, 0, 0, 91 1, // a 1byte object starting at address 4 in segment 0 92 // END TUPLES 93 0, 0, 0, 0, 0, 0, 0, 0, 0 // terminator 94 }; 95 llvm::DWARFDataExtractor data(llvm::ArrayRef<unsigned char>(binary_data), 96 /*isLittleEndian=*/false, /*AddrSize=*/4); 97 98 DWARFDebugArangeSet debug_aranges; 99 offset_t off = 0; 100 llvm::Error error = debug_aranges.extract(data, &off); 101 EXPECT_TRUE(bool(error)); 102 EXPECT_EQ("non-zero segment selector size in address range table at offset " 103 "0x0 is not supported", 104 llvm::toString(std::move(error))); 105 EXPECT_EQ(off, 12U); // Parser should read no further than the segment size 106 } 107 108 TEST_F(SymbolFileDWARFTests, ParseArangesWithMultipleTerminators) { 109 // This .debug_aranges set has multiple terminator entries which appear in 110 // binaries produced by popular linux compilers and linker combinations. We 111 // must be able to parse all the way through the data for each 112 // DWARFDebugArangeSet. Previously the DWARFDebugArangeSet::extract() 113 // function would stop parsing as soon as we ran into a terminator even 114 // though the length field stated that there was more data that follows. This 115 // would cause the next DWARFDebugArangeSet to be parsed immediately 116 // following the first terminator and it would attempt to decode the 117 // DWARFDebugArangeSet header using the remaining segment + address pairs 118 // from the remaining bytes. 119 unsigned char binary_data[] = { 120 0, 0, 0, 0, // unit_length that will be set correctly after this 121 0, 2, // DWARF version number (uint16_t) 122 0, 0, 0, 255, // CU offset 123 4, // address size 124 0, // segment size 125 0, 0, 0, 0, // alignment for the first tuple 126 // BEGIN TUPLES 127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // premature terminator 128 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100) 129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // premature terminator 130 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, // [0x2000-0x2010) 131 // END TUPLES 132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator 133 }; 134 // Set the big endian length correctly. 135 const offset_t binary_data_size = sizeof(binary_data); 136 binary_data[3] = (uint8_t)binary_data_size - 4; 137 DWARFDataExtractor data; 138 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data, 139 lldb::ByteOrder::eByteOrderBig); 140 DWARFDebugAranges debug_aranges; 141 debug_aranges.extract(data); 142 // Parser should read all terminators to the end of the length specified. 143 ASSERT_EQ(debug_aranges.GetNumRanges(), 2U); 144 EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET); 145 EXPECT_EQ(debug_aranges.FindAddress(0x1000), 255u); 146 EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 255u); 147 EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET); 148 EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET); 149 EXPECT_EQ(debug_aranges.FindAddress(0x2000), 255u); 150 EXPECT_EQ(debug_aranges.FindAddress(0x2010 - 1), 255u); 151 EXPECT_EQ(debug_aranges.FindAddress(0x2010), DW_INVALID_OFFSET); 152 } 153 154 TEST_F(SymbolFileDWARFTests, ParseArangesIgnoreEmpty) { 155 // This .debug_aranges set has some address ranges which have zero length 156 // and we ensure that these are ignored by our DWARFDebugArangeSet parser 157 // and not included in the descriptors that are returned. 158 unsigned char binary_data[] = { 159 0, 0, 0, 0, // unit_length that will be set correctly after this 160 0, 2, // DWARF version number (uint16_t) 161 0, 0, 0, 255, // CU offset 162 4, // address size 163 0, // segment size 164 0, 0, 0, 0, // alignment for the first tuple 165 // BEGIN TUPLES 166 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100) 167 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, // [0x1100-0x1100) 168 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, // [0x2000-0x2010) 169 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, // [0x2010-0x2010) 170 // END TUPLES 171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator 172 }; 173 // Set the big endian length correctly. 174 const offset_t binary_data_size = sizeof(binary_data); 175 binary_data[3] = (uint8_t)binary_data_size - 4; 176 DWARFDataExtractor data; 177 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data, 178 lldb::ByteOrder::eByteOrderBig); 179 DWARFDebugAranges debug_aranges; 180 debug_aranges.extract(data); 181 // Parser should read all terminators to the end of the length specified. 182 // Previously the DWARFDebugArangeSet would stop at the first terminator 183 // entry and leave the offset in the middle of the current 184 // DWARFDebugArangeSet data, and that would cause the next extracted 185 // DWARFDebugArangeSet to fail. 186 ASSERT_EQ(debug_aranges.GetNumRanges(), 2U); 187 EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET); 188 EXPECT_EQ(debug_aranges.FindAddress(0x1000), 255u); 189 EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 255u); 190 EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET); 191 EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET); 192 EXPECT_EQ(debug_aranges.FindAddress(0x2000), 255u); 193 EXPECT_EQ(debug_aranges.FindAddress(0x2010 - 1), 255u); 194 EXPECT_EQ(debug_aranges.FindAddress(0x2010), DW_INVALID_OFFSET); 195 } 196 197 TEST_F(SymbolFileDWARFTests, ParseAranges) { 198 // Test we can successfully parse a DWARFDebugAranges. The initial error 199 // checking code had a bug where it would always return an empty address 200 // ranges for everything in .debug_aranges and no error. 201 unsigned char binary_data[] = { 202 0, 0, 0, 0, // unit_length that will be set correctly after this 203 2, 0, // DWARF version number 204 255, 0, 0, 0, // offset into the .debug_info_table 205 8, // address size 206 0, // segment size 207 0, 0, 0, 0, // pad bytes 208 // BEGIN TUPLES 209 // First tuple: [0x1000-0x1100) 210 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x1000 211 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size 0x0100 212 // Second tuple: [0x2000-0x2100) 213 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x2000 214 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size 0x0100 215 // Terminating tuple 216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Terminator 217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Terminator 218 }; 219 // Set the little endian length correctly. 220 binary_data[0] = sizeof(binary_data) - 4; 221 DWARFDataExtractor data; 222 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data, 223 lldb::ByteOrder::eByteOrderLittle); 224 DWARFDebugAranges debug_aranges; 225 debug_aranges.extract(data); 226 EXPECT_EQ(debug_aranges.GetNumRanges(), 2u); 227 EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET); 228 EXPECT_EQ(debug_aranges.FindAddress(0x1000), 255u); 229 EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 255u); 230 EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET); 231 EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET); 232 EXPECT_EQ(debug_aranges.FindAddress(0x2000), 255u); 233 EXPECT_EQ(debug_aranges.FindAddress(0x2100 - 1), 255u); 234 EXPECT_EQ(debug_aranges.FindAddress(0x2100), DW_INVALID_OFFSET); 235 } 236 237 TEST_F(SymbolFileDWARFTests, ParseArangesSkipErrors) { 238 // Test we can successfully parse a DWARFDebugAranges that contains some 239 // valid DWARFDebugArangeSet objects and some with errors as long as their 240 // length is set correctly. This helps LLDB ensure that it can parse newer 241 // .debug_aranges version that LLDB currently doesn't support, or ignore 242 // errors in individual DWARFDebugArangeSet objects as long as the length 243 // is set correctly. 244 const unsigned char binary_data[] = { 245 // This DWARFDebugArangeSet is well formed and has a single address range 246 // for [0x1000-0x1100) with a CU offset of 0x00000000. 247 0, 0, 0, 28, // unit_length that will be set correctly after this 248 0, 2, // DWARF version number (uint16_t) 249 0, 0, 0, 0, // CU offset = 0x00000000 250 4, // address size 251 0, // segment size 252 0, 0, 0, 0, // alignment for the first tuple 253 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100) 254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator 255 // This DWARFDebugArangeSet has the correct length, but an invalid 256 // version. We need to be able to skip this correctly and ignore it. 257 0, 0, 0, 20, // unit_length that will be set correctly after this 258 0, 44, // invalid DWARF version number (uint16_t) 259 0, 0, 1, 0, // CU offset = 0x00000100 260 4, // address size 261 0, // segment size 262 0, 0, 0, 0, // alignment for the first tuple 263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator 264 // This DWARFDebugArangeSet is well formed and has a single address range 265 // for [0x2000-0x2100) with a CU offset of 0x00000000. 266 0, 0, 0, 28, // unit_length that will be set correctly after this 267 0, 2, // DWARF version number (uint16_t) 268 0, 0, 2, 0, // CU offset = 0x00000200 269 4, // address size 270 0, // segment size 271 0, 0, 0, 0, // alignment for the first tuple 272 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x2000-0x2100) 273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator 274 }; 275 276 DWARFDataExtractor data; 277 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data, 278 lldb::ByteOrder::eByteOrderBig); 279 DWARFDebugAranges debug_aranges; 280 debug_aranges.extract(data); 281 EXPECT_EQ(debug_aranges.GetNumRanges(), 2u); 282 EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET); 283 EXPECT_EQ(debug_aranges.FindAddress(0x1000), 0u); 284 EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 0u); 285 EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET); 286 EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET); 287 EXPECT_EQ(debug_aranges.FindAddress(0x2000), 0x200u); 288 EXPECT_EQ(debug_aranges.FindAddress(0x2100 - 1), 0x200u); 289 EXPECT_EQ(debug_aranges.FindAddress(0x2100), DW_INVALID_OFFSET); 290 } 291