/// Dwarf form code.
dwarf::Form Form;
+ /// Dwarf attribute value for DW_FORM_implicit_const
+ int64_t Value;
+
public:
- DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {}
+ DIEAbbrevData(dwarf::Attribute A, dwarf::Form F)
+ : Attribute(A), Form(F), Value(0) {}
+ DIEAbbrevData(dwarf::Attribute A, int64_t V)
+ : Attribute(A), Form(dwarf::DW_FORM_implicit_const), Value(V) {}
/// Accessors.
/// @{
dwarf::Attribute getAttribute() const { return Attribute; }
dwarf::Form getForm() const { return Form; }
+ int64_t getValue() const { return Value; }
/// @}
/// Used to gather unique data for the abbreviation folding set.
Data.push_back(DIEAbbrevData(Attribute, Form));
}
+ /// Adds attribute with DW_FORM_implicit_const value
+ void AddImplicitConstAttribute(dwarf::Attribute Attribute, int64_t Value) {
+ Data.push_back(DIEAbbrevData(Attribute, Value));
+ }
+
/// Used to gather unique data for the abbreviation folding set.
void Profile(FoldingSetNodeID &ID) const;
class DWARFAbbreviationDeclaration {
public:
struct AttributeSpec {
- AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<uint8_t> S)
- : Attr(A), Form(F), ByteSize(S) {}
+ AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<int64_t> V)
+ : Attr(A), Form(F), ByteSizeOrValue(V) {}
dwarf::Attribute Attr;
dwarf::Form Form;
- /// If ByteSize has a value, then it contains the fixed size in bytes for
- /// the Form in this object. If ByteSize doesn't have a value, then the
- /// byte size of Form either varies according to the DWARFUnit that it is
- /// contained in or the value size varies and must be decoded from the
- /// debug information in order to determine its size.
- Optional<uint8_t> ByteSize;
+ /// The following field is used for ByteSize for non-implicit_const
+ /// attributes and as value for implicit_const ones, indicated by
+ /// Form == DW_FORM_implicit_const.
+ /// The following cases are distinguished:
+ /// * Form != DW_FORM_implicit_const and ByteSizeOrValue has a value:
+ /// ByteSizeOrValue contains the fixed size in bytes
+ /// for the Form in this object.
+ /// * Form != DW_FORM_implicit_const and ByteSizeOrValue is None:
+ /// byte size of Form either varies according to the DWARFUnit
+ /// that it is contained in or the value size varies and must be
+ /// decoded from the debug information in order to determine its size.
+ /// * Form == DW_FORM_implicit_const:
+ /// ByteSizeOrValue contains value for the implicit_const attribute.
+ Optional<int64_t> ByteSizeOrValue;
+ bool isImplicitConst() const {
+ return Form == dwarf::DW_FORM_implicit_const;
+ }
/// Get the fixed byte size of this Form if possible. This function might
/// use the DWARFUnit to calculate the size of the Form, like for
/// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for
/// the ByteSize member.
- Optional<uint8_t> getByteSize(const DWARFUnit &U) const;
+ Optional<int64_t> getByteSize(const DWARFUnit &U) const;
};
typedef SmallVector<AttributeSpec, 8> AttributeSpecVector;
DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F), U(nullptr) {}
dwarf::Form getForm() const { return Form; }
void setForm(dwarf::Form F) { Form = F; }
+ void setUValue(uint64_t V) { Value.uval = V; }
+ void setSValue(int64_t V) { Value.sval = V; }
+ void setPValue(const char *V) { Value.cstr = V; }
bool isFormClass(FormClass FC) const;
const DWARFUnit *getUnit() const { return U; }
void dump(raw_ostream &OS) const;
// Emit form type.
AP->EmitULEB128(AttrData.getForm(),
dwarf::FormEncodingString(AttrData.getForm()).data());
+
+ // Emit value for DW_FORM_implicit_const.
+ if (AttrData.getForm() == dwarf::DW_FORM_implicit_const) {
+ assert(AP->getDwarfVersion() >= 5 &&
+ "DW_FORM_implicit_const is supported starting from DWARFv5");
+ AP->EmitSLEB128(AttrData.getValue());
+ }
}
// Mark end of abbreviation.
DIEAbbrev DIE::generateAbbrev() const {
DIEAbbrev Abbrev(Tag, hasChildren());
for (const DIEValue &V : values())
- Abbrev.AddAttribute(V.getAttribute(), V.getForm());
+ if (V.getForm() == dwarf::DW_FORM_implicit_const)
+ Abbrev.AddImplicitConstAttribute(V.getAttribute(),
+ V.getDIEInteger().getValue());
+ else
+ Abbrev.AddAttribute(V.getAttribute(), V.getForm());
return Abbrev;
}
///
void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
switch (Form) {
+ case dwarf::DW_FORM_implicit_const:
+ LLVM_FALLTHROUGH;
case dwarf::DW_FORM_flag_present:
// Emit something to keep the lines and comments in sync.
// FIXME: Is there a better way to do this?
///
unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
switch (Form) {
+ case dwarf::DW_FORM_implicit_const: LLVM_FALLTHROUGH;
case dwarf::DW_FORM_flag_present: return 0;
case dwarf::DW_FORM_flag: LLVM_FALLTHROUGH;
case dwarf::DW_FORM_ref1: LLVM_FALLTHROUGH;
Optional<dwarf::Form> Form, uint64_t Integer) {
if (!Form)
Form = DIEInteger::BestForm(false, Integer);
+ assert(Form != dwarf::DW_FORM_implicit_const &&
+ "DW_FORM_implicit_const is used only for signed integers");
Die.addValue(DIEValueAllocator, Attribute, *Form, DIEInteger(Integer));
}
auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr));
auto F = static_cast<Form>(Data.getULEB128(OffsetPtr));
if (A && F) {
- auto FixedFormByteSize = DWARFFormValue::getFixedByteSize(F);
- AttributeSpecs.push_back(AttributeSpec(A, F, FixedFormByteSize));
+ Optional<int64_t> V;
+ bool IsImplicitConst = (F == DW_FORM_implicit_const);
+ if (IsImplicitConst)
+ V = Data.getSLEB128(OffsetPtr);
+ else if (auto Size = DWARFFormValue::getFixedByteSize(F))
+ V = *Size;
+ AttributeSpecs.push_back(AttributeSpec(A, F, V));
+ if (IsImplicitConst)
+ continue;
// If this abbrevation still has a fixed byte size, then update the
// FixedAttributeSize as needed.
if (FixedAttributeSize) {
- if (FixedFormByteSize)
- FixedAttributeSize->NumBytes += *FixedFormByteSize;
+ if (V)
+ FixedAttributeSize->NumBytes += *V;
else {
switch (F) {
case DW_FORM_addr:
OS << formString;
else
OS << format("DW_FORM_Unknown_%x", Spec.Form);
+ if (Spec.isImplicitConst())
+ OS << '\t' << *Spec.ByteSizeOrValue;
OS << '\n';
}
OS << '\n';
if (*MatchAttrIndex == AttrIndex) {
// We have arrived at the attribute to extract, extract if from Offset.
DWARFFormValue FormValue(Spec.Form);
+ if (Spec.isImplicitConst()) {
+ FormValue.setSValue(*Spec.ByteSizeOrValue);
+ return FormValue;
+ }
if (FormValue.extractValue(DebugInfoData, &Offset, &U))
return FormValue;
}
// March Offset along until we get to the attribute we want.
- if (Optional<uint8_t> FixedSize = Spec.getByteSize(U))
+ if (auto FixedSize = Spec.getByteSize(U))
Offset += *FixedSize;
else
DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, &U);
return ByteSize;
}
-Optional<uint8_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
+Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
const DWARFUnit &U) const {
- return ByteSize ? ByteSize : DWARFFormValue::getFixedByteSize(Form, &U);
+ if (isImplicitConst())
+ return 0;
+ if (ByteSizeOrValue)
+ return ByteSizeOrValue;
+ Optional<int64_t> S;
+ auto FixedByteSize = DWARFFormValue::getFixedByteSize(Form, &U);
+ if (FixedByteSize)
+ S = *FixedByteSize;
+ return S;
}
Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(
// Skip all data in the .debug_info for the attributes
for (const auto &AttrSpec : AbbrevDecl->attributes()) {
// Check if this attribute has a fixed byte size.
- if (Optional<uint8_t> FixedSize = AttrSpec.getByteSize(U)) {
+ if (auto FixedSize = AttrSpec.getByteSize(U)) {
// Attribute byte size if fixed, just add the size to the offset.
*OffsetPtr += *FixedSize;
} else if (!DWARFFormValue::skipValue(AttrSpec.Form, DebugInfoData,
return 16;
case DW_FORM_implicit_const:
- // The implicit value is stored in the abbreviation as a ULEB128, any
+ // The implicit value is stored in the abbreviation as a SLEB128, and
// there no data in debug info.
return 0;
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
return (FC == FC_String);
+ case DW_FORM_implicit_const:
+ return (FC == FC_Constant);
default:
break;
}
--- /dev/null
+RUN: llvm-dwarfdump -debug-dump=abbrev %p/Inputs/implicit-const-test.o | FileCheck %s
+CHECK: DW_FORM_implicit_const -9223372036854775808
const uint64_t Data8 = 0x0011223344556677ULL;
const uint64_t Data8_2 = 0xAABBCCDDEEFF0011ULL;
const int64_t SData = INT64_MIN;
+ const int64_t ICSData = INT64_MAX; // DW_FORM_implicit_const SData
const uint64_t UData[] = {UINT64_MAX - 1, UINT64_MAX - 2, UINT64_MAX - 3,
UINT64_MAX - 4, UINT64_MAX - 5, UINT64_MAX - 6,
UINT64_MAX - 7, UINT64_MAX - 8, UINT64_MAX - 9};
const auto Attr_DW_FORM_sdata = static_cast<dwarf::Attribute>(Attr++);
CUDie.addAttribute(Attr_DW_FORM_sdata, DW_FORM_sdata, SData);
+ const auto Attr_DW_FORM_implicit_const =
+ static_cast<dwarf::Attribute>(Attr++);
+ if (Version >= 5)
+ CUDie.addAttribute(Attr_DW_FORM_implicit_const, DW_FORM_implicit_const,
+ ICSData);
+
//----------------------------------------------------------------------
// Test ULEB128 based forms
//----------------------------------------------------------------------
Attr_DW_FORM_flag_present, 0ULL),
1ULL);
- // TODO: test Attr_DW_FORM_implicit_const extraction
-
//----------------------------------------------------------------------
// Test SLEB128 based forms
//----------------------------------------------------------------------
EXPECT_EQ(DieDG.getAttributeValueAsSignedConstant(Attr_DW_FORM_sdata, 0),
SData);
+ if (Version >= 5)
+ EXPECT_EQ(DieDG.getAttributeValueAsSignedConstant(
+ Attr_DW_FORM_implicit_const, 0), ICSData);
//----------------------------------------------------------------------
// Test ULEB128 based forms
TestAllForms<4, AddrType, RefAddrType>();
}
+TEST(DWARFDebugInfo, TestDWARF32Version5Addr4AllForms) {
+ // Test that we can decode all forms for DWARF32, version 5, with 4 byte
+ // addresses.
+ typedef uint32_t AddrType;
+ // DW_FORM_ref_addr are 4 bytes in DWARF32 for version 3 and later
+ typedef uint32_t RefAddrType;
+ TestAllForms<5, AddrType, RefAddrType>();
+}
+
+TEST(DWARFDebugInfo, TestDWARF32Version5Addr8AllForms) {
+ // Test that we can decode all forms for DWARF32, version 5, with 8 byte
+ // addresses.
+ typedef uint64_t AddrType;
+ // DW_FORM_ref_addr are 4 bytes in DWARF32 for version 3 and later
+ typedef uint32_t RefAddrType;
+ TestAllForms<5, AddrType, RefAddrType>();
+}
+
template <uint16_t Version, class AddrType> void TestChildren() {
// Test that we can decode DW_FORM_ref_addr values correctly in DWARF 2 with
// 4 byte addresses. DW_FORM_ref_addr values should be 4 bytes when using