blob: ecb5967ac532d768428a0bf3db9d12c66e3d1e94 [file] [log] [blame]
//===--- 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>;