[llvm] r326932 - [DebugInfo] Support DWARF expressions in eh_frame
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 7 14:15:09 PST 2018
Looks like this change broke an lld test.
$ bin/llvm-lit -v /ssd/llvm-project/lld/test/ELF/eh-frame-hdr-augmentation.s
ninja: no work to do.
-- Testing: 1 tests, 1 threads --
FAIL: lld :: ELF/eh-frame-hdr-augmentation.s (1 of 1)
******************** TEST 'lld :: ELF/eh-frame-hdr-augmentation.s' FAILED
********************
Script:
--
/ssd/b/bin/llvm-mc -filetype=obj -triple=x86_64-pc-linux
/ssd/llvm-project/lld/test/ELF/eh-frame-hdr-augmentation.s -o
/ssd/b/tools/lld/test/ELF/Output/eh-frame-hdr-augmentation.s.tmp.o
/ssd/b/bin/ld.lld --hash-style=sysv --eh-frame-hdr
/ssd/b/tools/lld/test/ELF/Output/eh-frame-hdr-augmentation.s.tmp.o -o
/ssd/b/tools/lld/test/ELF/Output/eh-frame-hdr-augmentation.s.tmp -shared
/ssd/b/bin/llvm-objdump --dwarf=frames
/ssd/b/tools/lld/test/ELF/Output/eh-frame-hdr-augmentation.s.tmp |
/ssd/b/bin/FileCheck
/ssd/llvm-project/lld/test/ELF/eh-frame-hdr-augmentation.s
--
Exit Code: 1
Command Output (stderr):
--
/ssd/llvm-project/lld/test/ELF/eh-frame-hdr-augmentation.s:14:16: error:
CHECK-NEXT: is not on the line after the previous match
// CHECK-NEXT: Augmentation data:
^
<stdin>:17:2: note: 'next' match was here
Augmentation data: 9B AD 0D 00 00 1B 1B
^
<stdin>:15:27: note: previous match ended here
Return address column: 16
^
<stdin>:16:1: note: non-matching line after previous match is here
Personality Address: 00000dad
^
--
********************
Testing Time: 0.10s
********************
Failing Tests (1):
lld :: ELF/eh-frame-hdr-augmentation.s
Unexpected Failures: 1
On Wed, Mar 7, 2018 at 11:22 AM Rafael Auler via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: rafauler
> Date: Wed Mar 7 11:19:51 2018
> New Revision: 326932
>
> URL: http://llvm.org/viewvc/llvm-project?rev=326932&view=rev
> Log:
> [DebugInfo] Support DWARF expressions in eh_frame
>
> This patch enhances DWARFDebugFrame with the capability of parsing and
> printing DWARF expressions in CFI instructions. It also makes FDEs and
> CIEs accessible to lib users, so they can process them in client tools
> that rely on LLVM. To make it self-contained with a test case, it
> teaches llvm-readobj to be able to dump EH frames and checks they are
> correct in a unit test. The llvm-readobj code is Maksim Panchenko's work
> (maksfb).
>
> Reviewers: JDevlieghere, espindola
>
> Reviewed By: JDevlieghere
>
> Differential Revision: https://reviews.llvm.org/D43313
>
> Added:
> llvm/trunk/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml
> llvm/trunk/test/tools/llvm-readobj/unwind.test
> llvm/trunk/tools/llvm-readobj/DwarfCFIEHPrinter.h
> Modified:
> llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
> llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
> llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFExpression.h
> llvm/trunk/include/llvm/Support/ScopedPrinter.h
> llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
> llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
> llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
> llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp
> llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
> llvm/trunk/tools/llvm-readobj/CMakeLists.txt
> llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
>
> Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h?rev=326932&r1=326931&r2=326932&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h (original)
> +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h Wed Mar
> 7 11:19:51 2018
> @@ -44,6 +44,13 @@ public:
> uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr)
> const {
> return getRelocatedValue(getAddressSize(), Off, SecIx);
> }
> +
> + /// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding.
> + /// There is a DWARF encoding that uses a PC-relative adjustment.
> + /// For these values, \p AbsPosOffset is used to fix them, which should
> + /// reflect the absolute address of this pointer.
> + Optional<uint64_t> getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
> + uint64_t AbsPosOffset = 0) const;
> };
>
> } // end namespace llvm
>
> Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h?rev=326932&r1=326931&r2=326932&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h (original)
> +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h Wed Mar 7
> 11:19:51 2018
> @@ -10,40 +10,290 @@
> #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
> #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
>
> -#include "llvm/Support/DataExtractor.h"
> +#include "llvm/ADT/ArrayRef.h"
> +#include "llvm/ADT/iterator.h"
> +#include "llvm/ADT/SmallString.h"
> +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
> +#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
> +#include "llvm/Support/Error.h"
> #include <memory>
> #include <vector>
>
> namespace llvm {
>
> -class FrameEntry;
> class raw_ostream;
>
> -/// \brief A parsed .debug_frame or .eh_frame section
> -///
> +namespace dwarf {
> +
> +/// Represent a sequence of Call Frame Information instructions that,
> when read
> +/// in order, construct a table mapping PC to frame state. This can also
> be
> +/// referred to as "CFI rules" in DWARF literature to avoid confusion with
> +/// computer programs in the broader sense, and in this context each
> instruction
> +/// would be a rule to establish the mapping. Refer to pg. 172 in the
> DWARF5
> +/// manual, "6.4.1 Structure of Call Frame Information".
> +class CFIProgram {
> +public:
> + typedef SmallVector<uint64_t, 2> Operands;
> +
> + /// An instruction consists of a DWARF CFI opcode and an optional
> sequence of
> + /// operands. If it refers to an expression, then this expression has
> its own
> + /// sequence of operations and operands handled separately by
> DWARFExpression.
> + struct Instruction {
> + Instruction(uint8_t Opcode) : Opcode(Opcode) {}
> +
> + uint8_t Opcode;
> + Operands Ops;
> + // Associated DWARF expression in case this instruction refers to one
> + Optional<DWARFExpression> Expression;
> + };
> +
> + using InstrList = std::vector<Instruction>;
> + using iterator = InstrList::iterator;
> + using const_iterator = InstrList::const_iterator;
> +
> + iterator begin() { return Instructions.begin(); }
> + const_iterator begin() const { return Instructions.begin(); }
> + iterator end() { return Instructions.end(); }
> + const_iterator end() const { return Instructions.end(); }
> +
> + unsigned size() const { return (unsigned)Instructions.size(); }
> + bool empty() const { return Instructions.empty(); }
> +
> + CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor)
> + : CodeAlignmentFactor(CodeAlignmentFactor),
> + DataAlignmentFactor(DataAlignmentFactor) {}
> +
> + /// Parse and store a sequence of CFI instructions from Data,
> + /// starting at *Offset and ending at EndOffset. *Offset is updated
> + /// to EndOffset upon successful parsing, or indicates the offset
> + /// where a problem occurred in case an error is returned.
> + Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset);
> +
> + void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
> + unsigned IndentLevel = 1) const;
> +
> +private:
> + std::vector<Instruction> Instructions;
> + const uint64_t CodeAlignmentFactor;
> + const int64_t DataAlignmentFactor;
> +
> + /// Convenience method to add a new instruction with the given opcode.
> + void addInstruction(uint8_t Opcode) {
> + Instructions.push_back(Instruction(Opcode));
> + }
> +
> + /// Add a new single-operand instruction.
> + void addInstruction(uint8_t Opcode, uint64_t Operand1) {
> + Instructions.push_back(Instruction(Opcode));
> + Instructions.back().Ops.push_back(Operand1);
> + }
> +
> + /// Add a new instruction that has two operands.
> + void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t
> Operand2) {
> + Instructions.push_back(Instruction(Opcode));
> + Instructions.back().Ops.push_back(Operand1);
> + Instructions.back().Ops.push_back(Operand2);
> + }
> +
> + /// Types of operands to CFI instructions
> + /// In DWARF, this type is implicitly tied to a CFI instruction opcode
> and
> + /// thus this type doesn't need to be explictly written to the file
> (this is
> + /// not a DWARF encoding). The relationship of instrs to operand types
> can
> + /// be obtained from getOperandTypes() and is only used to simplify
> + /// instruction printing.
> + enum OperandType {
> + OT_Unset,
> + OT_None,
> + OT_Address,
> + OT_Offset,
> + OT_FactoredCodeOffset,
> + OT_SignedFactDataOffset,
> + OT_UnsignedFactDataOffset,
> + OT_Register,
> + OT_Expression
> + };
> +
> + /// Retrieve the array describing the types of operands according to
> the enum
> + /// above. This is indexed by opcode.
> + static ArrayRef<OperandType[2]> getOperandTypes();
> +
> + /// Print \p Opcode's operand number \p OperandIdx which has value \p
> Operand.
> + void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
> + const Instruction &Instr, unsigned OperandIdx,
> + uint64_t Operand) const;
> +};
> +
> +/// An entry in either debug_frame or eh_frame. This entry can be a CIE
> or an
> +/// FDE.
> +class FrameEntry {
> +public:
> + enum FrameKind { FK_CIE, FK_FDE };
> +
> + FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t
> CodeAlign,
> + int64_t DataAlign)
> + : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign,
> DataAlign) {}
> +
> + virtual ~FrameEntry() {}
> +
> + FrameKind getKind() const { return Kind; }
> + uint64_t getOffset() const { return Offset; }
> + uint64_t getLength() const { return Length; }
> + const CFIProgram &cfis() const { return CFIs; }
> + CFIProgram &cfis() { return CFIs; }
> +
> + /// Dump the instructions in this CFI fragment
> + virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
> + bool IsEH) const = 0;
> +
> +protected:
> + const FrameKind Kind;
> +
> + /// Offset of this entry in the section.
> + const uint64_t Offset;
> +
> + /// Entry length as specified in DWARF.
> + const uint64_t Length;
> +
> + CFIProgram CFIs;
> +};
> +
> +/// DWARF Common Information Entry (CIE)
> +class CIE : public FrameEntry {
> +public:
> + // CIEs (and FDEs) are simply container classes, so the only sensible
> way to
> + // create them is by providing the full parsed contents in the
> constructor.
> + CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
> + SmallString<8> Augmentation, uint8_t AddressSize,
> + uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
> + int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
> + SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
> + uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality,
> + Optional<uint32_t> PersonalityEnc)
> + : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor,
> + DataAlignmentFactor),
> + Version(Version), Augmentation(std::move(Augmentation)),
> + AddressSize(AddressSize),
> SegmentDescriptorSize(SegmentDescriptorSize),
> + CodeAlignmentFactor(CodeAlignmentFactor),
> + DataAlignmentFactor(DataAlignmentFactor),
> + ReturnAddressRegister(ReturnAddressRegister),
> + AugmentationData(std::move(AugmentationData)),
> + FDEPointerEncoding(FDEPointerEncoding),
> + LSDAPointerEncoding(LSDAPointerEncoding),
> Personality(Personality),
> + PersonalityEnc(PersonalityEnc) {}
> +
> + static bool classof(const FrameEntry *FE) { return FE->getKind() ==
> FK_CIE; }
> +
> + StringRef getAugmentationString() const { return Augmentation; }
> + uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
> + int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
> + uint8_t getVersion() const { return Version; }
> + uint64_t getReturnAddressRegister() const { return
> ReturnAddressRegister; }
> + Optional<uint64_t> getPersonalityAddress() const { return Personality; }
> + Optional<uint32_t> getPersonalityEncoding() const { return
> PersonalityEnc; }
> +
> + uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
> +
> + uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
> +
> + void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
> + bool IsEH) const override;
> +
> +private:
> + /// The following fields are defined in section 6.4.1 of the DWARF
> standard v4
> + const uint8_t Version;
> + const SmallString<8> Augmentation;
> + const uint8_t AddressSize;
> + const uint8_t SegmentDescriptorSize;
> + const uint64_t CodeAlignmentFactor;
> + const int64_t DataAlignmentFactor;
> + const uint64_t ReturnAddressRegister;
> +
> + // The following are used when the CIE represents an EH frame entry.
> + const SmallString<8> AugmentationData;
> + const uint32_t FDEPointerEncoding;
> + const uint32_t LSDAPointerEncoding;
> + const Optional<uint64_t> Personality;
> + const Optional<uint32_t> PersonalityEnc;
> +};
> +
> +/// DWARF Frame Description Entry (FDE)
> +class FDE : public FrameEntry {
> +public:
> + // Each FDE has a CIE it's "linked to". Our FDE contains is constructed
> with
> + // an offset to the CIE (provided by parsing the FDE header). The CIE
> itself
> + // is obtained lazily once it's actually required.
> + FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
> + uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
> + Optional<uint64_t> LSDAAddress)
> + : FrameEntry(FK_FDE, Offset, Length,
> + Cie ? Cie->getCodeAlignmentFactor() : 0,
> + Cie ? Cie->getDataAlignmentFactor() : 0),
> + LinkedCIEOffset(LinkedCIEOffset),
> InitialLocation(InitialLocation),
> + AddressRange(AddressRange), LinkedCIE(Cie),
> LSDAAddress(LSDAAddress) {}
> +
> + ~FDE() override = default;
> +
> + const CIE *getLinkedCIE() const { return LinkedCIE; }
> + uint64_t getInitialLocation() const { return InitialLocation; }
> + uint64_t getAddressRange() const { return AddressRange; }
> + Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
> +
> + void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
> + bool IsEH) const override;
> +
> + static bool classof(const FrameEntry *FE) { return FE->getKind() ==
> FK_FDE; }
> +
> +private:
> + /// The following fields are defined in section 6.4.1 of the DWARF
> standard v3
> + const uint64_t LinkedCIEOffset;
> + const uint64_t InitialLocation;
> + const uint64_t AddressRange;
> + const CIE *LinkedCIE;
> + const Optional<uint64_t> LSDAAddress;
> +};
> +
> +} // end namespace dwarf
> +
> +/// A parsed .debug_frame or .eh_frame section
> class DWARFDebugFrame {
> // True if this is parsing an eh_frame section.
> - bool IsEH;
> + const bool IsEH;
> + // Not zero for sane pointer values coming out of eh_frame
> + const uint64_t EHFrameAddress;
> +
> + std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries;
> + using iterator = pointee_iterator<decltype(Entries)::const_iterator>;
> +
> + /// Return the entry at the given offset or nullptr.
> + dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
>
> public:
> - DWARFDebugFrame(bool IsEH);
> + // If IsEH is true, assume it is a .eh_frame section. Otherwise,
> + // it is a .debug_frame section. EHFrameAddress should be different
> + // than zero for correct parsing of .eh_frame addresses when they
> + // use a PC-relative encoding.
> + DWARFDebugFrame(bool IsEH = false, uint64_t EHFrameAddress = 0);
> ~DWARFDebugFrame();
>
> /// Dump the section data into the given stream.
> - void dump(raw_ostream &OS, Optional<uint64_t> Offset) const;
> + void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
> + Optional<uint64_t> Offset) const;
>
> - /// \brief Parse the section from raw data.
> - /// data is assumed to be pointing to the beginning of the section.
> - void parse(DataExtractor Data);
> + /// Parse the section from raw data. \p Data is assumed to contain the
> whole
> + /// frame section contents to be parsed.
> + void parse(DWARFDataExtractor Data);
>
> /// Return whether the section has any entries.
> bool empty() const { return Entries.empty(); }
>
> - /// Return the entry at the given offset or nullptr.
> - FrameEntry *getEntryAtOffset(uint64_t Offset) const;
> + /// DWARF Frame entries accessors
> + iterator begin() const { return Entries.begin(); }
> + iterator end() const { return Entries.end(); }
> + iterator_range<iterator> entries() const {
> + return iterator_range<iterator>(Entries.begin(), Entries.end());
> + }
>
> -private:
> - std::vector<std::unique_ptr<FrameEntry>> Entries;
> + uint64_t getEHFrameAddress() const { return EHFrameAddress; }
> };
>
> } // end namespace llvm
>
> Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFExpression.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFExpression.h?rev=326932&r1=326931&r2=326932&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFExpression.h (original)
> +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFExpression.h Wed Mar 7
> 11:19:51 2018
> @@ -93,12 +93,13 @@ public:
>
> /// An iterator to go through the expression operations.
> class iterator
> - : public iterator_facade_base<iterator, std::forward_iterator_tag,
> Operation> {
> + : public iterator_facade_base<iterator, std::forward_iterator_tag,
> + Operation> {
> friend class DWARFExpression;
> - DWARFExpression *Expr;
> + const DWARFExpression *Expr;
> uint32_t Offset;
> Operation Op;
> - iterator(DWARFExpression *Expr, uint32_t Offset)
> + iterator(const DWARFExpression *Expr, uint32_t Offset)
> : Expr(Expr), Offset(Offset) {
> Op.Error =
> Offset >= Expr->Data.getData().size() ||
> @@ -127,10 +128,11 @@ public:
> assert(AddressSize == 8 || AddressSize == 4);
> }
>
> - iterator begin() { return iterator(this, 0); }
> - iterator end() { return iterator(this, Data.getData().size()); }
> + iterator begin() const { return iterator(this, 0); }
> + iterator end() const { return iterator(this, Data.getData().size()); }
>
> - void print(raw_ostream &OS, const MCRegisterInfo *RegInfo);
> + void print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
> + bool IsEH = false) const;
>
> private:
> DataExtractor Data;
>
> Modified: llvm/trunk/include/llvm/Support/ScopedPrinter.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ScopedPrinter.h?rev=326932&r1=326931&r2=326932&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Support/ScopedPrinter.h (original)
> +++ llvm/trunk/include/llvm/Support/ScopedPrinter.h Wed Mar 7 11:19:51
> 2018
> @@ -80,6 +80,8 @@ public:
>
> void resetIndent() { IndentLevel = 0; }
>
> + int getIndentLevel() { return IndentLevel; }
> +
> void setPrefix(StringRef P) { Prefix = P; }
>
> void printIndent() {
>
> Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=326932&r1=326931&r2=326932&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)
> +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Wed Mar 7 11:19:51
> 2018
> @@ -349,11 +349,11 @@ void DWARFContext::dump(
>
> if (shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
> DObj->getDebugFrameSection()))
> - getDebugFrame()->dump(OS, DumpOffset);
> + getDebugFrame()->dump(OS, getRegisterInfo(), DumpOffset);
>
> if (shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
> DObj->getEHFrameSection()))
> - getEHFrame()->dump(OS, DumpOffset);
> + getEHFrame()->dump(OS, getRegisterInfo(), DumpOffset);
>
> if (DumpType & DIDT_DebugMacro) {
> if (Explicit || !getDebugMacro()->empty()) {
> @@ -712,8 +712,8 @@ const DWARFDebugFrame *DWARFContext::get
> // provides this information). This problem is fixed in DWARFv4
> // See this dwarf-discuss discussion for more details:
> //
> http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
> - DataExtractor debugFrameData(DObj->getDebugFrameSection(),
> isLittleEndian(),
> - DObj->getAddressSize());
> + DWARFDataExtractor debugFrameData(DObj->getDebugFrameSection(),
> + isLittleEndian(),
> DObj->getAddressSize());
> DebugFrame.reset(new DWARFDebugFrame(false /* IsEH */));
> DebugFrame->parse(debugFrameData);
> return DebugFrame.get();
> @@ -723,8 +723,8 @@ const DWARFDebugFrame *DWARFContext::get
> if (EHFrame)
> return EHFrame.get();
>
> - DataExtractor debugFrameData(DObj->getEHFrameSection(),
> isLittleEndian(),
> - DObj->getAddressSize());
> + DWARFDataExtractor debugFrameData(DObj->getEHFrameSection(),
> isLittleEndian(),
> + DObj->getAddressSize());
> DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */));
> DebugFrame->parse(debugFrameData);
> return DebugFrame.get();
>
> Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp?rev=326932&r1=326931&r2=326932&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp (original)
> +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp Wed Mar 7
> 11:19:51 2018
> @@ -8,6 +8,7 @@
>
> //===----------------------------------------------------------------------===//
>
> #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
> +#include "llvm/BinaryFormat/Dwarf.h"
> #include "llvm/DebugInfo/DWARF/DWARFContext.h"
>
> using namespace llvm;
> @@ -25,3 +26,71 @@ uint64_t DWARFDataExtractor::getRelocate
> *SecNdx = Rel->SectionIndex;
> return getUnsigned(Off, Size) + Rel->Value;
> }
> +
> +Optional<uint64_t>
> +DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
> + uint64_t PCRelOffset) const {
> + if (Encoding == dwarf::DW_EH_PE_omit)
> + return None;
> +
> + uint64_t Result = 0;
> + uint32_t OldOffset = *Offset;
> + // First get value
> + switch (Encoding & 0x0F) {
> + case dwarf::DW_EH_PE_absptr:
> + switch (getAddressSize()) {
> + case 2:
> + case 4:
> + case 8:
> + Result = getUnsigned(Offset, getAddressSize());
> + break;
> + default:
> + return None;
> + }
> + break;
> + case dwarf::DW_EH_PE_uleb128:
> + Result = getULEB128(Offset);
> + break;
> + case dwarf::DW_EH_PE_sleb128:
> + Result = getSLEB128(Offset);
> + break;
> + case dwarf::DW_EH_PE_udata2:
> + Result = getUnsigned(Offset, 2);
> + break;
> + case dwarf::DW_EH_PE_udata4:
> + Result = getUnsigned(Offset, 4);
> + break;
> + case dwarf::DW_EH_PE_udata8:
> + Result = getUnsigned(Offset, 8);
> + break;
> + case dwarf::DW_EH_PE_sdata2:
> + Result = getSigned(Offset, 2);
> + break;
> + case dwarf::DW_EH_PE_sdata4:
> + Result = getSigned(Offset, 4);
> + break;
> + case dwarf::DW_EH_PE_sdata8:
> + Result = getSigned(Offset, 8);
> + break;
> + default:
> + return None;
> + }
> + // Then add relative offset, if required
> + switch (Encoding & 0x70) {
> + case dwarf::DW_EH_PE_absptr:
> + // do nothing
> + break;
> + case dwarf::DW_EH_PE_pcrel:
> + Result += PCRelOffset;
> + break;
> + case dwarf::DW_EH_PE_datarel:
> + case dwarf::DW_EH_PE_textrel:
> + case dwarf::DW_EH_PE_funcrel:
> + case dwarf::DW_EH_PE_aligned:
> + default:
> + *Offset = OldOffset;
> + return None;
> + }
> +
> + return Result;
> +}
>
> Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp?rev=326932&r1=326931&r2=326932&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp (original)
> +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp Wed Mar 7 11:19:51
> 2018
> @@ -8,10 +8,8 @@
>
> //===----------------------------------------------------------------------===//
>
> #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
> -#include "llvm/ADT/ArrayRef.h"
> #include "llvm/ADT/DenseMap.h"
> #include "llvm/ADT/Optional.h"
> -#include "llvm/ADT/SmallString.h"
> #include "llvm/ADT/StringExtras.h"
> #include "llvm/ADT/StringRef.h"
> #include "llvm/BinaryFormat/Dwarf.h"
> @@ -31,87 +29,13 @@
> using namespace llvm;
> using namespace dwarf;
>
> -/// \brief Abstract frame entry defining the common interface concrete
> -/// entries implement.
> -class llvm::FrameEntry {
> -public:
> - enum FrameKind {FK_CIE, FK_FDE};
> -
> - FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
> - : Kind(K), Offset(Offset), Length(Length) {}
> -
> - virtual ~FrameEntry() = default;
> -
> - FrameKind getKind() const { return Kind; }
> - virtual uint64_t getOffset() const { return Offset; }
> -
> - /// Parse and store a sequence of CFI instructions from Data,
> - /// starting at *Offset and ending at EndOffset. If everything
> - /// goes well, *Offset should be equal to EndOffset when this method
> - /// returns. Otherwise, an error occurred.
> - virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
> - uint32_t EndOffset);
> -
> - /// Dump the entry header to the given output stream.
> - virtual void dumpHeader(raw_ostream &OS) const = 0;
> -
> - /// Dump the entry's instructions to the given output stream.
> - virtual void dumpInstructions(raw_ostream &OS) const;
> -
> - /// Dump the entire entry to the given output stream.
> - void dump(raw_ostream &OS) const {
> - dumpHeader(OS);
> - dumpInstructions(OS);
> - OS << "\n";
> - }
> -
> -protected:
> - const FrameKind Kind;
> -
> - /// \brief Offset of this entry in the section.
> - uint64_t Offset;
> -
> - /// \brief Entry length as specified in DWARF.
> - uint64_t Length;
> -
> - /// An entry may contain CFI instructions. An instruction consists of an
> - /// opcode and an optional sequence of operands.
> - using Operands = std::vector<uint64_t>;
> - struct Instruction {
> - Instruction(uint8_t Opcode)
> - : Opcode(Opcode)
> - {}
> -
> - uint8_t Opcode;
> - Operands Ops;
> - };
> -
> - std::vector<Instruction> Instructions;
> -
> - /// Convenience methods to add a new instruction with the given opcode
> and
> - /// operands to the Instructions vector.
> - void addInstruction(uint8_t Opcode) {
> - Instructions.push_back(Instruction(Opcode));
> - }
> -
> - void addInstruction(uint8_t Opcode, uint64_t Operand1) {
> - Instructions.push_back(Instruction(Opcode));
> - Instructions.back().Ops.push_back(Operand1);
> - }
> -
> - void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t
> Operand2) {
> - Instructions.push_back(Instruction(Opcode));
> - Instructions.back().Ops.push_back(Operand1);
> - Instructions.back().Ops.push_back(Operand2);
> - }
> -};
>
> // See DWARF standard v3, section 7.23
> const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
> const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
>
> -void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
> - uint32_t EndOffset) {
> +Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset,
> + uint32_t EndOffset) {
> while (*Offset < EndOffset) {
> uint8_t Opcode = Data.getU8(Offset);
> // Some instructions have a primary opcode encoded in the top bits.
> @@ -122,67 +46,73 @@ void FrameEntry::parseInstructions(DataE
> // bits of the opcode itself.
> uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
> switch (Primary) {
> - default: llvm_unreachable("Impossible primary CFI opcode");
> - case DW_CFA_advance_loc:
> - case DW_CFA_restore:
> - addInstruction(Primary, Op1);
> - break;
> - case DW_CFA_offset:
> - addInstruction(Primary, Op1, Data.getULEB128(Offset));
> - break;
> + default:
> + return make_error<StringError>(
> + "Invalid primary CFI opcode",
> + std::make_error_code(std::errc::illegal_byte_sequence));
> + case DW_CFA_advance_loc:
> + case DW_CFA_restore:
> + addInstruction(Primary, Op1);
> + break;
> + case DW_CFA_offset:
> + addInstruction(Primary, Op1, Data.getULEB128(Offset));
> + break;
> }
> } else {
> // Extended opcode - its value is Opcode itself.
> switch (Opcode) {
> - default: llvm_unreachable("Invalid extended CFI opcode");
> - case DW_CFA_nop:
> - case DW_CFA_remember_state:
> - case DW_CFA_restore_state:
> - case DW_CFA_GNU_window_save:
> - // No operands
> - addInstruction(Opcode);
> - break;
> - case DW_CFA_set_loc:
> - // Operands: Address
> - addInstruction(Opcode, Data.getAddress(Offset));
> - break;
> - case DW_CFA_advance_loc1:
> - // Operands: 1-byte delta
> - addInstruction(Opcode, Data.getU8(Offset));
> - break;
> - case DW_CFA_advance_loc2:
> - // Operands: 2-byte delta
> - addInstruction(Opcode, Data.getU16(Offset));
> - break;
> - case DW_CFA_advance_loc4:
> - // Operands: 4-byte delta
> - addInstruction(Opcode, Data.getU32(Offset));
> - break;
> - case DW_CFA_restore_extended:
> - case DW_CFA_undefined:
> - case DW_CFA_same_value:
> - case DW_CFA_def_cfa_register:
> - case DW_CFA_def_cfa_offset:
> - case DW_CFA_GNU_args_size:
> - // Operands: ULEB128
> - addInstruction(Opcode, Data.getULEB128(Offset));
> - break;
> - case DW_CFA_def_cfa_offset_sf:
> - // Operands: SLEB128
> - addInstruction(Opcode, Data.getSLEB128(Offset));
> - break;
> - case DW_CFA_offset_extended:
> - case DW_CFA_register:
> - case DW_CFA_def_cfa:
> - case DW_CFA_val_offset: {
> - // Operands: ULEB128, ULEB128
> - // Note: We can not embed getULEB128 directly into function
> - // argument list. getULEB128 changes Offset and order of
> evaluation
> - // for arguments is unspecified.
> - auto op1 = Data.getULEB128(Offset);
> - auto op2 = Data.getULEB128(Offset);
> - addInstruction(Opcode, op1, op2);
> - break;
> + default:
> + return make_error<StringError>(
> + "Invalid extended CFI opcode",
> + std::make_error_code(std::errc::illegal_byte_sequence));
> + case DW_CFA_nop:
> + case DW_CFA_remember_state:
> + case DW_CFA_restore_state:
> + case DW_CFA_GNU_window_save:
> + // No operands
> + addInstruction(Opcode);
> + break;
> + case DW_CFA_set_loc:
> + // Operands: Address
> + addInstruction(Opcode, Data.getAddress(Offset));
> + break;
> + case DW_CFA_advance_loc1:
> + // Operands: 1-byte delta
> + addInstruction(Opcode, Data.getU8(Offset));
> + break;
> + case DW_CFA_advance_loc2:
> + // Operands: 2-byte delta
> + addInstruction(Opcode, Data.getU16(Offset));
> + break;
> + case DW_CFA_advance_loc4:
> + // Operands: 4-byte delta
> + addInstruction(Opcode, Data.getU32(Offset));
> + break;
> + case DW_CFA_restore_extended:
> + case DW_CFA_undefined:
> + case DW_CFA_same_value:
> + case DW_CFA_def_cfa_register:
> + case DW_CFA_def_cfa_offset:
> + case DW_CFA_GNU_args_size:
> + // Operands: ULEB128
> + addInstruction(Opcode, Data.getULEB128(Offset));
> + break;
> + case DW_CFA_def_cfa_offset_sf:
> + // Operands: SLEB128
> + addInstruction(Opcode, Data.getSLEB128(Offset));
> + break;
> + case DW_CFA_offset_extended:
> + case DW_CFA_register:
> + case DW_CFA_def_cfa:
> + case DW_CFA_val_offset: {
> + // Operands: ULEB128, ULEB128
> + // Note: We can not embed getULEB128 directly into function
> + // argument list. getULEB128 changes Offset and order of
> evaluation
> + // for arguments is unspecified.
> + auto op1 = Data.getULEB128(Offset);
> + auto op2 = Data.getULEB128(Offset);
> + addInstruction(Opcode, op1, op2);
> + break;
> }
> case DW_CFA_offset_extended_sf:
> case DW_CFA_def_cfa_sf:
> @@ -194,162 +124,49 @@ void FrameEntry::parseInstructions(DataE
> addInstruction(Opcode, op1, op2);
> break;
> }
> - case DW_CFA_def_cfa_expression:
> - // FIXME: Parse the actual instruction.
> - *Offset += Data.getULEB128(Offset);
> + case DW_CFA_def_cfa_expression: {
> + uint32_t ExprLength = Data.getULEB128(Offset);
> + addInstruction(Opcode, 0);
> + DataExtractor Extractor(
> + Data.getData().slice(*Offset, *Offset + ExprLength),
> + Data.isLittleEndian(), Data.getAddressSize());
> + Instructions.back().Expression = DWARFExpression(
> + Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION);
> + *Offset += ExprLength;
> break;
> + }
> case DW_CFA_expression:
> case DW_CFA_val_expression: {
> - // FIXME: Parse the actual instruction.
> - Data.getULEB128(Offset);
> - *Offset += Data.getULEB128(Offset);
> + auto RegNum = Data.getULEB128(Offset);
> + auto BlockLength = Data.getULEB128(Offset);
> + addInstruction(Opcode, RegNum, 0);
> + DataExtractor Extractor(
> + Data.getData().slice(*Offset, *Offset + BlockLength),
> + Data.isLittleEndian(), Data.getAddressSize());
> + Instructions.back().Expression = DWARFExpression(
> + Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION);
> + *Offset += BlockLength;
> break;
> }
> }
> }
> }
> +
> + return Error::success();
> }
>
> namespace {
>
> -/// \brief DWARF Common Information Entry (CIE)
> -class CIE : public FrameEntry {
> -public:
> - // CIEs (and FDEs) are simply container classes, so the only sensible
> way to
> - // create them is by providing the full parsed contents in the
> constructor.
> - CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
> - SmallString<8> Augmentation, uint8_t AddressSize,
> - uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
> - int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
> - SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
> - uint32_t LSDAPointerEncoding)
> - : FrameEntry(FK_CIE, Offset, Length), Version(Version),
> - Augmentation(std::move(Augmentation)), AddressSize(AddressSize),
> - SegmentDescriptorSize(SegmentDescriptorSize),
> - CodeAlignmentFactor(CodeAlignmentFactor),
> - DataAlignmentFactor(DataAlignmentFactor),
> - ReturnAddressRegister(ReturnAddressRegister),
> - AugmentationData(std::move(AugmentationData)),
> - FDEPointerEncoding(FDEPointerEncoding),
> - LSDAPointerEncoding(LSDAPointerEncoding) {}
> -
> - ~CIE() override = default;
> -
> - StringRef getAugmentationString() const { return Augmentation; }
> - uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
> - int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
> -
> - uint32_t getFDEPointerEncoding() const {
> - return FDEPointerEncoding;
> - }
> -
> - uint32_t getLSDAPointerEncoding() const {
> - return LSDAPointerEncoding;
> - }
> -
> - void dumpHeader(raw_ostream &OS) const override {
> - OS << format("%08x %08x %08x CIE",
> - (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
> - << "\n";
> - OS << format(" Version: %d\n", Version);
> - OS << " Augmentation: \"" << Augmentation << "\"\n";
> - if (Version >= 4) {
> - OS << format(" Address size: %u\n",
> - (uint32_t)AddressSize);
> - OS << format(" Segment desc size: %u\n",
> - (uint32_t)SegmentDescriptorSize);
> - }
> - OS << format(" Code alignment factor: %u\n",
> - (uint32_t)CodeAlignmentFactor);
> - OS << format(" Data alignment factor: %d\n",
> - (int32_t)DataAlignmentFactor);
> - OS << format(" Return address column: %d\n",
> - (int32_t)ReturnAddressRegister);
> - if (!AugmentationData.empty()) {
> - OS << " Augmentation data: ";
> - for (uint8_t Byte : AugmentationData)
> - OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
> - OS << "\n";
> - }
> - OS << "\n";
> - }
> -
> - static bool classof(const FrameEntry *FE) {
> - return FE->getKind() == FK_CIE;
> - }
> -
> -private:
> - /// The following fields are defined in section 6.4.1 of the DWARF
> standard v4
> - uint8_t Version;
> - SmallString<8> Augmentation;
> - uint8_t AddressSize;
> - uint8_t SegmentDescriptorSize;
> - uint64_t CodeAlignmentFactor;
> - int64_t DataAlignmentFactor;
> - uint64_t ReturnAddressRegister;
> -
> - // The following are used when the CIE represents an EH frame entry.
> - SmallString<8> AugmentationData;
> - uint32_t FDEPointerEncoding;
> - uint32_t LSDAPointerEncoding;
> -};
> -
> -/// \brief DWARF Frame Description Entry (FDE)
> -class FDE : public FrameEntry {
> -public:
> - // Each FDE has a CIE it's "linked to". Our FDE contains is constructed
> with
> - // an offset to the CIE (provided by parsing the FDE header). The CIE
> itself
> - // is obtained lazily once it's actually required.
> - FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
> - uint64_t InitialLocation, uint64_t AddressRange,
> - CIE *Cie)
> - : FrameEntry(FK_FDE, Offset, Length),
> LinkedCIEOffset(LinkedCIEOffset),
> - InitialLocation(InitialLocation), AddressRange(AddressRange),
> - LinkedCIE(Cie) {}
> -
> - ~FDE() override = default;
> -
> - CIE *getLinkedCIE() const { return LinkedCIE; }
> -
> - void dumpHeader(raw_ostream &OS) const override {
> - OS << format("%08x %08x %08x FDE ",
> - (uint32_t)Offset, (uint32_t)Length,
> (int32_t)LinkedCIEOffset);
> - OS << format("cie=%08x pc=%08x...%08x\n",
> - (int32_t)LinkedCIEOffset,
> - (uint32_t)InitialLocation,
> - (uint32_t)InitialLocation + (uint32_t)AddressRange);
> - }
> -
> - static bool classof(const FrameEntry *FE) {
> - return FE->getKind() == FK_FDE;
> - }
> -
> -private:
> - /// The following fields are defined in section 6.4.1 of the DWARF
> standard v3
> - uint64_t LinkedCIEOffset;
> - uint64_t InitialLocation;
> - uint64_t AddressRange;
> - CIE *LinkedCIE;
> -};
> -
> -/// \brief Types of operands to CF instructions.
> -enum OperandType {
> - OT_Unset,
> - OT_None,
> - OT_Address,
> - OT_Offset,
> - OT_FactoredCodeOffset,
> - OT_SignedFactDataOffset,
> - OT_UnsignedFactDataOffset,
> - OT_Register,
> - OT_Expression
> -};
>
> } // end anonymous namespace
>
> -/// \brief Initialize the array describing the types of operands.
> -static ArrayRef<OperandType[2]> getOperandTypes() {
> +ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() {
> static OperandType OpTypes[DW_CFA_restore+1][2];
> + static bool Initialized = false;
> + if (Initialized) {
> + return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
> + }
> + Initialized = true;
>
> #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
> do { \
> @@ -396,15 +213,13 @@ static ArrayRef<OperandType[2]> getOpera
> return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
> }
>
> -static ArrayRef<OperandType[2]> OpTypes = getOperandTypes();
> -
> -/// \brief Print \p Opcode's operand number \p OperandIdx which has
> -/// value \p Operand.
> -static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned
> OperandIdx,
> - uint64_t Operand, uint64_t CodeAlignmentFactor,
> - int64_t DataAlignmentFactor) {
> +/// Print \p Opcode's operand number \p OperandIdx which has value \p
> Operand.
> +void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI,
> + bool IsEH, const Instruction &Instr,
> + unsigned OperandIdx, uint64_t Operand)
> const {
> assert(OperandIdx < 2);
> - OperandType Type = OpTypes[Opcode][OperandIdx];
> + uint8_t Opcode = Instr.Opcode;
> + OperandType Type = getOperandTypes()[Opcode][OperandIdx];
>
> switch (Type) {
> case OT_Unset: {
> @@ -449,36 +264,68 @@ static void printOperand(raw_ostream &OS
> OS << format(" reg%" PRId64, Operand);
> break;
> case OT_Expression:
> - OS << " expression";
> + assert(Instr.Expression && "missing DWARFExpression object");
> + OS << " ";
> + Instr.Expression->print(OS, MRI, IsEH);
> break;
> }
> }
>
> -void FrameEntry::dumpInstructions(raw_ostream &OS) const {
> - uint64_t CodeAlignmentFactor = 0;
> - int64_t DataAlignmentFactor = 0;
> - const CIE *Cie = dyn_cast<CIE>(this);
> -
> - if (!Cie)
> - Cie = cast<FDE>(this)->getLinkedCIE();
> - if (Cie) {
> - CodeAlignmentFactor = Cie->getCodeAlignmentFactor();
> - DataAlignmentFactor = Cie->getDataAlignmentFactor();
> - }
> -
> +void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool
> IsEH,
> + unsigned IndentLevel) const {
> for (const auto &Instr : Instructions) {
> uint8_t Opcode = Instr.Opcode;
> if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
> Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
> - OS << " " << CallFrameString(Opcode) << ":";
> + OS.indent(2 * IndentLevel);
> + OS << CallFrameString(Opcode) << ":";
> for (unsigned i = 0; i < Instr.Ops.size(); ++i)
> - printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor,
> - DataAlignmentFactor);
> + printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]);
> OS << '\n';
> }
> }
>
> -DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) {}
> +void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH)
> const {
> + OS << format("%08x %08x %08x CIE", (uint32_t)Offset, (uint32_t)Length,
> + DW_CIE_ID)
> + << "\n";
> + OS << format(" Version: %d\n", Version);
> + OS << " Augmentation: \"" << Augmentation << "\"\n";
> + if (Version >= 4) {
> + OS << format(" Address size: %u\n", (uint32_t)AddressSize);
> + OS << format(" Segment desc size: %u\n",
> + (uint32_t)SegmentDescriptorSize);
> + }
> + OS << format(" Code alignment factor: %u\n",
> (uint32_t)CodeAlignmentFactor);
> + OS << format(" Data alignment factor: %d\n",
> (int32_t)DataAlignmentFactor);
> + OS << format(" Return address column: %d\n",
> (int32_t)ReturnAddressRegister);
> + if (Personality)
> + OS << format(" Personality Address: %08x\n", *Personality);
> + if (!AugmentationData.empty()) {
> + OS << " Augmentation data: ";
> + for (uint8_t Byte : AugmentationData)
> + OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
> + OS << "\n";
> + }
> + OS << "\n";
> + CFIs.dump(OS, MRI, IsEH);
> + OS << "\n";
> +}
> +
> +void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH)
> const {
> + OS << format("%08x %08x %08x FDE ", (uint32_t)Offset, (uint32_t)Length,
> + (int32_t)LinkedCIEOffset);
> + OS << format("cie=%08x pc=%08x...%08x\n", (int32_t)LinkedCIEOffset,
> + (uint32_t)InitialLocation,
> + (uint32_t)InitialLocation + (uint32_t)AddressRange);
> + if (LSDAAddress)
> + OS << format(" LSDA Address: %08x\n", *LSDAAddress);
> + CFIs.dump(OS, MRI, IsEH);
> + OS << "\n";
> +}
> +
> +DWARFDebugFrame::DWARFDebugFrame(bool IsEH, uint64_t EHFrameAddress)
> + : IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
>
> DWARFDebugFrame::~DWARFDebugFrame() = default;
>
> @@ -492,40 +339,6 @@ static void LLVM_ATTRIBUTE_UNUSED dumpDa
> errs() << "\n";
> }
>
> -static unsigned getSizeForEncoding(const DataExtractor &Data,
> - unsigned symbolEncoding) {
> - unsigned format = symbolEncoding & 0x0f;
> - switch (format) {
> - default: llvm_unreachable("Unknown Encoding");
> - case DW_EH_PE_absptr:
> - case DW_EH_PE_signed:
> - return Data.getAddressSize();
> - case DW_EH_PE_udata2:
> - case DW_EH_PE_sdata2:
> - return 2;
> - case DW_EH_PE_udata4:
> - case DW_EH_PE_sdata4:
> - return 4;
> - case DW_EH_PE_udata8:
> - case DW_EH_PE_sdata8:
> - return 8;
> - }
> -}
> -
> -static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset,
> - unsigned Encoding) {
> - switch (getSizeForEncoding(Data, Encoding)) {
> - case 2:
> - return Data.getU16(&Offset);
> - case 4:
> - return Data.getU32(&Offset);
> - case 8:
> - return Data.getU64(&Offset);
> - default:
> - llvm_unreachable("Illegal data size");
> - }
> -}
> -
> // This is a workaround for old compilers which do not allow
> // noreturn attribute usage in lambdas. Once the support for those
> // compilers are phased out, we can remove this and return back to
> @@ -539,7 +352,7 @@ static void LLVM_ATTRIBUTE_NORETURN Repo
> report_fatal_error(Str);
> }
>
> -void DWARFDebugFrame::parse(DataExtractor Data) {
> +void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
> uint32_t Offset = 0;
> DenseMap<uint32_t, CIE *> CIEs;
>
> @@ -569,9 +382,8 @@ void DWARFDebugFrame::parse(DataExtracto
>
> // The Id field's size depends on the DWARF format
> Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
> - bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) ||
> - Id == DW_CIE_ID ||
> - (IsEH && !Id));
> + bool IsCIE =
> + ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID || (IsEH &&
> !Id));
>
> if (IsCIE) {
> uint8_t Version = Data.getU8(&Offset);
> @@ -589,10 +401,9 @@ void DWARFDebugFrame::parse(DataExtracto
> StringRef AugmentationData("");
> uint32_t FDEPointerEncoding = DW_EH_PE_omit;
> uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
> + Optional<uint64_t> Personality;
> + Optional<uint32_t> PersonalityEncoding;
> if (IsEH) {
> - Optional<uint32_t> PersonalityEncoding;
> - Optional<uint64_t> Personality;
> -
> Optional<uint64_t> AugmentationLength;
> uint32_t StartAugmentationOffset;
> uint32_t EndAugmentationOffset;
> @@ -611,7 +422,9 @@ void DWARFDebugFrame::parse(DataExtracto
> ReportError(StartOffset,
> "Duplicate personality in entry at %lx");
> PersonalityEncoding = Data.getU8(&Offset);
> - Personality = readPointer(Data, Offset,
> *PersonalityEncoding);
> + Personality = Data.getEncodedPointer(
> + &Offset, *PersonalityEncoding,
> + EHFrameAddress ? EHFrameAddress + Offset : 0);
> break;
> }
> case 'R':
> @@ -639,14 +452,11 @@ void DWARFDebugFrame::parse(DataExtracto
> }
> }
>
> - auto Cie = llvm::make_unique<CIE>(StartOffset, Length, Version,
> - AugmentationString, AddressSize,
> - SegmentDescriptorSize,
> - CodeAlignmentFactor,
> - DataAlignmentFactor,
> - ReturnAddressRegister,
> - AugmentationData,
> FDEPointerEncoding,
> - LSDAPointerEncoding);
> + auto Cie = llvm::make_unique<CIE>(
> + StartOffset, Length, Version, AugmentationString, AddressSize,
> + SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor,
> + ReturnAddressRegister, AugmentationData, FDEPointerEncoding,
> + LSDAPointerEncoding, Personality, PersonalityEncoding);
> CIEs[StartOffset] = Cie.get();
> Entries.emplace_back(std::move(Cie));
> } else {
> @@ -654,6 +464,7 @@ void DWARFDebugFrame::parse(DataExtracto
> uint64_t CIEPointer = Id;
> uint64_t InitialLocation = 0;
> uint64_t AddressRange = 0;
> + Optional<uint64_t> LSDAAddress;
> CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) :
> CIEPointer];
>
> if (IsEH) {
> @@ -662,10 +473,15 @@ void DWARFDebugFrame::parse(DataExtracto
> ReportError(StartOffset,
> "Parsing FDE data at %lx failed due to missing
> CIE");
>
> - InitialLocation = readPointer(Data, Offset,
> - Cie->getFDEPointerEncoding());
> - AddressRange = readPointer(Data, Offset,
> - Cie->getFDEPointerEncoding());
> + if (auto Val = Data.getEncodedPointer(
> + &Offset, Cie->getFDEPointerEncoding(),
> + EHFrameAddress ? EHFrameAddress + Offset : 0)) {
> + InitialLocation = *Val;
> + }
> + if (auto Val = Data.getEncodedPointer(
> + &Offset, Cie->getFDEPointerEncoding(), 0)) {
> + AddressRange = *Val;
> + }
>
> StringRef AugmentationString = Cie->getAugmentationString();
> if (!AugmentationString.empty()) {
> @@ -676,8 +492,11 @@ void DWARFDebugFrame::parse(DataExtracto
> Offset + static_cast<uint32_t>(AugmentationLength);
>
> // Decode the LSDA if the CIE augmentation string said we
> should.
> - if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit)
> - readPointer(Data, Offset, Cie->getLSDAPointerEncoding());
> + if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
> + LSDAAddress = Data.getEncodedPointer(
> + &Offset, Cie->getLSDAPointerEncoding(),
> + EHFrameAddress ? Offset + EHFrameAddress : 0);
> + }
>
> if (Offset != EndAugmentationOffset)
> ReportError(StartOffset, "Parsing augmentation data at %lx
> failed");
> @@ -689,10 +508,13 @@ void DWARFDebugFrame::parse(DataExtracto
>
> Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
> InitialLocation, AddressRange,
> - Cie));
> + Cie, LSDAAddress));
> }
>
> - Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
> + if (Error E =
> + Entries.back()->cfis().parse(Data, &Offset,
> EndStructureOffset)) {
> + report_fatal_error(toString(std::move(E)));
> + }
>
> if (Offset != EndStructureOffset)
> ReportError(StartOffset, "Parsing entry instructions at %lx
> failed");
> @@ -709,14 +531,15 @@ FrameEntry *DWARFDebugFrame::getEntryAtO
> return nullptr;
> }
>
> -void DWARFDebugFrame::dump(raw_ostream &OS, Optional<uint64_t> Offset)
> const {
> +void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
> + Optional<uint64_t> Offset) const {
> if (Offset) {
> if (auto *Entry = getEntryAtOffset(*Offset))
> - Entry->dump(OS);
> + Entry->dump(OS, MRI, IsEH);
> return;
> }
>
> OS << "\n";
> for (const auto &Entry : Entries)
> - Entry->dump(OS);
> + Entry->dump(OS, MRI, IsEH);
> }
>
> Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp?rev=326932&r1=326931&r2=326932&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp (original)
> +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp Wed Mar 7 11:19:51
> 2018
> @@ -258,9 +258,10 @@ bool DWARFExpression::Operation::print(r
> return true;
> }
>
> -void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo
> *RegInfo) {
> +void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo
> *RegInfo,
> + bool IsEH) const {
> for (auto &Op : *this) {
> - if (!Op.print(OS, this, RegInfo, /* isEH */ false)) {
> + if (!Op.print(OS, this, RegInfo, IsEH)) {
> uint32_t FailOffset = Op.getEndOffset();
> while (FailOffset < Data.getData().size())
> OS << format(" %02x", Data.getU8(&FailOffset));
>
> Modified: llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ELFYAML.cpp?rev=326932&r1=326931&r2=326932&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ObjectYAML/ELFYAML.cpp (original)
> +++ llvm/trunk/lib/ObjectYAML/ELFYAML.cpp Wed Mar 7 11:19:51 2018
> @@ -50,6 +50,7 @@ void ScalarEnumerationTraits<ELFYAML::EL
> ECase(PT_SHLIB);
> ECase(PT_PHDR);
> ECase(PT_TLS);
> + ECase(PT_GNU_EH_FRAME);
> #undef ECase
> IO.enumFallback<Hex32>(Value);
> }
>
> Added:
> llvm/trunk/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml?rev=326932&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml
> (added)
> +++ llvm/trunk/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml
> Wed Mar 7 11:19:51 2018
> @@ -0,0 +1,46 @@
> +--- !ELF
> +FileHeader:
> + Class: ELFCLASS64
> + Data: ELFDATA2LSB
> + Type: ET_EXEC
> + Machine: EM_X86_64
> + Entry: 0x0000000000400000
> +Sections:
> + - Name: .text
> + Type: SHT_PROGBITS
> + Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
> + Address: 0x0000000000400000
> + AddressAlign: 16
> + Content: 50C704240020400031C05AC3
> + - Name: .eh_frame_hdr
> + Type: SHT_PROGBITS
> + Flags: [ SHF_ALLOC ]
> + Address: 0x00000000004013c0
> + AddressAlign: 4
> + Content:
> 011B033B3C00000006000000E0F0FFFF8800000010F1FFFF58000000F6F1FFFFB000000010F2FFFFD000000090FEFFFF0001000000FFFFFF30010000
> + - Name: .eh_frame
> + Type: SHT_PROGBITS
> + Flags: [ SHF_ALLOC ]
> + Address: 0x0000000000401400
> + AddressAlign: 8
> + Content:
> 1400000000000000017A5200017810011B0C070890010710140000001C000000B0F0FFFF2A00000000000000000000001400000000000000017A5200017810011B0C070890010000240000001C00000050F0FFFF20000000000E10460E184A0F0B770880003F1A3B2A332422000000001C000000440000003EF1FFFF1000000000410E108602430D064B0C07080000002C0000006400000038F1FFFF7F0C000000450C0A00491006027600450F0376780603660C0C0A00450C070800000000002C0000009400000088FDFFFF6600000000410E108602430D06428F03458E04478D058C06488307024B0C07080000000014000000C4000000C8FDFFFF01000000000000000000000000000000
> +Symbols:
> + Global:
> + - Name: myfunc
> + Type: STT_FUNC
> + Section: .text
> + Value: 0x0000000000400000
> +ProgramHeaders:
> + - Type: PT_LOAD
> + Flags: [ PF_X, PF_R ]
> + VAddr: 0x00400000
> + PAddr: 0x00400000
> + Sections:
> + - Section: .text
> + - Type: PT_GNU_EH_FRAME
> + Flags: [ PF_X, PF_R ]
> + VAddr: 0x004013C0
> + PAddr: 0x004013C0
> + Sections:
> + - Section: .eh_frame_hdr
> +...
>
> Added: llvm/trunk/test/tools/llvm-readobj/unwind.test
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/unwind.test?rev=326932&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/llvm-readobj/unwind.test (added)
> +++ llvm/trunk/test/tools/llvm-readobj/unwind.test Wed Mar 7 11:19:51 2018
> @@ -0,0 +1,170 @@
> +RUN: yaml2obj %p/Inputs/dwarf-exprs.exe-x86-64.yaml > %t.exe
> +RUN: llvm-readobj -unwind %t.exe | FileCheck %s
> +
> +CHECK: EH_FRAME Header [
> +CHECK-NEXT: Address: 0x4013c0
> +CHECK-NEXT: Offset: 0x27c
> +CHECK-NEXT: Size: 0x3c
> +CHECK-NEXT: Corresponding Section: .eh_frame_hdr
> +CHECK-NEXT: Header {
> +CHECK-NEXT: version: 1
> +CHECK-NEXT: eh_frame_ptr_enc: 0x1b
> +CHECK-NEXT: fde_count_enc: 0x3
> +CHECK-NEXT: table_enc: 0x3b
> +CHECK-NEXT: eh_frame_ptr: 0x401400
> +CHECK-NEXT: fde_count: 6
> +CHECK-NEXT: entry 0 {
> +CHECK-NEXT: initial_location: 0x4004a0
> +CHECK-NEXT: address: 0x401448
> +CHECK-NEXT: }
> +CHECK-NEXT: entry 1 {
> +CHECK-NEXT: initial_location: 0x4004d0
> +CHECK-NEXT: address: 0x401418
> +CHECK-NEXT: }
> +CHECK-NEXT: entry 2 {
> +CHECK-NEXT: initial_location: 0x4005b6
> +CHECK-NEXT: address: 0x401470
> +CHECK-NEXT: }
> +CHECK-NEXT: entry 3 {
> +CHECK-NEXT: initial_location: 0x4005d0
> +CHECK-NEXT: address: 0x401490
> +CHECK-NEXT: }
> +CHECK-NEXT: entry 4 {
> +CHECK-NEXT: initial_location: 0x401250
> +CHECK-NEXT: address: 0x4014c0
> +CHECK-NEXT: }
> +CHECK-NEXT: entry 5 {
> +CHECK-NEXT: initial_location: 0x4012c0
> +CHECK-NEXT: address: 0x4014f0
> +CHECK-NEXT: }
> +CHECK-NEXT: }
> +CHECK-NEXT:]
> +
> +CHECK: .eh_frame section at offset 0x2b8 address 0x401400:
> +CHECK-NEXT: [0x401400] CIE length=20
> +CHECK-NEXT: version: 1
> +CHECK-NEXT: augmentation: zR
> +CHECK-NEXT: code_alignment_factor: 1
> +CHECK-NEXT: data_alignment_factor: -8
> +CHECK-NEXT: return_address_register: 16
> +
> +CHECK: Program:
> +CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
> +CHECK-NEXT: DW_CFA_offset: reg16 -8
> +CHECK-NEXT: DW_CFA_undefined: reg16
> +
> +CHECK: [0x401418] FDE length=20 cie=[0x401400]
> +CHECK-NEXT: initial_location: 0x4004d0
> +CHECK-NEXT: address_range: 0x2a (end : 0x4004fa)
> +
> +CHECK: Program:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +
> +CHECK: [0x401430] CIE length=20
> +CHECK-NEXT: version: 1
> +CHECK-NEXT: augmentation: zR
> +CHECK-NEXT: code_alignment_factor: 1
> +CHECK-NEXT: data_alignment_factor: -8
> +CHECK-NEXT: return_address_register: 16
> +
> +CHECK: Program:
> +CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
> +CHECK-NEXT: DW_CFA_offset: reg16 -8
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +
> +CHECK: [0x401448] FDE length=36 cie=[0x401430]
> +CHECK-NEXT: initial_location: 0x4004a0
> +CHECK-NEXT: address_range: 0x20 (end : 0x4004c0)
> +
> +CHECK: Program:
> +CHECK-NEXT: DW_CFA_def_cfa_offset: +16
> +CHECK-NEXT: DW_CFA_advance_loc: 6
> +CHECK-NEXT: DW_CFA_def_cfa_offset: +24
> +CHECK-NEXT: DW_CFA_advance_loc: 10
> +CHECK-NEXT: DW_CFA_def_cfa_expression: DW_OP_breg7 +8, DW_OP_breg16
> +0, DW_OP_lit15, DW_OP_and, DW_OP_lit11, DW_OP_ge, DW_OP_lit3, DW_OP_shl,
> DW_OP_plus
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +
> +CHECK: [0x401470] FDE length=28 cie=[0x401430]
> +CHECK-NEXT: initial_location: 0x4005b6
> +CHECK-NEXT: address_range: 0x10 (end : 0x4005c6)
> +
> +CHECK: Program:
> +CHECK-NEXT: DW_CFA_advance_loc: 1
> +CHECK-NEXT: DW_CFA_def_cfa_offset: +16
> +CHECK-NEXT: DW_CFA_offset: reg6 -16
> +CHECK-NEXT: DW_CFA_advance_loc: 3
> +CHECK-NEXT: DW_CFA_def_cfa_register: reg6
> +CHECK-NEXT: DW_CFA_advance_loc: 11
> +CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +
> +CHECK: [0x401490] FDE length=44 cie=[0x401430]
> +CHECK-NEXT: initial_location: 0x4005d0
> +CHECK-NEXT: address_range: 0xc7f (end : 0x40124f)
> +
> +CHECK: Program:
> +CHECK-NEXT: DW_CFA_advance_loc: 5
> +CHECK-NEXT: DW_CFA_def_cfa: reg10 +0
> +CHECK-NEXT: DW_CFA_advance_loc: 9
> +CHECK-NEXT: DW_CFA_expression: reg6 DW_OP_breg6 +0
> +CHECK-NEXT: DW_CFA_advance_loc: 5
> +CHECK-NEXT: DW_CFA_def_cfa_expression: DW_OP_breg6 -8, DW_OP_deref
> +CHECK-NEXT: DW_CFA_advance_loc2: 3174
> +CHECK-NEXT: DW_CFA_def_cfa: reg10 +0
> +CHECK-NEXT: DW_CFA_advance_loc: 5
> +CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +
> +CHECK: [0x4014c0] FDE length=44 cie=[0x401430]
> +CHECK-NEXT: initial_location: 0x401250
> +CHECK-NEXT: address_range: 0x66 (end : 0x4012b6)
> +
> +CHECK: Program:
> +CHECK-NEXT: DW_CFA_advance_loc: 1
> +CHECK-NEXT: DW_CFA_def_cfa_offset: +16
> +CHECK-NEXT: DW_CFA_offset: reg6 -16
> +CHECK-NEXT: DW_CFA_advance_loc: 3
> +CHECK-NEXT: DW_CFA_def_cfa_register: reg6
> +CHECK-NEXT: DW_CFA_advance_loc: 2
> +CHECK-NEXT: DW_CFA_offset: reg15 -24
> +CHECK-NEXT: DW_CFA_advance_loc: 5
> +CHECK-NEXT: DW_CFA_offset: reg14 -32
> +CHECK-NEXT: DW_CFA_advance_loc: 7
> +CHECK-NEXT: DW_CFA_offset: reg13 -40
> +CHECK-NEXT: DW_CFA_offset: reg12 -48
> +CHECK-NEXT: DW_CFA_advance_loc: 8
> +CHECK-NEXT: DW_CFA_offset: reg3 -56
> +CHECK-NEXT: DW_CFA_advance_loc1: 75
> +CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +
> +CHECK: [0x4014f0] FDE length=20 cie=[0x401430]
> +CHECK-NEXT: initial_location: 0x4012c0
> +CHECK-NEXT: address_range: 0x1 (end : 0x4012c1)
> +
> +CHECK: Program:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
> +CHECK-NEXT: DW_CFA_nop:
>
> Modified: llvm/trunk/tools/llvm-readobj/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/CMakeLists.txt?rev=326932&r1=326931&r2=326932&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/llvm-readobj/CMakeLists.txt (original)
> +++ llvm/trunk/tools/llvm-readobj/CMakeLists.txt Wed Mar 7 11:19:51 2018
> @@ -1,5 +1,6 @@
> set(LLVM_LINK_COMPONENTS
> DebugInfoCodeView
> + DebugInfoDWARF
> Object
> BinaryFormat
> Support
>
> Added: llvm/trunk/tools/llvm-readobj/DwarfCFIEHPrinter.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/DwarfCFIEHPrinter.h?rev=326932&view=auto
>
> ==============================================================================
> --- llvm/trunk/tools/llvm-readobj/DwarfCFIEHPrinter.h (added)
> +++ llvm/trunk/tools/llvm-readobj/DwarfCFIEHPrinter.h Wed Mar 7 11:19:51
> 2018
> @@ -0,0 +1,244 @@
> +//===--- DwarfCFIEHPrinter.h - DWARF-based Unwind Information Printer
> -----===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
> +#define LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
> +
> +#include "Error.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/BinaryFormat/Dwarf.h"
> +#include "llvm/Object/ELF.h"
> +#include "llvm/Object/ELFTypes.h"
> +#include "llvm/Support/Casting.h"
> +#include "llvm/Support/ScopedPrinter.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
> +#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
> +#include "llvm/Support/Endian.h"
> +#include "llvm/Support/Format.h"
> +#include "llvm/Support/type_traits.h"
> +
> +namespace llvm {
> +namespace DwarfCFIEH {
> +
> +template <typename ELFT>
> +class PrinterContext {
> + ScopedPrinter &W;
> + const object::ELFFile<ELFT> *Obj;
> +
> + void printEHFrameHdr(uint64_t Offset, uint64_t Address, uint64_t Size)
> const;
> +
> + void printEHFrame(const typename ELFT::Shdr *EHFrameShdr) const;
> +
> +public:
> + PrinterContext(ScopedPrinter &W, const object::ELFFile<ELFT> *Obj)
> + : W(W), Obj(Obj) {}
> +
> + void printUnwindInformation() const;
> +};
> +
> +template <class ELFO>
> +static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO
> *Obj,
> + uint64_t Addr)
> {
> + auto Sections = Obj->sections();
> + if (Error E = Sections.takeError())
> + reportError(toString(std::move(E)));
> +
> + for (const auto &Shdr : *Sections)
> + if (Shdr.sh_addr == Addr)
> + return &Shdr;
> + return nullptr;
> +}
> +
> +template <typename ELFT>
> +void PrinterContext<ELFT>::printUnwindInformation() const {
> + const typename ELFT::Phdr *EHFramePhdr = nullptr;
> +
> + auto PHs = Obj->program_headers();
> + if (Error E = PHs.takeError())
> + reportError(toString(std::move(E)));
> +
> + for (const auto &Phdr : *PHs) {
> + if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) {
> + EHFramePhdr = &Phdr;
> + if (Phdr.p_memsz != Phdr.p_filesz)
> + reportError("p_memsz does not match p_filesz for GNU_EH_FRAME");
> + break;
> + }
> + }
> +
> + if (EHFramePhdr)
> + printEHFrameHdr(EHFramePhdr->p_offset, EHFramePhdr->p_vaddr,
> + EHFramePhdr->p_memsz);
> +
> + auto Sections = Obj->sections();
> + if (Error E = Sections.takeError())
> + reportError(toString(std::move(E)));
> +
> + for (const auto &Shdr : *Sections) {
> + auto SectionName = Obj->getSectionName(&Shdr);
> + if (Error E = SectionName.takeError())
> + reportError(toString(std::move(E)));
> +
> + if (*SectionName == ".eh_frame")
> + printEHFrame(&Shdr);
> + }
> +}
> +
> +template <typename ELFT>
> +void PrinterContext<ELFT>::printEHFrameHdr(uint64_t EHFrameHdrOffset,
> + uint64_t EHFrameHdrAddress,
> + uint64_t EHFrameHdrSize) const
> {
> + ListScope L(W, "EH_FRAME Header");
> + W.startLine() << format("Address: 0x%" PRIx64 "\n", EHFrameHdrAddress);
> + W.startLine() << format("Offset: 0x%" PRIx64 "\n", EHFrameHdrOffset);
> + W.startLine() << format("Size: 0x%" PRIx64 "\n", EHFrameHdrSize);
> +
> + const auto *EHFrameHdrShdr = findSectionByAddress(Obj,
> EHFrameHdrAddress);
> + if (EHFrameHdrShdr) {
> + auto SectionName = Obj->getSectionName(EHFrameHdrShdr);
> + if (Error E = SectionName.takeError())
> + reportError(toString(std::move(E)));
> +
> + W.printString("Corresponding Section", *SectionName);
> + }
> +
> + DataExtractor DE(
> + StringRef(reinterpret_cast<const char *>(Obj->base()) +
> EHFrameHdrOffset,
> + EHFrameHdrSize),
> + ELFT::TargetEndianness == support::endianness::little,
> + ELFT::Is64Bits ? 8 : 4);
> +
> + DictScope D(W, "Header");
> + uint32_t Offset = 0;
> +
> + auto Version = DE.getU8(&Offset);
> + W.printNumber("version", Version);
> + if (Version != 1)
> + reportError("only version 1 of .eh_frame_hdr is supported");
> +
> + auto EHFramePtrEnc = DE.getU8(&Offset);
> + W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64 "\n",
> EHFramePtrEnc);
> + if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4))
> + reportError("unexpected encoding eh_frame_ptr_enc");
> +
> + auto FDECountEnc = DE.getU8(&Offset);
> + W.startLine() << format("fde_count_enc: 0x%" PRIx64 "\n", FDECountEnc);
> + if (FDECountEnc != dwarf::DW_EH_PE_udata4)
> + reportError("unexpected encoding fde_count_enc");
> +
> + auto TableEnc = DE.getU8(&Offset);
> + W.startLine() << format("table_enc: 0x%" PRIx64 "\n", TableEnc);
> + if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4))
> + reportError("unexpected encoding table_enc");
> +
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180307/f1e1f440/attachment-0001.html>
More information about the llvm-commits
mailing list