add_llvm_library(LLVMObjectYAML
COFFYAML.cpp
DWARFEmitter.cpp
+ DWARFVisitor.cpp
DWARFYAML.cpp
ELFYAML.cpp
MachOYAML.cpp
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SwapByteOrder.h"
+#include "DWARFVisitor.h"
+
#include <algorithm>
using namespace llvm;
}
}
-void DWARFYAML::EmitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
+/// \brief An extension of the DWARFYAML::ConstVisitor which writes compile
+/// units and DIEs to a stream.
+class DumpVisitor : public DWARFYAML::ConstVisitor {
+ raw_ostream &OS;
+
+protected:
+ virtual void onStartCompileUnit(const DWARFYAML::Unit &CU) {
+ writeInitialLength(CU.Length, OS, DebugInfo.IsLittleEndian);
+ writeInteger((uint16_t)CU.Version, OS, DebugInfo.IsLittleEndian);
+ writeInteger((uint32_t)CU.AbbrOffset, OS, DebugInfo.IsLittleEndian);
+ writeInteger((uint8_t)CU.AddrSize, OS, DebugInfo.IsLittleEndian);
+ }
- for (auto CU : DI.CompileUnits) {
- writeInitialLength(CU.Length, OS, DI.IsLittleEndian);
- writeInteger((uint16_t)CU.Version, OS, DI.IsLittleEndian);
- writeInteger((uint32_t)CU.AbbrOffset, OS, DI.IsLittleEndian);
- writeInteger((uint8_t)CU.AddrSize, OS, DI.IsLittleEndian);
-
- auto FirstAbbrevCode = CU.Entries[0].AbbrCode;
-
- for (auto Entry : CU.Entries) {
- encodeULEB128(Entry.AbbrCode, OS);
- if (Entry.AbbrCode == 0u)
- continue;
- bool Indirect = false;
- assert(Entry.AbbrCode - FirstAbbrevCode < DI.AbbrevDecls.size() &&
- "Out of range AbbCode");
- auto &Abbrev = DI.AbbrevDecls[Entry.AbbrCode - FirstAbbrevCode];
-
- auto FormVal = Entry.Values.begin();
- auto AbbrForm = Abbrev.Attributes.begin();
- for (;
- FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
- ++FormVal, ++AbbrForm) {
- dwarf::Form Form = AbbrForm->Form;
- do {
- Indirect = false;
- switch (Form) {
- case dwarf::DW_FORM_addr:
- writeVariableSizedInteger(FormVal->Value, CU.AddrSize, OS,
- DI.IsLittleEndian);
- break;
- case dwarf::DW_FORM_ref_addr: {
- // TODO: Handle DWARF32/DWARF64 after Line Table data is done
- auto writeSize = CU.Version == 2 ? CU.AddrSize : 4;
- writeVariableSizedInteger(FormVal->Value, writeSize, OS,
- DI.IsLittleEndian);
- break;
- }
- case dwarf::DW_FORM_exprloc:
- case dwarf::DW_FORM_block:
- encodeULEB128(FormVal->BlockData.size(), OS);
- OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
- FormVal->BlockData.size());
- break;
- case dwarf::DW_FORM_block1: {
- auto writeSize = FormVal->BlockData.size();
- writeInteger((uint8_t)writeSize, OS, DI.IsLittleEndian);
- OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
- FormVal->BlockData.size());
- break;
- }
- case dwarf::DW_FORM_block2: {
- auto writeSize = FormVal->BlockData.size();
- writeInteger((uint16_t)writeSize, OS, DI.IsLittleEndian);
- OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
- FormVal->BlockData.size());
- break;
- }
- case dwarf::DW_FORM_block4: {
- auto writeSize = FormVal->BlockData.size();
- writeInteger((uint32_t)writeSize, OS, DI.IsLittleEndian);
- OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
- FormVal->BlockData.size());
- break;
- }
- case dwarf::DW_FORM_data1:
- case dwarf::DW_FORM_ref1:
- case dwarf::DW_FORM_flag:
- writeInteger((uint8_t)FormVal->Value, OS, DI.IsLittleEndian);
- break;
- case dwarf::DW_FORM_data2:
- case dwarf::DW_FORM_ref2:
- writeInteger((uint16_t)FormVal->Value, OS, DI.IsLittleEndian);
- break;
- case dwarf::DW_FORM_data4:
- case dwarf::DW_FORM_ref4:
- writeInteger((uint32_t)FormVal->Value, OS, DI.IsLittleEndian);
- break;
- case dwarf::DW_FORM_data8:
- case dwarf::DW_FORM_ref8:
- writeInteger((uint64_t)FormVal->Value, OS, DI.IsLittleEndian);
- break;
- case dwarf::DW_FORM_sdata:
- encodeSLEB128(FormVal->Value, OS);
- break;
- case dwarf::DW_FORM_udata:
- case dwarf::DW_FORM_ref_udata:
- encodeULEB128(FormVal->Value, OS);
- break;
- case dwarf::DW_FORM_string:
- OS.write(FormVal->CStr.data(), FormVal->CStr.size());
- OS.write('\0');
- break;
- case dwarf::DW_FORM_indirect:
- encodeULEB128(FormVal->Value, OS);
- Indirect = true;
- Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
- ++FormVal;
- break;
- case dwarf::DW_FORM_strp:
- case dwarf::DW_FORM_sec_offset:
- case dwarf::DW_FORM_GNU_ref_alt:
- case dwarf::DW_FORM_GNU_strp_alt:
- case dwarf::DW_FORM_line_strp:
- case dwarf::DW_FORM_strp_sup:
- case dwarf::DW_FORM_ref_sup:
- // TODO: Handle DWARF32/64
- writeInteger((uint32_t)FormVal->Value, OS, DI.IsLittleEndian);
- break;
- case dwarf::DW_FORM_ref_sig8:
- writeInteger((uint64_t)FormVal->Value, OS, DI.IsLittleEndian);
- break;
- case dwarf::DW_FORM_GNU_addr_index:
- case dwarf::DW_FORM_GNU_str_index:
- encodeULEB128(FormVal->Value, OS);
- break;
- default:
- break;
- }
- } while (Indirect);
- }
- }
+ virtual void onStartDIE(const DWARFYAML::Unit &CU,
+ const DWARFYAML::Entry &DIE) {
+ encodeULEB128(DIE.AbbrCode, OS);
+ }
+
+ virtual void onValue(const uint8_t U) {
+ writeInteger(U, OS, DebugInfo.IsLittleEndian);
+ }
+
+ virtual void onValue(const uint16_t U) {
+ writeInteger(U, OS, DebugInfo.IsLittleEndian);
+ }
+ virtual void onValue(const uint32_t U) {
+ writeInteger(U, OS, DebugInfo.IsLittleEndian);
}
+ virtual void onValue(const uint64_t U, const bool LEB = false) {
+ if (LEB)
+ encodeULEB128(U, OS);
+ else
+ writeInteger(U, OS, DebugInfo.IsLittleEndian);
+ }
+
+ virtual void onValue(const int64_t S, const bool LEB = false) {
+ if (LEB)
+ encodeSLEB128(S, OS);
+ else
+ writeInteger(S, OS, DebugInfo.IsLittleEndian);
+ }
+
+ virtual void onValue(const StringRef String) {
+ OS.write(String.data(), String.size());
+ OS.write('\0');
+ }
+
+ virtual void onValue(const MemoryBufferRef MBR) {
+ OS.write(MBR.getBufferStart(), MBR.getBufferSize());
+ }
+
+public:
+ DumpVisitor(const DWARFYAML::Data &DI, raw_ostream &Out)
+ : DWARFYAML::ConstVisitor(DI), OS(Out) {}
+};
+
+void DWARFYAML::EmitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
+ DumpVisitor Visitor(DI, OS);
+ Visitor.traverseDebugInfo();
}
static void EmitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
--- /dev/null
+//===--- DWARFVisitor.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFVisitor.h"
+#include "llvm/ObjectYAML/DWARFYAML.h"
+
+using namespace llvm;
+
+template <typename T>
+void DWARFYAML::VisitorImpl<T>::onVariableSizeValue(uint64_t U, unsigned Size) {
+ switch (Size) {
+ case 8:
+ onValue((uint64_t)U);
+ break;
+ case 4:
+ onValue((uint32_t)U);
+ break;
+ case 2:
+ onValue((uint16_t)U);
+ break;
+ case 1:
+ onValue((uint8_t)U);
+ break;
+ default:
+ llvm_unreachable("Invalid integer write size.");
+ }
+}
+
+unsigned getRefSize(const DWARFYAML::Unit &Unit) {
+ if (Unit.Version == 2)
+ return Unit.AddrSize;
+ return Unit.Length.isDWARF64() ? 8 : 4;
+}
+
+template <typename T> void DWARFYAML::VisitorImpl<T>::traverseDebugInfo() {
+ for (auto &Unit : DebugInfo.CompileUnits) {
+ onStartCompileUnit(Unit);
+ auto FirstAbbrevCode = Unit.Entries[0].AbbrCode;
+
+ for (auto &Entry : Unit.Entries) {
+ onStartDIE(Unit, Entry);
+ if (Entry.AbbrCode == 0u)
+ continue;
+ auto &Abbrev = DebugInfo.AbbrevDecls[Entry.AbbrCode - FirstAbbrevCode];
+ auto FormVal = Entry.Values.begin();
+ auto AbbrForm = Abbrev.Attributes.begin();
+ for (;
+ FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
+ ++FormVal, ++AbbrForm) {
+ onForm(*AbbrForm, *FormVal);
+ dwarf::Form Form = AbbrForm->Form;
+ bool Indirect;
+ do {
+ Indirect = false;
+ switch (Form) {
+ case dwarf::DW_FORM_addr:
+ onVariableSizeValue(FormVal->Value, Unit.AddrSize);
+ break;
+ case dwarf::DW_FORM_ref_addr:
+ onVariableSizeValue(FormVal->Value, getRefSize(Unit));
+ break;
+ case dwarf::DW_FORM_exprloc:
+ case dwarf::DW_FORM_block:
+ onValue((uint64_t)FormVal->BlockData.size(), true);
+ onValue(
+ MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
+ FormVal->BlockData.size()),
+ ""));
+ break;
+ case dwarf::DW_FORM_block1: {
+ auto writeSize = FormVal->BlockData.size();
+ onValue((uint8_t)writeSize);
+ onValue(
+ MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
+ FormVal->BlockData.size()),
+ ""));
+ break;
+ }
+ case dwarf::DW_FORM_block2: {
+ auto writeSize = FormVal->BlockData.size();
+ onValue((uint16_t)writeSize);
+ onValue(
+ MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
+ FormVal->BlockData.size()),
+ ""));
+ break;
+ }
+ case dwarf::DW_FORM_block4: {
+ auto writeSize = FormVal->BlockData.size();
+ onValue((uint32_t)writeSize);
+ onValue(
+ MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
+ FormVal->BlockData.size()),
+ ""));
+ break;
+ }
+ case dwarf::DW_FORM_data1:
+ case dwarf::DW_FORM_ref1:
+ case dwarf::DW_FORM_flag:
+ onValue((uint8_t)FormVal->Value);
+ break;
+ case dwarf::DW_FORM_data2:
+ case dwarf::DW_FORM_ref2:
+ onValue((uint16_t)FormVal->Value);
+ break;
+ case dwarf::DW_FORM_data4:
+ case dwarf::DW_FORM_ref4:
+ onValue((uint32_t)FormVal->Value);
+ break;
+ case dwarf::DW_FORM_data8:
+ case dwarf::DW_FORM_ref8:
+ onValue((uint64_t)FormVal->Value);
+ break;
+ case dwarf::DW_FORM_sdata:
+ onValue((int64_t)FormVal->Value, true);
+ break;
+ case dwarf::DW_FORM_udata:
+ case dwarf::DW_FORM_ref_udata:
+ onValue((uint64_t)FormVal->Value, true);
+ break;
+ case dwarf::DW_FORM_string:
+ onValue(FormVal->CStr);
+ break;
+ case dwarf::DW_FORM_indirect:
+ onValue((uint64_t)FormVal->Value, true);
+ Indirect = true;
+ Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
+ ++FormVal;
+ break;
+ case dwarf::DW_FORM_strp:
+ case dwarf::DW_FORM_sec_offset:
+ case dwarf::DW_FORM_GNU_ref_alt:
+ case dwarf::DW_FORM_GNU_strp_alt:
+ case dwarf::DW_FORM_line_strp:
+ case dwarf::DW_FORM_strp_sup:
+ case dwarf::DW_FORM_ref_sup:
+ onVariableSizeValue(FormVal->Value, getRefSize(Unit));
+ break;
+ case dwarf::DW_FORM_ref_sig8:
+ onValue((uint64_t)FormVal->Value);
+ break;
+ case dwarf::DW_FORM_GNU_addr_index:
+ case dwarf::DW_FORM_GNU_str_index:
+ onValue((uint64_t)FormVal->Value, true);
+ break;
+ default:
+ break;
+ }
+ } while (Indirect);
+ }
+ onEndDIE(Unit, Entry);
+ }
+ onEndCompileUnit(Unit);
+ }
+}
+
+// Explicitly instantiate the two template expansions.
+template class DWARFYAML::VisitorImpl<DWARFYAML::Data>;
+template class DWARFYAML::VisitorImpl<const DWARFYAML::Data>;
--- /dev/null
+//===--- DWARFVisitor.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_DWARFVISITOR_H
+#define LLVM_OBJECTYAML_DWARFVISITOR_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace llvm {
+
+namespace DWARFYAML {
+
+struct Data;
+struct Unit;
+struct Entry;
+struct FormValue;
+struct AttributeAbbrev;
+
+/// \brief A class to visits DWARFYAML Compile Units and DIEs in preorder.
+///
+/// Extensions of this class can either maintain const or non-const references
+/// to the DWARFYAML::Data object.
+template <typename T> class VisitorImpl {
+protected:
+ T &DebugInfo;
+
+ /// Visitor Functions
+ /// @{
+ virtual void onStartCompileUnit(Unit &CU) {}
+ virtual void onEndCompileUnit(Unit &CU) {}
+ virtual void onStartDIE(Unit &CU, Entry &DIE) {}
+ virtual void onEndDIE(Unit &CU, Entry &DIE) {}
+ virtual void onForm(AttributeAbbrev &AttAbbrev, FormValue &Value) {}
+ /// @}
+
+ /// Const Visitor Functions
+ /// @{
+ virtual void onStartCompileUnit(const Unit &CU) {}
+ virtual void onEndCompileUnit(const Unit &CU) {}
+ virtual void onStartDIE(const Unit &CU, const Entry &DIE) {}
+ virtual void onEndDIE(const Unit &CU, const Entry &DIE) {}
+ virtual void onForm(const AttributeAbbrev &AttAbbrev,
+ const FormValue &Value) {}
+ /// @}
+
+ /// Value visitors
+ /// @{
+ virtual void onValue(const uint8_t U) {}
+ virtual void onValue(const uint16_t U) {}
+ virtual void onValue(const uint32_t U) {}
+ virtual void onValue(const uint64_t U, const bool LEB = false) {}
+ virtual void onValue(const int64_t S, const bool LEB = false) {}
+ virtual void onValue(const StringRef String) {}
+ virtual void onValue(const MemoryBufferRef MBR) {}
+ /// @}
+
+public:
+ VisitorImpl(T &DI) : DebugInfo(DI) {}
+
+ virtual ~VisitorImpl() {}
+
+ void traverseDebugInfo();
+
+private:
+ void onVariableSizeValue(uint64_t U, unsigned Size);
+};
+
+// Making the visior instantiations extern and explicit in the cpp file. This
+// prevents them from being instantiated in every compile unit that uses the
+// visitors.
+extern template class VisitorImpl<DWARFYAML::Data>;
+extern template class VisitorImpl<const DWARFYAML::Data>;
+
+class Visitor : public VisitorImpl<Data> {
+public:
+ Visitor(Data &DI) : VisitorImpl<Data>(DI) {}
+};
+
+class ConstVisitor : public VisitorImpl<const Data> {
+public:
+ ConstVisitor(const Data &DI) : VisitorImpl<const Data>(DI) {}
+};
+
+} // namespace DWARFYAML
+} // namespace llvm
+
+#endif