Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -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 @@ SmallVector, 4> UncompressedSections; + StringRef *MapSectionToMember(StringRef Name); + public: DWARFContextInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr); + DWARFContextInMemory(const StringMap> &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; } Index: llvm/trunk/include/llvm/ObjectYAML/DWARFEmitter.h =================================================================== --- llvm/trunk/include/llvm/ObjectYAML/DWARFEmitter.h +++ llvm/trunk/include/llvm/ObjectYAML/DWARFEmitter.h @@ -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 +#include + namespace llvm { class raw_ostream; @@ -30,6 +38,10 @@ void EmitDebugInfo(llvm::raw_ostream &OS, const llvm::DWARFYAML::Data &DI); void EmitDebugLine(llvm::raw_ostream &OS, const llvm::DWARFYAML::Data &DI); +Expected>> +EmitDebugSections(StringRef YAMLString, + bool IsLittleEndian = sys::IsLittleEndianHost); + } // namespace DWARFYAML } // namespace llvm Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -617,40 +617,7 @@ name = name.substr( name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes. - StringRef *SectionData = - StringSwitch(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 StringMap> &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(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() { } Index: llvm/trunk/lib/ObjectYAML/DWARFEmitter.cpp =================================================================== --- llvm/trunk/lib/ObjectYAML/DWARFEmitter.cpp +++ llvm/trunk/lib/ObjectYAML/DWARFEmitter.cpp @@ -330,3 +330,42 @@ } } } + +typedef void (*EmitFuncType)(raw_ostream &, const DWARFYAML::Data &); + +void EmitDebugSectionImpl( + const DWARFYAML::Data &DI, EmitFuncType EmitFunc, StringRef Sec, + StringMap> &OutputBuffers) { + std::string Data; + raw_string_ostream DebugInfoStream(Data); + EmitFunc(DebugInfoStream, DI); + DebugInfoStream.flush(); + if (!Data.empty()) + OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data); +} + +Expected>> +DWARFYAML::EmitDebugSections(StringRef YAMLString, + bool IsLittleEndian) { + StringMap> 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); +} Index: llvm/trunk/unittests/DebugInfo/DWARF/CMakeLists.txt =================================================================== --- llvm/trunk/unittests/DebugInfo/DWARF/CMakeLists.txt +++ llvm/trunk/unittests/DebugInfo/DWARF/CMakeLists.txt @@ -4,6 +4,7 @@ DebugInfoDWARF MC Object + ObjectYAML Support ) Index: llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp =================================================================== --- llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -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 @@ 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());