summaryrefslogtreecommitdiff
path: root/lib/DebugInfo/DWARFDebugFrame.cpp
diff options
context:
space:
mode:
authorEli Bendersky <eliben@google.com>2013-02-05 23:30:58 +0000
committerEli Bendersky <eliben@google.com>2013-02-05 23:30:58 +0000
commit60bdc5b16e2fc17be184b515a00c2e2a2eb40b89 (patch)
treebe55ca14395e80a1b7d7440cdb177e27e8e5c799 /lib/DebugInfo/DWARFDebugFrame.cpp
parent5e215f9bfd9e113d2b14e1d2cd7395fbeb3c0561 (diff)
downloadllvm-60bdc5b16e2fc17be184b515a00c2e2a2eb40b89.tar.gz
llvm-60bdc5b16e2fc17be184b515a00c2e2a2eb40b89.tar.bz2
llvm-60bdc5b16e2fc17be184b515a00c2e2a2eb40b89.tar.xz
Initial support for DWARF CFI parsing and dumping in LLVM
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174463 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/DebugInfo/DWARFDebugFrame.cpp')
-rw-r--r--lib/DebugInfo/DWARFDebugFrame.cpp195
1 files changed, 195 insertions, 0 deletions
diff --git a/lib/DebugInfo/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARFDebugFrame.cpp
new file mode 100644
index 0000000000..0b78cce1dd
--- /dev/null
+++ b/lib/DebugInfo/DWARFDebugFrame.cpp
@@ -0,0 +1,195 @@
+//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugFrame.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace dwarf;
+
+
+class llvm::FrameEntry {
+public:
+ enum FrameKind {FK_CIE, FK_FDE};
+ FrameEntry(FrameKind K, DataExtractor D, uint64_t Offset, uint64_t Length)
+ : Kind(K), Data(D), Offset(Offset), Length(Length)
+ {}
+
+ FrameKind getKind() const { return Kind; }
+
+ virtual void dumpHeader(raw_ostream &OS) const = 0;
+protected:
+ const FrameKind Kind;
+ DataExtractor Data;
+ uint64_t Offset;
+ uint64_t Length;
+};
+
+
+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(DataExtractor D, uint64_t Offset, uint64_t Length, uint8_t Version,
+ SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
+ int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
+ : FrameEntry(FK_CIE, D, Offset, Length), Version(Version),
+ Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor),
+ DataAlignmentFactor(DataAlignmentFactor),
+ ReturnAddressRegister(ReturnAddressRegister)
+ {}
+
+ void dumpHeader(raw_ostream &OS) const {
+ OS << format("%08x %08x %08x CIE", Offset, Length, DW_CIE_ID) << "\n";
+ OS << format(" Version: %d\n", Version);
+ OS << " Augmentation: \"" << Augmentation << "\"\n";
+ OS << format(" Code alignment factor: %u\n", CodeAlignmentFactor);
+ OS << format(" Data alignment factor: %d\n", DataAlignmentFactor);
+ OS << format(" Return address column: %d\n", ReturnAddressRegister);
+ OS << "\n";
+ }
+
+ static bool classof(const FrameEntry *FE) {
+ return FE->getKind() == FK_CIE;
+ }
+private:
+ uint8_t Version;
+ SmallString<8> Augmentation;
+ uint64_t CodeAlignmentFactor;
+ int64_t DataAlignmentFactor;
+ uint64_t ReturnAddressRegister;
+};
+
+
+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(DataExtractor D, uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
+ uint64_t InitialLocation, uint64_t AddressRange)
+ : FrameEntry(FK_FDE, D, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
+ InitialLocation(InitialLocation), AddressRange(AddressRange),
+ LinkedCIE(NULL)
+ {}
+
+ void dumpHeader(raw_ostream &OS) const {
+ OS << format("%08x %08x %08x FDE ", Offset, Length, LinkedCIEOffset);
+ OS << format("cie=%08x pc=%08x...%08x\n",
+ LinkedCIEOffset, InitialLocation,
+ InitialLocation + AddressRange);
+ OS << "\n";
+ }
+
+ static bool classof(const FrameEntry *FE) {
+ return FE->getKind() == FK_FDE;
+ }
+private:
+ uint64_t LinkedCIEOffset;
+ uint64_t InitialLocation;
+ uint64_t AddressRange;
+ CIE *LinkedCIE;
+};
+
+
+DWARFDebugFrame::DWARFDebugFrame()
+{
+}
+
+
+DWARFDebugFrame::~DWARFDebugFrame()
+{
+ for (EntryVector::iterator I = Entries.begin(), E = Entries.end();
+ I != E; ++I) {
+ delete *I;
+ }
+}
+
+
+static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
+ uint32_t Offset, int Length) {
+ errs() << "DUMP: ";
+ for (int i = 0; i < Length; ++i) {
+ uint8_t c = Data.getU8(&Offset);
+ errs().write_hex(c); errs() << " ";
+ }
+ errs() << "\n";
+}
+
+
+void DWARFDebugFrame::parse(DataExtractor Data) {
+ uint32_t Offset = 0;
+
+ while (Data.isValidOffset(Offset)) {
+ uint32_t StartOffset = Offset;
+
+ bool IsDWARF64 = false;
+ uint64_t Length = Data.getU32(&Offset);
+ uint64_t Id;
+
+ if (Length == UINT32_MAX) {
+ // DWARF-64 is distinguished by the first 32 bits of the initial length
+ // field being 0xffffffff. Then, the next 64 bits are the actual entry
+ // length.
+ IsDWARF64 = true;
+ Length = Data.getU64(&Offset);
+ }
+
+ // At this point, Offset points to the next field after Length.
+ // Length is the structure size excluding itself. Compute an offset one
+ // past the end of the structure (needed to know how many instructions to
+ // read).
+ // TODO: For honest DWARF64 support, DataExtractor will have to treat
+ // offset_ptr as uint64_t*
+ uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
+
+ // The Id field's size depends on the DWARF format
+ Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
+ bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
+
+ if (IsCIE) {
+ // Note: this is specifically DWARFv3 CIE header structure. It was
+ // changed in DWARFv4.
+ uint8_t Version = Data.getU8(&Offset);
+ const char *Augmentation = Data.getCStr(&Offset);
+ uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
+ int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
+ uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
+
+ CIE *NewCIE = new CIE(Data, StartOffset, Length, Version,
+ StringRef(Augmentation), CodeAlignmentFactor,
+ DataAlignmentFactor, ReturnAddressRegister);
+ Entries.push_back(NewCIE);
+ } else {
+ // FDE
+ uint64_t CIEPointer = Id;
+ uint64_t InitialLocation = Data.getAddress(&Offset);
+ uint64_t AddressRange = Data.getAddress(&Offset);
+
+ FDE *NewFDE = new FDE(Data, StartOffset, Length, CIEPointer,
+ InitialLocation, AddressRange);
+ Entries.push_back(NewFDE);
+ }
+
+ Offset = EndStructureOffset;
+ }
+}
+
+
+void DWARFDebugFrame::dump(raw_ostream &OS) const {
+ OS << "\n";
+ for (EntryVector::const_iterator I = Entries.begin(), E = Entries.end();
+ I != E; ++I) {
+ (*I)->dumpHeader(OS);
+ }
+}
+