#ifndef LLVM_DEBUGINFO_DICONTEXT_H
#define LLVM_DEBUGINFO_DICONTEXT_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
namespace llvm {
struct DILineInfo {
static constexpr const char *const BadString = "<invalid>";
static constexpr const char *const Addr2LineBadString = "??";
std::string FileName;
std::string FunctionName;
std::string StartFileName;
Optional<StringRef> Source;
uint32_t Line = 0;
uint32_t Column = 0;
uint32_t StartLine = 0;
Optional<uint64_t> StartAddress;
uint32_t Discriminator = 0;
DILineInfo()
: FileName(BadString), FunctionName(BadString), StartFileName(BadString) {
}
bool operator==(const DILineInfo &RHS) const {
return Line == RHS.Line && Column == RHS.Column &&
FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
StartFileName == RHS.StartFileName && StartLine == RHS.StartLine &&
Discriminator == RHS.Discriminator;
}
bool operator!=(const DILineInfo &RHS) const { return !(*this == RHS); }
bool operator<(const DILineInfo &RHS) const {
return std::tie(FileName, FunctionName, StartFileName, Line, Column,
StartLine, Discriminator) <
std::tie(RHS.FileName, RHS.FunctionName, RHS.StartFileName, RHS.Line,
RHS.Column, RHS.StartLine, RHS.Discriminator);
}
explicit operator bool() const { return *this != DILineInfo(); }
void dump(raw_ostream &OS) {
OS << "Line info: ";
if (FileName != BadString)
OS << "file '" << FileName << "', ";
if (FunctionName != BadString)
OS << "function '" << FunctionName << "', ";
OS << "line " << Line << ", ";
OS << "column " << Column << ", ";
if (StartFileName != BadString)
OS << "start file '" << StartFileName << "', ";
OS << "start line " << StartLine << '\n';
}
};
using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>;
class DIInliningInfo {
SmallVector<DILineInfo, 4> Frames;
public:
DIInliningInfo() = default;
const DILineInfo &getFrame(unsigned Index) const {
assert(Index < Frames.size());
return Frames[Index];
}
DILineInfo *getMutableFrame(unsigned Index) {
assert(Index < Frames.size());
return &Frames[Index];
}
uint32_t getNumberOfFrames() const { return Frames.size(); }
void addFrame(const DILineInfo &Frame) { Frames.push_back(Frame); }
void resize(unsigned i) { Frames.resize(i); }
};
struct DIGlobal {
std::string Name;
uint64_t Start = 0;
uint64_t Size = 0;
std::string DeclFile;
uint64_t DeclLine = 0;
DIGlobal() : Name(DILineInfo::BadString) {}
};
struct DILocal {
std::string FunctionName;
std::string Name;
std::string DeclFile;
uint64_t DeclLine = 0;
Optional<int64_t> FrameOffset;
Optional<uint64_t> Size;
Optional<uint64_t> TagOffset;
};
enum class DINameKind { None, ShortName, LinkageName };
struct DILineInfoSpecifier {
enum class FileLineInfoKind {
None,
RawValue,
BaseNameOnly,
RelativeFilePath,
AbsoluteFilePath
};
using FunctionNameKind = DINameKind;
FileLineInfoKind FLIKind;
FunctionNameKind FNKind;
DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::RawValue,
FunctionNameKind FNKind = FunctionNameKind::None)
: FLIKind(FLIKind), FNKind(FNKind) {}
inline bool operator==(const DILineInfoSpecifier &RHS) const {
return FLIKind == RHS.FLIKind && FNKind == RHS.FNKind;
}
};
enum DIDumpTypeCounter {
#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
DIDT_ID_##ENUM_NAME,
#include "llvm/BinaryFormat/Dwarf.def"
#undef HANDLE_DWARF_SECTION
DIDT_ID_UUID,
DIDT_ID_Count
};
static_assert(DIDT_ID_Count <= 32, "section types overflow storage");
enum DIDumpType : unsigned {
DIDT_Null,
DIDT_All = ~0U,
#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME,
#include "llvm/BinaryFormat/Dwarf.def"
#undef HANDLE_DWARF_SECTION
DIDT_UUID = 1 << DIDT_ID_UUID,
};
struct DIDumpOptions {
unsigned DumpType = DIDT_All;
unsigned ChildRecurseDepth = -1U;
unsigned ParentRecurseDepth = -1U;
uint16_t Version = 0; uint8_t AddrSize = 4; bool ShowAddresses = true;
bool ShowChildren = false;
bool ShowParents = false;
bool ShowForm = false;
bool SummarizeTypes = false;
bool Verbose = false;
bool DisplayRawContents = false;
static DIDumpOptions getForSingleDIE() {
DIDumpOptions Opts;
Opts.ChildRecurseDepth = 0;
Opts.ParentRecurseDepth = 0;
return Opts;
}
DIDumpOptions noImplicitRecursion() const {
DIDumpOptions Opts = *this;
if (ChildRecurseDepth == -1U && !ShowChildren)
Opts.ChildRecurseDepth = 0;
if (ParentRecurseDepth == -1U && !ShowParents)
Opts.ParentRecurseDepth = 0;
return Opts;
}
std::function<void(Error)> RecoverableErrorHandler =
WithColor::defaultErrorHandler;
std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
};
class DIContext {
public:
enum DIContextKind { CK_DWARF, CK_PDB };
DIContext(DIContextKind K) : Kind(K) {}
virtual ~DIContext() = default;
DIContextKind getKind() const { return Kind; }
virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) {
return true;
}
virtual DILineInfo getLineInfoForAddress(
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
virtual DILineInfo
getLineInfoForDataAddress(object::SectionedAddress Address) = 0;
virtual DILineInfoTable getLineInfoForAddressRange(
object::SectionedAddress Address, uint64_t Size,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
virtual DIInliningInfo getInliningInfoForAddress(
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
virtual std::vector<DILocal>
getLocalsForAddress(object::SectionedAddress Address) = 0;
private:
const DIContextKind Kind;
};
class LoadedObjectInfo {
protected:
LoadedObjectInfo() = default;
LoadedObjectInfo(const LoadedObjectInfo &) = default;
public:
virtual ~LoadedObjectInfo() = default;
virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const {
return 0;
}
virtual bool getLoadedSectionContents(const object::SectionRef &Sec,
StringRef &Data) const {
return false;
}
virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0;
};
template <typename Derived, typename Base = LoadedObjectInfo>
struct LoadedObjectInfoHelper : Base {
protected:
LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default;
LoadedObjectInfoHelper() = default;
public:
template <typename... Ts>
LoadedObjectInfoHelper(Ts &&...Args) : Base(std::forward<Ts>(Args)...) {}
std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
return std::make_unique<Derived>(static_cast<const Derived &>(*this));
}
};
}
#endif