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