| //===--- DWARFVisitor.cpp ---------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #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>; |