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:
parent
2e6ad7c3a0
commit
28f40b61a1
@ -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; }
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() { }
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
|
||||
DebugInfoDWARF
|
||||
MC
|
||||
Object
|
||||
ObjectYAML
|
||||
Support
|
||||
)
|
||||
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user