[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:
Xing GUO 2020-07-23 23:00:19 +08:00
parent a997e6edb9
commit 92874d2866
11 changed files with 296 additions and 410 deletions

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -6,7 +6,6 @@ add_llvm_component_library(LLVMObjectYAML
COFFEmitter.cpp
COFFYAML.cpp
DWARFEmitter.cpp
DWARFVisitor.cpp
DWARFYAML.cpp
ELFEmitter.cpp
ELFYAML.cpp

View File

@ -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);

View File

@ -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>;

View File

@ -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

View File

@ -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);

View File

@ -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]

View File

@ -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);

View File

@ -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{