Index: include/llvm/DebugInfo/DWARFFormValue.h =================================================================== --- include/llvm/DebugInfo/DWARFFormValue.h +++ include/llvm/DebugInfo/DWARFFormValue.h @@ -67,6 +67,7 @@ /// DWARFFormValue has form class is suitable for representing Foo. Optional getAsReference(const DWARFUnit *U) const; Optional getAsUnsignedConstant() const; + Optional getAsSignedConstant() const; Optional getAsCString(const DWARFUnit *U) const; Optional getAsAddress(const DWARFUnit *U) const; Optional getAsSectionOffset() const; Index: lib/DebugInfo/DWARFFormValue.cpp =================================================================== --- lib/DebugInfo/DWARFFormValue.cpp +++ lib/DebugInfo/DWARFFormValue.cpp @@ -549,6 +549,24 @@ return Value.uval; } +Optional DWARFFormValue::getAsSignedConstant() const { + if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) + || Form == DW_FORM_udata) + return None; + switch (Form) { + case DW_FORM_data4: + return (int32_t)Value.uval; + case DW_FORM_data2: + return (int16_t)Value.uval; + case DW_FORM_data1: + return (int8_t)Value.uval; + case DW_FORM_sdata: + case DW_FORM_data8: + default: + return Value.sval; + } +} + Optional> DWARFFormValue::getAsBlock() const { if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc)) return None; Index: unittests/DebugInfo/DWARFFormValueTest.cpp =================================================================== --- unittests/DebugInfo/DWARFFormValueTest.cpp +++ unittests/DebugInfo/DWARFFormValueTest.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "../lib/DebugInfo/DWARFContext.h" #include "llvm/DebugInfo/DWARFFormValue.h" #include "llvm/Support/Dwarf.h" #include "gtest/gtest.h" @@ -46,4 +47,67 @@ EXPECT_TRUE(isFormClass(DW_FORM_ref_sig8, DWARFFormValue::FC_Reference)); } + +class DWARFTestContext : public DWARFContext { + Section DummySection; + TypeSectionMap DummySectionMap; +public: + bool isLittleEndian() const override { return sys::IsLittleEndianHost; } + uint8_t getAddressSize() const override { return sizeof(void *); } + const Section &getInfoSection() override { return DummySection; } + const TypeSectionMap &getTypesSections() override { return DummySectionMap; } + StringRef getAbbrevSection() override { return StringRef(); } + const Section &getLocSection() override { return DummySection; } + const Section &getLocDWOSection() override { return DummySection; } + StringRef getARangeSection() override { return StringRef(); } + StringRef getDebugFrameSection() override { return StringRef(); } + const Section &getLineSection() override { return DummySection; } + const Section &getLineDWOSection() override { return DummySection; } + StringRef getStringSection() override { return StringRef(); } + StringRef getRangeSection() override { return StringRef(); } + StringRef getPubNamesSection() override { return StringRef(); } + StringRef getPubTypesSection() override { return StringRef(); } + StringRef getGnuPubNamesSection() override { return StringRef(); } + StringRef getGnuPubTypesSection() override { return StringRef(); } + const Section &getInfoDWOSection() override { return DummySection; } + const TypeSectionMap &getTypesDWOSections() override { return DummySectionMap; } + StringRef getAbbrevDWOSection() override { return StringRef(); } + StringRef getStringDWOSection() override { return StringRef(); } + StringRef getStringOffsetDWOSection() override { return StringRef(); } + StringRef getRangeDWOSection() override { return StringRef(); } + StringRef getAddrSection() override { return StringRef(); } +}; + + +static DWARFTestContext TestContext; +static DWARFUnitSection DummyUnitSection; +static RelocAddrMap DummyRelocMap; +static DWARFCompileUnit DummyCompileUnit(TestContext, nullptr, StringRef(), + StringRef(), StringRef(), StringRef(), + StringRef(), &DummyRelocMap, + sys::IsLittleEndianHost, DummyUnitSection); + +DWARFFormValue createFromValue(uint16_t Form, uint64_t Value) { + union { + uint64_t Val; + char Raw[8]; + } U = { Value }; + uint32_t Offset = 0; + DWARFFormValue Result(Form); + DataExtractor Data(U.Raw, sys::IsLittleEndianHost, sizeof(void*)); + Result.extractValue(Data, &Offset, &DummyCompileUnit); + return Result; +} + +TEST(DWARFFormValue, SignedConstantForms) { + DWARFFormValue data1 = createFromValue(DW_FORM_data1, 0xFF); + DWARFFormValue data2 = createFromValue(DW_FORM_data2, 0xFFFF); + DWARFFormValue data4 = createFromValue(DW_FORM_data4, 0xFFFFFFFF); + DWARFFormValue data8 = createFromValue(DW_FORM_data8, 0xFFFFFFFFFFFFFFFF); + EXPECT_EQ(data1.getAsSignedConstant().getValue(), -1); + EXPECT_EQ(data2.getAsSignedConstant().getValue(), -1); + EXPECT_EQ(data4.getAsSignedConstant().getValue(), -1); + EXPECT_EQ(data8.getAsSignedConstant().getValue(), -1); +} + } // end anonymous namespace