Skip to content

Commit

Permalink
[llvm-debuginfo-analyzer] (05/09) - Select elements
Browse files Browse the repository at this point in the history
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:

Select elements
- Support for logical elements selection:
  LVPatterns

Reviewed By: psamolysov, probinson

Differential Revision: https://reviews.llvm.org/D125780
  • Loading branch information
CarlosAlbertoEnciso committed Oct 21, 2022
1 parent 8516697 commit 0332a8e
Show file tree
Hide file tree
Showing 16 changed files with 1,002 additions and 16 deletions.
8 changes: 8 additions & 0 deletions llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
Expand Up @@ -17,7 +17,9 @@
#include "llvm/DebugInfo/LogicalView/Core/LVObject.h"
#include "llvm/DebugInfo/LogicalView/Core/LVStringPool.h"
#include "llvm/Support/Casting.h"
#include <map>
#include <set>
#include <vector>

namespace llvm {
namespace logicalview {
Expand Down Expand Up @@ -60,6 +62,8 @@ enum class LVSubclassID : unsigned char {

enum class LVElementKind { Discarded, Global, Optimized, LastEntry };
using LVElementKindSet = std::set<LVElementKind>;
using LVElementDispatch = std::map<LVElementKind, LVElementGetFunction>;
using LVElementRequest = std::vector<LVElementGetFunction>;

class LVElement : public LVObject {
enum class Property {
Expand Down Expand Up @@ -98,6 +102,7 @@ class LVElement : public LVObject {
};
// Typed bitvector with properties for this element.
LVProperties<Property> Properties;
static LVElementDispatch Dispatch;

/// RTTI.
const LVSubclassID SubclassID;
Expand Down Expand Up @@ -330,6 +335,9 @@ class LVElement : public LVObject {
virtual void resolveName();
virtual void resolveReferences() {}
void resolveParents();

public:
static LVElementDispatch &getDispatch() { return Dispatch; }
};

} // end namespace logicalview
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h
Expand Up @@ -33,11 +33,14 @@ enum class LVLineKind {
LastEntry
};
using LVLineKindSet = std::set<LVLineKind>;
using LVLineDispatch = std::map<LVLineKind, LVLineGetFunction>;
using LVLineRequest = std::vector<LVLineGetFunction>;

// Class to represent a logical line.
class LVLine : public LVElement {
// Typed bitvector with kinds for this line.
LVProperties<LVLineKind> Kinds;
static LVLineDispatch Dispatch;

public:
LVLine() : LVElement(LVSubclassID::LV_LINE) {
Expand Down Expand Up @@ -78,6 +81,8 @@ class LVLine : public LVElement {
return lineAsString(getLineNumber(), getDiscriminator(), ShowZero);
}

static LVLineDispatch &getDispatch() { return Dispatch; }

void print(raw_ostream &OS, bool Full = true) const override;
void printExtra(raw_ostream &OS, bool Full = true) const override {}

Expand Down
197 changes: 196 additions & 1 deletion llvm/include/llvm/DebugInfo/LogicalView/Core/LVOptions.h
Expand Up @@ -16,10 +16,10 @@

#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
#include "llvm/Support/Regex.h"
#include <set>
#include <string>

Expand Down Expand Up @@ -445,6 +445,201 @@ class LVOptions {
inline LVOptions &options() { return (*LVOptions::getOptions()); }
inline void setOptions(LVOptions *Options) { LVOptions::setOptions(Options); }

class LVPatterns final {
// Pattern Mode.
enum class LVMatchMode {
None = 0, // No given pattern.
Match, // Perfect match.
NoCase, // Ignore case.
Regex // Regular expression.
};

// Keep the search pattern information.
struct LVMatch {
std::string Pattern; // Normal pattern.
std::shared_ptr<Regex> RE; // Regular Expression Pattern.
LVMatchMode Mode = LVMatchMode::None; // Match mode.
};

using LVMatchInfo = std::vector<LVMatch>;
LVMatchInfo GenericMatchInfo;
using LVMatchOffsets = std::vector<uint64_t>;
LVMatchOffsets OffsetMatchInfo;

// Element selection.
LVElementDispatch ElementDispatch;
LVLineDispatch LineDispatch;
LVScopeDispatch ScopeDispatch;
LVSymbolDispatch SymbolDispatch;
LVTypeDispatch TypeDispatch;

// Element selection request.
LVElementRequest ElementRequest;
LVLineRequest LineRequest;
LVScopeRequest ScopeRequest;
LVSymbolRequest SymbolRequest;
LVTypeRequest TypeRequest;

// Check an element printing Request.
template <typename T, typename U>
bool checkElementRequest(const T *Element, const U &Requests) const {
assert(Element && "Element must not be nullptr");
for (const auto &Request : Requests)
if ((Element->*Request)())
return true;
// Check generic element requests.
for (const LVElementGetFunction &Request : ElementRequest)
if ((Element->*Request)())
return true;
return false;
}

// Add an element printing request based on its kind.
template <typename T, typename U, typename V>
void addRequest(const T &Selection, const U &Dispatch, V &Request) const {
for (const auto &Entry : Selection) {
// Find target function to fullfit request.
typename U::const_iterator Iter = Dispatch.find(Entry);
if (Iter != Dispatch.end())
Request.push_back(Iter->second);
}
}

void addElement(LVElement *Element);

template <typename T, typename U>
void resolveGenericPatternMatch(T *Element, const U &Requests) {
assert(Element && "Element must not be nullptr");
auto CheckPattern = [=]() -> bool {
return Element->isNamed() &&
(matchGenericPattern(Element->getName()) ||
matchGenericPattern(Element->getTypeName()));
};
auto CheckOffset = [=]() -> bool {
return matchOffsetPattern(Element->getOffset());
};
if ((options().getSelectGenericPattern() && CheckPattern()) ||
(options().getSelectOffsetPattern() && CheckOffset()) ||
((Requests.size() || ElementRequest.size()) &&
checkElementRequest(Element, Requests)))
addElement(Element);
}

template <typename U>
void resolveGenericPatternMatch(LVLine *Line, const U &Requests) {
assert(Line && "Line must not be nullptr");
auto CheckPattern = [=]() -> bool {
return matchGenericPattern(Line->lineNumberAsStringStripped()) ||
matchGenericPattern(Line->getName()) ||
matchGenericPattern(Line->getPathname());
};
auto CheckOffset = [=]() -> bool {
return matchOffsetPattern(Line->getAddress());
};
if ((options().getSelectGenericPattern() && CheckPattern()) ||
(options().getSelectOffsetPattern() && CheckOffset()) ||
(Requests.size() && checkElementRequest(Line, Requests)))
addElement(Line);
}

Error createMatchEntry(LVMatchInfo &Filters, StringRef Pattern,
bool IgnoreCase, bool UseRegex);

public:
static LVPatterns *getPatterns();

LVPatterns() {
ElementDispatch = LVElement::getDispatch();
LineDispatch = LVLine::getDispatch();
ScopeDispatch = LVScope::getDispatch();
SymbolDispatch = LVSymbol::getDispatch();
TypeDispatch = LVType::getDispatch();
}
LVPatterns(const LVPatterns &) = delete;
LVPatterns &operator=(const LVPatterns &) = delete;
~LVPatterns() = default;

// Clear any existing patterns.
void clear() {
GenericMatchInfo.clear();
OffsetMatchInfo.clear();
ElementRequest.clear();
LineRequest.clear();
ScopeRequest.clear();
SymbolRequest.clear();
TypeRequest.clear();

options().resetSelectGenericKind();
options().resetSelectGenericPattern();
options().resetSelectOffsetPattern();
}

void addRequest(LVElementKindSet &Selection) {
addRequest(Selection, ElementDispatch, ElementRequest);
}
void addRequest(LVLineKindSet &Selection) {
addRequest(Selection, LineDispatch, LineRequest);
}
void addRequest(LVScopeKindSet &Selection) {
addRequest(Selection, ScopeDispatch, ScopeRequest);
}
void addRequest(LVSymbolKindSet &Selection) {
addRequest(Selection, SymbolDispatch, SymbolRequest);
}
void addRequest(LVTypeKindSelection &Selection) {
addRequest(Selection, TypeDispatch, TypeRequest);
}

void updateReportOptions();

bool matchPattern(StringRef Input, const LVMatchInfo &MatchInfo);
// Match a pattern (--select='pattern').
bool matchGenericPattern(StringRef Input) {
return matchPattern(Input, GenericMatchInfo);
}
bool matchOffsetPattern(LVOffset Offset) {
return std::find(OffsetMatchInfo.begin(), OffsetMatchInfo.end(), Offset) !=
OffsetMatchInfo.end();
}

void resolvePatternMatch(LVLine *Line) {
resolveGenericPatternMatch(Line, LineRequest);
}

void resolvePatternMatch(LVScope *Scope) {
resolveGenericPatternMatch(Scope, ScopeRequest);
}

void resolvePatternMatch(LVSymbol *Symbol) {
resolveGenericPatternMatch(Symbol, SymbolRequest);
}

void resolvePatternMatch(LVType *Type) {
resolveGenericPatternMatch(Type, TypeRequest);
}

void addPatterns(StringSet<> &Patterns, LVMatchInfo &Filters);

// Add generic and offset patterns info.
void addGenericPatterns(StringSet<> &Patterns);
void addOffsetPatterns(const LVOffsetSet &Patterns);

// Conditions to print an object.
bool printElement(const LVLine *Line) const;
bool printObject(const LVLocation *Location) const;
bool printElement(const LVScope *Scope) const;
bool printElement(const LVSymbol *Symbol) const;
bool printElement(const LVType *Type) const;

void print(raw_ostream &OS) const;

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void dump() const { print(dbgs()); }
#endif
};

inline LVPatterns &patterns() { return *LVPatterns::getPatterns(); }

} // namespace logicalview
} // namespace llvm

Expand Down
20 changes: 15 additions & 5 deletions llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
Expand Up @@ -141,11 +141,21 @@ class LVReader {
LVSplitContext &getSplitContext() { return SplitContext; }

// Conditions to print an object.
bool doPrintLine(const LVLine *Line) const { return true; }
bool doPrintLocation(const LVLocation *Location) const { return true; }
bool doPrintScope(const LVScope *Scope) const { return true; }
bool doPrintSymbol(const LVSymbol *Symbol) const { return true; }
bool doPrintType(const LVType *Type) const { return true; }
bool doPrintLine(const LVLine *Line) const {
return patterns().printElement(Line);
}
bool doPrintLocation(const LVLocation *Location) const {
return patterns().printObject(Location);
}
bool doPrintScope(const LVScope *Scope) const {
return patterns().printElement(Scope);
}
bool doPrintSymbol(const LVSymbol *Symbol) const {
return patterns().printElement(Symbol);
}
bool doPrintType(const LVType *Type) const {
return patterns().printElement(Type);
}

static LVReader &getInstance();
static void setInstance(LVReader *Reader);
Expand Down
21 changes: 19 additions & 2 deletions llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
Expand Up @@ -53,6 +53,8 @@ enum class LVScopeKind {
LastEntry
};
using LVScopeKindSet = std::set<LVScopeKind>;
using LVScopeDispatch = std::map<LVScopeKind, LVScopeGetFunction>;
using LVScopeRequest = std::vector<LVScopeGetFunction>;

using LVOffsetElementMap = std::map<LVOffset, LVElement *>;

Expand All @@ -78,6 +80,7 @@ class LVScope : public LVElement {
// Typed bitvector with kinds and properties for this scope.
LVProperties<LVScopeKind> Kinds;
LVProperties<Property> Properties;
static LVScopeDispatch Dispatch;

// Coverage factor in units (bytes).
unsigned CoverageFactor = 0;
Expand Down Expand Up @@ -118,8 +121,8 @@ class LVScope : public LVElement {
void printEncodedArgs(raw_ostream &OS, bool Full) const;

void printActiveRanges(raw_ostream &OS, bool Full = true) const;
virtual void printSizes(raw_ostream &OS) const {};
virtual void printSummary(raw_ostream &OS) const {};
virtual void printSizes(raw_ostream &OS) const {}
virtual void printSummary(raw_ostream &OS) const {}

// Encoded template arguments.
virtual StringRef getEncodedArgs() const { return StringRef(); }
Expand Down Expand Up @@ -259,6 +262,8 @@ class LVScope : public LVElement {

void resolveElements();

static LVScopeDispatch &getDispatch() { return Dispatch; }

void print(raw_ostream &OS, bool Full = true) const override;
void printExtra(raw_ostream &OS, bool Full = true) const override;
virtual void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) {}
Expand Down Expand Up @@ -385,6 +390,10 @@ class LVScopeCompileUnit final : public LVScope {
LVScopeCompileUnit &operator=(const LVScopeCompileUnit &) = delete;
~LVScopeCompileUnit() = default;

LVScope *getCompileUnitParent() const override {
return static_cast<LVScope *>(const_cast<LVScopeCompileUnit *>(this));
}

// Get the line located at the given address.
LVLine *lineLowerBound(LVAddress Address) const;
LVLine *lineUpperBound(LVAddress Address) const;
Expand Down Expand Up @@ -412,6 +421,14 @@ class LVScopeCompileUnit final : public LVScope {
void processRangeLocationCoverage(
LVValidLocation ValidLocation = &LVLocation::validateRanges);

// Add matched element.
void addMatched(LVElement *Element) { MatchedElements.push_back(Element); }
void addMatched(LVScope *Scope) { MatchedScopes.push_back(Scope); }
void propagatePatternMatch();

const LVElements &getMatchedElements() const { return MatchedElements; }
const LVScopes &getMatchedScopes() const { return MatchedScopes; }

void printLocalNames(raw_ostream &OS, bool Full = true) const;
void printSummary(raw_ostream &OS, const LVCounter &Counter,
const char *Header) const;
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h
Expand Up @@ -30,13 +30,16 @@ enum class LVSymbolKind {
LastEntry
};
using LVSymbolKindSet = std::set<LVSymbolKind>;
using LVSymbolDispatch = std::map<LVSymbolKind, LVSymbolGetFunction>;
using LVSymbolRequest = std::vector<LVSymbolGetFunction>;

class LVSymbol final : public LVElement {
enum class Property { HasLocation, FillGaps, LastEntry };

// Typed bitvector with kinds and properties for this symbol.
LVProperties<LVSymbolKind> Kinds;
LVProperties<Property> Properties;
static LVSymbolDispatch Dispatch;

// CodeView symbol Linkage name.
size_t LinkageNameIndex = 0;
Expand Down Expand Up @@ -152,6 +155,8 @@ class LVSymbol final : public LVElement {
void resolveName() override;
void resolveReferences() override;

static LVSymbolDispatch &getDispatch() { return Dispatch; }

void print(raw_ostream &OS, bool Full = true) const override;
void printExtra(raw_ostream &OS, bool Full = true) const override;

Expand Down

0 comments on commit 0332a8e

Please sign in to comment.