|  | //===--- 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."); | 
|  | } | 
|  | } | 
|  |  | 
|  | static unsigned getOffsetSize(const DWARFYAML::Unit &Unit) { | 
|  | return Unit.Length.isDWARF64() ? 8 : 4; | 
|  | } | 
|  |  | 
|  | static unsigned getRefSize(const DWARFYAML::Unit &Unit) { | 
|  | if (Unit.Version == 2) | 
|  | return Unit.AddrSize; | 
|  | return getOffsetSize(Unit); | 
|  | } | 
|  |  | 
|  | 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: | 
|  | case dwarf::DW_FORM_strx1: | 
|  | case dwarf::DW_FORM_addrx1: | 
|  | onValue((uint8_t)FormVal->Value); | 
|  | break; | 
|  | case dwarf::DW_FORM_data2: | 
|  | case dwarf::DW_FORM_ref2: | 
|  | case dwarf::DW_FORM_strx2: | 
|  | case dwarf::DW_FORM_addrx2: | 
|  | onValue((uint16_t)FormVal->Value); | 
|  | break; | 
|  | case dwarf::DW_FORM_data4: | 
|  | case dwarf::DW_FORM_ref4: | 
|  | case dwarf::DW_FORM_ref_sup4: | 
|  | case dwarf::DW_FORM_strx4: | 
|  | case dwarf::DW_FORM_addrx4: | 
|  | onValue((uint32_t)FormVal->Value); | 
|  | break; | 
|  | case dwarf::DW_FORM_data8: | 
|  | case dwarf::DW_FORM_ref8: | 
|  | case dwarf::DW_FORM_ref_sup8: | 
|  | 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: | 
|  | onVariableSizeValue(FormVal->Value, getOffsetSize(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>; |