Index: llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -43,6 +43,7 @@ namespace llvm { class DataExtractor; +class MCRegisterInfo; class MemoryBuffer; class raw_ostream; @@ -72,6 +73,7 @@ std::deque> DWOTUs; std::unique_ptr AbbrevDWO; std::unique_ptr LocDWO; + std::unique_ptr RegInfo; /// The maximum DWARF version of all units. unsigned MaxVersion = 0; @@ -106,9 +108,9 @@ public: DWARFContext(std::unique_ptr DObj, - std::string DWPName = "") - : DIContext(CK_DWARF), DWPName(std::move(DWPName)), - DObj(std::move(DObj)) {} + std::string DWPName = ""); + ~DWARFContext(); + DWARFContext(DWARFContext &) = delete; DWARFContext &operator=(DWARFContext &) = delete; @@ -243,6 +245,8 @@ std::shared_ptr getDWOContext(StringRef AbsolutePath); + const MCRegisterInfo *getRegisterInfo(); + /// Function used to handle default error reporting policy. Prints a error /// message and returns Continue, so DWARF context ignores the error. static ErrorPolicy defaultErrorHandler(Error E); Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" @@ -18,8 +19,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. @@ -37,8 +40,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: using LocationLists = SmallVector; /// A list of all the variables in the debug_loc section, each one describing @@ -47,14 +53,19 @@ public: /// 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 /// address size also given in 'data' to interpret the address ranges. void parse(const DWARFDataExtractor &data); + + Optional parseOneLocationList(DWARFDataExtractor Data, + unsigned AddressSize, + uint32_t *Offset); }; class DWARFDebugLocDWO { +public: struct Entry { uint64_t Start; uint32_t Length; @@ -64,15 +75,21 @@ struct LocationList { unsigned Offset; SmallVector Entries; + void dump(raw_ostream &OS, const DWARFUnit *Unit, + unsigned Indent = 12) const; }; +private: using LocationLists = SmallVector; 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); }; } // end namespace llvm Index: llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h =================================================================== --- /dev/null +++ llvm/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: llvm/include/llvm/DebugInfo/DWARFExpression.h =================================================================== --- /dev/null +++ llvm/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: llvm/lib/DebugInfo/DWARF/CMakeLists.txt =================================================================== --- llvm/lib/DebugInfo/DWARF/CMakeLists.txt +++ llvm/lib/DebugInfo/DWARF/CMakeLists.txt @@ -15,6 +15,7 @@ DWARFDebugPubTable.cpp DWARFDebugRangeList.cpp DWARFDie.cpp + DWARFExpression.cpp DWARFFormValue.cpp DWARFGdbIndex.cpp DWARFTypeUnit.cpp Index: llvm/lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -31,10 +31,12 @@ #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" #include "llvm/DebugInfo/DWARF/DWARFVerifier.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Object/Decompressor.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/RelocVisitor.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Error.h" @@ -59,6 +61,12 @@ using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind; using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind; +DWARFContext::DWARFContext(std::unique_ptr DObj, + std::string DWPName) + : DIContext(CK_DWARF), DWPName(std::move(DWPName)), DObj(std::move(DObj)) {} + +DWARFContext::~DWARFContext() = default; + static void dumpAccelSection(raw_ostream &OS, StringRef Name, const DWARFObject &Obj, const DWARFSection &Section, @@ -237,12 +245,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) { @@ -838,6 +852,29 @@ return std::shared_ptr(std::move(S), Ctxt); } +const MCRegisterInfo *DWARFContext::getRegisterInfo() { + if (RegInfo) + return RegInfo.get(); + + // Detect the architecture from the object file. We usually don't need OS info + // to lookup a target and create register info. + Triple TT; + assert(DObj->getFile() && "can't get register info without an object file"); + TT.setArch(Triple::ArchType(DObj->getFile()->getArch())); + TT.setVendor(Triple::UnknownVendor); + TT.setOS(Triple::UnknownOS); + + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget(TT.str(), Error); + // FIXME: Warn. + if (!Error.empty()) + return nullptr; + + RegInfo.reset(TheTarget->createMCRegInfo(TT.str())); + return RegInfo.get(); +} + + static Error createError(const Twine &Reason, llvm::Error E) { return make_error(Reason + toString(std::move(E)), inconvertibleErrorCode()); Index: llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -11,7 +11,10 @@ #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include @@ -20,104 +23,144 @@ 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()) << ": "; + + DWARFDataExtractor 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(DWARFDataExtractor 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; + 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.getRelocatedAddress(Offset); + + // 2. An ending address offset. ... + E.End = Data.getRelocatedAddress(Offset); + + // 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(const DWARFDataExtractor &data) { uint32_t Offset = 0; - while (data.isValidOffset(Offset+data.getAddressSize()-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) { - // A beginning and ending address offsets. - Entry E; - E.Begin = data.getRelocatedAddress(&Offset); - E.End = data.getRelocatedAddress(&Offset); - - // 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.append(str.begin(), str.end()); - Loc.Entries.push_back(std::move(E)); - } + while (data.isValidOffset(Offset + data.getAddressSize() - 1)) { + if (auto LL = parseOneLocationList(data, data.getAddressSize(), &Offset)) + Locations.push_back(std::move(*LL)); + else + break; } if (data.isValidOffset(Offset)) 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) { + 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) { - - if (Kind != dwarf::DW_LLE_startx_length) { - 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 << "): "; + DWARFDataExtractor 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: llvm/lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -16,6 +16,7 @@ #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Object/ObjectFile.h" @@ -81,6 +82,46 @@ } } +static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, + DWARFUnit *U, unsigned Indent) { + DWARFContext &Ctx = U->getContext(); + const DWARFObject &Obj = Ctx.getDWARFObj(); + if (FormValue.isFormClass(DWARFFormValue::FC_Block) || + FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { + ArrayRef Expr = *FormValue.getAsBlock(); + DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), + Ctx.isLittleEndian(), 0); + DWARFExpression(Data, U).Print(OS); + return; + } + + FormValue.dump(OS); + if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { + const DWARFSection &LocSection = Obj.getLocSection(); + const DWARFSection &LocDWOSection = Obj.getLocDWOSection(); + uint32_t Offset = *FormValue.getAsSectionOffset(); + + if (LocSection.Data.size()) { + DWARFDebugLoc DebugLoc; + DWARFDataExtractor Data(Obj, LocSection, Ctx.isLittleEndian(), + Obj.getAddressSize()); + 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, Ctx.isLittleEndian(), 0); + auto LL = DWARFDebugLocDWO::parseOneLocationList(Data, &Offset); + if (LL) + LL->dump(OS, U, Indent); + else + OS << "error extracting location list."; + } + } +} + static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, uint32_t *OffsetPtr, dwarf::Attribute Attr, dwarf::Form Form, unsigned Indent, @@ -129,6 +170,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, DumpOpts); Index: llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp =================================================================== --- /dev/null +++ llvm/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/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/Format.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->getLLVMRegNum(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; + } + + StringRef Name = OperationEncodingString(Opcode); + assert(!Name.empty() && "DW_OP has no name!"); + OS << Name.drop_front(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().getRegisterInfo()) + 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: llvm/test/CodeGen/ARM/debug-info-sreg2.ll =================================================================== --- llvm/test/CodeGen/ARM/debug-info-sreg2.ll +++ llvm/test/CodeGen/ARM/debug-info-sreg2.ll @@ -5,12 +5,9 @@ ; 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 !dbg !1 { entry: Index: llvm/test/CodeGen/X86/2011-01-24-DbgValue-Before-Use.ll =================================================================== --- llvm/test/CodeGen/X86/2011-01-24-DbgValue-Before-Use.ll +++ llvm/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: llvm/test/DebugInfo/Generic/incorrect-variable-debugloc1.ll =================================================================== --- llvm/test/DebugInfo/Generic/incorrect-variable-debugloc1.ll +++ llvm/test/DebugInfo/Generic/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 !dbg !4 { Index: llvm/test/DebugInfo/SystemZ/variable-loc.ll =================================================================== --- llvm/test/DebugInfo/SystemZ/variable-loc.ll +++ llvm/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: llvm/test/DebugInfo/X86/DW_AT_location-reference.ll =================================================================== --- llvm/test/DebugInfo/X86/DW_AT_location-reference.ll +++ llvm/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: llvm/test/DebugInfo/X86/block-capture.ll =================================================================== --- llvm/test/DebugInfo/X86/block-capture.ll +++ llvm/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: llvm/test/DebugInfo/X86/data_member_location.ll =================================================================== --- llvm/test/DebugInfo/X86/data_member_location.ll +++ llvm/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) source_filename = "test/DebugInfo/X86/data_member_location.ll" Index: llvm/test/DebugInfo/X86/debug-info-blocks.ll =================================================================== --- llvm/test/DebugInfo/X86/debug-info-blocks.ll +++ llvm/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: llvm/test/DebugInfo/X86/fission-cu.ll =================================================================== --- llvm/test/DebugInfo/X86/fission-cu.ll +++ llvm/test/DebugInfo/X86/fission-cu.ll @@ -79,7 +79,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 (00000004) string = "int") Index: llvm/test/DebugInfo/X86/pieces-1.ll =================================================================== --- llvm/test/DebugInfo/X86/pieces-1.ll +++ llvm/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: llvm/test/DebugInfo/X86/template.ll =================================================================== --- llvm/test/DebugInfo/X86/template.ll +++ llvm/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: llvm/test/DebugInfo/dwarfdump-debug-loc-simple.test =================================================================== --- llvm/test/DebugInfo/dwarfdump-debug-loc-simple.test +++ llvm/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