1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[DWARF] [ObjectYAML] Adding APIs for unittesting

Summary: This patch adds some new APIs to enable using the YAML DWARF representation in unit tests. The most basic new API is DWARFYAML::EmitDebugSections which converts a YAML string into a series of owned MemoryBuffer objects stored in a StringMap. The string map can then be used to construct a DWARFContext for parsing in place of an ObjectFile.

Reviewers: dblaikie, clayborg

Subscribers: mgorny, fhahn, jgosnell, aprantl, llvm-commits

Differential Revision: https://reviews.llvm.org/D28828

llvm-svn: 292634
This commit is contained in:
Chris Bieneman 2017-01-20 19:03:14 +00:00
parent 2e6ad7c3a0
commit 28f40b61a1
6 changed files with 131 additions and 64 deletions

View File

@ -15,6 +15,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
@ -293,10 +294,16 @@ class DWARFContextInMemory : public DWARFContext {
SmallVector<SmallString<32>, 4> UncompressedSections;
StringRef *MapSectionToMember(StringRef Name);
public:
DWARFContextInMemory(const object::ObjectFile &Obj,
const LoadedObjectInfo *L = nullptr);
DWARFContextInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
uint8_t AddrSize,
bool isLittleEndian = sys::IsLittleEndianHost);
bool isLittleEndian() const override { return IsLittleEndian; }
uint8_t getAddressSize() const override { return AddressSize; }
const DWARFSection &getInfoSection() override { return InfoSection; }

View File

@ -13,6 +13,14 @@
#ifndef LLVM_OBJECTYAML_DWARFEMITTER_H
#define LLVM_OBJECTYAML_DWARFEMITTER_H
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include <memory>
#include <vector>
namespace llvm {
class raw_ostream;
@ -30,6 +38,10 @@ void EmitPubSection(llvm::raw_ostream &OS,
void EmitDebugInfo(llvm::raw_ostream &OS, const llvm::DWARFYAML::Data &DI);
void EmitDebugLine(llvm::raw_ostream &OS, const llvm::DWARFYAML::Data &DI);
Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
EmitDebugSections(StringRef YAMLString,
bool IsLittleEndian = sys::IsLittleEndianHost);
} // namespace DWARFYAML
} // namespace llvm

View File

@ -617,40 +617,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
name = name.substr(
name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes.
StringRef *SectionData =
StringSwitch<StringRef *>(name)
.Case("debug_info", &InfoSection.Data)
.Case("debug_abbrev", &AbbrevSection)
.Case("debug_loc", &LocSection.Data)
.Case("debug_line", &LineSection.Data)
.Case("debug_aranges", &ARangeSection)
.Case("debug_frame", &DebugFrameSection)
.Case("eh_frame", &EHFrameSection)
.Case("debug_str", &StringSection)
.Case("debug_ranges", &RangeSection)
.Case("debug_macinfo", &MacinfoSection)
.Case("debug_pubnames", &PubNamesSection)
.Case("debug_pubtypes", &PubTypesSection)
.Case("debug_gnu_pubnames", &GnuPubNamesSection)
.Case("debug_gnu_pubtypes", &GnuPubTypesSection)
.Case("debug_info.dwo", &InfoDWOSection.Data)
.Case("debug_abbrev.dwo", &AbbrevDWOSection)
.Case("debug_loc.dwo", &LocDWOSection.Data)
.Case("debug_line.dwo", &LineDWOSection.Data)
.Case("debug_str.dwo", &StringDWOSection)
.Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
.Case("debug_addr", &AddrSection)
.Case("apple_names", &AppleNamesSection.Data)
.Case("apple_types", &AppleTypesSection.Data)
.Case("apple_namespaces", &AppleNamespacesSection.Data)
.Case("apple_namespac", &AppleNamespacesSection.Data)
.Case("apple_objc", &AppleObjCSection.Data)
.Case("debug_cu_index", &CUIndexSection)
.Case("debug_tu_index", &TUIndexSection)
.Case("gdb_index", &GdbIndexSection)
// Any more debug info sections go here.
.Default(nullptr);
if (SectionData) {
if (StringRef *SectionData = MapSectionToMember(name)) {
*SectionData = data;
if (name == "debug_ranges") {
// FIXME: Use the other dwo range section when we emit it.
@ -811,4 +778,49 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
}
}
DWARFContextInMemory::DWARFContextInMemory(
const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, uint8_t AddrSize,
bool isLittleEndian)
: IsLittleEndian(isLittleEndian), AddressSize(AddrSize) {
for (const auto &SecIt : Sections) {
if (StringRef *SectionData = MapSectionToMember(SecIt.first()))
*SectionData = SecIt.second->getBuffer();
}
}
StringRef *DWARFContextInMemory::MapSectionToMember(StringRef Name) {
return StringSwitch<StringRef *>(Name)
.Case("debug_info", &InfoSection.Data)
.Case("debug_abbrev", &AbbrevSection)
.Case("debug_loc", &LocSection.Data)
.Case("debug_line", &LineSection.Data)
.Case("debug_aranges", &ARangeSection)
.Case("debug_frame", &DebugFrameSection)
.Case("eh_frame", &EHFrameSection)
.Case("debug_str", &StringSection)
.Case("debug_ranges", &RangeSection)
.Case("debug_macinfo", &MacinfoSection)
.Case("debug_pubnames", &PubNamesSection)
.Case("debug_pubtypes", &PubTypesSection)
.Case("debug_gnu_pubnames", &GnuPubNamesSection)
.Case("debug_gnu_pubtypes", &GnuPubTypesSection)
.Case("debug_info.dwo", &InfoDWOSection.Data)
.Case("debug_abbrev.dwo", &AbbrevDWOSection)
.Case("debug_loc.dwo", &LocDWOSection.Data)
.Case("debug_line.dwo", &LineDWOSection.Data)
.Case("debug_str.dwo", &StringDWOSection)
.Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
.Case("debug_addr", &AddrSection)
.Case("apple_names", &AppleNamesSection.Data)
.Case("apple_types", &AppleTypesSection.Data)
.Case("apple_namespaces", &AppleNamespacesSection.Data)
.Case("apple_namespac", &AppleNamespacesSection.Data)
.Case("apple_objc", &AppleObjCSection.Data)
.Case("debug_cu_index", &CUIndexSection)
.Case("debug_tu_index", &TUIndexSection)
.Case("gdb_index", &GdbIndexSection)
// Any more debug info sections go here.
.Default(nullptr);
}
void DWARFContextInMemory::anchor() { }

View File

@ -330,3 +330,42 @@ void DWARFYAML::EmitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
}
}
}
typedef void (*EmitFuncType)(raw_ostream &, const DWARFYAML::Data &);
void EmitDebugSectionImpl(
const DWARFYAML::Data &DI, EmitFuncType EmitFunc, StringRef Sec,
StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
std::string Data;
raw_string_ostream DebugInfoStream(Data);
EmitFunc(DebugInfoStream, DI);
DebugInfoStream.flush();
if (!Data.empty())
OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);
}
Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
DWARFYAML::EmitDebugSections(StringRef YAMLString,
bool IsLittleEndian) {
StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
yaml::Input YIn(YAMLString);
DWARFYAML::Data DI;
DI.IsLittleEndian = IsLittleEndian;
YIn >> DI;
if (YIn.error())
return errorCodeToError(YIn.error());
EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugInfo, "debug_info",
DebugSections);
EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugLine, "debug_line",
DebugSections);
EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugStr, "debug_str",
DebugSections);
EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugAbbrev, "debug_abbrev",
DebugSections);
EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugAranges, "debug_aranges",
DebugSections);
return std::move(DebugSections);
}

View File

@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
DebugInfoDWARF
MC
Object
ObjectYAML
Support
)

View File

@ -13,6 +13,8 @@
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/ObjectYAML/DWARFYAML.h"
#include "llvm/ObjectYAML/DWARFEmitter.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetSelect.h"
@ -1157,41 +1159,35 @@ TEST(DWARFDebugInfo, TestChildIteratorsOnInvalidDie) {
EXPECT_EQ(begin, end);
}
TEST(DWARFDebugInfo, TestEmptyChildren) {
// Test a DIE that says it has children in the abbreviation, but actually
// doesn't have any attributes, will not return anything during iteration.
// We do this by making sure the begin and end iterators are equal.
uint16_t Version = 4;
const uint8_t AddrSize = sizeof(void *);
initLLVMIfNeeded();
Triple Triple = getHostTripleForAddrSize(AddrSize);
auto ExpectedDG = dwarfgen::Generator::create(Triple, Version);
if (HandleExpectedError(ExpectedDG))
return;
dwarfgen::Generator *DG = ExpectedDG.get().get();
dwarfgen::CompileUnit &CU = DG->addCompileUnit();
// Scope to allow us to re-use the same DIE names
{
// Create a compile unit DIE that has an abbreviation that says it has
// children, but doesn't have any actual attributes. This helps us test
// a DIE that has only one child: a NULL DIE.
auto CUDie = CU.getUnitDIE();
CUDie.setForceChildren();
}
MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
const char *yamldata = "debug_abbrev:\n"
" - Code: 0x00000001\n"
" Tag: DW_TAG_compile_unit\n"
" Children: DW_CHILDREN_yes\n"
" Attributes:\n"
"debug_info:\n"
" - Length: 9\n"
" Version: 4\n"
" AbbrOffset: 0\n"
" AddrSize: 8\n"
" Entries:\n"
" - AbbrCode: 0x00000001\n"
" Values:\n"
" - AbbrCode: 0x00000000\n"
" Values:\n";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
EXPECT_TRUE((bool)ErrOrSections);
auto &DebugSections = *ErrOrSections;
DWARFContextInMemory DwarfContext(DebugSections, 8);
// Verify the number of compile units is correct.
uint32_t NumCUs = DwarfContext.getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false);
EXPECT_TRUE(CUDie.isValid());