summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp')
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp545
1 files changed, 361 insertions, 184 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index b9dc2151e06..3312da67804 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -8,8 +8,10 @@
//===----------------------------------------------------------------------===//
#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"
@@ -29,13 +31,87 @@
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;
-Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset,
- uint32_t EndOffset) {
+void FrameEntry::parseInstructions(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.
@@ -46,73 +122,67 @@ Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset,
// bits of the opcode itself.
uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
switch (Primary) {
- 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;
+ 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;
}
} else {
// Extended opcode - its value is Opcode itself.
switch (Opcode) {
- 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;
+ 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;
}
case DW_CFA_offset_extended_sf:
case DW_CFA_def_cfa_sf:
@@ -124,49 +194,162 @@ Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset,
addInstruction(Opcode, op1, op2);
break;
}
- 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;
+ case DW_CFA_def_cfa_expression:
+ // FIXME: Parse the actual instruction.
+ *Offset += Data.getULEB128(Offset);
break;
- }
case DW_CFA_expression:
case DW_CFA_val_expression: {
- 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;
+ // FIXME: Parse the actual instruction.
+ Data.getULEB128(Offset);
+ *Offset += Data.getULEB128(Offset);
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
-ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() {
+/// \brief Initialize the array describing the types of operands.
+static ArrayRef<OperandType[2]> 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 { \
@@ -213,13 +396,15 @@ ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() {
return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
}
-/// 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 {
+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) {
assert(OperandIdx < 2);
- uint8_t Opcode = Instr.Opcode;
- OperandType Type = getOperandTypes()[Opcode][OperandIdx];
+ OperandType Type = OpTypes[Opcode][OperandIdx];
switch (Type) {
case OT_Unset: {
@@ -264,68 +449,36 @@ void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI,
OS << format(" reg%" PRId64, Operand);
break;
case OT_Expression:
- assert(Instr.Expression && "missing DWARFExpression object");
- OS << " ";
- Instr.Expression->print(OS, MRI, IsEH);
+ OS << " expression";
break;
}
}
-void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
- unsigned IndentLevel) const {
+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();
+ }
+
for (const auto &Instr : Instructions) {
uint8_t Opcode = Instr.Opcode;
if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
- OS.indent(2 * IndentLevel);
- OS << CallFrameString(Opcode) << ":";
+ OS << " " << CallFrameString(Opcode) << ":";
for (unsigned i = 0; i < Instr.Ops.size(); ++i)
- printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]);
+ printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor,
+ DataAlignmentFactor);
OS << '\n';
}
}
-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(bool IsEH) : IsEH(IsEH) {}
DWARFDebugFrame::~DWARFDebugFrame() = default;
@@ -339,6 +492,40 @@ static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
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
@@ -352,7 +539,7 @@ static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset,
report_fatal_error(Str);
}
-void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
+void DWARFDebugFrame::parse(DataExtractor Data) {
uint32_t Offset = 0;
DenseMap<uint32_t, CIE *> CIEs;
@@ -382,8 +569,9 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
// 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);
@@ -401,9 +589,10 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
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;
@@ -422,9 +611,7 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
ReportError(StartOffset,
"Duplicate personality in entry at %lx");
PersonalityEncoding = Data.getU8(&Offset);
- Personality = Data.getEncodedPointer(
- &Offset, *PersonalityEncoding,
- EHFrameAddress ? EHFrameAddress + Offset : 0);
+ Personality = readPointer(Data, Offset, *PersonalityEncoding);
break;
}
case 'R':
@@ -452,11 +639,14 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
}
}
- auto Cie = llvm::make_unique<CIE>(
- StartOffset, Length, Version, AugmentationString, AddressSize,
- SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor,
- ReturnAddressRegister, AugmentationData, FDEPointerEncoding,
- LSDAPointerEncoding, Personality, PersonalityEncoding);
+ auto Cie = llvm::make_unique<CIE>(StartOffset, Length, Version,
+ AugmentationString, AddressSize,
+ SegmentDescriptorSize,
+ CodeAlignmentFactor,
+ DataAlignmentFactor,
+ ReturnAddressRegister,
+ AugmentationData, FDEPointerEncoding,
+ LSDAPointerEncoding);
CIEs[StartOffset] = Cie.get();
Entries.emplace_back(std::move(Cie));
} else {
@@ -464,7 +654,6 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
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) {
@@ -473,15 +662,10 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
ReportError(StartOffset,
"Parsing FDE data at %lx failed due to missing CIE");
- 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;
- }
+ InitialLocation = readPointer(Data, Offset,
+ Cie->getFDEPointerEncoding());
+ AddressRange = readPointer(Data, Offset,
+ Cie->getFDEPointerEncoding());
StringRef AugmentationString = Cie->getAugmentationString();
if (!AugmentationString.empty()) {
@@ -492,11 +676,8 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
Offset + static_cast<uint32_t>(AugmentationLength);
// Decode the LSDA if the CIE augmentation string said we should.
- if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
- LSDAAddress = Data.getEncodedPointer(
- &Offset, Cie->getLSDAPointerEncoding(),
- EHFrameAddress ? Offset + EHFrameAddress : 0);
- }
+ if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit)
+ readPointer(Data, Offset, Cie->getLSDAPointerEncoding());
if (Offset != EndAugmentationOffset)
ReportError(StartOffset, "Parsing augmentation data at %lx failed");
@@ -508,13 +689,10 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
InitialLocation, AddressRange,
- Cie, LSDAAddress));
+ Cie));
}
- if (Error E =
- Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) {
- report_fatal_error(toString(std::move(E)));
- }
+ Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
if (Offset != EndStructureOffset)
ReportError(StartOffset, "Parsing entry instructions at %lx failed");
@@ -531,15 +709,14 @@ FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
return nullptr;
}
-void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
- Optional<uint64_t> Offset) const {
+void DWARFDebugFrame::dump(raw_ostream &OS, Optional<uint64_t> Offset) const {
if (Offset) {
if (auto *Entry = getEntryAtOffset(*Offset))
- Entry->dump(OS, MRI, IsEH);
+ Entry->dump(OS);
return;
}
OS << "\n";
for (const auto &Entry : Entries)
- Entry->dump(OS, MRI, IsEH);
+ Entry->dump(OS);
}
OpenPOWER on IntegriCloud