mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-24 12:20:00 +00:00
[dwarf] Unify unknown dwarf enum formatting code
Summary: We have had at least three pieces of code (in DWARFAbbreviationDeclaration, DWARFAcceleratorTable and DWARFDie) that have hand-rolled support for dumping unknown dwarf enum values. While not terrible, they are a bit distracting and enable small differences to creep in (Unknown_ffff vs. Unknown_0xffff). I ended up needing to add a fourth place (DWARFVerifier), so it seems it would be a good time to centralize. This patch creates an alternative to the XXXString dumping functions in the BinaryFormat library, which formats an unknown value as DW_TYPE_unknown_1234, instead of just an empty string. It is based on the formatv function, as that allows us to avoid materializing the string for unknown values (and because this way I don't have to invent a name for the new functions :P). In this patch I add formatters for dwarf attributes, forms, tags, and index attributes as these are the ones in use currently, but adding other enums is straight-forward. Reviewers: dblaikie, JDevlieghere, aprantl Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D44570 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328090 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
74473fc50b
commit
8abcf8e6ef
@ -24,6 +24,8 @@
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/FormatVariadicDetails.h"
|
||||
|
||||
namespace llvm {
|
||||
class StringRef;
|
||||
@ -405,8 +407,8 @@ enum GDBIndexEntryLinkage { GIEL_EXTERNAL, GIEL_STATIC };
|
||||
/// \defgroup DwarfConstantsDumping Dwarf constants dumping functions
|
||||
///
|
||||
/// All these functions map their argument's value back to the
|
||||
/// corresponding enumerator name or return nullptr if the value isn't
|
||||
/// known.
|
||||
/// corresponding enumerator name or return an empty StringRef if the value
|
||||
/// isn't known.
|
||||
///
|
||||
/// @{
|
||||
StringRef TagString(unsigned Tag);
|
||||
@ -573,8 +575,46 @@ private:
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Enum> struct EnumTraits : public std::false_type {};
|
||||
|
||||
template <> struct EnumTraits<Attribute> : public std::true_type {
|
||||
static constexpr char Type[] = "AT";
|
||||
static constexpr StringRef (*StringFn)(unsigned) = &AttributeString;
|
||||
};
|
||||
|
||||
template <> struct EnumTraits<Form> : public std::true_type {
|
||||
static constexpr char Type[] = "FORM";
|
||||
static constexpr StringRef (*StringFn)(unsigned) = &FormEncodingString;
|
||||
};
|
||||
|
||||
template <> struct EnumTraits<Index> : public std::true_type {
|
||||
static constexpr char Type[] = "IDX";
|
||||
static constexpr StringRef (*StringFn)(unsigned) = &IndexString;
|
||||
};
|
||||
|
||||
template <> struct EnumTraits<Tag> : public std::true_type {
|
||||
static constexpr char Type[] = "TAG";
|
||||
static constexpr StringRef (*StringFn)(unsigned) = &TagString;
|
||||
};
|
||||
} // End of namespace dwarf
|
||||
|
||||
/// Dwarf constants format_provider
|
||||
///
|
||||
/// Specialization of the format_provider template for dwarf enums. Unlike the
|
||||
/// dumping functions above, these format unknown enumerator values as
|
||||
/// DW_TYPE_unknown_1234 (e.g. DW_TAG_unknown_ffff).
|
||||
template <typename Enum>
|
||||
struct format_provider<
|
||||
Enum, typename std::enable_if<dwarf::EnumTraits<Enum>::value>::type> {
|
||||
static void format(const Enum &E, raw_ostream &OS, StringRef Style) {
|
||||
StringRef Str = dwarf::EnumTraits<Enum>::StringFn(E);
|
||||
if (Str.empty()) {
|
||||
OS << "DW_" << dwarf::EnumTraits<Enum>::Type << "_unknown_"
|
||||
<< llvm::format("%x", E);
|
||||
} else
|
||||
OS << Str;
|
||||
}
|
||||
};
|
||||
} // End of namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -675,3 +675,8 @@ bool llvm::dwarf::isValidFormForVersion(Form F, unsigned Version,
|
||||
}
|
||||
return ExtensionsOk;
|
||||
}
|
||||
|
||||
const char llvm::dwarf::EnumTraits<Attribute>::Type[];
|
||||
const char llvm::dwarf::EnumTraits<Form>::Type[];
|
||||
const char llvm::dwarf::EnumTraits<Index>::Type[];
|
||||
const char llvm::dwarf::EnumTraits<Tag>::Type[];
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@ -126,26 +127,11 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data,
|
||||
}
|
||||
|
||||
void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
|
||||
auto tagString = TagString(getTag());
|
||||
OS << '[' << getCode() << "] ";
|
||||
if (!tagString.empty())
|
||||
OS << tagString;
|
||||
else
|
||||
OS << format("DW_TAG_Unknown_%x", getTag());
|
||||
OS << formatv("{0}", getTag());
|
||||
OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
|
||||
for (const AttributeSpec &Spec : AttributeSpecs) {
|
||||
OS << '\t';
|
||||
auto attrString = AttributeString(Spec.Attr);
|
||||
if (!attrString.empty())
|
||||
OS << attrString;
|
||||
else
|
||||
OS << format("DW_AT_Unknown_%x", Spec.Attr);
|
||||
OS << '\t';
|
||||
auto formString = FormEncodingString(Spec.Form);
|
||||
if (!formString.empty())
|
||||
OS << formString;
|
||||
else
|
||||
OS << format("DW_FORM_Unknown_%x", Spec.Form);
|
||||
OS << formatv("\t{0}\t{1}", Spec.Attr, Spec.Form);
|
||||
if (Spec.isImplicitConst())
|
||||
OS << '\t' << Spec.getImplicitConstValue();
|
||||
OS << '\n';
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/DJB.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/ScopedPrinter.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstddef>
|
||||
@ -24,35 +25,19 @@
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
struct DwarfConstant {
|
||||
StringRef (*StringFn)(unsigned);
|
||||
StringRef Type;
|
||||
struct Atom {
|
||||
unsigned Value;
|
||||
};
|
||||
|
||||
static raw_ostream &operator<<(raw_ostream &OS, const DwarfConstant &C) {
|
||||
StringRef Str = C.StringFn(C.Value);
|
||||
static raw_ostream &operator<<(raw_ostream &OS, const Atom &A) {
|
||||
StringRef Str = dwarf::AtomTypeString(A.Value);
|
||||
if (!Str.empty())
|
||||
return OS << Str;
|
||||
return OS << "DW_" << C.Type << "_Unknown_0x" << format("%x", C.Value);
|
||||
return OS << "DW_ATOM_unknown_" << format("%x", A.Value);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
static DwarfConstant formatTag(unsigned Tag) {
|
||||
return {dwarf::TagString, "TAG", Tag};
|
||||
}
|
||||
|
||||
static DwarfConstant formatForm(unsigned Form) {
|
||||
return {dwarf::FormEncodingString, "FORM", Form};
|
||||
}
|
||||
|
||||
static DwarfConstant formatIndex(unsigned Idx) {
|
||||
return {dwarf::IndexString, "IDX", Idx};
|
||||
}
|
||||
|
||||
static DwarfConstant formatAtom(unsigned Atom) {
|
||||
return {dwarf::AtomTypeString, "ATOM", Atom};
|
||||
}
|
||||
static Atom formatAtom(unsigned Atom) { return {Atom}; }
|
||||
|
||||
DWARFAcceleratorTable::~DWARFAcceleratorTable() = default;
|
||||
|
||||
@ -226,7 +211,7 @@ LLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const {
|
||||
for (const auto &Atom : HdrData.Atoms) {
|
||||
DictScope AtomScope(W, ("Atom " + Twine(i++)).str());
|
||||
W.startLine() << "Type: " << formatAtom(Atom.first) << '\n';
|
||||
W.startLine() << "Form: " << formatForm(Atom.second) << '\n';
|
||||
W.startLine() << "Form: " << formatv("{0}", Atom.second) << '\n';
|
||||
AtomForms.push_back(DWARFFormValue(Atom.second));
|
||||
}
|
||||
}
|
||||
@ -415,12 +400,10 @@ llvm::Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
|
||||
|
||||
void DWARFDebugNames::Abbrev::dump(ScopedPrinter &W) const {
|
||||
DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str());
|
||||
W.startLine() << "Tag: " << formatTag(Tag) << '\n';
|
||||
W.startLine() << formatv("Tag: {0}\n", Tag);
|
||||
|
||||
for (const auto &Attr : Attributes) {
|
||||
W.startLine() << formatIndex(Attr.Index) << ": " << formatForm(Attr.Form)
|
||||
<< '\n';
|
||||
}
|
||||
for (const auto &Attr : Attributes)
|
||||
W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);
|
||||
}
|
||||
|
||||
static constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc() {
|
||||
@ -583,11 +566,10 @@ Optional<uint64_t> DWARFDebugNames::Entry::getDIESectionOffset() const {
|
||||
|
||||
void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const {
|
||||
W.printHex("Abbrev", Abbr->Code);
|
||||
W.startLine() << "Tag: " << formatTag(Abbr->Tag) << "\n";
|
||||
|
||||
W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
|
||||
assert(Abbr->Attributes.size() == Values.size());
|
||||
for (const auto &Tuple : zip_first(Abbr->Attributes, Values)) {
|
||||
W.startLine() << formatIndex(std::get<0>(Tuple).Index) << ": ";
|
||||
W.startLine() << formatv("{0}: ", std::get<0>(Tuple).Index);
|
||||
std::get<1>(Tuple).dump(W.getOStream());
|
||||
W.getOStream() << '\n';
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/WithColor.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
@ -188,20 +189,10 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
|
||||
const char BaseIndent[] = " ";
|
||||
OS << BaseIndent;
|
||||
OS.indent(Indent + 2);
|
||||
auto attrString = AttributeString(Attr);
|
||||
if (!attrString.empty())
|
||||
WithColor(OS, HighlightColor::Attribute) << attrString;
|
||||
else
|
||||
WithColor(OS, HighlightColor::Attribute).get()
|
||||
<< format("DW_AT_Unknown_%x", Attr);
|
||||
WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr);
|
||||
|
||||
if (DumpOpts.Verbose || DumpOpts.ShowForm) {
|
||||
auto formString = FormEncodingString(Form);
|
||||
if (!formString.empty())
|
||||
OS << " [" << formString << ']';
|
||||
else
|
||||
OS << format(" [DW_FORM_Unknown_%x]", Form);
|
||||
}
|
||||
if (DumpOpts.Verbose || DumpOpts.ShowForm)
|
||||
OS << formatv(" [{0}]", Form);
|
||||
|
||||
DWARFUnit *U = Die.getDwarfUnit();
|
||||
DWARFFormValue formValue(Form);
|
||||
@ -465,13 +456,8 @@ void DWARFDie::dump(raw_ostream &OS, unsigned Indent,
|
||||
if (abbrCode) {
|
||||
auto AbbrevDecl = getAbbreviationDeclarationPtr();
|
||||
if (AbbrevDecl) {
|
||||
auto tagString = TagString(getTag());
|
||||
if (!tagString.empty())
|
||||
WithColor(OS, HighlightColor::Tag).get().indent(Indent) << tagString;
|
||||
else
|
||||
WithColor(OS, HighlightColor::Tag).get().indent(Indent)
|
||||
<< format("DW_TAG_Unknown_%x", getTag());
|
||||
|
||||
WithColor(OS, HighlightColor::Tag).get().indent(Indent)
|
||||
<< formatv("{0}", getTag());
|
||||
if (DumpOpts.Verbose)
|
||||
OS << format(" [%u] %c", abbrCode,
|
||||
AbbrevDecl->hasChildren() ? '*' : ' ');
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
@ -192,4 +193,14 @@ TEST(DwarfTest, FixedFormSizes) {
|
||||
EXPECT_EQ(*RefSize, 8);
|
||||
}
|
||||
|
||||
TEST(DwarfTest, format_provider) {
|
||||
EXPECT_EQ("DW_AT_name", formatv("{0}", DW_AT_name).str());
|
||||
EXPECT_EQ("DW_AT_unknown_3fff", formatv("{0}", DW_AT_hi_user).str());
|
||||
EXPECT_EQ("DW_FORM_addr", formatv("{0}", DW_FORM_addr).str());
|
||||
EXPECT_EQ("DW_FORM_unknown_1f00", formatv("{0}", DW_FORM_lo_user).str());
|
||||
EXPECT_EQ("DW_IDX_compile_unit", formatv("{0}", DW_IDX_compile_unit).str());
|
||||
EXPECT_EQ("DW_IDX_unknown_3fff", formatv("{0}", DW_IDX_hi_user).str());
|
||||
EXPECT_EQ("DW_TAG_compile_unit", formatv("{0}", DW_TAG_compile_unit).str());
|
||||
EXPECT_EQ("DW_TAG_unknown_ffff", formatv("{0}", DW_TAG_hi_user).str());
|
||||
}
|
||||
} // end namespace
|
||||
|
Loading…
Reference in New Issue
Block a user