Skip to content

Commit

Permalink
[llvm-debuginfo-analyzer] (09/09) - CodeView Reader
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:

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
  • Loading branch information
CarlosAlbertoEnciso committed Feb 27, 2023
1 parent b6f4834 commit e7950fc
Show file tree
Hide file tree
Showing 45 changed files with 7,204 additions and 9 deletions.
19 changes: 18 additions & 1 deletion llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ class LVElement : public LVObject {
size_t getNameIndex() const { return NameIndex; }
size_t getQualifiedNameIndex() const { return QualifiedNameIndex; }

void setInnerComponent() { setInnerComponent(getName()); }
void setInnerComponent(StringRef Name);

// Element type name.
StringRef getTypeName() const;

Expand Down Expand Up @@ -253,7 +256,7 @@ class LVElement : public LVObject {
virtual void setDiscriminator(uint32_t Value) {}

// Process the values for a DW_TAG_enumerator.
virtual std::string getValue() const { return {}; }
virtual StringRef getValue() const { return {}; }
virtual void setValue(StringRef Value) {}
virtual size_t getValueIndex() const { return 0; }

Expand All @@ -263,6 +266,13 @@ class LVElement : public LVObject {
StringRef
accessibilityString(uint32_t Access = dwarf::DW_ACCESS_private) const;

// CodeView Accessibility Codes.
std::optional<uint32_t> getAccessibilityCode(codeview::MemberAccess Access);
void setAccessibilityCode(codeview::MemberAccess Access) {
if (std::optional<uint32_t> Code = getAccessibilityCode(Access))
AccessibilityCode = Code.value();
}

// DWARF Inline Codes.
uint32_t getInlineCode() const { return InlineCode; }
void setInlineCode(uint32_t Code) { InlineCode = Code; }
Expand All @@ -274,6 +284,13 @@ class LVElement : public LVObject {
StringRef
virtualityString(uint32_t Virtuality = dwarf::DW_VIRTUALITY_none) const;

// CodeView Virtuality Codes.
std::optional<uint32_t> getVirtualityCode(codeview::MethodKind Virtuality);
void setVirtualityCode(codeview::MethodKind Virtuality) {
if (std::optional<uint32_t> Code = getVirtualityCode(Virtuality))
VirtualityCode = Code.value();
}

// DWARF Extern Codes.
StringRef externalString() const;

Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ class LVReader {
assert(Scope && Scope->isCompileUnit() && "Scope is not a compile unit");
CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
}
void setCompileUnitCPUType(codeview::CPUType Type) {
CompileUnit->setCPUType(Type);
}
codeview::CPUType getCompileUnitCPUType() {
return CompileUnit->getCPUType();
}

// Access to the scopes root.
LVScopeRoot *getScopesRoot() const { return Root; }
Expand Down
10 changes: 10 additions & 0 deletions llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,9 @@ class LVScopeCompileUnit final : public LVScope {
// Compilation directory name.
size_t CompilationDirectoryIndex = 0;

// Used by the CodeView Reader.
codeview::CPUType CompilationCPUType = codeview::CPUType::X64;

// Keep record of elements. They are needed at the compilation unit level
// to print the summary at the end of the printing.
LVCounter Allocated;
Expand Down Expand Up @@ -537,6 +540,9 @@ class LVScopeCompileUnit final : public LVScope {
ProducerIndex = getStringPool().getIndex(ProducerName);
}

void setCPUType(codeview::CPUType Type) { CompilationCPUType = Type; }
codeview::CPUType getCPUType() { return CompilationCPUType; }

// Record DWARF tags.
void addDebugTag(dwarf::Tag Target, LVOffset Offset);
// Record elements with invalid offsets.
Expand Down Expand Up @@ -789,6 +795,10 @@ class LVScopeRoot final : public LVScope {
FileFormatNameIndex = getStringPool().getIndex(FileFormatName);
}

// The CodeView Reader uses scoped names. Recursively transform the
// element name to use just the most inner component.
void transformScopedName();

// Process the collected location, ranges and calculate coverage.
void processRangeInformation();

Expand Down
14 changes: 14 additions & 0 deletions llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ namespace logicalview {
// Returns the unique string pool instance.
LVStringPool &getStringPool();

using LVStringRefs = std::vector<StringRef>;
using LVLexicalComponent = std::tuple<StringRef, StringRef>;
using LVLexicalIndex =
std::tuple<LVStringRefs::size_type, LVStringRefs::size_type>;

// Used to record specific characteristics about the objects.
template <typename T> class LVProperties {
SmallBitVector Bits = SmallBitVector(static_cast<unsigned>(T::LastEntry) + 1);
Expand Down Expand Up @@ -221,6 +226,15 @@ inline std::string formattedNames(StringRef Name1, StringRef Name2) {
return (Twine("'") + Twine(Name1) + Twine(Name2) + Twine("'")).str();
}

// The given string represents a symbol or type name with optional enclosing
// scopes, such as: name, name<..>, scope::name, scope::..::name, etc.
// The string can have multiple references to template instantiations.
// It returns the inner most component.
LVLexicalComponent getInnerComponent(StringRef Name);
LVStringRefs getAllLexicalComponents(StringRef Name);
std::string getScopedName(const LVStringRefs &Components,
StringRef BaseName = {});

// These are the values assigned to the debug location record IDs.
// See DebugInfo/CodeView/CodeViewSymbols.def.
// S_DEFRANGE 0x113f
Expand Down
4 changes: 2 additions & 2 deletions llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ class LVSymbol final : public LVElement {
void setBitSize(uint32_t Size) override { BitSize = Size; }

// Process the values for a DW_AT_const_value.
std::string getValue() const override {
return std::string(getStringPool().getString(ValueIndex));
StringRef getValue() const override {
return getStringPool().getString(ValueIndex);
}
void setValue(StringRef Value) override {
ValueIndex = getStringPool().getIndex(Value);
Expand Down
8 changes: 4 additions & 4 deletions llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ class LVTypeEnumerator final : public LVType {
~LVTypeEnumerator() = default;

// Process the values for a DW_TAG_enumerator.
std::string getValue() const override {
return std::string(getStringPool().getString(ValueIndex));
StringRef getValue() const override {
return getStringPool().getString(ValueIndex);
}
void setValue(StringRef Value) override {
ValueIndex = getStringPool().getIndex(Value);
Expand Down Expand Up @@ -222,8 +222,8 @@ class LVTypeParam final : public LVType {
~LVTypeParam() = default;

// Template parameter value.
std::string getValue() const override {
return std::string(getStringPool().getString(ValueIndex));
StringRef getValue() const override {
return getStringPool().getString(ValueIndex);
}
void setValue(StringRef Value) override {
ValueIndex = getStringPool().getIndex(Value);
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/DebugInfo/LogicalView/LVReaderHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class LVReaderHandler {
object::MachOUniversalBinary &Mach);
Error handleObject(LVReaders &Readers, StringRef Filename,
object::Binary &Binary);
Error handleObject(LVReaders &Readers, StringRef Filename, StringRef Buffer,
StringRef ExePath);

Error createReader(StringRef Filename, LVReaders &Readers, PdbOrObj &Input,
StringRef FileFormatName, StringRef ExePath = {});
Expand Down
19 changes: 19 additions & 0 deletions llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ObjectFile.h"

namespace llvm {
Expand Down Expand Up @@ -69,6 +70,12 @@ class LVBinaryReader : public LVReader {
// Function names extracted from the object symbol table.
LVSymbolTable SymbolTable;

// It contains the LVLineDebug elements representing the inlined logical
// lines for the current compile unit, created by parsing the CodeView
// S_INLINESITE symbol annotation data.
using LVInlineeLine = std::map<LVScope *, std::unique_ptr<LVLines>>;
LVInlineeLine CUInlineeLines;

// Instruction lines for a logical scope. These instructions are fetched
// during its merge with the debug lines.
LVDoubleMap<LVSectionIndex, LVScope *, LVLines *> ScopeInstructions;
Expand Down Expand Up @@ -135,6 +142,8 @@ class LVBinaryReader : public LVReader {
LVAddress LowerAddress, LVAddress UpperAddress);
LVRange *getSectionRanges(LVSectionIndex SectionIndex);

void includeInlineeLines(LVSectionIndex SectionIndex, LVScope *Function);

Error createInstructions();
Error createInstructions(LVScope *Function, LVSectionIndex SectionIndex);
Error createInstructions(LVScope *Function, LVSectionIndex SectionIndex,
Expand All @@ -153,6 +162,16 @@ class LVBinaryReader : public LVReader {
LVBinaryReader &operator=(const LVBinaryReader &) = delete;
virtual ~LVBinaryReader() = default;

void addInlineeLines(LVScope *Scope, LVLines &Lines) {
CUInlineeLines.emplace(Scope, std::make_unique<LVLines>(std::move(Lines)));
}

// Convert Segment::Offset pair to absolute address.
LVAddress linearAddress(uint16_t Segment, uint32_t Offset,
LVAddress Addendum = 0) {
return ImageBaseAddress + (Segment * VirtualAddress) + Offset + Addendum;
}

void addToSymbolTable(StringRef Name, LVScope *Function,
LVSectionIndex SectionIndex = 0);
void addToSymbolTable(StringRef Name, LVAddress Address,
Expand Down

0 comments on commit e7950fc

Please sign in to comment.