Tweak and extend handling of DWARF debug metadata

This commit is contained in:
baldurk
2023-02-16 13:04:04 +00:00
parent 9c09f2879c
commit f05c4efde8
3 changed files with 147 additions and 23 deletions
@@ -755,6 +755,9 @@ struct DIBase
Expression,
LexicalBlock,
Subrange,
Namespace,
ImportedEntity,
Enum,
} type;
DIBase(Type t) : type(t) {}
@@ -29,6 +29,15 @@
namespace DXIL
{
// DXIL is SO AWFUL. There is an svbr encoding used for the bitcode which negates and shifts. This
// encoding bitwise-nots and shifts, for no reason?
static int64_t debug_only_svbr(uint64_t val)
{
if(val & 0x1)
return int64_t(~(val >> 1));
return val >> 1;
}
bool Program::ParseDebugMetaRecord(MetadataList &metadata, const LLVMBC::BlockOrRecord &metaRecord,
Metadata &meta)
{
@@ -102,6 +111,13 @@ bool Program::ParseDebugMetaRecord(MetadataList &metadata, const LLVMBC::BlockOr
metadata.getOrNULL(metaRecord.ops[6]), metadata.getOrNULL(metaRecord.ops[11]),
metadata.getOrNULL(metaRecord.ops[14])};
}
else if(id == LLVMBC::MetaDataRecord::ENUMERATOR)
{
meta.isDistinct = (metaRecord.ops[0] & 0x1);
meta.dwarf =
new DIEnum(debug_only_svbr(metaRecord.ops[1]), metadata.getStringOrNULL(metaRecord.ops[2]));
}
else if(id == LLVMBC::MetaDataRecord::TEMPLATE_TYPE)
{
meta.isDistinct = (metaRecord.ops[0] & 0x1);
@@ -193,7 +209,7 @@ bool Program::ParseDebugMetaRecord(MetadataList &metadata, const LLVMBC::BlockOr
DW_TAG(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2]),
metadata.getStringOrNULL(metaRecord.ops[3]), metadata.getOrNULL(metaRecord.ops[4]),
metaRecord.ops[5], metadata.getOrNULL(metaRecord.ops[6]), metaRecord.ops[7],
DIFlags(metaRecord.ops[8]), metaRecord.ops[8]);
DIFlags(metaRecord.ops[8]));
meta.children = {metadata.getOrNULL(metaRecord.ops[2]), metadata.getOrNULL(metaRecord.ops[4]),
metadata.getOrNULL(metaRecord.ops[6])};
@@ -212,7 +228,28 @@ bool Program::ParseDebugMetaRecord(MetadataList &metadata, const LLVMBC::BlockOr
{
meta.isDistinct = (metaRecord.ops[0] & 0x1);
meta.dwarf = new DISubrange(metaRecord.ops[1], LLVMBC::BitReader::svbr(metaRecord.ops[2]));
meta.dwarf = new DISubrange(int64_t(metaRecord.ops[1]), debug_only_svbr(metaRecord.ops[2]));
}
else if(id == LLVMBC::MetaDataRecord::NAMESPACE)
{
meta.isDistinct = (metaRecord.ops[0] & 0x1);
meta.dwarf = new DINamespace(metadata.getOrNULL(metaRecord.ops[1]),
metadata.getOrNULL(metaRecord.ops[2]),
metadata.getStringOrNULL(metaRecord.ops[3]), metaRecord.ops[4]);
meta.children = {metadata.getOrNULL(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2])};
}
else if(id == LLVMBC::MetaDataRecord::IMPORTED_ENTITY)
{
meta.isDistinct = (metaRecord.ops[0] & 0x1);
meta.dwarf =
new DIImportedEntity(DW_TAG(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2]),
metadata.getOrNULL(metaRecord.ops[3]), metaRecord.ops[4],
metadata.getStringOrNULL(metaRecord.ops[5]));
meta.children = {metadata.getOrNULL(metaRecord.ops[2]), metadata.getOrNULL(metaRecord.ops[3])};
}
else if(id == LLVMBC::MetaDataRecord::EXPRESSION)
{
@@ -393,6 +430,15 @@ rdcstr DICompositeType::toString() const
return ret;
}
rdcstr DIEnum::toString() const
{
rdcstr ret = "!DIEnumerator(";
ret += StringFormat::Fmt("name: %s", escapeString(*name).c_str());
ret += StringFormat::Fmt(", value: %lld", value);
ret += ")";
return ret;
}
rdcstr DITemplateTypeParameter::toString() const
{
return StringFormat::Fmt("!DITemplateTypeParameter(name: %s, type: %s)",
@@ -410,16 +456,17 @@ rdcstr DITemplateValueParameter::toString() const
rdcstr DISubprogram::toString() const
{
rdcstr ret =
StringFormat::Fmt("!DISubprogram(name: %s", escapeString(name ? *name : rdcstr()).c_str());
rdcstr ret = "!DISubprogram(";
if(name)
ret += StringFormat::Fmt("name: %s, ", escapeString(*name).c_str());
if(linkageName)
ret += StringFormat::Fmt(", linkageName: %s", escapeString(*linkageName).c_str());
ret += StringFormat::Fmt("linkageName: %s, ", escapeString(*linkageName).c_str());
if(scope)
ret += StringFormat::Fmt(", scope: %s", scope->refString().c_str());
ret += StringFormat::Fmt("scope: %s, ", scope->refString().c_str());
if(file)
ret += StringFormat::Fmt(", file: %s", file->refString().c_str());
ret += StringFormat::Fmt("file: %s", file->refString().c_str());
else
ret += ", file: null";
ret += "file: null";
if(line)
ret += StringFormat::Fmt(", line: %llu", line);
if(type)
@@ -480,6 +527,8 @@ rdcstr DIGlobalVariable::toString() const
ret += StringFormat::Fmt(", type: %s", type->refString().c_str());
ret += StringFormat::Fmt(", isLocal: %s", isLocal ? "true" : "false");
ret += StringFormat::Fmt(", isDefinition: %s", isDefinition ? "true" : "false");
if(declaration)
ret += StringFormat::Fmt(", declaration: %s", declaration->refString().c_str());
if(variable)
ret += StringFormat::Fmt(", variable: %s", variable->refString().c_str());
ret += ")";
@@ -490,22 +539,20 @@ rdcstr DILocalVariable::toString() const
{
rdcstr ret = StringFormat::Fmt("!DILocalVariable(tag: %s, name: %s", ToStr(tag).c_str(),
escapeString(name ? *name : rdcstr()).c_str());
if(arg)
if(arg || tag != DW_TAG_auto_variable)
ret += StringFormat::Fmt(", arg: %llu", arg);
if(scope)
ret += StringFormat::Fmt(", scope: %s", scope->refString().c_str());
else
ret += ", scope: null";
if(file)
ret += StringFormat::Fmt(", file: %s", file->refString().c_str());
else
ret += ", file: null";
if(line)
ret += StringFormat::Fmt(", line: %llu", line);
if(type)
ret += StringFormat::Fmt(", type: %s", type->refString().c_str());
if(flags != DIFlagNone)
ret += StringFormat::Fmt(", flags: %s", ToStr(flags).c_str());
if(alignInBits)
ret += StringFormat::Fmt(", align: %llu", alignInBits);
ret += ")";
return ret;
}
@@ -553,13 +600,46 @@ rdcstr DILexicalBlock::toString() const
rdcstr DISubrange::toString() const
{
rdcstr ret = "!DISubrange(";
ret += StringFormat::Fmt("count: %llu", count);
ret += StringFormat::Fmt("count: %lld", count);
if(lowerBound)
ret += StringFormat::Fmt(", lowerBound: %lld", lowerBound);
ret += ")";
return ret;
}
rdcstr DINamespace::toString() const
{
rdcstr ret = "!DINamespace(";
if(name)
ret += StringFormat::Fmt("name: %s, ", escapeString(*name).c_str());
if(scope)
ret += StringFormat::Fmt("scope: %s", scope->refString().c_str());
else
ret += "scope: null";
if(file)
ret += StringFormat::Fmt(", file: %s", file->refString().c_str());
ret += StringFormat::Fmt(", line: %llu", line);
ret += ")";
return ret;
}
rdcstr DIImportedEntity::toString() const
{
rdcstr ret = StringFormat::Fmt("!DIImportedEntity(tag: %s", ToStr(tag).c_str());
if(name)
ret += StringFormat::Fmt(", name: %s, ", escapeString(*name).c_str());
if(scope)
ret += StringFormat::Fmt(", scope: %s", scope->refString().c_str());
else
ret += ", scope: null";
if(entity)
ret += StringFormat::Fmt(", entity: %s", entity->refString().c_str());
if(line)
ret += StringFormat::Fmt(", line: %llu", line);
ret += ")";
return ret;
}
}; // namespace DXIL
template <>
+50 -9
View File
@@ -505,6 +505,16 @@ struct DICompositeType : public DIBase
virtual rdcstr toString() const;
};
struct DIEnum : public DIBase
{
static const DIBase::Type DIType = DIBase::Enum;
DIEnum(int64_t value, const rdcstr *name) : DIBase(DIType), value(value), name(name) {}
int64_t value;
const rdcstr *name;
virtual rdcstr toString() const;
};
struct DITemplateTypeParameter : public DIBase
{
static const DIBase::Type DIType = DIBase::TemplateTypeParameter;
@@ -607,7 +617,7 @@ struct DIGlobalVariable : public DIBase
static const DIBase::Type DIType = DIBase::GlobalVariable;
DIGlobalVariable(const Metadata *scope, const rdcstr *name, const rdcstr *linkageName,
const Metadata *file, uint64_t line, const Metadata *type, bool isLocal,
bool isDefinition, const Metadata *variable, const Metadata *staticData)
bool isDefinition, const Metadata *variable, const Metadata *declaration)
: DIBase(DIType),
scope(scope),
name(name),
@@ -618,7 +628,7 @@ struct DIGlobalVariable : public DIBase
isLocal(isLocal),
isDefinition(isDefinition),
variable(variable),
staticData(staticData)
declaration(declaration)
{
}
@@ -631,7 +641,7 @@ struct DIGlobalVariable : public DIBase
bool isLocal;
bool isDefinition;
const Metadata *variable;
const Metadata *staticData;
const Metadata *declaration;
virtual rdcstr toString() const;
};
@@ -640,8 +650,7 @@ struct DILocalVariable : public DIBase
{
static const DIBase::Type DIType = DIBase::LocalVariable;
DILocalVariable(DW_TAG tag, const Metadata *scope, const rdcstr *name, const Metadata *file,
uint64_t line, const Metadata *type, uint64_t arg, DIFlags flags,
uint64_t alignInBits)
uint64_t line, const Metadata *type, uint64_t arg, DIFlags flags)
: DIBase(DIType),
tag(tag),
scope(scope),
@@ -650,8 +659,7 @@ struct DILocalVariable : public DIBase
line(line),
type(type),
arg(arg),
flags(flags),
alignInBits(alignInBits)
flags(flags)
{
}
@@ -705,17 +713,50 @@ struct DILexicalBlock : public DIBase
struct DISubrange : public DIBase
{
static const DIBase::Type DIType = DIBase::Subrange;
DISubrange(uint64_t count, int64_t lowerBound)
DISubrange(int64_t count, int64_t lowerBound)
: DIBase(DIType), count(count), lowerBound(lowerBound)
{
}
uint64_t count;
int64_t count;
int64_t lowerBound;
virtual rdcstr toString() const;
};
struct DINamespace : public DIBase
{
static const DIBase::Type DIType = DIBase::Namespace;
DINamespace(const Metadata *scope, const Metadata *file, const rdcstr *name, uint64_t line)
: DIBase(DIType), scope(scope), file(file), name(name), line(line)
{
}
const Metadata *scope;
const Metadata *file;
const rdcstr *name;
uint64_t line;
virtual rdcstr toString() const;
};
struct DIImportedEntity : public DIBase
{
static const DIBase::Type DIType = DIBase::ImportedEntity;
DIImportedEntity(DW_TAG tag, const Metadata *scope, const Metadata *entity, uint64_t line,
const rdcstr *name)
: DIBase(DIType), tag(tag), scope(scope), entity(entity), line(line), name(name)
{
}
DW_TAG tag;
const Metadata *scope;
const Metadata *entity;
uint64_t line;
const rdcstr *name;
virtual rdcstr toString() const;
};
}; // namespace DXIL
DECLARE_REFLECTION_ENUM(DXIL::DW_LANG);