
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: Compare elements - Support for logical elements comparison. See '--compare' options. LVCompare Reviewed By: psamolysov, probinson Differential Revision: https://reviews.llvm.org/D125782
223 lines
7.2 KiB
C++
223 lines
7.2 KiB
C++
//===-- LVLine.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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This implements the LVLine class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::logicalview;
|
|
|
|
#define DEBUG_TYPE "Line"
|
|
|
|
namespace {
|
|
const char *const KindBasicBlock = "BasicBlock";
|
|
const char *const KindDiscriminator = "Discriminator";
|
|
const char *const KindEndSequence = "EndSequence";
|
|
const char *const KindEpilogueBegin = "EpilogueBegin";
|
|
const char *const KindLineDebug = "Line";
|
|
const char *const KindLineSource = "Code";
|
|
const char *const KindNewStatement = "NewStatement";
|
|
const char *const KindPrologueEnd = "PrologueEnd";
|
|
const char *const KindUndefined = "Undefined";
|
|
const char *const KindAlwaysStepInto = "AlwaysStepInto"; // CodeView
|
|
const char *const KindNeverStepInto = "NeverStepInto"; // CodeView
|
|
} // end anonymous namespace
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Logical line.
|
|
//===----------------------------------------------------------------------===//
|
|
// Return a string representation for the line kind.
|
|
const char *LVLine::kind() const {
|
|
const char *Kind = KindUndefined;
|
|
if (getIsLineDebug())
|
|
Kind = KindLineDebug;
|
|
else if (getIsLineAssembler())
|
|
Kind = KindLineSource;
|
|
return Kind;
|
|
}
|
|
|
|
LVLineDispatch LVLine::Dispatch = {
|
|
{LVLineKind::IsBasicBlock, &LVLine::getIsBasicBlock},
|
|
{LVLineKind::IsDiscriminator, &LVLine::getIsDiscriminator},
|
|
{LVLineKind::IsEndSequence, &LVLine::getIsEndSequence},
|
|
{LVLineKind::IsLineDebug, &LVLine::getIsLineDebug},
|
|
{LVLineKind::IsLineAssembler, &LVLine::getIsLineAssembler},
|
|
{LVLineKind::IsNewStatement, &LVLine::getIsNewStatement},
|
|
{LVLineKind::IsEpilogueBegin, &LVLine::getIsEpilogueBegin},
|
|
{LVLineKind::IsPrologueEnd, &LVLine::getIsPrologueEnd},
|
|
{LVLineKind::IsAlwaysStepInto, &LVLine::getIsAlwaysStepInto},
|
|
{LVLineKind::IsNeverStepInto, &LVLine::getIsNeverStepInto}};
|
|
|
|
// String used as padding for printing elements with no line number.
|
|
std::string LVLine::noLineAsString(bool ShowZero) const {
|
|
if (options().getInternalNone())
|
|
return LVObject::noLineAsString(ShowZero);
|
|
return (ShowZero || options().getAttributeZero()) ? (" 0 ")
|
|
: (" - ");
|
|
}
|
|
|
|
void LVLine::markMissingParents(const LVLines *References,
|
|
const LVLines *Targets) {
|
|
if (!(References && Targets))
|
|
return;
|
|
|
|
LLVM_DEBUG({
|
|
dbgs() << "\n[LVLine::markMissingParents]\n";
|
|
for (const LVLine *Reference : *References)
|
|
dbgs() << "References: "
|
|
<< "Kind = " << formattedKind(Reference->kind()) << ", "
|
|
<< "Line = " << Reference->getLineNumber() << "\n";
|
|
for (const LVLine *Target : *Targets)
|
|
dbgs() << "Targets : "
|
|
<< "Kind = " << formattedKind(Target->kind()) << ", "
|
|
<< "Line = " << Target->getLineNumber() << "\n";
|
|
});
|
|
|
|
for (LVLine *Reference : *References) {
|
|
LLVM_DEBUG({
|
|
dbgs() << "Search Reference: Line = " << Reference->getLineNumber()
|
|
<< "\n";
|
|
});
|
|
if (!Reference->findIn(Targets))
|
|
Reference->markBranchAsMissing();
|
|
}
|
|
}
|
|
|
|
LVLine *LVLine::findIn(const LVLines *Targets) const {
|
|
if (!Targets)
|
|
return nullptr;
|
|
|
|
LLVM_DEBUG({
|
|
dbgs() << "\n[LVLine::findIn]\n"
|
|
<< "Reference: "
|
|
<< "Level = " << getLevel() << ", "
|
|
<< "Kind = " << formattedKind(kind()) << ", "
|
|
<< "Line = " << getLineNumber() << "\n";
|
|
for (const LVLine *Target : *Targets)
|
|
dbgs() << "Target : "
|
|
<< "Level = " << Target->getLevel() << ", "
|
|
<< "Kind = " << formattedKind(Target->kind()) << ", "
|
|
<< "Line = " << Target->getLineNumber() << "\n";
|
|
});
|
|
|
|
for (LVLine *Line : *Targets)
|
|
if (equals(Line))
|
|
return Line;
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
bool LVLine::equals(const LVLine *Line) const {
|
|
return LVElement::equals(Line);
|
|
}
|
|
|
|
bool LVLine::equals(const LVLines *References, const LVLines *Targets) {
|
|
if (!References && !Targets)
|
|
return true;
|
|
if (References && Targets && References->size() == Targets->size()) {
|
|
for (const LVLine *Reference : *References)
|
|
if (!Reference->findIn(Targets))
|
|
return false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void LVLine::report(LVComparePass Pass) {
|
|
getComparator().printItem(this, Pass);
|
|
}
|
|
|
|
void LVLine::print(raw_ostream &OS, bool Full) const {
|
|
if (getReader().doPrintLine(this)) {
|
|
getReaderCompileUnit()->incrementPrintedLines();
|
|
LVElement::print(OS, Full);
|
|
printExtra(OS, Full);
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// DWARF line record.
|
|
//===----------------------------------------------------------------------===//
|
|
std::string LVLineDebug::statesInfo(bool Formatted) const {
|
|
// Returns the DWARF extra qualifiers.
|
|
std::string String;
|
|
raw_string_ostream Stream(String);
|
|
|
|
std::string Separator = Formatted ? " " : "";
|
|
if (getIsNewStatement()) {
|
|
Stream << Separator << "{" << KindNewStatement << "}";
|
|
Separator = " ";
|
|
}
|
|
if (getIsDiscriminator()) {
|
|
Stream << Separator << "{" << KindDiscriminator << "}";
|
|
Separator = " ";
|
|
}
|
|
if (getIsBasicBlock()) {
|
|
Stream << Separator << "{" << KindBasicBlock << "}";
|
|
Separator = " ";
|
|
}
|
|
if (getIsEndSequence()) {
|
|
Stream << Separator << "{" << KindEndSequence << "}";
|
|
Separator = " ";
|
|
}
|
|
if (getIsEpilogueBegin()) {
|
|
Stream << Separator << "{" << KindEpilogueBegin << "}";
|
|
Separator = " ";
|
|
}
|
|
if (getIsPrologueEnd()) {
|
|
Stream << Separator << "{" << KindPrologueEnd << "}";
|
|
Separator = " ";
|
|
}
|
|
if (getIsAlwaysStepInto()) {
|
|
Stream << Separator << "{" << KindAlwaysStepInto << "}";
|
|
Separator = " ";
|
|
}
|
|
if (getIsNeverStepInto()) {
|
|
Stream << Separator << "{" << KindNeverStepInto << "}";
|
|
Separator = " ";
|
|
}
|
|
|
|
return String;
|
|
}
|
|
|
|
bool LVLineDebug::equals(const LVLine *Line) const {
|
|
if (!LVLine::equals(Line))
|
|
return false;
|
|
return getFilenameIndex() == Line->getFilenameIndex();
|
|
}
|
|
|
|
void LVLineDebug::printExtra(raw_ostream &OS, bool Full) const {
|
|
OS << formattedKind(kind());
|
|
|
|
if (options().getAttributeQualifier()) {
|
|
// The qualifier includes the states information and the source filename
|
|
// that contains the line element.
|
|
OS << statesInfo(/*Formatted=*/true);
|
|
OS << " " << formattedName(getPathname());
|
|
}
|
|
OS << "\n";
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Assembler line extracted from the ELF .text section.
|
|
//===----------------------------------------------------------------------===//
|
|
bool LVLineAssembler::equals(const LVLine *Line) const {
|
|
return LVLine::equals(Line);
|
|
}
|
|
|
|
void LVLineAssembler::printExtra(raw_ostream &OS, bool Full) const {
|
|
OS << formattedKind(kind());
|
|
OS << " " << formattedName(getName());
|
|
OS << "\n";
|
|
}
|