[llvm] r326932 - [DebugInfo] Support DWARF expressions in eh_frame
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 7 14:33:26 PST 2018
I reverted this change in r326953. Feel free to re-submit with a fix for
the broken test.
On Wed, Mar 7, 2018 at 2:18 PM Rui Ueyama <ruiu at google.com> wrote:
> 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/34772eba/attachment-0001.html>
More information about the llvm-commits
mailing list