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/PDB/PDBSymbolData.h" 13 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 14 #include "llvm/Support/FileSystem.h" 15 #include "llvm/Support/Path.h" 16 17 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" 18 #include "Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h" 19 #include "Plugins/SymbolFile/DWARF/DWARFDataExtractor.h" 20 #include "Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h" 21 #include "Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h" 22 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" 23 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h" 24 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 25 #include "TestingSupport/SubsystemRAII.h" 26 #include "TestingSupport/TestUtilities.h" 27 #include "lldb/Core/Address.h" 28 #include "lldb/Core/Module.h" 29 #include "lldb/Core/ModuleSpec.h" 30 #include "lldb/Host/FileSystem.h" 31 #include "lldb/Host/HostInfo.h" 32 #include "lldb/Symbol/CompileUnit.h" 33 #include "lldb/Symbol/LineTable.h" 34 #include "lldb/Utility/ArchSpec.h" 35 #include "lldb/Utility/DataEncoder.h" 36 #include "lldb/Utility/FileSpec.h" 37 #include "lldb/Utility/StreamString.h" 38 39 using namespace lldb; 40 using namespace lldb_private; 41 42 class SymbolFileDWARFTests : public testing::Test { 43 SubsystemRAII<FileSystem, HostInfo, ObjectFilePECOFF, SymbolFileDWARF, 44 TypeSystemClang, SymbolFilePDB> 45 subsystems; 46 47 public: 48 void SetUp() override { 49 m_dwarf_test_exe = GetInputFilePath("test-dwarf.exe"); 50 } 51 52 protected: 53 std::string m_dwarf_test_exe; 54 }; 55 56 TEST_F(SymbolFileDWARFTests, TestAbilitiesForDWARF) { 57 // Test that when we have Dwarf debug info, SymbolFileDWARF is used. 58 FileSpec fspec(m_dwarf_test_exe); 59 ArchSpec aspec("i686-pc-windows"); 60 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 61 62 SymbolFile *symfile = module->GetSymbolFile(); 63 ASSERT_NE(nullptr, symfile); 64 EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic()); 65 66 uint32_t expected_abilities = SymbolFile::kAllAbilities; 67 EXPECT_EQ(expected_abilities, symfile->CalculateAbilities()); 68 } 69 70 TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start1) { 71 // Test that if we have a .debug_abbrev that contains ordered abbreviation 72 // codes that start at 1, that we get O(1) access. 73 74 const auto byte_order = eByteOrderLittle; 75 const uint8_t addr_size = 4; 76 StreamString encoder(Stream::eBinary, addr_size, byte_order); 77 encoder.PutULEB128(1); // Abbrev code 1 78 encoder.PutULEB128(DW_TAG_compile_unit); 79 encoder.PutHex8(DW_CHILDREN_yes); 80 encoder.PutULEB128(DW_AT_name); 81 encoder.PutULEB128(DW_FORM_strp); 82 encoder.PutULEB128(0); 83 encoder.PutULEB128(0); 84 85 encoder.PutULEB128(2); // Abbrev code 2 86 encoder.PutULEB128(DW_TAG_subprogram); 87 encoder.PutHex8(DW_CHILDREN_no); 88 encoder.PutULEB128(DW_AT_name); 89 encoder.PutULEB128(DW_FORM_strp); 90 encoder.PutULEB128(0); 91 encoder.PutULEB128(0); 92 93 encoder.PutULEB128(0); // Abbrev code 0 (termination) 94 95 DWARFDataExtractor data; 96 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); 97 DWARFAbbreviationDeclarationSet abbrev_set; 98 lldb::offset_t data_offset = 0; 99 llvm::Error error = abbrev_set.extract(data, &data_offset); 100 EXPECT_FALSE(bool(error)); 101 // Make sure we have O(1) access to each abbreviation by making sure the 102 // index offset is 1 and not UINT32_MAX 103 EXPECT_EQ(abbrev_set.GetIndexOffset(), 1u); 104 105 auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(1); 106 EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit); 107 EXPECT_TRUE(abbrev1->HasChildren()); 108 EXPECT_EQ(abbrev1->NumAttributes(), 1u); 109 auto abbrev2 = abbrev_set.GetAbbreviationDeclaration(2); 110 EXPECT_EQ(abbrev2->Tag(), DW_TAG_subprogram); 111 EXPECT_FALSE(abbrev2->HasChildren()); 112 EXPECT_EQ(abbrev2->NumAttributes(), 1u); 113 } 114 115 TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start5) { 116 // Test that if we have a .debug_abbrev that contains ordered abbreviation 117 // codes that start at 5, that we get O(1) access. 118 119 const auto byte_order = eByteOrderLittle; 120 const uint8_t addr_size = 4; 121 StreamString encoder(Stream::eBinary, addr_size, byte_order); 122 encoder.PutULEB128(5); // Abbrev code 5 123 encoder.PutULEB128(DW_TAG_compile_unit); 124 encoder.PutHex8(DW_CHILDREN_yes); 125 encoder.PutULEB128(DW_AT_name); 126 encoder.PutULEB128(DW_FORM_strp); 127 encoder.PutULEB128(0); 128 encoder.PutULEB128(0); 129 130 encoder.PutULEB128(6); // Abbrev code 6 131 encoder.PutULEB128(DW_TAG_subprogram); 132 encoder.PutHex8(DW_CHILDREN_no); 133 encoder.PutULEB128(DW_AT_name); 134 encoder.PutULEB128(DW_FORM_strp); 135 encoder.PutULEB128(0); 136 encoder.PutULEB128(0); 137 138 encoder.PutULEB128(0); // Abbrev code 0 (termination) 139 140 DWARFDataExtractor data; 141 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); 142 DWARFAbbreviationDeclarationSet abbrev_set; 143 lldb::offset_t data_offset = 0; 144 llvm::Error error = abbrev_set.extract(data, &data_offset); 145 EXPECT_FALSE(bool(error)); 146 // Make sure we have O(1) access to each abbreviation by making sure the 147 // index offset is 5 and not UINT32_MAX 148 EXPECT_EQ(abbrev_set.GetIndexOffset(), 5u); 149 150 auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(5); 151 EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit); 152 EXPECT_TRUE(abbrev1->HasChildren()); 153 EXPECT_EQ(abbrev1->NumAttributes(), 1u); 154 auto abbrev2 = abbrev_set.GetAbbreviationDeclaration(6); 155 EXPECT_EQ(abbrev2->Tag(), DW_TAG_subprogram); 156 EXPECT_FALSE(abbrev2->HasChildren()); 157 EXPECT_EQ(abbrev2->NumAttributes(), 1u); 158 } 159 160 TEST_F(SymbolFileDWARFTests, TestAbbrevOutOfOrder) { 161 // Test that if we have a .debug_abbrev that contains unordered abbreviation 162 // codes, that we can access the information correctly. 163 164 const auto byte_order = eByteOrderLittle; 165 const uint8_t addr_size = 4; 166 StreamString encoder(Stream::eBinary, addr_size, byte_order); 167 encoder.PutULEB128(2); // Abbrev code 2 168 encoder.PutULEB128(DW_TAG_compile_unit); 169 encoder.PutHex8(DW_CHILDREN_yes); 170 encoder.PutULEB128(DW_AT_name); 171 encoder.PutULEB128(DW_FORM_strp); 172 encoder.PutULEB128(0); 173 encoder.PutULEB128(0); 174 175 encoder.PutULEB128(1); // Abbrev code 1 176 encoder.PutULEB128(DW_TAG_subprogram); 177 encoder.PutHex8(DW_CHILDREN_no); 178 encoder.PutULEB128(DW_AT_name); 179 encoder.PutULEB128(DW_FORM_strp); 180 encoder.PutULEB128(0); 181 encoder.PutULEB128(0); 182 183 encoder.PutULEB128(0); // Abbrev code 0 (termination) 184 185 DWARFDataExtractor data; 186 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); 187 DWARFAbbreviationDeclarationSet abbrev_set; 188 lldb::offset_t data_offset = 0; 189 llvm::Error error = abbrev_set.extract(data, &data_offset); 190 EXPECT_FALSE(bool(error)); 191 // Make sure we don't have O(1) access to each abbreviation by making sure 192 // the index offset is UINT32_MAX 193 EXPECT_EQ(abbrev_set.GetIndexOffset(), UINT32_MAX); 194 195 auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(2); 196 EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit); 197 EXPECT_TRUE(abbrev1->HasChildren()); 198 EXPECT_EQ(abbrev1->NumAttributes(), 1u); 199 auto abbrev2 = abbrev_set.GetAbbreviationDeclaration(1); 200 EXPECT_EQ(abbrev2->Tag(), DW_TAG_subprogram); 201 EXPECT_FALSE(abbrev2->HasChildren()); 202 EXPECT_EQ(abbrev2->NumAttributes(), 1u); 203 } 204 205 TEST_F(SymbolFileDWARFTests, TestAbbrevInvalidNULLTag) { 206 // Test that we detect when an abbreviation has a NULL tag and that we get 207 // an error when decoding. 208 209 const auto byte_order = eByteOrderLittle; 210 const uint8_t addr_size = 4; 211 StreamString encoder(Stream::eBinary, addr_size, byte_order); 212 encoder.PutULEB128(1); // Abbrev code 1 213 encoder.PutULEB128(0); // Invalid NULL tag here! 214 encoder.PutHex8(DW_CHILDREN_no); 215 encoder.PutULEB128(0); 216 encoder.PutULEB128(0); 217 218 encoder.PutULEB128(0); // Abbrev code 0 (termination) 219 220 DWARFDataExtractor data; 221 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); 222 DWARFAbbreviationDeclarationSet abbrev_set; 223 lldb::offset_t data_offset = 0; 224 llvm::Error error = abbrev_set.extract(data, &data_offset); 225 // Verify we get an error 226 EXPECT_TRUE(bool(error)); 227 EXPECT_EQ("abbrev decl requires non-null tag.", 228 llvm::toString(std::move(error))); 229 230 } 231 232 TEST_F(SymbolFileDWARFTests, TestAbbrevNullAttrValidForm) { 233 // Test that we detect when an abbreviation has a NULL attribute and a non 234 // NULL form and that we get an error when decoding. 235 236 const auto byte_order = eByteOrderLittle; 237 const uint8_t addr_size = 4; 238 StreamString encoder(Stream::eBinary, addr_size, byte_order); 239 encoder.PutULEB128(1); // Abbrev code 1 240 encoder.PutULEB128(DW_TAG_compile_unit); 241 encoder.PutHex8(DW_CHILDREN_no); 242 encoder.PutULEB128(0); // Invalid NULL DW_AT 243 encoder.PutULEB128(DW_FORM_strp); // With a valid form 244 encoder.PutULEB128(0); 245 encoder.PutULEB128(0); 246 247 encoder.PutULEB128(0); // Abbrev code 0 (termination) 248 249 DWARFDataExtractor data; 250 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); 251 DWARFAbbreviationDeclarationSet abbrev_set; 252 lldb::offset_t data_offset = 0; 253 llvm::Error error = abbrev_set.extract(data, &data_offset); 254 // Verify we get an error 255 EXPECT_TRUE(bool(error)); 256 EXPECT_EQ("malformed abbreviation declaration attribute", 257 llvm::toString(std::move(error))); 258 259 } 260 261 TEST_F(SymbolFileDWARFTests, TestAbbrevValidAttrNullForm) { 262 // Test that we detect when an abbreviation has a valid attribute and a 263 // NULL form and that we get an error when decoding. 264 265 const auto byte_order = eByteOrderLittle; 266 const uint8_t addr_size = 4; 267 StreamString encoder(Stream::eBinary, addr_size, byte_order); 268 encoder.PutULEB128(1); // Abbrev code 1 269 encoder.PutULEB128(DW_TAG_compile_unit); 270 encoder.PutHex8(DW_CHILDREN_no); 271 encoder.PutULEB128(DW_AT_name); // Valid attribute 272 encoder.PutULEB128(0); // NULL form 273 encoder.PutULEB128(0); 274 encoder.PutULEB128(0); 275 276 encoder.PutULEB128(0); // Abbrev code 0 (termination) 277 278 DWARFDataExtractor data; 279 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); 280 DWARFAbbreviationDeclarationSet abbrev_set; 281 lldb::offset_t data_offset = 0; 282 llvm::Error error = abbrev_set.extract(data, &data_offset); 283 // Verify we get an error 284 EXPECT_TRUE(bool(error)); 285 EXPECT_EQ("malformed abbreviation declaration attribute", 286 llvm::toString(std::move(error))); 287 } 288 289 TEST_F(SymbolFileDWARFTests, TestAbbrevMissingTerminator) { 290 // Test that we detect when an abbreviation has a valid attribute and a 291 // form, but is missing the NULL attribute and form that terminates an 292 // abbreviation 293 294 const auto byte_order = eByteOrderLittle; 295 const uint8_t addr_size = 4; 296 StreamString encoder(Stream::eBinary, addr_size, byte_order); 297 encoder.PutULEB128(1); // Abbrev code 1 298 encoder.PutULEB128(DW_TAG_compile_unit); 299 encoder.PutHex8(DW_CHILDREN_no); 300 encoder.PutULEB128(DW_AT_name); 301 encoder.PutULEB128(DW_FORM_strp); 302 // Don't add the NULL DW_AT and NULL DW_FORM terminator 303 304 DWARFDataExtractor data; 305 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); 306 DWARFAbbreviationDeclarationSet abbrev_set; 307 lldb::offset_t data_offset = 0; 308 llvm::Error error = abbrev_set.extract(data, &data_offset); 309 // Verify we get an error 310 EXPECT_TRUE(bool(error)); 311 EXPECT_EQ("abbreviation declaration attribute list not terminated with a " 312 "null entry", llvm::toString(std::move(error))); 313 } 314 315 TEST_F(SymbolFileDWARFTests, ParseArangesNonzeroSegmentSize) { 316 // This `.debug_aranges` table header is a valid 32bit big-endian section 317 // according to the DWARFv5 spec:6.2.1, but contains segment selectors which 318 // are not supported by lldb, and should be gracefully rejected 319 const unsigned char binary_data[] = { 320 0, 0, 0, 41, // unit_length (length field not including this field itself) 321 0, 2, // DWARF version number (half) 322 0, 0, 0, 0, // offset into the .debug_info_table (ignored for the purposes 323 // of this test 324 4, // address size 325 1, // segment size 326 // alignment for the first tuple which "begins at an offset that is a 327 // multiple of the size of a single tuple". Tuples are nine bytes in this 328 // example. 329 0, 0, 0, 0, 0, 0, 330 // BEGIN TUPLES 331 1, 0, 0, 0, 4, 0, 0, 0, 332 1, // a 1byte object starting at address 4 in segment 1 333 0, 0, 0, 0, 4, 0, 0, 0, 334 1, // a 1byte object starting at address 4 in segment 0 335 // END TUPLES 336 0, 0, 0, 0, 0, 0, 0, 0, 0 // terminator 337 }; 338 DWARFDataExtractor data; 339 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data, 340 lldb::ByteOrder::eByteOrderBig); 341 DWARFDebugArangeSet debug_aranges; 342 offset_t off = 0; 343 llvm::Error error = debug_aranges.extract(data, &off); 344 EXPECT_TRUE(bool(error)); 345 EXPECT_EQ("segmented arange entries are not supported", 346 llvm::toString(std::move(error))); 347 EXPECT_EQ(off, 12U); // Parser should read no further than the segment size 348 } 349