diff options
Diffstat (limited to 'llvm/tools/yaml2obj/yaml2coff.cpp')
| -rw-r--r-- | llvm/tools/yaml2obj/yaml2coff.cpp | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/llvm/tools/yaml2obj/yaml2coff.cpp b/llvm/tools/yaml2obj/yaml2coff.cpp index 8f3f5217952..1f302fdc45a 100644 --- a/llvm/tools/yaml2obj/yaml2coff.cpp +++ b/llvm/tools/yaml2obj/yaml2coff.cpp @@ -17,6 +17,8 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" #include "llvm/Object/COFF.h" #include "llvm/ObjectYAML/ObjectYAML.h" #include "llvm/Support/Endian.h" @@ -142,6 +144,8 @@ struct COFFParser { COFFYAML::Object &Obj; + codeview::StringsAndChecksums StringsAndChecksums; + BumpPtrAllocator Allocator; StringMap<unsigned> StringTableMap; std::string StringTable; uint32_t SectionTableStart; @@ -165,6 +169,32 @@ namespace { enum { DOSStubSize = 128 }; } +static yaml::BinaryRef +toDebugS(ArrayRef<CodeViewYAML::YAMLDebugSubsection> Subsections, + const codeview::StringsAndChecksums &SC, BumpPtrAllocator &Allocator) { + using namespace codeview; + ExitOnError Err("Error occurred writing .debug$S section"); + auto CVSS = + Err(CodeViewYAML::toCodeViewSubsectionList(Allocator, Subsections, SC)); + + std::vector<DebugSubsectionRecordBuilder> Builders; + uint32_t Size = sizeof(uint32_t); + for (auto &SS : CVSS) { + DebugSubsectionRecordBuilder B(SS, CodeViewContainer::ObjectFile); + Size += B.calculateSerializedLength(); + Builders.push_back(std::move(B)); + } + uint8_t *Buffer = Allocator.Allocate<uint8_t>(Size); + MutableArrayRef<uint8_t> Output(Buffer, Size); + BinaryStreamWriter Writer(Output, support::little); + + Err(Writer.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC)); + for (const auto &B : Builders) { + Err(B.commit(Writer)); + } + return {Output}; +} + // Take a CP and assign addresses and sizes to everything. Returns false if the // layout is not valid to do. static bool layoutCOFF(COFFParser &CP) { @@ -179,8 +209,33 @@ static bool layoutCOFF(COFFParser &CP) { uint32_t CurrentSectionDataOffset = CP.SectionTableStart + CP.SectionTableSize; + for (COFFYAML::Section &S : CP.Obj.Sections) { + // We support specifying exactly one of SectionData or Subsections. So if + // there is already some SectionData, then we don't need to do any of this. + if (S.Name == ".debug$S" && S.SectionData.binary_size() == 0) { + CodeViewYAML::initializeStringsAndChecksums(S.DebugS, + CP.StringsAndChecksums); + if (CP.StringsAndChecksums.hasChecksums() && + CP.StringsAndChecksums.hasStrings()) + break; + } + } + // Assign each section data address consecutively. for (COFFYAML::Section &S : CP.Obj.Sections) { + if (S.Name == ".debug$S") { + if (S.SectionData.binary_size() == 0) { + assert(CP.StringsAndChecksums.hasStrings() && + "Object file does not have debug string table!"); + + S.SectionData = + toDebugS(S.DebugS, CP.StringsAndChecksums, CP.Allocator); + } + } else if (S.Name == ".debug$T") { + if (S.SectionData.binary_size() == 0) + S.SectionData = CodeViewYAML::toDebugT(S.DebugT, CP.Allocator); + } + if (S.SectionData.binary_size() > 0) { CurrentSectionDataOffset = alignTo(CurrentSectionDataOffset, CP.isPE() ? CP.getFileAlignment() : 4); @@ -543,6 +598,7 @@ int yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out) { errs() << "yaml2obj: Failed to layout optional header for COFF file!\n"; return 1; } + if (!layoutCOFF(CP)) { errs() << "yaml2obj: Failed to layout COFF file!\n"; return 1; |

