llvm-debuginfo-analyzer is a command line tool that processes debug info contained in a binary file and produces a debug information format agnostic “Logical View”, which is a high-level semantic representation of the debug info, independent of the low-level format. The code has been divided into the following patches: 1) Interval tree 2) Driver and documentation 3) Logical elements 4) Locations and ranges 5) Select elements 6) Warning and internal options 7) Compare elements 8) ELF Reader 9) CodeView Reader Full details: https://discourse.llvm.org/t/llvm-dev-rfc-llvm-dva-debug-information-visual-analyzer/62570 This patch: This is a high level summary of the changes in this patch. CodeView Reader - Support for CodeView/PDB. LVCodeViewReader, LVTypeVisitor, LVSymbolVisitor, LVLogicalVisitor Reviewed By: psamolysov, probinson, djtodoro, zequanwu Differential Revision: https://reviews.llvm.org/D125784
496 lines
17 KiB
C++
496 lines
17 KiB
C++
//===- llvm/unittest/DebugInfo/LogicalView/CodeViewReaderTest.cpp ---------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
|
|
#include "llvm/DebugInfo/LogicalView/LVReaderHandler.h"
|
|
#include "llvm/MC/TargetRegistry.h"
|
|
#include "llvm/Support/COM.h"
|
|
#include "llvm/Support/InitLLVM.h"
|
|
#include "llvm/Support/ScopedPrinter.h"
|
|
#include "llvm/Support/TargetSelect.h"
|
|
#include "llvm/Support/ToolOutputFile.h"
|
|
#include "llvm/Testing/Support/Error.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::logicalview;
|
|
|
|
extern const char *TestMainArgv0;
|
|
|
|
namespace {
|
|
|
|
const char *CodeViewClang = "test-codeview-clang.o";
|
|
const char *CodeViewMsvc = "test-codeview-msvc.o";
|
|
const char *CodeViewPdbMsvc = "test-codeview-pdb-msvc.o";
|
|
|
|
// Helper function to get the first scope child from the given parent.
|
|
LVScope *getFirstScopeChild(LVScope *Parent) {
|
|
EXPECT_NE(Parent, nullptr);
|
|
const LVScopes *Scopes = Parent->getScopes();
|
|
EXPECT_NE(Scopes, nullptr);
|
|
EXPECT_EQ(Scopes->size(), 1u);
|
|
|
|
LVScopes::const_iterator Iter = Scopes->begin();
|
|
LVScope *Child = *Iter;
|
|
EXPECT_NE(Child, nullptr);
|
|
return Child;
|
|
}
|
|
|
|
// Helper function to create a reader.
|
|
std::unique_ptr<LVReader> createReader(LVReaderHandler &ReaderHandler,
|
|
SmallString<128> &InputsDir,
|
|
StringRef Filename) {
|
|
SmallString<128> ObjectName(InputsDir);
|
|
llvm::sys::path::append(ObjectName, Filename);
|
|
|
|
Expected<std::unique_ptr<LVReader>> ReaderOrErr =
|
|
ReaderHandler.createReader(std::string(ObjectName));
|
|
EXPECT_THAT_EXPECTED(ReaderOrErr, Succeeded());
|
|
std::unique_ptr<LVReader> Reader = std::move(*ReaderOrErr);
|
|
EXPECT_NE(Reader, nullptr);
|
|
return Reader;
|
|
}
|
|
|
|
// Check the logical elements basic properties (Clang - Codeview).
|
|
void checkElementPropertiesClangCodeview(LVReader *Reader) {
|
|
LVScopeRoot *Root = Reader->getScopesRoot();
|
|
LVScopeCompileUnit *CompileUnit =
|
|
static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
|
|
LVScopeFunction *Function =
|
|
static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));
|
|
|
|
EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");
|
|
EXPECT_EQ(Root->getName(), CodeViewClang);
|
|
|
|
EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
|
|
EXPECT_TRUE(CompileUnit->getProducer().startswith("clang"));
|
|
EXPECT_EQ(CompileUnit->getName(), "test.cpp");
|
|
|
|
EXPECT_EQ(Function->lineCount(), 16u);
|
|
EXPECT_EQ(Function->scopeCount(), 1u);
|
|
EXPECT_EQ(Function->symbolCount(), 3u);
|
|
EXPECT_EQ(Function->typeCount(), 1u);
|
|
EXPECT_EQ(Function->rangeCount(), 1u);
|
|
|
|
const LVLocations *Ranges = Function->getRanges();
|
|
ASSERT_NE(Ranges, nullptr);
|
|
ASSERT_EQ(Ranges->size(), 1u);
|
|
LVLocations::const_iterator IterLocation = Ranges->begin();
|
|
LVLocation *Location = (*IterLocation);
|
|
EXPECT_STREQ(Location->getIntervalInfo().c_str(),
|
|
"{Range} Lines 2:9 [0x0000000000:0x0000000046]");
|
|
|
|
LVRange RangeList;
|
|
Function->getRanges(RangeList);
|
|
|
|
const LVRangeEntries &RangeEntries = RangeList.getEntries();
|
|
ASSERT_EQ(RangeEntries.size(), 2u);
|
|
LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
|
|
LVRangeEntry RangeEntry = *IterRanges;
|
|
EXPECT_EQ(RangeEntry.lower(), 0u);
|
|
EXPECT_EQ(RangeEntry.upper(), 0x46u);
|
|
EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
|
|
EXPECT_EQ(RangeEntry.scope()->getName(), "foo");
|
|
EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
|
|
|
|
++IterRanges;
|
|
RangeEntry = *IterRanges;
|
|
EXPECT_EQ(RangeEntry.lower(), 0x21u);
|
|
EXPECT_EQ(RangeEntry.upper(), 0x35u);
|
|
EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
|
|
EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
|
|
EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
|
|
|
|
const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
|
|
ASSERT_EQ(PublicNames.size(), 1u);
|
|
LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
|
|
LVScope *Foo = (*IterNames).first;
|
|
EXPECT_EQ(Foo->getName(), "foo");
|
|
EXPECT_EQ(Foo->getLineNumber(), 0u);
|
|
LVNameInfo NameInfo = (*IterNames).second;
|
|
EXPECT_EQ(NameInfo.first, 0u);
|
|
EXPECT_EQ(NameInfo.second, 0x46u);
|
|
|
|
// Lines (debug and assembler) for 'foo'.
|
|
const LVLines *Lines = Foo->getLines();
|
|
ASSERT_NE(Lines, nullptr);
|
|
EXPECT_EQ(Lines->size(), 0x10u);
|
|
}
|
|
|
|
// Check the logical elements basic properties (MSVC - Codeview).
|
|
void checkElementPropertiesMsvcCodeview(LVReader *Reader) {
|
|
LVScopeRoot *Root = Reader->getScopesRoot();
|
|
LVScopeCompileUnit *CompileUnit =
|
|
static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
|
|
LVScopeFunction *Function =
|
|
static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));
|
|
|
|
EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");
|
|
EXPECT_EQ(Root->getName(), CodeViewMsvc);
|
|
|
|
EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
|
|
EXPECT_TRUE(CompileUnit->getProducer().startswith("Microsoft"));
|
|
EXPECT_EQ(CompileUnit->getName(), "test.cpp");
|
|
|
|
EXPECT_EQ(Function->lineCount(), 14u);
|
|
EXPECT_EQ(Function->scopeCount(), 1u);
|
|
EXPECT_EQ(Function->symbolCount(), 3u);
|
|
EXPECT_EQ(Function->typeCount(), 0u);
|
|
EXPECT_EQ(Function->rangeCount(), 1u);
|
|
|
|
const LVLocations *Ranges = Function->getRanges();
|
|
ASSERT_NE(Ranges, nullptr);
|
|
ASSERT_EQ(Ranges->size(), 1u);
|
|
LVLocations::const_iterator IterLocation = Ranges->begin();
|
|
LVLocation *Location = (*IterLocation);
|
|
EXPECT_STREQ(Location->getIntervalInfo().c_str(),
|
|
"{Range} Lines 2:9 [0x0000000000:0x0000000031]");
|
|
|
|
LVRange RangeList;
|
|
Function->getRanges(RangeList);
|
|
|
|
const LVRangeEntries &RangeEntries = RangeList.getEntries();
|
|
ASSERT_EQ(RangeEntries.size(), 2u);
|
|
LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
|
|
LVRangeEntry RangeEntry = *IterRanges;
|
|
EXPECT_EQ(RangeEntry.lower(), 0u);
|
|
EXPECT_EQ(RangeEntry.upper(), 0x31u);
|
|
EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
|
|
EXPECT_EQ(RangeEntry.scope()->getName(), "foo");
|
|
EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
|
|
|
|
++IterRanges;
|
|
RangeEntry = *IterRanges;
|
|
EXPECT_EQ(RangeEntry.lower(), 0x1bu);
|
|
EXPECT_EQ(RangeEntry.upper(), 0x28u);
|
|
EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
|
|
EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
|
|
EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
|
|
|
|
const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
|
|
ASSERT_EQ(PublicNames.size(), 1u);
|
|
LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
|
|
LVScope *Foo = (*IterNames).first;
|
|
EXPECT_EQ(Foo->getName(), "foo");
|
|
EXPECT_EQ(Foo->getLineNumber(), 0u);
|
|
LVNameInfo NameInfo = (*IterNames).second;
|
|
EXPECT_EQ(NameInfo.first, 0u);
|
|
EXPECT_EQ(NameInfo.second, 0x31u);
|
|
|
|
// Lines (debug and assembler) for 'foo'.
|
|
const LVLines *Lines = Foo->getLines();
|
|
ASSERT_NE(Lines, nullptr);
|
|
EXPECT_EQ(Lines->size(), 0x0eu);
|
|
}
|
|
|
|
// Check the logical elements basic properties (MSVC - PDB).
|
|
void checkElementPropertiesMsvcCodeviewPdb(LVReader *Reader) {
|
|
LVScopeRoot *Root = Reader->getScopesRoot();
|
|
LVScopeCompileUnit *CompileUnit =
|
|
static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
|
|
LVScopeFunction *Function =
|
|
static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));
|
|
|
|
EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");
|
|
EXPECT_EQ(Root->getName(), CodeViewPdbMsvc);
|
|
|
|
EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
|
|
EXPECT_TRUE(CompileUnit->getProducer().startswith("Microsoft"));
|
|
EXPECT_EQ(CompileUnit->getName(), "test.cpp");
|
|
|
|
EXPECT_EQ(Function->lineCount(), 14u);
|
|
EXPECT_EQ(Function->scopeCount(), 1u);
|
|
EXPECT_EQ(Function->symbolCount(), 3u);
|
|
EXPECT_EQ(Function->typeCount(), 0u);
|
|
EXPECT_EQ(Function->rangeCount(), 1u);
|
|
|
|
const LVLocations *Ranges = Function->getRanges();
|
|
ASSERT_NE(Ranges, nullptr);
|
|
ASSERT_EQ(Ranges->size(), 1u);
|
|
LVLocations::const_iterator IterLocation = Ranges->begin();
|
|
LVLocation *Location = (*IterLocation);
|
|
EXPECT_STREQ(Location->getIntervalInfo().c_str(),
|
|
"{Range} Lines 2:9 [0x0000000000:0x0000000031]");
|
|
|
|
LVRange RangeList;
|
|
Function->getRanges(RangeList);
|
|
|
|
const LVRangeEntries &RangeEntries = RangeList.getEntries();
|
|
ASSERT_EQ(RangeEntries.size(), 2u);
|
|
LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
|
|
LVRangeEntry RangeEntry = *IterRanges;
|
|
EXPECT_EQ(RangeEntry.lower(), 0u);
|
|
EXPECT_EQ(RangeEntry.upper(), 0x31u);
|
|
EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
|
|
EXPECT_EQ(RangeEntry.scope()->getName(), "foo");
|
|
EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
|
|
|
|
++IterRanges;
|
|
RangeEntry = *IterRanges;
|
|
EXPECT_EQ(RangeEntry.lower(), 0x1bu);
|
|
EXPECT_EQ(RangeEntry.upper(), 0x28u);
|
|
EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
|
|
EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
|
|
EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
|
|
|
|
const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
|
|
ASSERT_EQ(PublicNames.size(), 1u);
|
|
LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
|
|
LVScope *Foo = (*IterNames).first;
|
|
EXPECT_EQ(Foo->getName(), "foo");
|
|
EXPECT_EQ(Foo->getLineNumber(), 0u);
|
|
LVNameInfo NameInfo = (*IterNames).second;
|
|
EXPECT_EQ(NameInfo.first, 0u);
|
|
EXPECT_EQ(NameInfo.second, 0x31u);
|
|
|
|
// Lines (debug and assembler) for 'foo'.
|
|
const LVLines *Lines = Foo->getLines();
|
|
ASSERT_NE(Lines, nullptr);
|
|
EXPECT_EQ(Lines->size(), 0x0eu);
|
|
}
|
|
|
|
struct SelectionInfo {
|
|
const char *Name;
|
|
LVElementGetFunction Function;
|
|
};
|
|
|
|
// Check the logical elements selection.
|
|
void checkElementSelection(LVReader *Reader, std::vector<SelectionInfo> &Data,
|
|
size_t Size) {
|
|
LVScopeRoot *Root = Reader->getScopesRoot();
|
|
LVScopeCompileUnit *CompileUnit =
|
|
static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
|
|
|
|
// Get the matched elements.
|
|
LVElements MatchedElements = CompileUnit->getMatchedElements();
|
|
std::map<StringRef, LVElement *> MapElements;
|
|
for (LVElement *Element : MatchedElements)
|
|
MapElements[Element->getName()] = Element;
|
|
ASSERT_EQ(MapElements.size(), Size);
|
|
|
|
std::map<StringRef, LVElement *>::iterator Iter = MapElements.begin();
|
|
for (const SelectionInfo &Entry : Data) {
|
|
// Get matched element.
|
|
EXPECT_NE(Iter, MapElements.end());
|
|
LVElement *Element = Iter->second;
|
|
ASSERT_NE(Element, nullptr);
|
|
EXPECT_NE(Element->getName().find(Entry.Name), StringRef::npos);
|
|
EXPECT_EQ((Element->*Entry.Function)(), 1u);
|
|
++Iter;
|
|
}
|
|
|
|
// Get the parents for the matched elements.
|
|
LVScopes MatchedScopes = CompileUnit->getMatchedScopes();
|
|
std::set<StringRef> SetScopes;
|
|
for (LVScope *Scope : MatchedScopes)
|
|
SetScopes.insert(Scope->getName());
|
|
ASSERT_EQ(SetScopes.size(), 3u);
|
|
|
|
// Parents of selected elements.
|
|
std::set<StringRef>::iterator IterScope;
|
|
IterScope = SetScopes.find("foo");
|
|
EXPECT_NE(IterScope, SetScopes.end());
|
|
IterScope = SetScopes.find("foo::?");
|
|
EXPECT_NE(IterScope, SetScopes.end());
|
|
IterScope = SetScopes.find("test.cpp");
|
|
EXPECT_NE(IterScope, SetScopes.end());
|
|
}
|
|
|
|
// Check the logical elements comparison.
|
|
void checkElementComparison(LVReader *Reference, LVReader *Target) {
|
|
LVCompare Compare(nulls());
|
|
Error Err = Compare.execute(Reference, Target);
|
|
ASSERT_THAT_ERROR(std::move(Err), Succeeded());
|
|
|
|
// Get comparison table.
|
|
LVPassTable PassTable = Compare.getPassTable();
|
|
ASSERT_EQ(PassTable.size(), 2u);
|
|
|
|
LVReader *Reader;
|
|
LVElement *Element;
|
|
LVComparePass Pass;
|
|
|
|
// Reference: Missing TypeDefinition 'INTEGER'
|
|
std::tie(Reader, Element, Pass) = PassTable[0];
|
|
ASSERT_NE(Reader, nullptr);
|
|
ASSERT_NE(Element, nullptr);
|
|
EXPECT_EQ(Reader, Reference);
|
|
EXPECT_EQ(Element->getLevel(), 3u);
|
|
EXPECT_EQ(Element->getLineNumber(), 0u);
|
|
EXPECT_EQ(Element->getName(), "INTEGER");
|
|
EXPECT_EQ(Pass, LVComparePass::Missing);
|
|
|
|
// Target: Added TypeDefinition 'INTEGER'
|
|
std::tie(Reader, Element, Pass) = PassTable[1];
|
|
ASSERT_NE(Reader, nullptr);
|
|
ASSERT_NE(Element, nullptr);
|
|
EXPECT_EQ(Reader, Target);
|
|
EXPECT_EQ(Element->getLevel(), 4u);
|
|
EXPECT_EQ(Element->getLineNumber(), 0u);
|
|
EXPECT_EQ(Element->getName(), "INTEGER");
|
|
EXPECT_EQ(Pass, LVComparePass::Added);
|
|
}
|
|
|
|
// Logical elements properties.
|
|
void elementProperties(SmallString<128> &InputsDir) {
|
|
// Reader options.
|
|
LVOptions ReaderOptions;
|
|
ReaderOptions.setAttributeOffset();
|
|
ReaderOptions.setAttributeFormat();
|
|
ReaderOptions.setAttributeFilename();
|
|
ReaderOptions.setAttributeProducer();
|
|
ReaderOptions.setAttributePublics();
|
|
ReaderOptions.setAttributeRange();
|
|
ReaderOptions.setAttributeLocation();
|
|
ReaderOptions.setPrintAll();
|
|
ReaderOptions.resolveDependencies();
|
|
|
|
std::vector<std::string> Objects;
|
|
ScopedPrinter W(outs());
|
|
LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
|
|
|
|
// Check logical elements properties.
|
|
{
|
|
std::unique_ptr<LVReader> Reader =
|
|
createReader(ReaderHandler, InputsDir, CodeViewClang);
|
|
checkElementPropertiesClangCodeview(Reader.get());
|
|
}
|
|
{
|
|
std::unique_ptr<LVReader> Reader =
|
|
createReader(ReaderHandler, InputsDir, CodeViewMsvc);
|
|
checkElementPropertiesMsvcCodeview(Reader.get());
|
|
}
|
|
{
|
|
std::unique_ptr<LVReader> Reader =
|
|
createReader(ReaderHandler, InputsDir, CodeViewPdbMsvc);
|
|
checkElementPropertiesMsvcCodeviewPdb(Reader.get());
|
|
}
|
|
}
|
|
|
|
// Logical elements selection.
|
|
void elementSelection(SmallString<128> &InputsDir) {
|
|
// Reader options.
|
|
LVOptions ReaderOptions;
|
|
ReaderOptions.setAttributeOffset();
|
|
ReaderOptions.setPrintAll();
|
|
|
|
ReaderOptions.setSelectIgnoreCase();
|
|
ReaderOptions.setSelectUseRegex();
|
|
|
|
ReaderOptions.setReportList(); // Matched elements.
|
|
ReaderOptions.setReportView(); // Parents for matched elements.
|
|
|
|
// Add patterns.
|
|
ReaderOptions.Select.Generic.insert("foo");
|
|
ReaderOptions.Select.Generic.insert("movl[ \t]?%");
|
|
ReaderOptions.Select.Generic.insert("INT[a-z]*");
|
|
ReaderOptions.Select.Generic.insert("CONSTANT");
|
|
|
|
ReaderOptions.resolveDependencies();
|
|
|
|
std::vector<std::string> Objects;
|
|
ScopedPrinter W(outs());
|
|
LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
|
|
|
|
// Check logical elements selection.
|
|
{
|
|
std::vector<SelectionInfo> DataClang = {
|
|
{"* const int", &LVElement::getIsType},
|
|
{"CONSTANT", &LVElement::getIsSymbol},
|
|
{"INTEGER", &LVElement::getIsType},
|
|
{"INTPTR", &LVElement::getIsType},
|
|
{"ParamPtr", &LVElement::getIsSymbol},
|
|
{"const int", &LVElement::getIsType},
|
|
{"foo", &LVElement::getIsScope},
|
|
{"foo::?", &LVElement::getIsScope},
|
|
{"int", &LVElement::getIsType},
|
|
{"movl", &LVElement::getIsLine},
|
|
{"movl", &LVElement::getIsLine}};
|
|
std::unique_ptr<LVReader> Reader =
|
|
createReader(ReaderHandler, InputsDir, CodeViewClang);
|
|
checkElementSelection(Reader.get(), DataClang, DataClang.size());
|
|
}
|
|
{
|
|
std::vector<SelectionInfo> DataMsvc = {
|
|
{"* const int", &LVElement::getIsType},
|
|
{"CONSTANT", &LVElement::getIsSymbol},
|
|
{"INTEGER", &LVElement::getIsType},
|
|
{"INTPTR", &LVElement::getIsType},
|
|
{"ParamPtr", &LVElement::getIsSymbol},
|
|
{"const int", &LVElement::getIsType},
|
|
{"foo", &LVElement::getIsScope},
|
|
{"foo::?", &LVElement::getIsScope},
|
|
{"int", &LVElement::getIsType},
|
|
{"movl", &LVElement::getIsLine}};
|
|
std::unique_ptr<LVReader> Reader =
|
|
createReader(ReaderHandler, InputsDir, CodeViewMsvc);
|
|
checkElementSelection(Reader.get(), DataMsvc, DataMsvc.size());
|
|
}
|
|
}
|
|
|
|
// Compare logical elements.
|
|
void compareElements(SmallString<128> &InputsDir) {
|
|
// Reader options.
|
|
LVOptions ReaderOptions;
|
|
ReaderOptions.setAttributeOffset();
|
|
ReaderOptions.setPrintLines();
|
|
ReaderOptions.setPrintSymbols();
|
|
ReaderOptions.setPrintTypes();
|
|
ReaderOptions.setCompareLines();
|
|
ReaderOptions.setCompareSymbols();
|
|
ReaderOptions.setCompareTypes();
|
|
|
|
ReaderOptions.resolveDependencies();
|
|
|
|
std::vector<std::string> Objects;
|
|
ScopedPrinter W(outs());
|
|
LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
|
|
|
|
// Check logical comparison.
|
|
std::unique_ptr<LVReader> Reference =
|
|
createReader(ReaderHandler, InputsDir, CodeViewClang);
|
|
std::unique_ptr<LVReader> Target =
|
|
createReader(ReaderHandler, InputsDir, CodeViewMsvc);
|
|
checkElementComparison(Reference.get(), Target.get());
|
|
}
|
|
|
|
TEST(LogicalViewTest, CodeViewReader) {
|
|
// Initialize targets and assembly printers/parsers.
|
|
llvm::InitializeAllTargetInfos();
|
|
llvm::InitializeAllTargetMCs();
|
|
InitializeAllDisassemblers();
|
|
|
|
llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
|
|
|
|
// This test requires a x86-registered-target.
|
|
Triple TT;
|
|
TT.setArch(Triple::x86_64);
|
|
TT.setVendor(Triple::UnknownVendor);
|
|
TT.setOS(Triple::UnknownOS);
|
|
|
|
std::string TargetLookupError;
|
|
if (!TargetRegistry::lookupTarget(std::string(TT.str()), TargetLookupError))
|
|
return;
|
|
|
|
SmallString<128> InputsDir = unittest::getInputFileDirectory(TestMainArgv0);
|
|
|
|
// Logical elements general properties and selection.
|
|
elementProperties(InputsDir);
|
|
elementSelection(InputsDir);
|
|
|
|
// Compare logical elements.
|
|
compareElements(InputsDir);
|
|
}
|
|
|
|
} // namespace
|