forked from OSchip/llvm-project
[DWARFYAML] Refactor emitDebugInfo() to make the length be inferred.
This patch refactors `emitDebugInfo()` to make the length field be inferred from its content. Besides, the `Visitor` class is removed in this patch. The original `Visitor` class helps us determine an appropriate length and emit the .debug_info section. These two processes can be merged into one process. Besides, the length field should be inferred when it's missing rather than when it's zero. Reviewed By: jhenderson, labath Differential Revision: https://reviews.llvm.org/D84008
This commit is contained in:
parent
a997e6edb9
commit
92874d2866
|
@ -93,7 +93,7 @@ public:
|
|||
|
||||
YAMLModuleTester::YAMLModuleTester(llvm::StringRef yaml_data,
|
||||
llvm::StringRef triple) {
|
||||
auto sections_map = llvm::DWARFYAML::emitDebugSections(yaml_data, true);
|
||||
auto sections_map = llvm::DWARFYAML::emitDebugSections(yaml_data);
|
||||
if (!sections_map)
|
||||
return;
|
||||
m_sections_map = std::move(*sections_map);
|
||||
|
|
|
@ -42,7 +42,7 @@ Error emitDebugStrOffsets(raw_ostream &OS, const Data &DI);
|
|||
Error emitDebugRnglists(raw_ostream &OS, const Data &DI);
|
||||
|
||||
Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
|
||||
emitDebugSections(StringRef YAMLString, bool ApplyFixups = false,
|
||||
emitDebugSections(StringRef YAMLString,
|
||||
bool IsLittleEndian = sys::IsLittleEndianHost);
|
||||
} // end namespace DWARFYAML
|
||||
} // end namespace llvm
|
||||
|
|
|
@ -120,7 +120,7 @@ struct DWARFContext {
|
|||
|
||||
struct Unit {
|
||||
dwarf::DwarfFormat Format;
|
||||
yaml::Hex64 Length;
|
||||
Optional<yaml::Hex64> Length;
|
||||
uint16_t Version;
|
||||
llvm::dwarf::UnitType Type; // Added in DWARF 5
|
||||
yaml::Hex64 AbbrOffset;
|
||||
|
|
|
@ -6,7 +6,6 @@ add_llvm_component_library(LLVMObjectYAML
|
|||
COFFEmitter.cpp
|
||||
COFFYAML.cpp
|
||||
DWARFEmitter.cpp
|
||||
DWARFVisitor.cpp
|
||||
DWARFYAML.cpp
|
||||
ELFEmitter.cpp
|
||||
ELFYAML.cpp
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ObjectYAML/DWARFEmitter.h"
|
||||
#include "DWARFVisitor.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
@ -205,79 +204,194 @@ Error DWARFYAML::emitPubSection(raw_ostream &OS,
|
|||
return Error::success();
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// An extension of the DWARFYAML::ConstVisitor which writes compile
|
||||
/// units and DIEs to a stream.
|
||||
class DumpVisitor : public DWARFYAML::ConstVisitor {
|
||||
raw_ostream &OS;
|
||||
static unsigned getOffsetSize(const DWARFYAML::Unit &Unit) {
|
||||
return Unit.Format == dwarf::DWARF64 ? 8 : 4;
|
||||
}
|
||||
|
||||
protected:
|
||||
void onStartCompileUnit(const DWARFYAML::Unit &CU) override {
|
||||
writeInitialLength(CU.Format, CU.Length, OS, DebugInfo.IsLittleEndian);
|
||||
writeInteger((uint16_t)CU.Version, OS, DebugInfo.IsLittleEndian);
|
||||
if (CU.Version >= 5) {
|
||||
writeInteger((uint8_t)CU.Type, OS, DebugInfo.IsLittleEndian);
|
||||
writeInteger((uint8_t)CU.AddrSize, OS, DebugInfo.IsLittleEndian);
|
||||
cantFail(writeVariableSizedInteger(CU.AbbrOffset,
|
||||
CU.Format == dwarf::DWARF64 ? 8 : 4,
|
||||
OS, DebugInfo.IsLittleEndian));
|
||||
} else {
|
||||
cantFail(writeVariableSizedInteger(CU.AbbrOffset,
|
||||
CU.Format == dwarf::DWARF64 ? 8 : 4,
|
||||
OS, DebugInfo.IsLittleEndian));
|
||||
writeInteger((uint8_t)CU.AddrSize, OS, DebugInfo.IsLittleEndian);
|
||||
}
|
||||
static unsigned getRefSize(const DWARFYAML::Unit &Unit) {
|
||||
if (Unit.Version == 2)
|
||||
return Unit.AddrSize;
|
||||
return getOffsetSize(Unit);
|
||||
}
|
||||
|
||||
static Expected<uint64_t> writeDIE(ArrayRef<DWARFYAML::Abbrev> AbbrevDecls,
|
||||
const DWARFYAML::Unit &Unit,
|
||||
const DWARFYAML::Entry &Entry,
|
||||
raw_ostream &OS, bool IsLittleEndian) {
|
||||
uint64_t EntryBegin = OS.tell();
|
||||
encodeULEB128(Entry.AbbrCode, OS);
|
||||
uint32_t AbbrCode = Entry.AbbrCode;
|
||||
if (AbbrCode == 0 || Entry.Values.empty())
|
||||
return OS.tell() - EntryBegin;
|
||||
|
||||
if (AbbrCode > AbbrevDecls.size())
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"abbrev code must be less than or equal to the number of "
|
||||
"entries in abbreviation table");
|
||||
const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1];
|
||||
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;
|
||||
bool Indirect;
|
||||
do {
|
||||
Indirect = false;
|
||||
switch (Form) {
|
||||
case dwarf::DW_FORM_addr:
|
||||
// TODO: Test this error.
|
||||
if (Error Err = writeVariableSizedInteger(FormVal->Value, Unit.AddrSize,
|
||||
OS, IsLittleEndian))
|
||||
return std::move(Err);
|
||||
break;
|
||||
case dwarf::DW_FORM_ref_addr:
|
||||
// TODO: Test this error.
|
||||
if (Error Err = writeVariableSizedInteger(
|
||||
FormVal->Value, getRefSize(Unit), OS, IsLittleEndian))
|
||||
return std::move(Err);
|
||||
break;
|
||||
case dwarf::DW_FORM_exprloc:
|
||||
case dwarf::DW_FORM_block:
|
||||
encodeULEB128(FormVal->BlockData.size(), OS);
|
||||
OS.write((const char *)FormVal->BlockData.data(),
|
||||
FormVal->BlockData.size());
|
||||
break;
|
||||
case dwarf::DW_FORM_block1: {
|
||||
writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian);
|
||||
OS.write((const char *)FormVal->BlockData.data(),
|
||||
FormVal->BlockData.size());
|
||||
break;
|
||||
}
|
||||
case dwarf::DW_FORM_block2: {
|
||||
writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian);
|
||||
OS.write((const char *)FormVal->BlockData.data(),
|
||||
FormVal->BlockData.size());
|
||||
break;
|
||||
}
|
||||
case dwarf::DW_FORM_block4: {
|
||||
writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian);
|
||||
OS.write((const char *)FormVal->BlockData.data(),
|
||||
FormVal->BlockData.size());
|
||||
break;
|
||||
}
|
||||
case dwarf::DW_FORM_strx:
|
||||
case dwarf::DW_FORM_addrx:
|
||||
case dwarf::DW_FORM_rnglistx:
|
||||
case dwarf::DW_FORM_loclistx:
|
||||
case dwarf::DW_FORM_udata:
|
||||
case dwarf::DW_FORM_ref_udata:
|
||||
case dwarf::DW_FORM_GNU_addr_index:
|
||||
case dwarf::DW_FORM_GNU_str_index:
|
||||
encodeULEB128(FormVal->Value, OS);
|
||||
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:
|
||||
writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian);
|
||||
break;
|
||||
case dwarf::DW_FORM_data2:
|
||||
case dwarf::DW_FORM_ref2:
|
||||
case dwarf::DW_FORM_strx2:
|
||||
case dwarf::DW_FORM_addrx2:
|
||||
writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian);
|
||||
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:
|
||||
writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian);
|
||||
break;
|
||||
case dwarf::DW_FORM_data8:
|
||||
case dwarf::DW_FORM_ref8:
|
||||
case dwarf::DW_FORM_ref_sup8:
|
||||
case dwarf::DW_FORM_ref_sig8:
|
||||
writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian);
|
||||
break;
|
||||
case dwarf::DW_FORM_sdata:
|
||||
encodeSLEB128(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:
|
||||
// TODO: Test this error.
|
||||
if (Error Err = writeVariableSizedInteger(
|
||||
FormVal->Value, getOffsetSize(Unit), OS, IsLittleEndian))
|
||||
return std::move(Err);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (Indirect);
|
||||
}
|
||||
|
||||
void onStartDIE(const DWARFYAML::Unit &CU,
|
||||
const DWARFYAML::Entry &DIE) override {
|
||||
encodeULEB128(DIE.AbbrCode, OS);
|
||||
}
|
||||
return OS.tell() - EntryBegin;
|
||||
}
|
||||
|
||||
void onValue(const uint8_t U) override {
|
||||
writeInteger(U, OS, DebugInfo.IsLittleEndian);
|
||||
}
|
||||
|
||||
void onValue(const uint16_t U) override {
|
||||
writeInteger(U, OS, DebugInfo.IsLittleEndian);
|
||||
}
|
||||
|
||||
void onValue(const uint32_t U) override {
|
||||
writeInteger(U, OS, DebugInfo.IsLittleEndian);
|
||||
}
|
||||
|
||||
void onValue(const uint64_t U, const bool LEB = false) override {
|
||||
if (LEB)
|
||||
encodeULEB128(U, OS);
|
||||
else
|
||||
writeInteger(U, OS, DebugInfo.IsLittleEndian);
|
||||
}
|
||||
|
||||
void onValue(const int64_t S, const bool LEB = false) override {
|
||||
if (LEB)
|
||||
encodeSLEB128(S, OS);
|
||||
else
|
||||
writeInteger(S, OS, DebugInfo.IsLittleEndian);
|
||||
}
|
||||
|
||||
void onValue(const StringRef String) override {
|
||||
OS.write(String.data(), String.size());
|
||||
OS.write('\0');
|
||||
}
|
||||
|
||||
void onValue(const MemoryBufferRef MBR) override {
|
||||
OS.write(MBR.getBufferStart(), MBR.getBufferSize());
|
||||
}
|
||||
|
||||
public:
|
||||
DumpVisitor(const DWARFYAML::Data &DI, raw_ostream &Out)
|
||||
: DWARFYAML::ConstVisitor(DI), OS(Out) {}
|
||||
};
|
||||
} // namespace
|
||||
static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format,
|
||||
raw_ostream &OS, bool IsLittleEndian) {
|
||||
cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4,
|
||||
OS, IsLittleEndian));
|
||||
}
|
||||
|
||||
Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
|
||||
DumpVisitor Visitor(DI, OS);
|
||||
return Visitor.traverseDebugInfo();
|
||||
for (const DWARFYAML::Unit &Unit : DI.CompileUnits) {
|
||||
uint64_t Length = 3; // sizeof(version) + sizeof(address_size)
|
||||
Length += Unit.Version >= 5 ? 1 : 0; // sizeof(unit_type)
|
||||
Length +=
|
||||
Unit.Format == dwarf::DWARF64 ? 8 : 4; // sizeof(debug_abbrev_offset)
|
||||
|
||||
// Since the length of the current compilation unit is undetermined yet, we
|
||||
// firstly write the content of the compilation unit to a buffer to
|
||||
// calculate it and then serialize the buffer content to the actual output
|
||||
// stream.
|
||||
std::string EntryBuffer;
|
||||
raw_string_ostream EntryBufferOS(EntryBuffer);
|
||||
|
||||
for (const DWARFYAML::Entry &Entry : Unit.Entries) {
|
||||
if (Expected<uint64_t> EntryLength = writeDIE(
|
||||
DI.AbbrevDecls, Unit, Entry, EntryBufferOS, DI.IsLittleEndian))
|
||||
Length += *EntryLength;
|
||||
else
|
||||
return EntryLength.takeError();
|
||||
}
|
||||
|
||||
// If the length is specified in the YAML description, we use it instead of
|
||||
// the actual length.
|
||||
if (Unit.Length)
|
||||
Length = *Unit.Length;
|
||||
|
||||
writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian);
|
||||
writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian);
|
||||
if (Unit.Version >= 5) {
|
||||
writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian);
|
||||
writeInteger((uint8_t)Unit.AddrSize, OS, DI.IsLittleEndian);
|
||||
writeDWARFOffset(Unit.AbbrOffset, Unit.Format, OS, DI.IsLittleEndian);
|
||||
} else {
|
||||
writeDWARFOffset(Unit.AbbrOffset, Unit.Format, OS, DI.IsLittleEndian);
|
||||
writeInteger((uint8_t)Unit.AddrSize, OS, DI.IsLittleEndian);
|
||||
}
|
||||
|
||||
OS.write(EntryBuffer.data(), EntryBuffer.size());
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
|
||||
|
@ -634,51 +748,8 @@ emitDebugSectionImpl(const DWARFYAML::Data &DI, EmitFuncType EmitFunc,
|
|||
return Error::success();
|
||||
}
|
||||
|
||||
namespace {
|
||||
class DIEFixupVisitor : public DWARFYAML::Visitor {
|
||||
uint64_t Length;
|
||||
|
||||
public:
|
||||
DIEFixupVisitor(DWARFYAML::Data &DI) : DWARFYAML::Visitor(DI){};
|
||||
|
||||
protected:
|
||||
void onStartCompileUnit(DWARFYAML::Unit &CU) override {
|
||||
// Size of the unit header, excluding the length field itself.
|
||||
Length = CU.Version >= 5 ? 8 : 7;
|
||||
}
|
||||
|
||||
void onEndCompileUnit(DWARFYAML::Unit &CU) override { CU.Length = Length; }
|
||||
|
||||
void onStartDIE(DWARFYAML::Unit &CU, DWARFYAML::Entry &DIE) override {
|
||||
Length += getULEB128Size(DIE.AbbrCode);
|
||||
}
|
||||
|
||||
void onValue(const uint8_t U) override { Length += 1; }
|
||||
void onValue(const uint16_t U) override { Length += 2; }
|
||||
void onValue(const uint32_t U) override { Length += 4; }
|
||||
void onValue(const uint64_t U, const bool LEB = false) override {
|
||||
if (LEB)
|
||||
Length += getULEB128Size(U);
|
||||
else
|
||||
Length += 8;
|
||||
}
|
||||
void onValue(const int64_t S, const bool LEB = false) override {
|
||||
if (LEB)
|
||||
Length += getSLEB128Size(S);
|
||||
else
|
||||
Length += 8;
|
||||
}
|
||||
void onValue(const StringRef String) override { Length += String.size() + 1; }
|
||||
|
||||
void onValue(const MemoryBufferRef MBR) override {
|
||||
Length += MBR.getBufferSize();
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
|
||||
DWARFYAML::emitDebugSections(StringRef YAMLString, bool ApplyFixups,
|
||||
bool IsLittleEndian) {
|
||||
DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian) {
|
||||
auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {
|
||||
*static_cast<SMDiagnostic *>(DiagContext) = Diag;
|
||||
};
|
||||
|
@ -693,12 +764,6 @@ DWARFYAML::emitDebugSections(StringRef YAMLString, bool ApplyFixups,
|
|||
if (YIn.error())
|
||||
return createStringError(YIn.error(), GeneratedDiag.getMessage());
|
||||
|
||||
if (ApplyFixups) {
|
||||
DIEFixupVisitor DIFixer(DI);
|
||||
if (Error Err = DIFixer.traverseDebugInfo())
|
||||
return std::move(Err);
|
||||
}
|
||||
|
||||
StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
|
||||
Error Err = emitDebugSectionImpl(DI, &DWARFYAML::emitDebugInfo, "debug_info",
|
||||
DebugSections);
|
||||
|
|
|
@ -1,188 +0,0 @@
|
|||
//===--- 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/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/ObjectYAML/DWARFYAML.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/Error.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.Format == dwarf::DWARF64 ? 8 : 4;
|
||||
}
|
||||
|
||||
static unsigned getRefSize(const DWARFYAML::Unit &Unit) {
|
||||
if (Unit.Version == 2)
|
||||
return Unit.AddrSize;
|
||||
return getOffsetSize(Unit);
|
||||
}
|
||||
|
||||
template <typename T> Error DWARFYAML::VisitorImpl<T>::traverseDebugInfo() {
|
||||
for (auto &Unit : DebugInfo.CompileUnits) {
|
||||
onStartCompileUnit(Unit);
|
||||
|
||||
for (auto &Entry : Unit.Entries) {
|
||||
onStartDIE(Unit, Entry);
|
||||
uint32_t AbbrCode = Entry.AbbrCode;
|
||||
if (AbbrCode == 0 || Entry.Values.empty())
|
||||
continue;
|
||||
|
||||
if (AbbrCode > DebugInfo.AbbrevDecls.size())
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"abbrev code must be less than or equal to the number of "
|
||||
"entries in abbreviation table");
|
||||
const DWARFYAML::Abbrev &Abbrev = DebugInfo.AbbrevDecls[AbbrCode - 1];
|
||||
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_strx:
|
||||
case dwarf::DW_FORM_addrx:
|
||||
case dwarf::DW_FORM_rnglistx:
|
||||
case dwarf::DW_FORM_loclistx:
|
||||
case dwarf::DW_FORM_udata:
|
||||
case dwarf::DW_FORM_ref_udata:
|
||||
case dwarf::DW_FORM_GNU_addr_index:
|
||||
case dwarf::DW_FORM_GNU_str_index:
|
||||
onValue((uint64_t)FormVal->Value, /*LEB=*/true);
|
||||
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:
|
||||
case dwarf::DW_FORM_ref_sig8:
|
||||
onValue((uint64_t)FormVal->Value);
|
||||
break;
|
||||
case dwarf::DW_FORM_sdata:
|
||||
onValue((int64_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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (Indirect);
|
||||
}
|
||||
onEndDIE(Unit, Entry);
|
||||
}
|
||||
onEndCompileUnit(Unit);
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// Explicitly instantiate the two template expansions.
|
||||
template class DWARFYAML::VisitorImpl<DWARFYAML::Data>;
|
||||
template class DWARFYAML::VisitorImpl<const DWARFYAML::Data>;
|
|
@ -1,97 +0,0 @@
|
|||
//===--- DWARFVisitor.h -----------------------------------------*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_OBJECTYAML_DWARFVISITOR_H
|
||||
#define LLVM_OBJECTYAML_DWARFVISITOR_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
||||
namespace llvm {
|
||||
class Error;
|
||||
|
||||
namespace DWARFYAML {
|
||||
|
||||
struct Data;
|
||||
struct Unit;
|
||||
struct Entry;
|
||||
struct FormValue;
|
||||
struct AttributeAbbrev;
|
||||
|
||||
/// 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() {}
|
||||
|
||||
Error 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
|
|
@ -143,7 +143,7 @@ void MappingTraits<DWARFYAML::PubSection>::mapping(
|
|||
|
||||
void MappingTraits<DWARFYAML::Unit>::mapping(IO &IO, DWARFYAML::Unit &Unit) {
|
||||
IO.mapOptional("Format", Unit.Format, dwarf::DWARF32);
|
||||
IO.mapOptional("Length", Unit.Length, 0);
|
||||
IO.mapOptional("Length", Unit.Length);
|
||||
IO.mapRequired("Version", Unit.Version);
|
||||
if (Unit.Version >= 5)
|
||||
IO.mapRequired("UnitType", Unit.Type);
|
||||
|
|
|
@ -735,3 +735,110 @@ DWARF:
|
|||
AbbrOffset: 0x1234
|
||||
AddrSize: 8
|
||||
Entries: []
|
||||
|
||||
## k) Test that yaml2obj is able to emit a correct length for compilation units.
|
||||
|
||||
# RUN: yaml2obj --docnum=13 %s -o %t13.o
|
||||
# RUN: llvm-readelf --hex-dump=.debug_info %t13.o | \
|
||||
# RUN: FileCheck %s --check-prefix=INFER-LENGTH
|
||||
|
||||
# INFER-LENGTH: Hex dump of section '.debug_info':
|
||||
# INFER-LENGTH-NEXT: 0x00000000 37000000 04000000 00000801 00000000 7...............
|
||||
## ^------- unit_length (0x37)
|
||||
## ^--- version (2-byte)
|
||||
## ^-------- debug_abbrev_offset (4-byte)
|
||||
## ^- address_size (1-byte)
|
||||
## ^- abbrev code (ULEB128) 0x01
|
||||
## ^------- Form: DW_FORM_strp (4-byte)
|
||||
# INFER-LENGTH-NEXT: 0x00000010 0c001600 00000000 00001e00 00002011 .............. .
|
||||
## ^--- Form: DW_FORM_data2 (2-byte)
|
||||
## ^-------- Form: DW_FORM_strp (4-byte)
|
||||
## ^-------- Form: DW_FORM_sec_offset (4-byte)
|
||||
## ^-------- Form: DW_FORM_strp (4-byte)
|
||||
## ^--- Form: DW_FORM_addr (8-byte)
|
||||
# INFER-LENGTH-NEXT: 0x00000020 00000000 00003300 00000220 11000000 ......3.... ....
|
||||
## -------------
|
||||
## ^-------- Form: DW_FORM_data4 (4-byte)
|
||||
## ^- abbrev code (ULEB128) 0x02
|
||||
## ^---------- Form: DW_FORM_addr (8-byte)
|
||||
# INFER-LENGTH-NEXT: 0x00000030 00000006 00000038 000000 .......8...
|
||||
## ------
|
||||
## ^-------- Form: DW_FORM_data4 (4-byte)
|
||||
## ^-------- Form: DW_FORM_strp (4-byte)
|
||||
|
||||
## The handwritten DIEs should look like:
|
||||
|
||||
## 0x0000000b: DW_TAG_compile_unit [1] *
|
||||
## DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000000] = "clang version 10.0.0 ")
|
||||
## DW_AT_language [DW_FORM_data2] (DW_LANG_C99)
|
||||
## DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000016] = "hello.c")
|
||||
## DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000)
|
||||
## DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x0000001e] = "/home/v/x/llvm/playground")
|
||||
## DW_AT_low_pc [DW_FORM_addr] (0x0000000000001120)
|
||||
## DW_AT_high_pc [DW_FORM_data4] (0x00000033)
|
||||
##
|
||||
## 0x0000002a: DW_TAG_subprogram [2]
|
||||
## DW_AT_low_pc [DW_FORM_addr] (0x0000000000001120)
|
||||
## DW_AT_high_pc [DW_FORM_data4] (0x00000006)
|
||||
## DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000038] = "main")
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
DWARF:
|
||||
debug_str:
|
||||
- "clang version 10.0.0 "
|
||||
- "hello.c"
|
||||
- "/home/v/x/llvm/playground"
|
||||
- "main"
|
||||
debug_abbrev:
|
||||
- Code: 1
|
||||
Tag: DW_TAG_compile_unit
|
||||
Children: DW_CHILDREN_yes
|
||||
Attributes:
|
||||
- Attribute: DW_AT_producer
|
||||
Form: DW_FORM_strp
|
||||
- Attribute: DW_AT_language
|
||||
Form: DW_FORM_data2
|
||||
- Attribute: DW_AT_name
|
||||
Form: DW_FORM_strp
|
||||
- Attribute: DW_AT_stmt_list
|
||||
Form: DW_FORM_sec_offset
|
||||
- Attribute: DW_AT_comp_dir
|
||||
Form: DW_FORM_strp
|
||||
- Attribute: DW_AT_low_pc
|
||||
Form: DW_FORM_addr
|
||||
- Attribute: DW_AT_high_pc
|
||||
Form: DW_FORM_data4
|
||||
- Code: 2
|
||||
Tag: DW_TAG_subprogram
|
||||
Children: DW_CHILDREN_no
|
||||
Attributes:
|
||||
- Attribute: DW_AT_low_pc
|
||||
Form: DW_FORM_addr
|
||||
- Attribute: DW_AT_high_pc
|
||||
Form: DW_FORM_data4
|
||||
- Attribute: DW_AT_name
|
||||
Form: DW_FORM_strp
|
||||
debug_info:
|
||||
- Version: 4
|
||||
AbbrOffset: 0x00
|
||||
AddrSize: 0x08
|
||||
Entries:
|
||||
- AbbrCode: 1
|
||||
Values:
|
||||
- Value: 0x00 ## DW_AT_producer [DW_FORM_strp]
|
||||
- Value: 0x0c ## DW_LANG_C99, DW_AT_language [DW_FORM_data2]
|
||||
- Value: 0x16 ## DW_AT_name [DW_FORM_strp]
|
||||
- Value: 0x00 ## DW_AT_stmt_list [DW_FORM_sec_offset]
|
||||
- Value: 0x1e ## DW_AT_comp_dir [DW_FORM_strp]
|
||||
- Value: 0x1120 ## DW_AT_low_pc [DW_FORM_addr]
|
||||
- Value: 0x33 ## DW_AT_high_pc [DW_FORM_data4]
|
||||
- AbbrCode: 2
|
||||
Values:
|
||||
- Value: 0x1120 ## DW_AT_low_pc [DW_FORM_addr]
|
||||
- Value: 0x06 ## DW_AT_high_pc [DW_FORM_data4]
|
||||
- Value: 0x38 ## DW_AT_name [DW_FORM_strp]
|
||||
|
|
|
@ -1377,7 +1377,7 @@ TEST(DWARFDebugInfo, TestEmptyChildren) {
|
|||
" - AbbrCode: 0x00000000\n"
|
||||
" Values:\n";
|
||||
|
||||
auto ErrOrSections = DWARFYAML::emitDebugSections(StringRef(yamldata), true);
|
||||
auto ErrOrSections = DWARFYAML::emitDebugSections(StringRef(yamldata));
|
||||
ASSERT_TRUE((bool)ErrOrSections);
|
||||
std::unique_ptr<DWARFContext> DwarfContext =
|
||||
DWARFContext::create(*ErrOrSections, 8);
|
||||
|
|
|
@ -48,7 +48,7 @@ TEST(DWARFDie, getLocations) {
|
|||
- Value: 25
|
||||
)";
|
||||
Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
|
||||
DWARFYAML::emitDebugSections(StringRef(yamldata), /*ApplyFixups=*/true,
|
||||
DWARFYAML::emitDebugSections(StringRef(yamldata),
|
||||
/*IsLittleEndian=*/true);
|
||||
ASSERT_THAT_EXPECTED(Sections, Succeeded());
|
||||
std::vector<uint8_t> Loclists{
|
||||
|
|
Loading…
Reference in New Issue