Index: include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -10,6 +10,7 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H #define LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/DataExtractor.h" @@ -17,8 +18,10 @@ namespace llvm { class raw_ostream; +class DWARFUnit; class DWARFDebugLoc { +public: /// A single location within a location list. struct Entry { /// The beginning address of the instruction range. @@ -36,8 +39,11 @@ unsigned Offset; /// All the locations in which the variable is stored. SmallVector Entries; + /// Dump this list on OS. + void dump(raw_ostream &OS, const DWARFUnit* Unit, unsigned Indent) const; }; +private: typedef SmallVector LocationLists; /// A list of all the variables in the debug_loc section, each one describing @@ -50,13 +56,17 @@ public: DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {} /// Print the location lists found within the debug_loc section. - void dump(raw_ostream &OS) const; + void dump(raw_ostream &OS, const DWARFUnit *Unit) const; /// Parse the debug_loc section accessible via the 'data' parameter using the /// specified address size to interpret the address ranges. void parse(DataExtractor data, unsigned AddressSize); + + Optional + parseOneLocationList(DataExtractor Data, unsigned AddressSize, uint32_t *Offset); }; class DWARFDebugLocDWO { +public: struct Entry { uint64_t Start; uint32_t Length; @@ -66,15 +76,20 @@ struct LocationList { unsigned Offset; SmallVector Entries; + void dump(raw_ostream &OS, const DWARFUnit *Unit, + unsigned Indent = 12) const; }; +private: typedef SmallVector LocationLists; - LocationLists Locations; public: void parse(DataExtractor data); - void dump(raw_ostream &OS) const; + void dump(raw_ostream &OS, const DWARFUnit *Unit) const; + + static Optional parseOneLocationList(DataExtractor Data, + uint32_t *Offset); }; } Index: include/llvm/DebugInfo/DWARF/DWARFExpression.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -0,0 +1,145 @@ +//===--- DWARFExpression.h - DWARF Expression handling ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFEXPRESSION_H +#define LLVM_DEBUGINFO_DWARFEXPRESSION_H + +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { +class DWARFUnit; +class raw_ostream; + +class DWARFExpression { +public: + class iterator; + + /// \brief This class represents an Operation in the + /// Expression. Each operation can have up to 2 oprerands. + /// + /// An Operation can be in Error state (check with isError()). This + /// means that it couldn't be decoded successfully and if it is the + /// case, all others fields contain undefined values. + class Op { + public: + /// \brief Size and signedness of expression operations' operands. + enum Encoding : uint8_t { + Size1 = 0, + Size2 = 1, + Size4 = 2, + Size8 = 3, + SizeLEB = 4, + SizeAddr = 5, + SizeRefAddr = 6, + SizeBlock = 7, ///< Preceding operand contains block size + SignBit = 0x8, + SignedSize1 = SignBit | Size1, + SignedSize2 = SignBit | Size2, + SignedSize4 = SignBit | Size4, + SignedSize8 = SignBit | Size8, + SignedSizeLEB = SignBit | SizeLEB, + SizeNA = 0xFF ///< Unused operands get this encoding. + }; + + enum DwarfVersion : uint8_t { + DwarfNA, ///< Serves as a marker for unused entries + Dwarf2 = 2, + Dwarf3, + Dwarf4 + }; + + /// \brief Description of the encoding of one expression Op. + struct Description { + DwarfVersion Version; ///< Dwarf version where the Op was introduced. + Encoding Op[2]; ///< Encoding for Op operands, or SizeNA. + + Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA, + Encoding Op2 = SizeNA) + : Version(Version) { + Op[0] = Op1; + Op[1] = Op2; + } + }; + + private: + friend class DWARFExpression::iterator; + uint8_t Opcode; ///< The Op Opcode, DW_OP_. + Description Desc; + bool Error; + uint32_t EndOffset; + uint64_t Operands[2]; + + public: + Description &getDescription() { return Desc; } + uint8_t getCode() { return Opcode; } + uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; } + uint32_t getEndOffset() { return EndOffset; } + bool Extract(DataExtractor Data, const DWARFUnit *U, uint32_t Offset); + bool isError() { return Error; } + bool Print(raw_ostream &OS, const DWARFExpression *U, bool isEH); + }; + + /// \brief An iterator to go through the expression operations. + class iterator + : public iterator_facade_base { + friend class DWARFExpression; + DWARFExpression *Expression; + uint32_t Offset; + Op Op; + iterator(DWARFExpression *Expression, uint32_t Offset) + : Expression(Expression), Offset(Offset) { + Op.Error = Offset >= Expression->Data.getData().size() || + !Op.Extract(Expression->Data, Expression->Unit, Offset); + } + + public: + class Op& operator++() { + Offset = Op.isError() ? Expression->Data.getData().size() : Op.EndOffset; + Op.Error = Offset >= Expression->Data.getData().size() || + !Op.Extract(Expression->Data, Expression->Unit, Offset); + return Op; + } + + class Op &operator*() { + return Op; + } + + // Comparison operators areprovided out of line. + friend bool operator==(const iterator&, const iterator&); + }; + + DWARFExpression(DataExtractor Data, const DWARFUnit *Unit) + : Data(Data), Unit(Unit) {} + + iterator begin() { return iterator(this, 0); } + iterator end() { return iterator(this, Data.getData().size()); } + iterator_range operations() { return make_range(begin(), end()); } + + void Print(raw_ostream &OS); + +private: + DataExtractor Data; + const DWARFUnit *Unit; +}; + +bool operator==(const DWARFExpression::iterator &LHS, + const DWARFExpression::iterator &RHS) { + return LHS.Expression == RHS.Expression && LHS.Offset == RHS.Offset; +} + +bool operator!=(const DWARFExpression::iterator &LHS, + const DWARFExpression::iterator &RHS) { + return !(LHS == RHS); +} + +} +#endif Index: include/llvm/DebugInfo/DWARFExpression.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/DWARFExpression.h @@ -0,0 +1,128 @@ +//===--- DWARFExpression.h - DWARF Expression handling ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFEXPRESSION_H +#define LLVM_DEBUGINFO_DWARFEXPRESSION_H + +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { +class DWARFUnit; +class raw_ostream; + +class DWARFExpression { +public: + class iterator; + + class Op { + public: + /// \brief Size and signedness of expression operations' operands. + enum Encoding : uint8_t { + Size1 = 0, + Size2 = 1, + Size4 = 2, + Size8 = 3, + SizeLEB = 4, + SizeAddr = 5, + SizeRefAddr = 6, + SizeBlock = 7, ///< Preceding operand contains block size + SignBit = 0x8, + SignedSize1 = SignBit | Size1, + SignedSize2 = SignBit | Size2, + SignedSize4 = SignBit | Size4, + SignedSize8 = SignBit | Size8, + SignedSizeLEB = SignBit | SizeLEB, + SizeNA = 0xFF ///< Unused operands get this encoding. + }; + + enum DwarfVersion : uint8_t { + DwarfNA, ///< Serves as a marker for unused entries + Dwarf2 = 2, + Dwarf3, + Dwarf4 + }; + + /// \brief Description of the encoding of one expression Op. + struct Description { + DwarfVersion Version; ///< Dwarf version where the Op was introduced. + Encoding Op[2]; ///< Encoding for Op operands, or SizeNA. + + Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA, + Encoding Op2 = SizeNA) + : Version(Version) { + Op[0] = Op1; + Op[1] = Op2; + } + }; + + private: + friend class DWARFExpression::iterator; + uint8_t Opcode; + Description Desc; + bool Error; + uint32_t EndOffset; + uint64_t Operands[2]; + + public: + Description &getDescription() { return Desc; } + uint8_t getCode() { return Opcode; } + uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; } + uint32_t getEndOffset() { return EndOffset; } + bool Extract(DataExtractor Data, const DWARFUnit *U, uint32_t Offset); + bool isError() { return Error; } + bool Print(raw_ostream &OS, const DWARFExpression *U, bool isEH); + }; + + /// \brief An iterator to go through the expression operations. + class iterator + : public iterator_facade_base { + friend class DWARFExpression; + DWARFExpression *Expression; + uint32_t Offset; + Op Op; + iterator(DWARFExpression *Expression, uint32_t Offset) + : Expression(Expression), Offset(Offset) { + Op.Error = Offset >= Expression->Data.getData().size() || + !Op.Extract(Expression->Data, Expression->Unit, Offset); + } + + public: + void operator++() { + Offset = Op.isError() ? Expression->Data.getData().size() : Op.EndOffset; + Op.Error = Offset >= Expression->Data.getData().size() || + !Op.Extract(Expression->Data, Expression->Unit, Offset); + } + + class Op &operator*() { + return Op; + } + + bool operator==(const iterator &I) const { + return Expression == I.Expression && Offset == I.Offset; + } + }; + + DWARFExpression(DataExtractor Data, const DWARFUnit *Unit) + : Data(Data), Unit(Unit) {} + + iterator begin() { return iterator(this, 0); } + iterator end() { return iterator(this, Data.getData().size()); } + iterator_range operations() { return make_range(begin(), end()); } + + void Print(raw_ostream &OS, bool isEH); + +private: + DataExtractor Data; + const DWARFUnit *Unit; +}; +} +#endif Index: lib/DebugInfo/CMakeLists.txt =================================================================== --- lib/DebugInfo/CMakeLists.txt +++ lib/DebugInfo/CMakeLists.txt @@ -1,2 +1,2 @@ -add_subdirectory(DWARF) \ No newline at end of file +add_subdirectory(DWARF) Index: lib/DebugInfo/DWARF/CMakeLists.txt =================================================================== --- lib/DebugInfo/DWARF/CMakeLists.txt +++ lib/DebugInfo/DWARF/CMakeLists.txt @@ -12,6 +12,7 @@ DWARFDebugLine.cpp DWARFDebugLoc.cpp DWARFDebugRangeList.cpp + DWARFExpression.cpp DWARFFormValue.cpp DWARFTypeUnit.cpp DWARFUnit.cpp Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -116,12 +116,18 @@ if (DumpType == DIDT_All || DumpType == DIDT_Loc) { OS << "\n.debug_loc contents:\n"; - getDebugLoc()->dump(OS); + // The compile unit is wrong, but the same dirty trick is used in + // getDebugLoc(). + if (getNumCompileUnits()) + getDebugLoc()->dump(OS, getCompileUnitAtIndex(0)); } if (DumpType == DIDT_All || DumpType == DIDT_LocDwo) { OS << "\n.debug_loc.dwo contents:\n"; - getDebugLocDWO()->dump(OS); + // The compile unit is wrong, but the same dirty trick is used in + // getDebugLoc(). + if (getNumCompileUnits()) + getDebugLocDWO()->dump(OS, getCompileUnitAtIndex(0)); } if (DumpType == DIDT_All || DumpType == DIDT_Frames) { Index: lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -12,6 +12,7 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Debug.h" @@ -108,6 +109,43 @@ } } +static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, + DWARFUnit *U, unsigned Indent) { + if (FormValue.isFormClass(DWARFFormValue::FC_Block) + || FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { + ArrayRef Expr = *FormValue.getAsBlock(); + DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), + U->getContext().isLittleEndian(), 0); + DWARFExpression(Data, U).Print(OS);; + return; + } + + FormValue.dump(OS, U); + if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { + const DWARFSection &LocSection = U->getContext().getLocSection(); + const DWARFSection &LocDWOSection = U->getContext().getLocDWOSection(); + uint32_t Offset = *FormValue.getAsSectionOffset(); + + if (LocSection.Data.size()) { + DWARFDebugLoc DebugLoc(LocSection.Relocs); + DataExtractor Data(LocSection.Data, U->getContext().isLittleEndian(), 0); + auto LL = DebugLoc.parseOneLocationList(Data, U->getAddressByteSize(), + &Offset); + if (LL) + LL->dump(OS, U, Indent); + else + OS << "error extracting location list."; + } else if (LocDWOSection.Data.size()) { + DataExtractor Data(LocDWOSection.Data, U->getContext().isLittleEndian(), 0); + auto LL = DWARFDebugLocDWO::parseOneLocationList(Data, &Offset); + if (LL) + LL->dump(OS, U, Indent); + else + OS << "error extracting location list."; + } + } +} + void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, DWARFUnit *u, uint32_t *offset_ptr, @@ -155,6 +193,9 @@ WithColor(OS, Color) << Name; else if (attr == DW_AT_decl_line || attr == DW_AT_call_line) OS << *formValue.getAsUnsignedConstant(); + else if (attr == DW_AT_location || attr == DW_AT_frame_base || + attr == DW_AT_data_member_location) + dumpLocation(OS, formValue, u, sizeof(BaseIndent)+indent+4); else formValue.dump(OS, u); Index: lib/DebugInfo/DWARF/DWARFDebugLoc.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -8,121 +8,163 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" +#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Dwarf.h" +#include using namespace llvm; -void DWARFDebugLoc::dump(raw_ostream &OS) const { +void DWARFDebugLoc::LocationList::dump(raw_ostream& OS, const DWARFUnit *Unit, + unsigned Indent) const +{ + for (const Entry &E : Entries) { + OS << '\n'; + OS.indent(Indent); + OS << format("0x%016" PRIx64, E.Begin+Unit->getBaseAddress()) << " - " + << format("0x%016" PRIx64, E.End+Unit->getBaseAddress()) << ": "; + + DataExtractor Data(StringRef((const char*)E.Loc.data(), E.Loc.size()), + Unit->getDebugInfoExtractor().isLittleEndian(), + Unit->getAddressByteSize()); + DWARFExpression(Data, Unit).Print(OS); + } +} + +void DWARFDebugLoc::dump(raw_ostream &OS, const DWARFUnit *Unit) const { for (const LocationList &L : Locations) { OS << format("0x%8.8x: ", L.Offset); - const unsigned Indent = 12; - for (const Entry &E : L.Entries) { - if (&E != L.Entries.begin()) - OS.indent(Indent); - OS << "Beginning address offset: " << format("0x%016" PRIx64, E.Begin) - << '\n'; - OS.indent(Indent) << " Ending address offset: " - << format("0x%016" PRIx64, E.End) << '\n'; - OS.indent(Indent) << " Location description: "; - for (unsigned char Loc : E.Loc) { - OS << format("%2.2x ", Loc); - } - OS << "\n\n"; + L.dump(OS, Unit, sizeof("0x00000000: ")); + OS << "\n\n"; + } +} + +Optional +DWARFDebugLoc::parseOneLocationList(DataExtractor Data, unsigned AddressSize, + unsigned *Offset) { + LocationList LL; + LL.Offset = *Offset; + + // 2.6.2 Location Lists + // A location list entry consists of: + while (true) { + Entry E; + RelocAddrMap::const_iterator AI = RelocMap.find(*Offset); + + if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * AddressSize)) { + llvm::errs() << "Location list overflows the debug_loc section.\n"; + return None; + } + + // 1. A beginning address offset. ... + E.Begin = Data.getUnsigned(Offset, AddressSize); + if (AI != RelocMap.end()) + E.Begin += AI->second.second; + + AI = RelocMap.find(*Offset); + // 2. An ending address offset. ... + E.End = Data.getUnsigned(Offset, AddressSize); + if (AI != RelocMap.end()) + E.End += AI->second.second; + + // The end of any given location list is marked by an end of list entry, + // which consists of a 0 for the beginning address offset and a 0 for the + // ending address offset. + if (E.Begin == 0 && E.End == 0) + return LL; + + if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) { + llvm::errs() << "Location list overflows the debug_loc section.\n"; + return None; } + + unsigned Bytes = Data.getU16(Offset); + if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) { + llvm::errs() << "Location list overflows the debug_loc section.\n"; + return None; + } + // A single location description describing the location of the object... + StringRef str = Data.getData().substr(*Offset, Bytes); + *Offset += Bytes; + E.Loc.reserve(str.size()); + std::copy(str.begin(), str.end(), std::back_inserter(E.Loc)); + LL.Entries.push_back(std::move(E)); } } void DWARFDebugLoc::parse(DataExtractor data, unsigned AddressSize) { uint32_t Offset = 0; while (data.isValidOffset(Offset+AddressSize-1)) { - Locations.resize(Locations.size() + 1); - LocationList &Loc = Locations.back(); - Loc.Offset = Offset; - // 2.6.2 Location Lists - // A location list entry consists of: - while (true) { - Entry E; - RelocAddrMap::const_iterator AI = RelocMap.find(Offset); - // 1. A beginning address offset. ... - E.Begin = data.getUnsigned(&Offset, AddressSize); - if (AI != RelocMap.end()) - E.Begin += AI->second.second; - - AI = RelocMap.find(Offset); - // 2. An ending address offset. ... - E.End = data.getUnsigned(&Offset, AddressSize); - if (AI != RelocMap.end()) - E.End += AI->second.second; - - // The end of any given location list is marked by an end of list entry, - // which consists of a 0 for the beginning address offset and a 0 for the - // ending address offset. - if (E.Begin == 0 && E.End == 0) - break; - - unsigned Bytes = data.getU16(&Offset); - // A single location description describing the location of the object... - StringRef str = data.getData().substr(Offset, Bytes); - Offset += Bytes; - E.Loc.reserve(str.size()); - std::copy(str.begin(), str.end(), std::back_inserter(E.Loc)); - Loc.Entries.push_back(std::move(E)); - } + if (auto LL = parseOneLocationList(data, AddressSize, &Offset)) + Locations.push_back(std::move(*LL)); + else + break; } if (data.isValidOffset(Offset)) llvm::errs() << "error: failed to consume entire .debug_loc section\n"; } +Optional +DWARFDebugLocDWO::parseOneLocationList(DataExtractor Data, unsigned *Offset) { + LocationList LL; + LL.Offset = *Offset; + + // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list. + while (auto Kind = static_cast(Data.getU8(Offset))) { + if (Kind != dwarf::DW_LLE_start_length_entry) { + llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind + << " not implemented\n"; + return None; + } + + Entry E; + E.Start = Data.getULEB128(Offset); + E.Length = Data.getU32(Offset); + + unsigned Bytes = Data.getU16(Offset); + // A single location description describing the location of the object... + StringRef str = Data.getData().substr(*Offset, Bytes); + *Offset += Bytes; + E.Loc.resize(str.size()); + std::copy(str.begin(), str.end(), E.Loc.begin()); + + LL.Entries.push_back(std::move(E)); + } + return LL; +} + void DWARFDebugLocDWO::parse(DataExtractor data) { uint32_t Offset = 0; while (data.isValidOffset(Offset)) { - Locations.resize(Locations.size() + 1); - LocationList &Loc = Locations.back(); - Loc.Offset = Offset; - dwarf::LocationListEntry Kind; - while ((Kind = static_cast( - data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list_entry) { - - if (Kind != dwarf::DW_LLE_start_length_entry) { - llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind - << " not implemented\n"; - return; - } - - Entry E; - - E.Start = data.getULEB128(&Offset); - E.Length = data.getU32(&Offset); - - unsigned Bytes = data.getU16(&Offset); - // A single location description describing the location of the object... - StringRef str = data.getData().substr(Offset, Bytes); - Offset += Bytes; - E.Loc.resize(str.size()); - std::copy(str.begin(), str.end(), E.Loc.begin()); - - Loc.Entries.push_back(std::move(E)); - } + if (auto LL = parseOneLocationList(data, &Offset)) + Locations.push_back(std::move(*LL)); + else + return; } } -void DWARFDebugLocDWO::dump(raw_ostream &OS) const { +void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, const DWARFUnit *Unit, + unsigned Indent) const { + for (const Entry &E : Entries) { + OS << '\n'; + OS.indent(Indent); + OS << "Addr idx " << E.Start << " (w/ length " << E.Length << "): "; + DataExtractor Data(StringRef((const char*)E.Loc.data(), E.Loc.size()), + Unit->getDebugInfoExtractor().isLittleEndian(), + Unit->getAddressByteSize()); + DWARFExpression(Data, Unit).Print(OS); + } +} + +void DWARFDebugLocDWO::dump(raw_ostream &OS, const DWARFUnit *Unit) const { for (const LocationList &L : Locations) { OS << format("0x%8.8x: ", L.Offset); - const unsigned Indent = 12; - for (const Entry &E : L.Entries) { - if (&E != L.Entries.begin()) - OS.indent(Indent); - OS << "Beginning address index: " << E.Start << '\n'; - OS.indent(Indent) << " Length: " << E.Length << '\n'; - OS.indent(Indent) << " Location description: "; - for (unsigned char Loc : E.Loc) - OS << format("%2.2x ", Loc); - OS << "\n\n"; - } + L.dump(OS, Unit); + OS << "\n\n"; } } Index: lib/DebugInfo/DWARF/DWARFExpression.cpp =================================================================== --- /dev/null +++ lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -0,0 +1,266 @@ +//===-- DWARFExpression.cpp -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Format.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include +#include +#include + +using namespace llvm; +using namespace dwarf; + +namespace llvm { + +typedef std::vector DescVector; + +static DescVector &getDescriptions() { + static DescVector Descriptions; + typedef DWARFExpression::Op Op; + typedef Op::Description Desc; + + Descriptions.resize(0xff); + Descriptions[DW_OP_addr] = Desc(Op::Dwarf2, Op::SizeAddr); + Descriptions[DW_OP_deref] = Desc(Op::Dwarf2); + Descriptions[DW_OP_const1u] = Desc(Op::Dwarf2, Op::Size1); + Descriptions[DW_OP_const1s] = Desc(Op::Dwarf2, Op::SignedSize1); + Descriptions[DW_OP_const2u] = Desc(Op::Dwarf2, Op::Size2); + Descriptions[DW_OP_const2s] = Desc(Op::Dwarf2, Op::SignedSize2); + Descriptions[DW_OP_const4u] = Desc(Op::Dwarf2, Op::Size4); + Descriptions[DW_OP_const4s] = Desc(Op::Dwarf2, Op::SignedSize4); + Descriptions[DW_OP_const8u] = Desc(Op::Dwarf2, Op::Size8); + Descriptions[DW_OP_const8s] = Desc(Op::Dwarf2, Op::SignedSize8); + Descriptions[DW_OP_constu] = Desc(Op::Dwarf2, Op::SizeLEB); + Descriptions[DW_OP_consts] = Desc(Op::Dwarf2, Op::SignedSizeLEB); + Descriptions[DW_OP_dup] = Desc(Op::Dwarf2); + Descriptions[DW_OP_drop] = Desc(Op::Dwarf2); + Descriptions[DW_OP_over] = Desc(Op::Dwarf2); + Descriptions[DW_OP_pick] = Desc(Op::Dwarf2, Op::Size1); + Descriptions[DW_OP_swap] = Desc(Op::Dwarf2); + Descriptions[DW_OP_rot] = Desc(Op::Dwarf2); + Descriptions[DW_OP_xderef] = Desc(Op::Dwarf2); + Descriptions[DW_OP_abs] = Desc(Op::Dwarf2); + Descriptions[DW_OP_and] = Desc(Op::Dwarf2); + Descriptions[DW_OP_div] = Desc(Op::Dwarf2); + Descriptions[DW_OP_minus] = Desc(Op::Dwarf2); + Descriptions[DW_OP_mod] = Desc(Op::Dwarf2); + Descriptions[DW_OP_mul] = Desc(Op::Dwarf2); + Descriptions[DW_OP_neg] = Desc(Op::Dwarf2); + Descriptions[DW_OP_not] = Desc(Op::Dwarf2); + Descriptions[DW_OP_or] = Desc(Op::Dwarf2); + Descriptions[DW_OP_plus] = Desc(Op::Dwarf2); + Descriptions[DW_OP_plus_uconst] = Desc(Op::Dwarf2, Op::SizeLEB); + Descriptions[DW_OP_shl] = Desc(Op::Dwarf2); + Descriptions[DW_OP_shr] = Desc(Op::Dwarf2); + Descriptions[DW_OP_shra] = Desc(Op::Dwarf2); + Descriptions[DW_OP_xor] = Desc(Op::Dwarf2); + Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2); + Descriptions[DW_OP_bra] = Desc(Op::Dwarf2, Op::SignedSize2); + Descriptions[DW_OP_eq] = Desc(Op::Dwarf2); + Descriptions[DW_OP_ge] = Desc(Op::Dwarf2); + Descriptions[DW_OP_gt] = Desc(Op::Dwarf2); + Descriptions[DW_OP_le] = Desc(Op::Dwarf2); + Descriptions[DW_OP_lt] = Desc(Op::Dwarf2); + Descriptions[DW_OP_ne] = Desc(Op::Dwarf2); + for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA) + Descriptions[LA] = Desc(Op::Dwarf2); + for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA) + Descriptions[LA] = Desc(Op::Dwarf2); + for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA) + Descriptions[LA] = Desc(Op::Dwarf2, Op::SignedSizeLEB); + Descriptions[DW_OP_regx] = Desc(Op::Dwarf2, Op::SizeLEB); + Descriptions[DW_OP_fbreg] = Desc(Op::Dwarf2, Op::SignedSizeLEB); + Descriptions[DW_OP_bregx] = Desc(Op::Dwarf2, Op::SizeLEB, Op::SignedSizeLEB); + Descriptions[DW_OP_piece] = Desc(Op::Dwarf2, Op::SizeLEB); + Descriptions[DW_OP_deref_size] = Desc(Op::Dwarf2, Op::Size1); + Descriptions[DW_OP_xderef_size] = Desc(Op::Dwarf2, Op::Size1); + Descriptions[DW_OP_nop] = Desc(Op::Dwarf2); + Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3); + Descriptions[DW_OP_call2] = Desc(Op::Dwarf3, Op::Size2); + Descriptions[DW_OP_call4] = Desc(Op::Dwarf3, Op::Size4); + Descriptions[DW_OP_call_ref] = Desc(Op::Dwarf3, Op::SizeRefAddr); + Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3); + Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3); + Descriptions[DW_OP_bit_piece] = Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeLEB); + Descriptions[DW_OP_implicit_value] = + Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeBlock); + Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf3); + Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3); + Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB); + Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB); + return Descriptions; +} + +static DWARFExpression::Op::Description getOpDesc(unsigned OpCode) { + static DescVector &Descriptions = getDescriptions(); + assert(OpCode < Descriptions.size()); + return Descriptions[OpCode]; +} + +static uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) { + return (Version == 2) ? AddrSize : 4; +} + +bool DWARFExpression::Op::Extract(DataExtractor Data, const DWARFUnit *U, + uint32_t Offset) { + Opcode = Data.getU8(&Offset); + + Desc = getOpDesc(Opcode); + if (Desc.Version == Op::DwarfNA) + return false; + + for (unsigned Operand = 0; Operand < 2; ++Operand) { + unsigned Size = Desc.Op[Operand]; + unsigned Signed = Size & Op::SignBit; + + if (Size == Op::SizeNA) + break; + + switch (Size & ~Op::SignBit) { + case Op::Size1: + Operands[Operand] = Data.getU8(&Offset); + if (Signed) + Operands[Operand] = (int8_t)Operands[Operand]; + break; + case Op::Size2: + Operands[Operand] = Data.getU16(&Offset); + if (Signed) + Operands[Operand] = (int16_t)Operands[Operand]; + break; + case Op::Size4: + Operands[Operand] = Data.getU32(&Offset); + if (Signed) + Operands[Operand] = (int32_t)Operands[Operand]; + break; + case Op::Size8: + Operands[Operand] = Data.getU64(&Offset); + break; + case Op::SizeAddr: + if (U->getAddressByteSize() == 8) { + Operands[Operand] = Data.getU64(&Offset); + } else { + assert(U->getAddressByteSize() == 4); + Operands[Operand] = Data.getU32(&Offset); + } + break; + case Op::SizeRefAddr: + if (getRefAddrSize(U->getAddressByteSize(), U->getVersion()) == 8) { + Operands[Operand] = Data.getU64(&Offset); + } else { + assert(getRefAddrSize(U->getAddressByteSize(), U->getVersion()) == 4); + Operands[Operand] = Data.getU32(&Offset); + } + break; + case Op::SizeLEB: + if (Signed) + Operands[Operand] = Data.getSLEB128(&Offset); + else + Operands[Operand] = Data.getULEB128(&Offset); + break; + case Op::SizeBlock: + // We need a size, so this cannot be the first operand + if (Operand == 0) + return false; + // Store the offset of the block as the value. + Operands[Operand] = Offset; + Offset += Operands[Operand - 1]; + break; + default: + llvm_unreachable("Unknown DWARFExpression Op size"); + } + } + + EndOffset = Offset; + return true; +} + +static bool prettyPrintRegisterOp(raw_ostream &OS, uint8_t Opcode, + uint64_t Operands[2], + const MCRegisterInfo *MRI, bool isEH) { + uint64_t DwarfRegNum; + unsigned OpNum = 0; + + if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx) + DwarfRegNum = Operands[OpNum++]; + else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx) + DwarfRegNum = Opcode - DW_OP_breg0; + else + DwarfRegNum = Opcode - DW_OP_reg0; + + int LLVMRegNum = MRI->tryGetLLVMRegNum(DwarfRegNum, isEH); + if (LLVMRegNum >= 0) + if (const char *RegName = MRI->getName(LLVMRegNum)) { + if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) || + Opcode == DW_OP_bregx) + OS << format(" %s%+" PRId64, RegName, Operands[OpNum]); + else + OS << ' ' << RegName; + return true; + } + + return false; +} + +bool DWARFExpression::Op::Print(raw_ostream &OS, const DWARFExpression *Expr, + bool isEH) { + if (Error) { + OS << "decoding error."; + return false; + } + + const char *Name = OperationEncodingString(Opcode); + assert(Name && "DW_OP has no name!"); + OS << Name + 3; + + if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) || + (Opcode >= DW_OP_reg0 && Opcode <= DW_OP_reg31) || + Opcode == DW_OP_bregx || Opcode == DW_OP_regx) + if (const MCRegisterInfo *MRI = + Expr->Unit->getContext().getTargetRegisterInfo()) + if (prettyPrintRegisterOp(OS, Opcode, Operands, MRI, isEH)) + return true; + + for (unsigned Operand = 0; Operand < 2; ++Operand) { + unsigned Size = Desc.Op[Operand]; + unsigned Signed = Size & Op::SignBit; + + if (Size == Op::SizeNA) + break; + + if (Size == Op::SizeBlock) { + uint32_t Offset = Operands[Operand]; + for (unsigned i = 0; i < Operands[Operand - 1]; ++i) + OS << format(" 0x%02x", Expr->Data.getU8(&Offset)); + } else { + if (Signed) + OS << format(" %+" PRId64, (int64_t)Operands[Operand]); + else + OS << format(" 0x%" PRIx64, Operands[Operand]); + } + } + return true; +} + +void DWARFExpression::Print(raw_ostream &OS) { + for (auto &Op : operations()) { + if (!Op.Print(OS, this, /* isEH */ false)) { + uint32_t FailOffset = Op.getEndOffset(); + while (FailOffset < Data.getData().size()) + OS << format(" %02x", Data.getU8(&FailOffset)); + return; + } + if (Op.getEndOffset() < Data.getData().size()) + OS << ", "; + } +} + +} // namespace llvm Index: test/CodeGen/ARM/2011-01-19-MergedGlobalDbg.ll =================================================================== --- test/CodeGen/ARM/2011-01-19-MergedGlobalDbg.ll +++ test/CodeGen/ARM/2011-01-19-MergedGlobalDbg.ll @@ -21,12 +21,12 @@ ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "x1" ; CHECK-NOT: {{DW_TAG|NULL}} -; CHECK: DW_AT_location [DW_FORM_exprloc] (<0x8> 03 [[ADDR:.. .. .. ..]] 10 00 22 ) +; CHECK: DW_AT_location [DW_FORM_exprloc] (OP_addr [[ADDR:0x[0-9a-f]*]], OP_constu 0x0, OP_plus) ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "x2" ; CHECK-NOT: {{DW_TAG|NULL}} -; CHECK: DW_AT_location [DW_FORM_exprloc] (<0x8> 03 [[ADDR]] 10 01 22 ) +; CHECK: DW_AT_location [DW_FORM_exprloc] (OP_addr [[ADDR]], OP_constu 0x1, OP_plus) define zeroext i8 @get1(i8 zeroext %a) nounwind optsize { entry: Index: test/CodeGen/ARM/2011-08-02-MergedGlobalDbg.ll =================================================================== --- test/CodeGen/ARM/2011-08-02-MergedGlobalDbg.ll +++ test/CodeGen/ARM/2011-08-02-MergedGlobalDbg.ll @@ -12,12 +12,13 @@ ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "x1" ; CHECK-NOT: {{DW_TAG|NULL}} -; CHECK: DW_AT_location [DW_FORM_exprloc] (<0x8> 03 [[ADDR:.. .. .. ..]] 10 00 22 ) +; (OP_reg0 R0) +; CHECK: DW_AT_location [DW_FORM_exprloc] (OP_addr [[ADDR:0x[0-9a-f]*]], OP_constu 0x0, OP_plus) ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "x2" ; CHECK-NOT: {{DW_TAG|NULL}} -; CHECK: DW_AT_location [DW_FORM_exprloc] (<0x8> 03 [[ADDR]] 10 04 22 ) +; CHECK: DW_AT_location [DW_FORM_exprloc] (OP_addr [[ADDR]], OP_constu 0x4, OP_plus) target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32" target triple = "thumbv7-apple-macosx10.7.0" Index: test/CodeGen/ARM/debug-info-sreg2.ll =================================================================== --- test/CodeGen/ARM/debug-info-sreg2.ll +++ test/CodeGen/ARM/debug-info-sreg2.ll @@ -5,12 +5,10 @@ ; Just making sure the first part of the location isn't a repetition ; of the size of the location description. -; -; 0x90 DW_OP_regx of super-register -; CHECK: 0x00000000: Beginning address offset: -; CHECK-NEXT: Ending address offset: -; CHECK-NEXT: Location description: 90 {{.. .. .. .. $}} +; CHECK: 0x00000000: +; CHECK-NEXT: 0x{{[0-9]*[a-f]*}} - 0x{{[0-9]*[a-f]*}}: OP_regx D8 + define void @_Z3foov() optsize ssp { entry: Index: test/CodeGen/X86/2011-01-24-DbgValue-Before-Use.ll =================================================================== --- test/CodeGen/X86/2011-01-24-DbgValue-Before-Use.ll +++ test/CodeGen/X86/2011-01-24-DbgValue-Before-Use.ll @@ -9,7 +9,8 @@ ; CHECK: DW_TAG_variable ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location -; CHECK-NEXT: DW_AT_name {{.*}} "z_s" +; CHECK-NOT: DW_{{TAG|AT}} +; CHECK: DW_AT_name {{.*}} "z_s" ; CHECK-NEXT: DW_AT_decl_file ; CHECK-NEXT: DW_AT_decl_line ; CHECK-NEXT: DW_AT_type{{.*}}{[[TYPE:.*]]} Index: test/DebugInfo/AArch64/coalescing.ll =================================================================== --- test/DebugInfo/AArch64/coalescing.ll +++ test/DebugInfo/AArch64/coalescing.ll @@ -23,9 +23,8 @@ ; CHECK: .debug_info contents: ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location + ; CHECK-NEXT: OP_breg0 W0+0) ; CHECK-NEXT: DW_AT_name {{.*}}"size" - ; CHECK: .debug_loc contents: - ; CHECK: Location description: 70 00 ret void, !dbg !18 } Index: test/DebugInfo/ARM/s-super-register.ll =================================================================== --- test/DebugInfo/ARM/s-super-register.ll +++ test/DebugInfo/ARM/s-super-register.ll @@ -7,7 +7,7 @@ ; 0x90 DW_OP_regx of super-register ; 0x93 DW_OP_piece ; 0x9d DW_OP_bit_piece -; CHECK: Location description: 90 {{.. .. ((93 ..)|(9d .. ..)) $}} +; CHECK: OP_regx D8, OP{{_bit_|_}}piece define void @_Z3foov() optsize ssp { entry: Index: test/DebugInfo/SystemZ/variable-loc.ll =================================================================== --- test/DebugInfo/SystemZ/variable-loc.ll +++ test/DebugInfo/SystemZ/variable-loc.ll @@ -14,9 +14,8 @@ ; CHECK: brasl %r14, populate_array@PLT ; DEBUG: DW_TAG_variable -; Rather hard-coded, but 0x91 => DW_OP_fbreg and 0xa401 is SLEB128 encoded 164. ; DEBUG-NOT: DW_TAG -; DEBUG: DW_AT_location {{.*}}(<0x3> 91 a4 01 ) +; DEBUG: DW_AT_location {{.*}}(OP_fbreg +164) ; DEBUG-NOT: DW_TAG ; DEBUG: DW_AT_name {{.*}} "main_arr" Index: test/DebugInfo/X86/DW_AT_location-reference.ll =================================================================== --- test/DebugInfo/X86/DW_AT_location-reference.ll +++ test/DebugInfo/X86/DW_AT_location-reference.ll @@ -31,22 +31,18 @@ ; // The 'x' variable and its symbol reference location ; CHECK: .debug_info contents: ; CHECK: DW_TAG_variable -; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000) +; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000 +; Check that the location contains only 4 ranges - this verifies that the 4th +; and 5th ranges were successfully merged into a single range. +; CHECK-NEXT: 0x{{[0-9a-f]*}} - 0x{{[0-9a-f]*}}: +; CHECK-NEXT: 0x{{[0-9a-f]*}} - 0x{{[0-9a-f]*}}: +; CHECK-NEXT: 0x{{[0-9a-f]*}} - 0x{{[0-9a-f]*}}: +; CHECK-NEXT: 0x{{[0-9a-f]*}} - 0x{{[0-9a-f]*}}: {{.*}}) ; CHECK-NEXT: DW_AT_name {{.*}} "x" ; CHECK-NEXT: DW_AT_decl_file ; CHECK-NEXT: DW_AT_decl_line ; CHECK-NEXT: DW_AT_type -; Check that the location contains only 4 ranges - this verifies that the 4th -; and 5th ranges were successfully merged into a single range. -; CHECK: .debug_loc contents: -; CHECK: 0x00000000: -; CHECK: Beginning address offset: -; CHECK: Beginning address offset: -; CHECK: Beginning address offset: -; CHECK: Beginning address offset: -; CHECK-NOT: Beginning address offset: - ; Check that we have no relocations in Darwin's output. ; DARWIN-NOT: X86_64_RELOC{{.*}} __debug_loc Index: test/DebugInfo/X86/block-capture.ll =================================================================== --- test/DebugInfo/X86/block-capture.ll +++ test/DebugInfo/X86/block-capture.ll @@ -4,8 +4,7 @@ ; Checks that we emit debug info for the block variable declare. ; CHECK: DW_TAG_subprogram ; CHECK: DW_TAG_variable -; fbreg +8, deref, +32 -; CHECK-NEXT: DW_AT_location [DW_FORM_block1] (<0x05> 91 08 06 23 20 ) +; CHECK-NEXT: DW_AT_location [DW_FORM_block1] (OP_fbreg +8, OP_deref, OP_plus_uconst 0x20) ; CHECK-NEXT: DW_AT_name {{.*}} "block" ; Extracted from the clang output for: Index: test/DebugInfo/X86/data_member_location.ll =================================================================== --- test/DebugInfo/X86/data_member_location.ll +++ test/DebugInfo/X86/data_member_location.ll @@ -20,11 +20,11 @@ ; DWARF2: DW_AT_name {{.*}} "c" ; DWARF2-NOT: DW_TAG -; DWARF2: DW_AT_data_member_location {{.*}} (<0x02> 23 00 ) +; DWARF2: DW_AT_data_member_location {{.*}} (OP_plus_uconst 0x0) ; DWARF2: DW_AT_name {{.*}} "i" ; DWARF2-NOT: DW_TAG -; DWARF2: DW_AT_data_member_location {{.*}} (<0x02> 23 04 ) +; DWARF2: DW_AT_data_member_location {{.*}} (OP_plus_uconst 0x4) %struct.foo = type { i8, i32 } Index: test/DebugInfo/X86/dbg-merge-loc-entry.ll =================================================================== --- test/DebugInfo/X86/dbg-merge-loc-entry.ll +++ test/DebugInfo/X86/dbg-merge-loc-entry.ll @@ -6,7 +6,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-darwin8" -;CHECK: DW_AT_location{{.*}}(<0x1> 55 ) +;CHECK: DW_AT_location{{.*}}(OP_reg5 RDI) %0 = type { i64, i1 } Index: test/DebugInfo/X86/dbg-value-const-byref.ll =================================================================== --- test/DebugInfo/X86/dbg-value-const-byref.ll +++ test/DebugInfo/X86/dbg-value-const-byref.ll @@ -21,28 +21,14 @@ ; CHECK: .debug_info contents: ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_location [DW_FORM_data4] ([[LOC:.*]]) +; CHECK: DW_AT_location [DW_FORM_data4] ( +; CHECK-NEXT: 0x{{[0-9a-f]*}} - 0x[[C1:[0-9a-f]*]]: OP_consts +3 +; CHECK-NEXT: 0x[[C1]] - 0x[[C2:[0-9a-f]*]]: OP_consts +7 +; CHECK-NEXT: 0x[[C2]] - 0x[[R1:[0-9a-f]*]]: OP_reg0 RAX, OP_piece 0x4 +; CHECK-NEXT: 0x[[R1]] - 0x{{[0-9a-f]*}}: OP_breg5 RDI+0) ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}}"i" -; CHECK: .debug_loc contents: -; CHECK: [[LOC]]: -; consts 0x00000003 -; CHECK: Beginning address offset: 0x0000000000000{{.*}} -; CHECK: Ending address offset: [[C1:.*]] -; CHECK: Location description: 11 03 -; consts 0x00000007 -; CHECK: Beginning address offset: [[C1]] -; CHECK: Ending address offset: [[C2:.*]] -; CHECK: Location description: 11 07 -; rax, piece 0x00000004 -; CHECK: Beginning address offset: [[C2]] -; CHECK: Ending address offset: [[R1:.*]] -; CHECK: Location description: 50 93 04 -; rdi+0 -; CHECK: Beginning address offset: [[R1]] -; CHECK: Ending address offset: [[R2:.*]] -; CHECK: Location description: 75 00 -; + target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.9.0" Index: test/DebugInfo/X86/debug-info-blocks.ll =================================================================== --- test/DebugInfo/X86/debug-info-blocks.ll +++ test/DebugInfo/X86/debug-info-blocks.ll @@ -27,10 +27,7 @@ ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG -; 0x06 = DW_OP_deref -; 0x23 = DW_OP_uconst -; 0x91 = DW_OP_fbreg -; CHECK: DW_AT_location{{.*}}91 {{[0-9]+}} 06 23 {{[0-9]+}} ) +; CHECK: DW_AT_location{{.*}}(OP_fbreg -24, OP_deref, OP_plus_uconst 0x20) ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}}"self" ; CHECK-NOT: DW_TAG Index: test/DebugInfo/X86/debug-loc-offset.ll =================================================================== --- test/DebugInfo/X86/debug-loc-offset.ll +++ test/DebugInfo/X86/debug-loc-offset.ll @@ -45,7 +45,9 @@ ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_location [DW_FORM_sec_offset] (0x00000000) +; CHECK: DW_AT_location [DW_FORM_sec_offset] (0x00000000 +; do not check the location displayed here, as it will be offseted by the +; compile unit's low_pc. The real check is below in the debug_loc section. ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name [DW_FORM_strp]{{.*}}"a" @@ -54,8 +56,8 @@ ; CHECK-NOT: DW_AT_location ; CHECK: .debug_loc contents: -; CHECK: 0x00000000: Beginning address offset: 0x0000000000000000 -; CHECK: Ending address offset: 0x000000000000001a +; CHECK: 0x00000000: +; CHECK-NEXT: 0x0000000000000000 - 0x000000000000001a %struct.A = type { i32 (...)**, i32 } Index: test/DebugInfo/X86/fission-cu.ll =================================================================== --- test/DebugInfo/X86/fission-cu.ll +++ test/DebugInfo/X86/fission-cu.ll @@ -77,7 +77,7 @@ ; CHECK: DW_AT_external [DW_FORM_flag_present] (true) ; CHECK: DW_AT_decl_file [DW_FORM_data1] (0x01) ; CHECK: DW_AT_decl_line [DW_FORM_data1] (1) -; CHECK: DW_AT_location [DW_FORM_exprloc] (<0x2> fb 00 ) +; CHECK: DW_AT_location [DW_FORM_exprloc] (OP_GNU_addr_index 0x0) ; CHECK: [[TYPE]]: DW_TAG_base_type ; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000003) string = "int") Index: test/DebugInfo/X86/fission-ranges.ll =================================================================== --- test/DebugInfo/X86/fission-ranges.ll +++ test/DebugInfo/X86/fission-ranges.ll @@ -10,37 +10,23 @@ ; CHECK-NEXT: DW_AT_GNU_dwo_id ; CHECK-NEXT: DW_AT_GNU_addr_base [DW_FORM_sec_offset] (0x00000000) - +; Don't assume these locations are entirely correct - feel free to update them +; if they've changed due to a bugfix, change in register allocation, etc. ; CHECK: .debug_info.dwo contents: -; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[A:0x[0-9a-z]*]]) -; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[E:0x[0-9a-z]*]]) -; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[B:0x[0-9a-z]*]]) -; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[D:0x[0-9a-z]*]]) +; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[A:0x[0-9a-z]*]] +; CHECK-NEXT: Addr idx 2 (w/ length 190): OP_consts +0, OP_stack_value +; CHECK-NEXT: Addr idx 3 (w/ length 23): OP_reg0 RAX, OP_piece 0x4) +; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[E:0x[0-9a-z]*]] +; CHECK-NEXT: Addr idx 4 (w/ length 21): OP_reg0 RAX, OP_piece 0x4) +; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[B:0x[0-9a-z]*]] +; CHECK-NEXT: Addr idx 5 (w/ length 19): OP_reg0 RAX, OP_piece 0x4) +; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[D:0x[0-9a-z]*]] +; CHECK-NEXT: Addr idx 6 (w/ length 23): OP_reg0 RAX, OP_piece 0x4) ; CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000 ; CHECK: .debug_loc contents: ; CHECK-NOT: Beginning address offset ; CHECK: .debug_loc.dwo contents: -; Don't assume these locations are entirely correct - feel free to update them -; if they've changed due to a bugfix, change in register allocation, etc. - -; CHECK: [[A]]: Beginning address index: 2 -; CHECK-NEXT: Length: 190 -; CHECK-NEXT: Location description: 11 00 -; CHECK-NEXT: {{^$}} -; CHECK-NEXT: Beginning address index: 3 -; CHECK-NEXT: Length: 23 -; CHECK-NEXT: Location description: 50 93 04 -; CHECK: [[E]]: Beginning address index: 4 -; CHECK-NEXT: Length: 21 -; CHECK-NEXT: Location description: 50 93 04 -; CHECK: [[B]]: Beginning address index: 5 -; CHECK-NEXT: Length: 19 -; CHECK-NEXT: Location description: 50 93 04 -; CHECK: [[D]]: Beginning address index: 6 -; CHECK-NEXT: Length: 23 -; CHECK-NEXT: Location description: 50 93 04 - ; Make sure we don't produce any relocations in any .dwo section (though in particular, debug_info.dwo) ; HDR-NOT: .rela.{{.*}}.dwo Index: test/DebugInfo/X86/op_deref.ll =================================================================== --- test/DebugInfo/X86/op_deref.ll +++ test/DebugInfo/X86/op_deref.ll @@ -7,22 +7,16 @@ ; FIXME: The location here needs to be fixed, but llvm-dwarfdump doesn't handle ; DW_AT_location lists yet. -; DWARF4: DW_AT_location [DW_FORM_sec_offset] (0x00000000) +; DWARF4: DW_AT_location [DW_FORM_sec_offset] (0x00000000 ; FIXME: The location here needs to be fixed, but llvm-dwarfdump doesn't handle ; DW_AT_location lists yet. -; DWARF3: DW_AT_location [DW_FORM_data4] (0x00000000) +; DWARF3: DW_AT_location [DW_FORM_data4] (0x00000000 +; CHECK-NEXT: OP_breg2 RCX+0 ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000067] = "vla") -; Unfortunately llvm-dwarfdump can't unparse a list of DW_AT_locations -; right now, so we check the asm output: -; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o - -filetype=asm | FileCheck %s -check-prefix=ASM-CHECK -; vla should have a register-indirect address at one point. -; ASM-CHECK: DEBUG_VALUE: vla <- RCX -; ASM-CHECK: DW_OP_breg2 - ; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s --check-prefix=PRETTY-PRINT ; PRETTY-PRINT: [ DW_TAG_expression ] [DW_OP_deref] Index: test/DebugInfo/X86/parameters.ll =================================================================== --- test/DebugInfo/X86/parameters.ll +++ test/DebugInfo/X86/parameters.ll @@ -23,19 +23,16 @@ ; } ; CHECK: debug_info contents -; 0x74 is DW_OP_breg4, showing that the parameter is accessed indirectly +; DW_OP_breg4 shows that the parameter is accessed indirectly ; (with a zero offset) from the register parameter -; CHECK: DW_AT_location{{.*}}(<0x0{{.}}> 74 00 +; CHECK: DW_AT_location{{.*}}(OP_breg4 RSI+0) ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}} = "f" -; CHECK: DW_AT_location{{.*}}([[G_LOC:0x[0-9]*]]) +; CHECK: DW_AT_location{{.*}}(0x00000000 +; CHECK-NEXT: OP_breg4 RSI+0 ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}} = "g" -; CHECK: debug_loc contents -; CHECK-NEXT: [[G_LOC]]: Beginning -; CHECK-NEXT: Ending -; CHECK-NEXT: Location description: 74 00 %"struct.pr14763::foo" = type { i8 } Index: test/DebugInfo/X86/pieces-1.ll =================================================================== --- test/DebugInfo/X86/pieces-1.ll +++ test/DebugInfo/X86/pieces-1.ll @@ -17,14 +17,9 @@ ; CHECK: .debug_loc contents: ; -; 0x0000000000000000 - 0x0000000000000006: rdi, piece 0x00000008, rsi, piece 0x00000004 -; CHECK: Beginning address offset: 0x0000000000000000 -; CHECK: Ending address offset: [[LTMP3:.*]] -; CHECK: Location description: 55 93 08 54 93 04 -; 0x0000000000000006 - 0x0000000000000008: rbp-8, piece 0x00000008, rax, piece 0x00000004 ) -; CHECK: Beginning address offset: [[LTMP3]] -; CHECK: Ending address offset: [[END:.*]] -; CHECK: Location description: 76 78 93 08 54 93 04 +; CHECK: 0x0000000000000000 - [[LTMP3:.*]]: OP_reg5 RDI, OP_piece 0x8, OP_reg4 RSI, OP_piece 0x4 +; 0x0000000000000006 - 0x0000000000000008: rbp-8, piece 0x8, rax, piece 0x4 ) +; CHECK: [[LTMP3]] - {{.*}}: OP_breg6 RBP-8, OP_piece 0x8, OP_reg4 RSI, OP_piece 0x4 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.9.0" Index: test/DebugInfo/X86/pieces-2.ll =================================================================== --- test/DebugInfo/X86/pieces-2.ll +++ test/DebugInfo/X86/pieces-2.ll @@ -17,8 +17,7 @@ ; ; ; CHECK: DW_TAG_variable [4] -; rax, piece 0x00000004 -; CHECK-NEXT: DW_AT_location [DW_FORM_block1]{{.*}}50 93 04 +; CHECK-NEXT: DW_AT_location [DW_FORM_block1]{{.*}} (OP_reg0 RAX, OP_piece 0x4 ; CHECK-NEXT: DW_AT_name {{.*}}"i1" ; ; ModuleID = '/Volumes/Data/llvm/test/DebugInfo/X86/sroasplit-1.ll' Index: test/DebugInfo/X86/pieces-3.ll =================================================================== --- test/DebugInfo/X86/pieces-3.ll +++ test/DebugInfo/X86/pieces-3.ll @@ -16,20 +16,14 @@ ; } ; ; CHECK: DW_TAG_formal_parameter [3] -; CHECK-NEXT: DW_AT_location [DW_FORM_data4] ([[LOC:.*]]) +; CHECK-NEXT: DW_AT_location [DW_FORM_data4] ( +; CHECK-NEXT: 0x0000000000000000 - 0x0000000000000004: OP_reg5 RDI, OP_piece 0x8, OP_piece 0x4, OP_reg4 RSI, OP_piece 0x4 +; CHECK-NEXT: 0x0000000000000004 - 0x0000000000000008: OP_reg5 RDI, OP_piece 0x8, OP_piece 0x4, OP_reg4 RSI, OP_piece 0x4) ; CHECK-NEXT: DW_AT_name {{.*}}"outer" ; CHECK: DW_TAG_variable -; rsi, piece 0x00000004 -; CHECK-NEXT: DW_AT_location [DW_FORM_block1] {{.*}} 54 93 04 +; CHECK-NEXT: DW_AT_location [DW_FORM_block1]{{.*}}(OP_reg4 RSI, OP_piece 0x4 ; CHECK-NEXT: "i1" ; -; CHECK: .debug_loc -; CHECK: [[LOC]]: -; CHECK: Beginning address offset: 0x0000000000000000 -; CHECK: Ending address offset: 0x0000000000000004 -; rdi, piece 0x00000008, piece 0x00000004, rsi, piece 0x00000004 -; CHECK: Location description: 55 93 08 93 04 54 93 04 -; ; ModuleID = '/Volumes/Data/llvm/test/DebugInfo/X86/sroasplit-2.ll' target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.9.0" Index: test/DebugInfo/X86/subregisters.ll =================================================================== --- test/DebugInfo/X86/subregisters.ll +++ test/DebugInfo/X86/subregisters.ll @@ -6,7 +6,7 @@ ; ; rdar://problem/16015314 ; -; CHECK: DW_AT_location [DW_FORM_block1] (<0x03> 54 93 04 ) +; CHECK: DW_AT_location [DW_FORM_block1] (OP_reg4 RSI, OP_piece 0x4) ; CHECK: DW_AT_name [DW_FORM_strp]{{.*}} "a" ; ; struct bar { Index: test/DebugInfo/X86/template.ll =================================================================== --- test/DebugInfo/X86/template.ll +++ test/DebugInfo/X86/template.ll @@ -29,7 +29,7 @@ ; The address of the global 'glbl', followed by DW_OP_stack_value (9f), to use ; the value immediately, rather than indirecting through the address. -; CHECK-NEXT: DW_AT_location [DW_FORM_exprloc]{{ *}}(<0xa> 03 00 00 00 00 00 00 00 00 9f ) +; CHECK-NEXT: DW_AT_location [DW_FORM_exprloc]{{ *}}(OP_addr 0x0, OP_stack_value) ; CHECK-NOT: NULL ; CHECK: DW_TAG_GNU_template_template_param Index: test/DebugInfo/dwarfdump-debug-loc-simple.test =================================================================== --- test/DebugInfo/dwarfdump-debug-loc-simple.test +++ test/DebugInfo/dwarfdump-debug-loc-simple.test @@ -3,24 +3,20 @@ CHECK: .debug_info CHECK: DW_AT_name{{.*}}"f" -CHECK: DW_AT_location{{.*}}([[F_LOC:0x[0-9a-f]*]]) +CHECK: DW_AT_location{{.*}}([[F_LOC:0x[0-9a-f]*]] +CHECK-NEXT: 0x0000000000000000 - 0x0000000000000023: OP_reg1 ECX +CHECK-NEXT: 0x0000000000000023 - 0x000000000000005d: OP_breg5 EBP-16) CHECK: DW_AT_name{{.*}}"g" -CHECK: DW_AT_location{{.*}}([[G_LOC:0x[0-9a-f]*]]) +CHECK: DW_AT_location{{.*}}([[G_LOC:0x[0-9a-f]*]] +CHECK-NEXT: 0x0000000000000000 - 0x0000000000000020: OP_reg0 EAX +CHECK-NEXT: 0x0000000000000020 - 0x000000000000005d: OP_breg5 EBP-12) + CHECK: .debug_loc contents: -CHECK-NEXT: [[F_LOC]]: Beginning address offset: 0x0000000000000000 -CHECK-NEXT: Ending address offset: 0x0000000000000023 +CHECK-NEXT: [[F_LOC]]: this is actually the wrong location due to PR14763, but that doesn't matter for the purposes of testing dwarfdump -CHECK-NEXT: Location description: 51 -CHECK-NEXT: {{^$}} -CHECK-NEXT: Beginning address offset: 0x0000000000000023 -CHECK-NEXT: Ending address offset: 0x000000000000005d -CHECK-NEXT: Location description: 75 70 -CHECK-NEXT: {{^$}} -CHECK-NEXT: [[G_LOC]]: Beginning address offset: 0x0000000000000000 -CHECK-NEXT: Ending address offset: 0x0000000000000020 -CHECK-NEXT: Location description: 50 -CHECK-NEXT: {{^$}} -CHECK-NEXT: Beginning address offset: 0x0000000000000020 -CHECK-NEXT: Ending address offset: 0x000000000000005d -CHECK-NEXT: Location description: 75 74 +CHECK-NEXT: 0x0000000000000000 - 0x0000000000000023: OP_reg1 ECX +CHECK-NEXT: 0x0000000000000023 - 0x000000000000005d: OP_breg5 EBP-16 +CHECK: [[G_LOC]]: +CHECK-NEXT: 0x0000000000000000 - 0x0000000000000020: OP_reg0 EAX +CHECK-NEXT: 0x0000000000000020 - 0x000000000000005d: OP_breg5 EBP-12 Index: test/DebugInfo/incorrect-variable-debugloc1.ll =================================================================== --- test/DebugInfo/incorrect-variable-debugloc1.ll +++ test/DebugInfo/incorrect-variable-debugloc1.ll @@ -23,8 +23,11 @@ ; return c; ; } -; DWARF23: Location description: 10 0d {{$}} -; DWARF4: Location description: 10 0d 9f +; CHECK: DW_TAG_variable +; CHECK: DW_AT_location +; CHECK-NOT: DW_AT +; DWARF23: OP_constu 0xd{{$}} +; DWARF4: OP_constu 0xd, OP_stack_value{{$}} ; Function Attrs: uwtable define i32 @main() #0 {