1 //===- llvm/unittest/DebugInfo/LogicalView/DWARFGeneratedTest.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 "../DWARF/DwarfGenerator.h" 10 #include "../DWARF/DwarfUtils.h" 11 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 12 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 13 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h" 14 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h" 15 #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h" 16 #include "llvm/DebugInfo/LogicalView/Core/LVType.h" 17 #include "llvm/DebugInfo/LogicalView/LVReaderHandler.h" 18 #include "llvm/MC/TargetRegistry.h" 19 #include "llvm/Support/COM.h" 20 #include "llvm/Support/InitLLVM.h" 21 #include "llvm/Support/ScopedPrinter.h" 22 #include "llvm/Support/TargetSelect.h" 23 #include "llvm/Support/ToolOutputFile.h" 24 #include "llvm/Testing/Support/Error.h" 25 #include "llvm/Testing/Support/SupportHelpers.h" 26 27 #include "gtest/gtest.h" 28 29 using namespace llvm; 30 using namespace llvm::logicalview; 31 using namespace llvm::dwarf; 32 using namespace llvm::dwarf::utils; 33 34 namespace { 35 36 // Helper function to get the first compile unit. 37 LVScopeCompileUnit *getFirstCompileUnit(LVScopeRoot *Root) { 38 if (!Root) 39 return nullptr; 40 41 const LVScopes *CompileUnits = Root->getScopes(); 42 if (!CompileUnits) 43 return nullptr; 44 45 LVScopes::const_iterator Iter = CompileUnits->begin(); 46 return (Iter != CompileUnits->end()) 47 ? static_cast<LVScopeCompileUnit *>(*Iter) 48 : nullptr; 49 } 50 51 // Helper function to create a reader. 52 std::unique_ptr<LVReader> createReader(LVReaderHandler &ReaderHandler, 53 SmallString<128> &InputsDir, 54 StringRef Filename) { 55 SmallString<128> ObjectName(InputsDir); 56 llvm::sys::path::append(ObjectName, Filename); 57 58 Expected<std::unique_ptr<LVReader>> ReaderOrErr = 59 ReaderHandler.createReader(std::string(ObjectName)); 60 EXPECT_THAT_EXPECTED(ReaderOrErr, Succeeded()); 61 std::unique_ptr<LVReader> Reader = std::move(*ReaderOrErr); 62 return Reader; 63 } 64 65 // Create a file with generated DWARF. 66 void generateDebugInfo(StringRef Path, Triple &Triple) { 67 uint16_t Version = 5; 68 auto ExpectedDG = dwarfgen::Generator::create(Triple, Version); 69 ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded()); 70 dwarfgen::Generator *DG = ExpectedDG.get().get(); 71 dwarfgen::CompileUnit &CU = DG->addCompileUnit(); 72 73 dwarfgen::DIE CUDie = CU.getUnitDIE(); 74 CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "test.cpp"); 75 CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C_plus_plus); 76 CUDie.addAttribute(DW_AT_producer, DW_FORM_strp, "dwarfgen::Generator"); 77 78 dwarfgen::DIE ScopeValueDie = CUDie.addChild(DW_TAG_inlined_subroutine); 79 ScopeValueDie.addAttribute(DW_AT_accessibility, DW_FORM_data1, 1); 80 ScopeValueDie.addAttribute(DW_AT_inline, DW_FORM_data4, 2); 81 ScopeValueDie.addAttribute(DW_AT_virtuality, DW_FORM_data4, 3); 82 ScopeValueDie.addAttribute(DW_AT_call_file, DW_FORM_data4, 4); 83 ScopeValueDie.addAttribute(DW_AT_call_line, DW_FORM_data4, 5); 84 ScopeValueDie.addAttribute(DW_AT_decl_file, DW_FORM_data4, 6); 85 ScopeValueDie.addAttribute(DW_AT_decl_line, DW_FORM_data4, 7); 86 ScopeValueDie.addAttribute(DW_AT_GNU_discriminator, DW_FORM_data4, 8); 87 88 dwarfgen::DIE ScopeNoValueDie = CUDie.addChild(DW_TAG_inlined_subroutine); 89 ScopeNoValueDie.addAttribute(DW_AT_accessibility, DW_FORM_sdata, 1); 90 ScopeNoValueDie.addAttribute(DW_AT_inline, DW_FORM_sdata, 2); 91 ScopeNoValueDie.addAttribute(DW_AT_virtuality, DW_FORM_sdata, 3); 92 ScopeNoValueDie.addAttribute(DW_AT_call_file, DW_FORM_sdata, 4); 93 ScopeNoValueDie.addAttribute(DW_AT_call_line, DW_FORM_sdata, 5); 94 ScopeNoValueDie.addAttribute(DW_AT_decl_file, DW_FORM_sdata, 6); 95 ScopeNoValueDie.addAttribute(DW_AT_decl_line, DW_FORM_sdata, 7); 96 ScopeNoValueDie.addAttribute(DW_AT_GNU_discriminator, DW_FORM_sdata, 8); 97 98 dwarfgen::DIE ScopeImplicitDie = CUDie.addChild(DW_TAG_inlined_subroutine); 99 ScopeImplicitDie.addAttribute(DW_AT_accessibility, DW_FORM_implicit_const, 1); 100 ScopeImplicitDie.addAttribute(DW_AT_inline, DW_FORM_implicit_const, 2); 101 ScopeImplicitDie.addAttribute(DW_AT_virtuality, DW_FORM_implicit_const, 3); 102 ScopeImplicitDie.addAttribute(DW_AT_call_file, DW_FORM_implicit_const, 4); 103 ScopeImplicitDie.addAttribute(DW_AT_call_line, DW_FORM_implicit_const, 5); 104 ScopeImplicitDie.addAttribute(DW_AT_decl_file, DW_FORM_implicit_const, 6); 105 ScopeImplicitDie.addAttribute(DW_AT_decl_line, DW_FORM_implicit_const, 7); 106 ScopeImplicitDie.addAttribute(DW_AT_GNU_discriminator, DW_FORM_implicit_const, 107 8); 108 109 dwarfgen::DIE SymbolValueDie = CUDie.addChild(DW_TAG_variable); 110 SymbolValueDie.addAttribute(DW_AT_bit_size, DW_FORM_data1, 1); 111 112 dwarfgen::DIE SymbolNoValueDie = CUDie.addChild(DW_TAG_variable); 113 SymbolNoValueDie.addAttribute(DW_AT_bit_size, DW_FORM_sdata, 1); 114 115 dwarfgen::DIE SymbolImplicitDie = CUDie.addChild(DW_TAG_variable); 116 SymbolImplicitDie.addAttribute(DW_AT_bit_size, DW_FORM_implicit_const, 1); 117 118 dwarfgen::DIE TypeValueCountDie = CUDie.addChild(DW_TAG_subrange_type); 119 TypeValueCountDie.addAttribute(DW_AT_count, DW_FORM_data4, 1); 120 121 dwarfgen::DIE TypeNoValueCountDie = CUDie.addChild(DW_TAG_subrange_type); 122 TypeNoValueCountDie.addAttribute(DW_AT_count, DW_FORM_sdata, 1); 123 124 dwarfgen::DIE TypeImplicitCountDie = CUDie.addChild(DW_TAG_subrange_type); 125 TypeImplicitCountDie.addAttribute(DW_AT_count, DW_FORM_implicit_const, 1); 126 127 dwarfgen::DIE TypeValueRangeDie = CUDie.addChild(DW_TAG_subrange_type); 128 TypeValueRangeDie.addAttribute(DW_AT_lower_bound, DW_FORM_data4, 1); 129 TypeValueRangeDie.addAttribute(DW_AT_upper_bound, DW_FORM_data4, 2); 130 131 dwarfgen::DIE TypeNoValueRangeDie = CUDie.addChild(DW_TAG_subrange_type); 132 TypeNoValueRangeDie.addAttribute(DW_AT_lower_bound, DW_FORM_addr, 3); 133 TypeNoValueRangeDie.addAttribute(DW_AT_upper_bound, DW_FORM_addr, 4); 134 135 dwarfgen::DIE TypeImplicitRangeDie = CUDie.addChild(DW_TAG_subrange_type); 136 TypeImplicitRangeDie.addAttribute(DW_AT_lower_bound, DW_FORM_implicit_const, 137 5); 138 TypeImplicitRangeDie.addAttribute(DW_AT_upper_bound, DW_FORM_implicit_const, 139 6); 140 141 // Generate the DWARF. 142 StringRef FileBytes = DG->generate(); 143 MemoryBufferRef FileBuffer(FileBytes, "dwarf"); 144 auto Obj = object::ObjectFile::createObjectFile(FileBuffer); 145 EXPECT_TRUE((bool)Obj); 146 std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj); 147 148 // Verify the number of compile units is correct. 149 uint32_t NumCUs = DwarfContext->getNumCompileUnits(); 150 EXPECT_EQ(NumCUs, 1u); 151 DWARFCompileUnit *U = cast<DWARFCompileUnit>(DwarfContext->getUnitAtIndex(0)); 152 auto DieDG = U->getUnitDIE(false); 153 EXPECT_TRUE(DieDG.isValid()); 154 155 // Verify the siblings correct order. 156 // ScopeValue 157 // ScopeNoValue 158 // ScopeImplicit 159 auto ScopeValueDieDG = DieDG.getFirstChild(); 160 EXPECT_TRUE(ScopeValueDieDG.isValid()); 161 EXPECT_EQ(ScopeValueDieDG.getTag(), DW_TAG_inlined_subroutine); 162 auto ScopeNoValueDieDG = ScopeValueDieDG.getSibling(); 163 EXPECT_TRUE(ScopeNoValueDieDG.isValid()); 164 EXPECT_EQ(ScopeNoValueDieDG.getTag(), DW_TAG_inlined_subroutine); 165 auto ScopeImplicitDieDG = ScopeNoValueDieDG.getSibling(); 166 EXPECT_TRUE(ScopeImplicitDieDG.isValid()); 167 EXPECT_EQ(ScopeImplicitDieDG.getTag(), DW_TAG_inlined_subroutine); 168 169 // Verify the siblings correct order. 170 // SymbolValue 171 // SymbolNoValue 172 // SymbolImplicitValue 173 auto SymbolValueDieDG = ScopeImplicitDieDG.getSibling(); 174 EXPECT_TRUE(SymbolValueDieDG.isValid()); 175 EXPECT_EQ(SymbolValueDieDG.getTag(), DW_TAG_variable); 176 auto SymbolNoValueDieDG = SymbolValueDieDG.getSibling(); 177 EXPECT_TRUE(SymbolNoValueDieDG.isValid()); 178 EXPECT_EQ(SymbolNoValueDieDG.getTag(), DW_TAG_variable); 179 auto SymbolImplicitDieDG = SymbolNoValueDieDG.getSibling(); 180 EXPECT_TRUE(SymbolImplicitDieDG.isValid()); 181 EXPECT_EQ(SymbolImplicitDieDG.getTag(), DW_TAG_variable); 182 183 // Verify the siblings correct order. 184 // TypeValueCount 185 // TypeNoValueCount 186 // TypeImplicitValueCount 187 auto TypeValueCountDieDG = SymbolImplicitDieDG.getSibling(); 188 EXPECT_TRUE(TypeValueCountDieDG.isValid()); 189 EXPECT_EQ(TypeValueCountDieDG.getTag(), DW_TAG_subrange_type); 190 auto TypeNoValueCountDieDG = TypeValueCountDieDG.getSibling(); 191 EXPECT_TRUE(TypeNoValueCountDieDG.isValid()); 192 EXPECT_EQ(TypeNoValueCountDieDG.getTag(), DW_TAG_subrange_type); 193 auto TypeImplicitCountDieDG = TypeNoValueCountDieDG.getSibling(); 194 EXPECT_TRUE(TypeImplicitCountDieDG.isValid()); 195 EXPECT_EQ(TypeImplicitCountDieDG.getTag(), DW_TAG_subrange_type); 196 197 // Verify the siblings correct order. 198 // TypeValueRange 199 // TypeNoValueRange 200 // TypeImplicitValueRange 201 auto TypeValueRangeDieDG = TypeImplicitCountDieDG.getSibling(); 202 EXPECT_TRUE(TypeValueRangeDieDG.isValid()); 203 EXPECT_EQ(TypeValueRangeDieDG.getTag(), DW_TAG_subrange_type); 204 auto TypeNoValueRangeDieDG = TypeValueRangeDieDG.getSibling(); 205 EXPECT_TRUE(TypeNoValueRangeDieDG.isValid()); 206 EXPECT_EQ(TypeNoValueRangeDieDG.getTag(), DW_TAG_subrange_type); 207 auto TypeImplicitRangeDieDG = TypeNoValueRangeDieDG.getSibling(); 208 EXPECT_TRUE(TypeImplicitRangeDieDG.isValid()); 209 EXPECT_EQ(TypeImplicitRangeDieDG.getTag(), DW_TAG_subrange_type); 210 211 // Save the generated DWARF file to disk. 212 EXPECT_TRUE(DG->saveFile(Path)); 213 } 214 215 // Check the logical elements basic properties. 216 void checkElementAttributes(LVReader *Reader) { 217 LVScopeRoot *Root = Reader->getScopesRoot(); 218 ASSERT_NE(Root, nullptr); 219 LVScopeCompileUnit *CompileUnit = getFirstCompileUnit(Root); 220 ASSERT_NE(CompileUnit, nullptr); 221 222 const LVScopes *Scopes = CompileUnit->getScopes(); 223 ASSERT_NE(Scopes, nullptr); 224 ASSERT_EQ(Scopes->size(), 3u); 225 226 // Check values. 227 LVScopes::const_iterator ScopeIter = Scopes->begin(); 228 ASSERT_NE(ScopeIter, Scopes->end()); 229 LVScope *Scope = static_cast<LVScope *>(*ScopeIter); 230 ASSERT_NE(Scope, nullptr); 231 EXPECT_EQ(Scope->getAccessibilityCode(), 1u); // Element 232 EXPECT_EQ(Scope->getInlineCode(), 2u); // Element 233 EXPECT_EQ(Scope->getVirtualityCode(), 3u); // Element 234 EXPECT_EQ(Scope->getCallFilenameIndex(), 5u); // ScopeFunctionInlined 235 EXPECT_EQ(Scope->getCallLineNumber(), 5u); // ScopeFunctionInlined 236 EXPECT_EQ(Scope->getFilenameIndex(), 7u); // Element 237 EXPECT_EQ(Scope->getLineNumber(), 7u); // Element 238 EXPECT_EQ(Scope->getDiscriminator(), 8u); // ScopeFunctionInlined 239 240 // Check no-values. 241 ASSERT_NE(++ScopeIter, Scopes->end()); 242 Scope = static_cast<LVScope *>(*ScopeIter); 243 ASSERT_NE(Scope, nullptr); 244 EXPECT_EQ(Scope->getAccessibilityCode(), 0u); // Element 245 EXPECT_EQ(Scope->getInlineCode(), 0u); // Element 246 EXPECT_EQ(Scope->getVirtualityCode(), 0u); // Element 247 EXPECT_EQ(Scope->getCallFilenameIndex(), 1u); // ScopeFunctionInlined 248 EXPECT_EQ(Scope->getCallLineNumber(), 0u); // ScopeFunctionInlined 249 EXPECT_EQ(Scope->getFilenameIndex(), 1u); // Element 250 EXPECT_EQ(Scope->getLineNumber(), 0u); // Element 251 EXPECT_EQ(Scope->getDiscriminator(), 0u); // ScopeFunctionInlined 252 253 // Check implicit values. 254 ASSERT_NE(++ScopeIter, Scopes->end()); 255 Scope = static_cast<LVScope *>(*ScopeIter); 256 ASSERT_NE(Scope, nullptr); 257 EXPECT_EQ(Scope->getAccessibilityCode(), 1u); // Element 258 EXPECT_EQ(Scope->getInlineCode(), 2u); // Element 259 EXPECT_EQ(Scope->getVirtualityCode(), 3u); // Element 260 EXPECT_EQ(Scope->getCallFilenameIndex(), 5u); // ScopeFunctionInlined 261 EXPECT_EQ(Scope->getCallLineNumber(), 5u); // ScopeFunctionInlined 262 EXPECT_EQ(Scope->getFilenameIndex(), 7u); // Element 263 EXPECT_EQ(Scope->getLineNumber(), 7u); // Element 264 EXPECT_EQ(Scope->getDiscriminator(), 8u); // ScopeFunctionInlined 265 266 const LVSymbols *Symbols = CompileUnit->getSymbols(); 267 ASSERT_NE(Symbols, nullptr); 268 ASSERT_EQ(Symbols->size(), 3u); 269 270 LVSymbols::const_iterator SymbolIter = Symbols->begin(); 271 ASSERT_NE(SymbolIter, Symbols->end()); 272 LVSymbol *Symbol = static_cast<LVSymbol *>(*SymbolIter); 273 ASSERT_NE(Symbol, nullptr); 274 EXPECT_EQ(Symbol->getBitSize(), 1u); // Symbol 275 276 ASSERT_NE(++SymbolIter, Symbols->end()); 277 Symbol = static_cast<LVSymbol *>(*SymbolIter); 278 ASSERT_NE(Symbol, nullptr); 279 EXPECT_EQ(Symbol->getBitSize(), 0u); // Symbol 280 281 ASSERT_NE(++SymbolIter, Symbols->end()); 282 Symbol = static_cast<LVSymbol *>(*SymbolIter); 283 ASSERT_NE(Symbol, nullptr); 284 EXPECT_EQ(Symbol->getBitSize(), 1u); // Symbol 285 286 const LVTypes *Types = CompileUnit->getTypes(); 287 ASSERT_NE(Types, nullptr); 288 ASSERT_EQ(Types->size(), 6u); 289 290 LVTypes::const_iterator TypeIter = Types->begin(); 291 ASSERT_NE(TypeIter, Types->end()); 292 LVType *Type = static_cast<LVType *>(*TypeIter); 293 ASSERT_NE(Type, nullptr); 294 EXPECT_EQ(Type->getCount(), 1u); // Type 295 296 ASSERT_NE(++TypeIter, Types->end()); 297 Type = static_cast<LVType *>(*TypeIter); 298 ASSERT_NE(Type, nullptr); 299 EXPECT_EQ(Type->getCount(), 0u); // Type 300 301 ASSERT_NE(++TypeIter, Types->end()); 302 Type = static_cast<LVType *>(*TypeIter); 303 ASSERT_NE(Type, nullptr); 304 EXPECT_EQ(Type->getCount(), 1u); // Type 305 306 ASSERT_NE(++TypeIter, Types->end()); 307 Type = static_cast<LVType *>(*TypeIter); 308 ASSERT_NE(Type, nullptr); 309 EXPECT_EQ(Type->getLowerBound(), 1u); // Type 310 EXPECT_EQ(Type->getUpperBound(), 2u); // Type 311 312 ASSERT_NE(++TypeIter, Types->end()); 313 Type = static_cast<LVType *>(*TypeIter); 314 ASSERT_NE(Type, nullptr); 315 EXPECT_EQ(Type->getLowerBound(), 0u); // Type 316 EXPECT_EQ(Type->getUpperBound(), 0u); // Type 317 318 ASSERT_NE(++TypeIter, Types->end()); 319 Type = static_cast<LVType *>(*TypeIter); 320 ASSERT_NE(Type, nullptr); 321 EXPECT_EQ(Type->getLowerBound(), 5u); // Type 322 EXPECT_EQ(Type->getUpperBound(), 6u); // Type 323 } 324 325 TEST(LogicalViewTest, ElementAttributes) { 326 // Initialize targets and assembly printers/parsers. 327 llvm::InitializeAllTargetInfos(); 328 llvm::InitializeAllTargetMCs(); 329 InitializeAllDisassemblers(); 330 331 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); 332 333 Triple Triple(Triple::normalize("x86_64-pc-linux-gnu")); 334 if (!isConfigurationSupported(Triple)) 335 GTEST_SKIP(); 336 337 unittest::TempDir TestDirectory("dwarf-test", /*Unique=*/true); 338 llvm::SmallString<128> DirName(TestDirectory.path()); 339 StringRef Filename("test.o"); 340 llvm::SmallString<128> Path(TestDirectory.path(Filename)); 341 generateDebugInfo(Path, Triple); 342 343 // Reader options. 344 LVOptions ReaderOptions; 345 ReaderOptions.setPrintScopes(); 346 ReaderOptions.setPrintSymbols(); 347 ReaderOptions.setPrintTypes(); 348 ReaderOptions.resolveDependencies(); 349 350 std::vector<std::string> Objects; 351 ScopedPrinter W(outs()); 352 LVReaderHandler ReaderHandler(Objects, W, ReaderOptions); 353 354 // Check logical elements properties. 355 std::unique_ptr<LVReader> Reader = 356 createReader(ReaderHandler, DirName, Filename); 357 ASSERT_NE(Reader, nullptr); 358 359 checkElementAttributes(Reader.get()); 360 } 361 362 } // namespace 363