363 lines · cpp
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-exception6//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 29using namespace llvm;30using namespace llvm::logicalview;31using namespace llvm::dwarf;32using namespace llvm::dwarf::utils;33 34namespace {35 36// Helper function to get the first compile unit.37LVScopeCompileUnit *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.52std::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.66void 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 // ScopeValue157 // ScopeNoValue158 // ScopeImplicit159 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 // SymbolValue171 // SymbolNoValue172 // SymbolImplicitValue173 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 // TypeValueCount185 // TypeNoValueCount186 // TypeImplicitValueCount187 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 // TypeValueRange199 // TypeNoValueRange200 // TypeImplicitValueRange201 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.216void 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); // Element232 EXPECT_EQ(Scope->getInlineCode(), 2u); // Element233 EXPECT_EQ(Scope->getVirtualityCode(), 3u); // Element234 EXPECT_EQ(Scope->getCallFilenameIndex(), 5u); // ScopeFunctionInlined235 EXPECT_EQ(Scope->getCallLineNumber(), 5u); // ScopeFunctionInlined236 EXPECT_EQ(Scope->getFilenameIndex(), 7u); // Element237 EXPECT_EQ(Scope->getLineNumber(), 7u); // Element238 EXPECT_EQ(Scope->getDiscriminator(), 8u); // ScopeFunctionInlined239 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); // Element245 EXPECT_EQ(Scope->getInlineCode(), 0u); // Element246 EXPECT_EQ(Scope->getVirtualityCode(), 0u); // Element247 EXPECT_EQ(Scope->getCallFilenameIndex(), 1u); // ScopeFunctionInlined248 EXPECT_EQ(Scope->getCallLineNumber(), 0u); // ScopeFunctionInlined249 EXPECT_EQ(Scope->getFilenameIndex(), 1u); // Element250 EXPECT_EQ(Scope->getLineNumber(), 0u); // Element251 EXPECT_EQ(Scope->getDiscriminator(), 0u); // ScopeFunctionInlined252 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); // Element258 EXPECT_EQ(Scope->getInlineCode(), 2u); // Element259 EXPECT_EQ(Scope->getVirtualityCode(), 3u); // Element260 EXPECT_EQ(Scope->getCallFilenameIndex(), 5u); // ScopeFunctionInlined261 EXPECT_EQ(Scope->getCallLineNumber(), 5u); // ScopeFunctionInlined262 EXPECT_EQ(Scope->getFilenameIndex(), 7u); // Element263 EXPECT_EQ(Scope->getLineNumber(), 7u); // Element264 EXPECT_EQ(Scope->getDiscriminator(), 8u); // ScopeFunctionInlined265 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); // Symbol275 276 ASSERT_NE(++SymbolIter, Symbols->end());277 Symbol = static_cast<LVSymbol *>(*SymbolIter);278 ASSERT_NE(Symbol, nullptr);279 EXPECT_EQ(Symbol->getBitSize(), 0u); // Symbol280 281 ASSERT_NE(++SymbolIter, Symbols->end());282 Symbol = static_cast<LVSymbol *>(*SymbolIter);283 ASSERT_NE(Symbol, nullptr);284 EXPECT_EQ(Symbol->getBitSize(), 1u); // Symbol285 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); // Type295 296 ASSERT_NE(++TypeIter, Types->end());297 Type = static_cast<LVType *>(*TypeIter);298 ASSERT_NE(Type, nullptr);299 EXPECT_EQ(Type->getCount(), 0u); // Type300 301 ASSERT_NE(++TypeIter, Types->end());302 Type = static_cast<LVType *>(*TypeIter);303 ASSERT_NE(Type, nullptr);304 EXPECT_EQ(Type->getCount(), 1u); // Type305 306 ASSERT_NE(++TypeIter, Types->end());307 Type = static_cast<LVType *>(*TypeIter);308 ASSERT_NE(Type, nullptr);309 EXPECT_EQ(Type->getLowerBound(), 1u); // Type310 EXPECT_EQ(Type->getUpperBound(), 2u); // Type311 312 ASSERT_NE(++TypeIter, Types->end());313 Type = static_cast<LVType *>(*TypeIter);314 ASSERT_NE(Type, nullptr);315 EXPECT_EQ(Type->getLowerBound(), 0u); // Type316 EXPECT_EQ(Type->getUpperBound(), 0u); // Type317 318 ASSERT_NE(++TypeIter, Types->end());319 Type = static_cast<LVType *>(*TypeIter);320 ASSERT_NE(Type, nullptr);321 EXPECT_EQ(Type->getLowerBound(), 5u); // Type322 EXPECT_EQ(Type->getUpperBound(), 6u); // Type323}324 325TEST(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} // namespace363