[llvm] r326932 - [DebugInfo] Support DWARF expressions in eh_frame
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 7 14:18:10 PST 2018
I'm going to revert this for now since the tree has been broken for two
hours.
On Wed, Mar 7, 2018 at 2:15 PM Rui Ueyama <ruiu at google.com> wrote:
> 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/447f294f/attachment.html>
More information about the llvm-commits
mailing list