123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785 |
- //===- yaml2xcoff - Convert YAML to a xcoff object file -------------------===//
- //
- // 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
- //
- //===----------------------------------------------------------------------===//
- ///
- /// \file
- /// The xcoff component of yaml2obj.
- ///
- //===----------------------------------------------------------------------===//
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/BinaryFormat/XCOFF.h"
- #include "llvm/MC/StringTableBuilder.h"
- #include "llvm/Object/XCOFFObjectFile.h"
- #include "llvm/ObjectYAML/ObjectYAML.h"
- #include "llvm/ObjectYAML/yaml2obj.h"
- #include "llvm/Support/EndianStream.h"
- #include "llvm/Support/LEB128.h"
- #include "llvm/Support/MemoryBuffer.h"
- #include "llvm/Support/raw_ostream.h"
- using namespace llvm;
- namespace {
- constexpr unsigned DefaultSectionAlign = 4;
- constexpr int16_t MaxSectionIndex = INT16_MAX;
- constexpr uint32_t MaxRawDataSize = UINT32_MAX;
- class XCOFFWriter {
- public:
- XCOFFWriter(XCOFFYAML::Object &Obj, raw_ostream &OS, yaml::ErrorHandler EH)
- : Obj(Obj), W(OS, support::big), ErrHandler(EH),
- StrTblBuilder(StringTableBuilder::XCOFF) {
- Is64Bit = Obj.Header.Magic == (llvm::yaml::Hex16)XCOFF::XCOFF64;
- }
- bool writeXCOFF();
- private:
- bool nameShouldBeInStringTable(StringRef SymbolName);
- bool initFileHeader(uint64_t CurrentOffset);
- void initAuxFileHeader();
- bool initSectionHeader(uint64_t &CurrentOffset);
- bool initRelocations(uint64_t &CurrentOffset);
- bool initStringTable();
- bool assignAddressesAndIndices();
- void writeFileHeader();
- void writeAuxFileHeader();
- void writeSectionHeader();
- bool writeSectionData();
- bool writeRelocations();
- bool writeSymbols();
- void writeStringTable();
- void writeAuxSymbol(const XCOFFYAML::CsectAuxEnt &AuxSym);
- void writeAuxSymbol(const XCOFFYAML::FileAuxEnt &AuxSym);
- void writeAuxSymbol(const XCOFFYAML::FunctionAuxEnt &AuxSym);
- void writeAuxSymbol(const XCOFFYAML::ExcpetionAuxEnt &AuxSym);
- void writeAuxSymbol(const XCOFFYAML::BlockAuxEnt &AuxSym);
- void writeAuxSymbol(const XCOFFYAML::SectAuxEntForDWARF &AuxSym);
- void writeAuxSymbol(const XCOFFYAML::SectAuxEntForStat &AuxSym);
- void writeAuxSymbol(const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym);
- XCOFFYAML::Object &Obj;
- bool Is64Bit = false;
- support::endian::Writer W;
- yaml::ErrorHandler ErrHandler;
- StringTableBuilder StrTblBuilder;
- uint64_t StartOffset;
- // Map the section name to its corrresponding section index.
- DenseMap<StringRef, int16_t> SectionIndexMap = {
- {StringRef("N_DEBUG"), XCOFF::N_DEBUG},
- {StringRef("N_ABS"), XCOFF::N_ABS},
- {StringRef("N_UNDEF"), XCOFF::N_UNDEF}};
- XCOFFYAML::FileHeader InitFileHdr = Obj.Header;
- XCOFFYAML::AuxiliaryHeader InitAuxFileHdr;
- std::vector<XCOFFYAML::Section> InitSections = Obj.Sections;
- };
- static void writeName(StringRef StrName, support::endian::Writer W) {
- char Name[XCOFF::NameSize];
- memset(Name, 0, XCOFF::NameSize);
- char SrcName[] = "";
- memcpy(Name, StrName.size() ? StrName.data() : SrcName, StrName.size());
- ArrayRef<char> NameRef(Name, XCOFF::NameSize);
- W.write(NameRef);
- }
- bool XCOFFWriter::nameShouldBeInStringTable(StringRef SymbolName) {
- // For XCOFF64: The symbol name is always in the string table.
- return (SymbolName.size() > XCOFF::NameSize) || Is64Bit;
- }
- bool XCOFFWriter::initRelocations(uint64_t &CurrentOffset) {
- for (XCOFFYAML::Section &InitSection : InitSections) {
- if (!InitSection.Relocations.empty()) {
- InitSection.NumberOfRelocations = InitSection.Relocations.size();
- InitSection.FileOffsetToRelocations = CurrentOffset;
- uint64_t RelSize = Is64Bit ? XCOFF::RelocationSerializationSize64
- : XCOFF::RelocationSerializationSize32;
- CurrentOffset += InitSection.NumberOfRelocations * RelSize;
- if (CurrentOffset > MaxRawDataSize) {
- ErrHandler("maximum object size of" + Twine(MaxRawDataSize) +
- "exceeded when writing relocation data");
- return false;
- }
- }
- }
- return true;
- }
- bool XCOFFWriter::initSectionHeader(uint64_t &CurrentOffset) {
- uint64_t CurrentSecAddr = 0;
- for (uint16_t I = 0, E = InitSections.size(); I < E; ++I) {
- if (CurrentOffset > MaxRawDataSize) {
- ErrHandler("maximum object size of" + Twine(MaxRawDataSize) +
- "exceeded when writing section data");
- return false;
- }
- // Assign indices for sections.
- if (InitSections[I].SectionName.size() &&
- !SectionIndexMap[InitSections[I].SectionName]) {
- // The section index starts from 1.
- SectionIndexMap[InitSections[I].SectionName] = I + 1;
- if ((I + 1) > MaxSectionIndex) {
- ErrHandler("exceeded the maximum permitted section index of " +
- Twine(MaxSectionIndex));
- return false;
- }
- }
- // Calculate the physical/virtual address. This field should contain 0 for
- // all sections except the text, data and bss sections.
- if (InitSections[I].Flags != XCOFF::STYP_TEXT &&
- InitSections[I].Flags != XCOFF::STYP_DATA &&
- InitSections[I].Flags != XCOFF::STYP_BSS)
- InitSections[I].Address = 0;
- else
- InitSections[I].Address = CurrentSecAddr;
- // Calculate the FileOffsetToData and data size for sections.
- if (InitSections[I].SectionData.binary_size()) {
- InitSections[I].FileOffsetToData = CurrentOffset;
- CurrentOffset += InitSections[I].SectionData.binary_size();
- // Ensure the offset is aligned to DefaultSectionAlign.
- CurrentOffset = alignTo(CurrentOffset, DefaultSectionAlign);
- InitSections[I].Size = CurrentOffset - InitSections[I].FileOffsetToData;
- CurrentSecAddr += InitSections[I].Size;
- }
- }
- return initRelocations(CurrentOffset);
- }
- bool XCOFFWriter::initStringTable() {
- if (Obj.StrTbl.RawContent) {
- size_t RawSize = Obj.StrTbl.RawContent->binary_size();
- if (Obj.StrTbl.Strings || Obj.StrTbl.Length) {
- ErrHandler(
- "can't specify Strings or Length when RawContent is specified");
- return false;
- }
- if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize < RawSize) {
- ErrHandler("specified ContentSize (" + Twine(*Obj.StrTbl.ContentSize) +
- ") is less than the RawContent data size (" + Twine(RawSize) +
- ")");
- return false;
- }
- return true;
- }
- if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize <= 3) {
- ErrHandler("ContentSize shouldn't be less than 4 without RawContent");
- return false;
- }
- // Build the string table.
- StrTblBuilder.clear();
- if (Obj.StrTbl.Strings) {
- // All specified strings should be added to the string table.
- for (StringRef StringEnt : *Obj.StrTbl.Strings)
- StrTblBuilder.add(StringEnt);
- size_t StrTblIdx = 0;
- size_t NumOfStrings = Obj.StrTbl.Strings->size();
- for (XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
- if (nameShouldBeInStringTable(YamlSym.SymbolName)) {
- if (StrTblIdx < NumOfStrings) {
- // Overwrite the symbol name with the specified string.
- YamlSym.SymbolName = (*Obj.StrTbl.Strings)[StrTblIdx];
- ++StrTblIdx;
- } else
- // Names that are not overwritten are still stored in the string
- // table.
- StrTblBuilder.add(YamlSym.SymbolName);
- }
- }
- } else {
- for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
- if (nameShouldBeInStringTable(YamlSym.SymbolName))
- StrTblBuilder.add(YamlSym.SymbolName);
- }
- }
- // Check if the file name in the File Auxiliary Entry should be added to the
- // string table.
- for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
- for (const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym :
- YamlSym.AuxEntries) {
- if (auto AS = dyn_cast<XCOFFYAML::FileAuxEnt>(AuxSym.get()))
- if (nameShouldBeInStringTable(AS->FileNameOrString.getValueOr("")))
- StrTblBuilder.add(AS->FileNameOrString.getValueOr(""));
- }
- }
- StrTblBuilder.finalize();
- size_t StrTblSize = StrTblBuilder.getSize();
- if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize < StrTblSize) {
- ErrHandler("specified ContentSize (" + Twine(*Obj.StrTbl.ContentSize) +
- ") is less than the size of the data that would otherwise be "
- "written (" +
- Twine(StrTblSize) + ")");
- return false;
- }
- return true;
- }
- bool XCOFFWriter::initFileHeader(uint64_t CurrentOffset) {
- // The default format of the object file is XCOFF32.
- InitFileHdr.Magic = XCOFF::XCOFF32;
- InitFileHdr.NumberOfSections = Obj.Sections.size();
- InitFileHdr.NumberOfSymTableEntries = Obj.Symbols.size();
- for (XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
- uint32_t AuxCount = YamlSym.AuxEntries.size();
- if (YamlSym.NumberOfAuxEntries && *YamlSym.NumberOfAuxEntries < AuxCount) {
- ErrHandler("specified NumberOfAuxEntries " +
- Twine(static_cast<uint32_t>(*YamlSym.NumberOfAuxEntries)) +
- " is less than the actual number "
- "of auxiliary entries " +
- Twine(AuxCount));
- return false;
- }
- YamlSym.NumberOfAuxEntries =
- YamlSym.NumberOfAuxEntries.getValueOr(AuxCount);
- // Add the number of auxiliary symbols to the total number.
- InitFileHdr.NumberOfSymTableEntries += *YamlSym.NumberOfAuxEntries;
- }
- // Calculate SymbolTableOffset for the file header.
- if (InitFileHdr.NumberOfSymTableEntries) {
- InitFileHdr.SymbolTableOffset = CurrentOffset;
- CurrentOffset +=
- InitFileHdr.NumberOfSymTableEntries * XCOFF::SymbolTableEntrySize;
- if (CurrentOffset > MaxRawDataSize) {
- ErrHandler("maximum object size of" + Twine(MaxRawDataSize) +
- "exceeded when writing symbols");
- return false;
- }
- }
- // TODO: Calculate FileOffsetToLineNumbers when line number supported.
- return true;
- }
- void XCOFFWriter::initAuxFileHeader() {
- InitAuxFileHdr = *Obj.AuxHeader;
- // In general, an object file might contain multiple sections of a given type,
- // but in a loadable module, there must be exactly one .text, .data, .bss, and
- // .loader section. A loadable object might also have one .tdata section and
- // one .tbss section.
- // Set these section-related values if not set explicitly. We assume that the
- // input YAML matches the format of the loadable object, but if multiple input
- // sections still have the same type, the first section with that type
- // prevails.
- for (uint16_t I = 0, E = InitSections.size(); I < E; ++I) {
- switch (InitSections[I].Flags) {
- case XCOFF::STYP_TEXT:
- if (!InitAuxFileHdr.TextSize)
- InitAuxFileHdr.TextSize = InitSections[I].Size;
- if (!InitAuxFileHdr.TextStartAddr)
- InitAuxFileHdr.TextStartAddr = InitSections[I].Address;
- if (!InitAuxFileHdr.SecNumOfText)
- InitAuxFileHdr.SecNumOfText = I + 1;
- break;
- case XCOFF::STYP_DATA:
- if (!InitAuxFileHdr.InitDataSize)
- InitAuxFileHdr.InitDataSize = InitSections[I].Size;
- if (!InitAuxFileHdr.DataStartAddr)
- InitAuxFileHdr.DataStartAddr = InitSections[I].Address;
- if (!InitAuxFileHdr.SecNumOfData)
- InitAuxFileHdr.SecNumOfData = I + 1;
- break;
- case XCOFF::STYP_BSS:
- if (!InitAuxFileHdr.BssDataSize)
- InitAuxFileHdr.BssDataSize = InitSections[I].Size;
- if (!InitAuxFileHdr.SecNumOfBSS)
- InitAuxFileHdr.SecNumOfBSS = I + 1;
- break;
- case XCOFF::STYP_TDATA:
- if (!InitAuxFileHdr.SecNumOfTData)
- InitAuxFileHdr.SecNumOfTData = I + 1;
- break;
- case XCOFF::STYP_TBSS:
- if (!InitAuxFileHdr.SecNumOfTBSS)
- InitAuxFileHdr.SecNumOfTBSS = I + 1;
- break;
- case XCOFF::STYP_LOADER:
- if (!InitAuxFileHdr.SecNumOfLoader)
- InitAuxFileHdr.SecNumOfLoader = I + 1;
- break;
- default:
- break;
- }
- }
- }
- bool XCOFFWriter::assignAddressesAndIndices() {
- uint64_t FileHdrSize =
- Is64Bit ? XCOFF::FileHeaderSize64 : XCOFF::FileHeaderSize32;
- uint64_t AuxFileHdrSize = 0;
- if (Obj.AuxHeader)
- AuxFileHdrSize = Obj.Header.AuxHeaderSize
- ? Obj.Header.AuxHeaderSize
- : (Is64Bit ? XCOFF::AuxFileHeaderSize64
- : XCOFF::AuxFileHeaderSize32);
- uint64_t SecHdrSize =
- Is64Bit ? XCOFF::SectionHeaderSize64 : XCOFF::SectionHeaderSize32;
- uint64_t CurrentOffset =
- FileHdrSize + AuxFileHdrSize + InitSections.size() * SecHdrSize;
- // Calculate section header info.
- if (!initSectionHeader(CurrentOffset))
- return false;
- InitFileHdr.AuxHeaderSize = AuxFileHdrSize;
- // Calculate file header info.
- if (!initFileHeader(CurrentOffset))
- return false;
- // Initialize the auxiliary file header.
- if (Obj.AuxHeader)
- initAuxFileHeader();
- // Initialize the string table.
- return initStringTable();
- }
- void XCOFFWriter::writeFileHeader() {
- W.write<uint16_t>(Obj.Header.Magic ? Obj.Header.Magic : InitFileHdr.Magic);
- W.write<uint16_t>(Obj.Header.NumberOfSections ? Obj.Header.NumberOfSections
- : InitFileHdr.NumberOfSections);
- W.write<int32_t>(Obj.Header.TimeStamp);
- if (Is64Bit) {
- W.write<uint64_t>(Obj.Header.SymbolTableOffset
- ? Obj.Header.SymbolTableOffset
- : InitFileHdr.SymbolTableOffset);
- W.write<uint16_t>(InitFileHdr.AuxHeaderSize);
- W.write<uint16_t>(Obj.Header.Flags);
- W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
- ? Obj.Header.NumberOfSymTableEntries
- : InitFileHdr.NumberOfSymTableEntries);
- } else {
- W.write<uint32_t>(Obj.Header.SymbolTableOffset
- ? Obj.Header.SymbolTableOffset
- : InitFileHdr.SymbolTableOffset);
- W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
- ? Obj.Header.NumberOfSymTableEntries
- : InitFileHdr.NumberOfSymTableEntries);
- W.write<uint16_t>(InitFileHdr.AuxHeaderSize);
- W.write<uint16_t>(Obj.Header.Flags);
- }
- }
- void XCOFFWriter::writeAuxFileHeader() {
- W.write<uint16_t>(InitAuxFileHdr.Magic.getValueOr(yaml::Hex16(1)));
- W.write<uint16_t>(InitAuxFileHdr.Version.getValueOr(yaml::Hex16(1)));
- if (Is64Bit) {
- W.OS.write_zeros(4); // Reserved for debugger.
- W.write<uint64_t>(InitAuxFileHdr.TextStartAddr.getValueOr(yaml::Hex64(0)));
- W.write<uint64_t>(InitAuxFileHdr.DataStartAddr.getValueOr(yaml::Hex64(0)));
- W.write<uint64_t>(InitAuxFileHdr.TOCAnchorAddr.getValueOr(yaml::Hex64(0)));
- } else {
- W.write<uint32_t>(InitAuxFileHdr.TextSize.getValueOr(yaml::Hex64(0)));
- W.write<uint32_t>(InitAuxFileHdr.InitDataSize.getValueOr(yaml::Hex64(0)));
- W.write<uint32_t>(InitAuxFileHdr.BssDataSize.getValueOr(yaml::Hex64(0)));
- W.write<uint32_t>(InitAuxFileHdr.EntryPointAddr.getValueOr(yaml::Hex64(0)));
- W.write<uint32_t>(InitAuxFileHdr.TextStartAddr.getValueOr(yaml::Hex64(0)));
- W.write<uint32_t>(InitAuxFileHdr.DataStartAddr.getValueOr(yaml::Hex64(0)));
- W.write<uint32_t>(InitAuxFileHdr.TOCAnchorAddr.getValueOr(yaml::Hex64(0)));
- }
- W.write<uint16_t>(InitAuxFileHdr.SecNumOfEntryPoint.getValueOr(0));
- W.write<uint16_t>(InitAuxFileHdr.SecNumOfText.getValueOr(0));
- W.write<uint16_t>(InitAuxFileHdr.SecNumOfData.getValueOr(0));
- W.write<uint16_t>(InitAuxFileHdr.SecNumOfTOC.getValueOr(0));
- W.write<uint16_t>(InitAuxFileHdr.SecNumOfLoader.getValueOr(0));
- W.write<uint16_t>(InitAuxFileHdr.SecNumOfBSS.getValueOr(0));
- W.write<uint16_t>(InitAuxFileHdr.MaxAlignOfText.getValueOr(yaml::Hex16(0)));
- W.write<uint16_t>(InitAuxFileHdr.MaxAlignOfData.getValueOr(yaml::Hex16(0)));
- W.write<uint16_t>(InitAuxFileHdr.ModuleType.getValueOr(yaml::Hex16(0)));
- W.write<uint8_t>(InitAuxFileHdr.CpuFlag.getValueOr(yaml::Hex8(0)));
- W.write<uint8_t>(0); // Reserved for CPU type.
- if (Is64Bit) {
- W.write<uint8_t>(InitAuxFileHdr.TextPageSize.getValueOr(yaml::Hex8(0)));
- W.write<uint8_t>(InitAuxFileHdr.DataPageSize.getValueOr(yaml::Hex8(0)));
- W.write<uint8_t>(InitAuxFileHdr.StackPageSize.getValueOr(yaml::Hex8(0)));
- W.write<uint8_t>(
- InitAuxFileHdr.FlagAndTDataAlignment.getValueOr(yaml::Hex8(0x80)));
- W.write<uint64_t>(InitAuxFileHdr.TextSize.getValueOr(yaml::Hex64(0)));
- W.write<uint64_t>(InitAuxFileHdr.InitDataSize.getValueOr(yaml::Hex64(0)));
- W.write<uint64_t>(InitAuxFileHdr.BssDataSize.getValueOr(yaml::Hex64(0)));
- W.write<uint64_t>(InitAuxFileHdr.EntryPointAddr.getValueOr(yaml::Hex64(0)));
- W.write<uint64_t>(InitAuxFileHdr.MaxStackSize.getValueOr(yaml::Hex64(0)));
- W.write<uint64_t>(InitAuxFileHdr.MaxDataSize.getValueOr(yaml::Hex64(0)));
- } else {
- W.write<uint32_t>(InitAuxFileHdr.MaxStackSize.getValueOr(yaml::Hex64(0)));
- W.write<uint32_t>(InitAuxFileHdr.MaxDataSize.getValueOr(yaml::Hex64(0)));
- W.OS.write_zeros(4); // Reserved for debugger.
- W.write<uint8_t>(InitAuxFileHdr.TextPageSize.getValueOr(yaml::Hex8(0)));
- W.write<uint8_t>(InitAuxFileHdr.DataPageSize.getValueOr(yaml::Hex8(0)));
- W.write<uint8_t>(InitAuxFileHdr.StackPageSize.getValueOr(yaml::Hex8(0)));
- W.write<uint8_t>(
- InitAuxFileHdr.FlagAndTDataAlignment.getValueOr(yaml::Hex8(0)));
- }
- W.write<uint16_t>(InitAuxFileHdr.SecNumOfTData.getValueOr(0));
- W.write<uint16_t>(InitAuxFileHdr.SecNumOfTBSS.getValueOr(0));
- if (Is64Bit) {
- W.write<uint16_t>(InitAuxFileHdr.Flag.getValueOr(yaml::Hex16(XCOFF::SHR_SYMTAB)));
- if (InitFileHdr.AuxHeaderSize > XCOFF::AuxFileHeaderSize64)
- W.OS.write_zeros(InitFileHdr.AuxHeaderSize - XCOFF::AuxFileHeaderSize64);
- } else if (InitFileHdr.AuxHeaderSize > XCOFF::AuxFileHeaderSize32) {
- W.OS.write_zeros(InitFileHdr.AuxHeaderSize - XCOFF::AuxFileHeaderSize32);
- }
- }
- void XCOFFWriter::writeSectionHeader() {
- for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
- XCOFFYAML::Section YamlSec = Obj.Sections[I];
- XCOFFYAML::Section DerivedSec = InitSections[I];
- writeName(YamlSec.SectionName, W);
- // Virtual address is the same as physical address.
- uint64_t SectionAddress =
- YamlSec.Address ? YamlSec.Address : DerivedSec.Address;
- if (Is64Bit) {
- W.write<uint64_t>(SectionAddress); // Physical address
- W.write<uint64_t>(SectionAddress); // Virtual address
- W.write<uint64_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
- W.write<uint64_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
- : DerivedSec.FileOffsetToData);
- W.write<uint64_t>(YamlSec.FileOffsetToRelocations
- ? YamlSec.FileOffsetToRelocations
- : DerivedSec.FileOffsetToRelocations);
- W.write<uint64_t>(YamlSec.FileOffsetToLineNumbers);
- W.write<uint32_t>(YamlSec.NumberOfRelocations
- ? YamlSec.NumberOfRelocations
- : DerivedSec.NumberOfRelocations);
- W.write<uint32_t>(YamlSec.NumberOfLineNumbers);
- W.write<int32_t>(YamlSec.Flags);
- W.OS.write_zeros(4);
- } else {
- W.write<uint32_t>(SectionAddress); // Physical address
- W.write<uint32_t>(SectionAddress); // Virtual address
- W.write<uint32_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
- W.write<uint32_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
- : DerivedSec.FileOffsetToData);
- W.write<uint32_t>(YamlSec.FileOffsetToRelocations
- ? YamlSec.FileOffsetToRelocations
- : DerivedSec.FileOffsetToRelocations);
- W.write<uint32_t>(YamlSec.FileOffsetToLineNumbers);
- W.write<uint16_t>(YamlSec.NumberOfRelocations
- ? YamlSec.NumberOfRelocations
- : DerivedSec.NumberOfRelocations);
- W.write<uint16_t>(YamlSec.NumberOfLineNumbers);
- W.write<int32_t>(YamlSec.Flags);
- }
- }
- }
- bool XCOFFWriter::writeSectionData() {
- for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
- XCOFFYAML::Section YamlSec = Obj.Sections[I];
- if (YamlSec.SectionData.binary_size()) {
- // Fill the padding size with zeros.
- int64_t PaddingSize =
- InitSections[I].FileOffsetToData - (W.OS.tell() - StartOffset);
- if (PaddingSize < 0) {
- ErrHandler("redundant data was written before section data");
- return false;
- }
- W.OS.write_zeros(PaddingSize);
- YamlSec.SectionData.writeAsBinary(W.OS);
- }
- }
- return true;
- }
- bool XCOFFWriter::writeRelocations() {
- for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
- XCOFFYAML::Section YamlSec = Obj.Sections[I];
- if (!YamlSec.Relocations.empty()) {
- int64_t PaddingSize =
- InitSections[I].FileOffsetToRelocations - (W.OS.tell() - StartOffset);
- if (PaddingSize < 0) {
- ErrHandler("redundant data was written before relocations");
- return false;
- }
- W.OS.write_zeros(PaddingSize);
- for (const XCOFFYAML::Relocation &YamlRel : YamlSec.Relocations) {
- if (Is64Bit)
- W.write<uint64_t>(YamlRel.VirtualAddress);
- else
- W.write<uint32_t>(YamlRel.VirtualAddress);
- W.write<uint32_t>(YamlRel.SymbolIndex);
- W.write<uint8_t>(YamlRel.Info);
- W.write<uint8_t>(YamlRel.Type);
- }
- }
- }
- return true;
- }
- void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::CsectAuxEnt &AuxSym) {
- if (Is64Bit) {
- W.write<uint32_t>(AuxSym.SectionOrLengthLo.getValueOr(0));
- W.write<uint32_t>(AuxSym.ParameterHashIndex.getValueOr(0));
- W.write<uint16_t>(AuxSym.TypeChkSectNum.getValueOr(0));
- W.write<uint8_t>(AuxSym.SymbolAlignmentAndType.getValueOr(0));
- W.write<uint8_t>(AuxSym.StorageMappingClass.getValueOr(XCOFF::XMC_PR));
- W.write<uint32_t>(AuxSym.SectionOrLengthHi.getValueOr(0));
- W.write<uint8_t>(0);
- W.write<uint8_t>(XCOFF::AUX_CSECT);
- } else {
- W.write<uint32_t>(AuxSym.SectionOrLength.getValueOr(0));
- W.write<uint32_t>(AuxSym.ParameterHashIndex.getValueOr(0));
- W.write<uint16_t>(AuxSym.TypeChkSectNum.getValueOr(0));
- W.write<uint8_t>(AuxSym.SymbolAlignmentAndType.getValueOr(0));
- W.write<uint8_t>(AuxSym.StorageMappingClass.getValueOr(XCOFF::XMC_PR));
- W.write<uint32_t>(AuxSym.StabInfoIndex.getValueOr(0));
- W.write<uint16_t>(AuxSym.StabSectNum.getValueOr(0));
- }
- }
- void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::ExcpetionAuxEnt &AuxSym) {
- assert(Is64Bit && "can't write the exception auxiliary symbol for XCOFF32");
- W.write<uint64_t>(AuxSym.OffsetToExceptionTbl.getValueOr(0));
- W.write<uint32_t>(AuxSym.SizeOfFunction.getValueOr(0));
- W.write<uint32_t>(AuxSym.SymIdxOfNextBeyond.getValueOr(0));
- W.write<uint8_t>(0);
- W.write<uint8_t>(XCOFF::AUX_EXCEPT);
- }
- void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::FunctionAuxEnt &AuxSym) {
- if (Is64Bit) {
- W.write<uint64_t>(AuxSym.PtrToLineNum.getValueOr(0));
- W.write<uint32_t>(AuxSym.SizeOfFunction.getValueOr(0));
- W.write<uint32_t>(AuxSym.SymIdxOfNextBeyond.getValueOr(0));
- W.write<uint8_t>(0);
- W.write<uint8_t>(XCOFF::AUX_FCN);
- } else {
- W.write<uint32_t>(AuxSym.OffsetToExceptionTbl.getValueOr(0));
- W.write<uint32_t>(AuxSym.SizeOfFunction.getValueOr(0));
- W.write<uint32_t>(AuxSym.PtrToLineNum.getValueOr(0));
- W.write<uint32_t>(AuxSym.SymIdxOfNextBeyond.getValueOr(0));
- W.OS.write_zeros(2);
- }
- }
- void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::FileAuxEnt &AuxSym) {
- StringRef FileName = AuxSym.FileNameOrString.getValueOr("");
- if (nameShouldBeInStringTable(FileName)) {
- W.write<int32_t>(0);
- W.write<uint32_t>(StrTblBuilder.getOffset(FileName));
- } else {
- writeName(FileName, W);
- }
- W.OS.write_zeros(XCOFF::FileNamePadSize);
- W.write<uint8_t>(AuxSym.FileStringType.getValueOr(XCOFF::XFT_FN));
- if (Is64Bit) {
- W.OS.write_zeros(2);
- W.write<uint8_t>(XCOFF::AUX_FILE);
- } else {
- W.OS.write_zeros(3);
- }
- }
- void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::BlockAuxEnt &AuxSym) {
- if (Is64Bit) {
- W.write<uint32_t>(AuxSym.LineNum.getValueOr(0));
- W.OS.write_zeros(13);
- W.write<uint8_t>(XCOFF::AUX_SYM);
- } else {
- W.OS.write_zeros(2);
- W.write<uint16_t>(AuxSym.LineNumHi.getValueOr(0));
- W.write<uint16_t>(AuxSym.LineNumLo.getValueOr(0));
- W.OS.write_zeros(12);
- }
- }
- void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::SectAuxEntForDWARF &AuxSym) {
- if (Is64Bit) {
- W.write<uint64_t>(AuxSym.LengthOfSectionPortion.getValueOr(0));
- W.write<uint64_t>(AuxSym.NumberOfRelocEnt.getValueOr(0));
- W.write<uint8_t>(0);
- W.write<uint8_t>(XCOFF::AUX_SECT);
- } else {
- W.write<uint32_t>(AuxSym.LengthOfSectionPortion.getValueOr(0));
- W.OS.write_zeros(4);
- W.write<uint32_t>(AuxSym.NumberOfRelocEnt.getValueOr(0));
- W.OS.write_zeros(6);
- }
- }
- void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::SectAuxEntForStat &AuxSym) {
- assert(!Is64Bit && "can't write the stat auxiliary symbol for XCOFF64");
- W.write<uint32_t>(AuxSym.SectionLength.getValueOr(0));
- W.write<uint16_t>(AuxSym.NumberOfRelocEnt.getValueOr(0));
- W.write<uint16_t>(AuxSym.NumberOfLineNum.getValueOr(0));
- W.OS.write_zeros(10);
- }
- void XCOFFWriter::writeAuxSymbol(
- const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym) {
- if (auto AS = dyn_cast<XCOFFYAML::CsectAuxEnt>(AuxSym.get()))
- writeAuxSymbol(*AS);
- else if (auto AS = dyn_cast<XCOFFYAML::FunctionAuxEnt>(AuxSym.get()))
- writeAuxSymbol(*AS);
- else if (auto AS = dyn_cast<XCOFFYAML::ExcpetionAuxEnt>(AuxSym.get()))
- writeAuxSymbol(*AS);
- else if (auto AS = dyn_cast<XCOFFYAML::FileAuxEnt>(AuxSym.get()))
- writeAuxSymbol(*AS);
- else if (auto AS = dyn_cast<XCOFFYAML::BlockAuxEnt>(AuxSym.get()))
- writeAuxSymbol(*AS);
- else if (auto AS = dyn_cast<XCOFFYAML::SectAuxEntForDWARF>(AuxSym.get()))
- writeAuxSymbol(*AS);
- else if (auto AS = dyn_cast<XCOFFYAML::SectAuxEntForStat>(AuxSym.get()))
- writeAuxSymbol(*AS);
- else
- llvm_unreachable("unknown auxiliary symbol type");
- }
- bool XCOFFWriter::writeSymbols() {
- int64_t PaddingSize =
- (uint64_t)InitFileHdr.SymbolTableOffset - (W.OS.tell() - StartOffset);
- if (PaddingSize < 0) {
- ErrHandler("redundant data was written before symbols");
- return false;
- }
- W.OS.write_zeros(PaddingSize);
- for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
- if (Is64Bit) {
- W.write<uint64_t>(YamlSym.Value);
- W.write<uint32_t>(StrTblBuilder.getOffset(YamlSym.SymbolName));
- } else {
- if (nameShouldBeInStringTable(YamlSym.SymbolName)) {
- // For XCOFF32: A value of 0 indicates that the symbol name is in the
- // string table.
- W.write<int32_t>(0);
- W.write<uint32_t>(StrTblBuilder.getOffset(YamlSym.SymbolName));
- } else {
- writeName(YamlSym.SymbolName, W);
- }
- W.write<uint32_t>(YamlSym.Value);
- }
- if (YamlSym.SectionName) {
- if (!SectionIndexMap.count(*YamlSym.SectionName)) {
- ErrHandler("the SectionName " + *YamlSym.SectionName +
- " specified in the symbol does not exist");
- return false;
- }
- if (YamlSym.SectionIndex &&
- SectionIndexMap[*YamlSym.SectionName] != *YamlSym.SectionIndex) {
- ErrHandler("the SectionName " + *YamlSym.SectionName +
- " and the SectionIndex (" + Twine(*YamlSym.SectionIndex) +
- ") refer to different sections");
- return false;
- }
- W.write<int16_t>(SectionIndexMap[*YamlSym.SectionName]);
- } else {
- W.write<int16_t>(YamlSym.SectionIndex ? *YamlSym.SectionIndex : 0);
- }
- W.write<uint16_t>(YamlSym.Type);
- W.write<uint8_t>(YamlSym.StorageClass);
- uint8_t NumOfAuxSym = YamlSym.NumberOfAuxEntries.getValueOr(0);
- W.write<uint8_t>(NumOfAuxSym);
- if (!NumOfAuxSym && !YamlSym.AuxEntries.size())
- continue;
- // Now write auxiliary entries.
- if (!YamlSym.AuxEntries.size()) {
- W.OS.write_zeros(XCOFF::SymbolTableEntrySize * NumOfAuxSym);
- } else {
- for (const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym :
- YamlSym.AuxEntries) {
- writeAuxSymbol(AuxSym);
- }
- // Pad with zeros.
- if (NumOfAuxSym > YamlSym.AuxEntries.size())
- W.OS.write_zeros(XCOFF::SymbolTableEntrySize *
- (NumOfAuxSym - YamlSym.AuxEntries.size()));
- }
- }
- return true;
- }
- void XCOFFWriter::writeStringTable() {
- if (Obj.StrTbl.RawContent) {
- Obj.StrTbl.RawContent->writeAsBinary(W.OS);
- if (Obj.StrTbl.ContentSize) {
- assert(*Obj.StrTbl.ContentSize >= Obj.StrTbl.RawContent->binary_size() &&
- "Specified ContentSize is less than the RawContent size.");
- W.OS.write_zeros(*Obj.StrTbl.ContentSize -
- Obj.StrTbl.RawContent->binary_size());
- }
- return;
- }
- size_t StrTblBuilderSize = StrTblBuilder.getSize();
- // If neither Length nor ContentSize is specified, write the StrTblBuilder
- // directly, which contains the auto-generated Length value.
- if (!Obj.StrTbl.Length && !Obj.StrTbl.ContentSize) {
- if (StrTblBuilderSize <= 4)
- return;
- StrTblBuilder.write(W.OS);
- return;
- }
- // Serialize the string table's content to a temporary buffer.
- std::unique_ptr<WritableMemoryBuffer> Buf =
- WritableMemoryBuffer::getNewMemBuffer(StrTblBuilderSize);
- uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart());
- StrTblBuilder.write(Ptr);
- // Replace the first 4 bytes, which contain the auto-generated Length value,
- // with the specified value.
- memset(Ptr, 0, 4);
- support::endian::write32be(Ptr, Obj.StrTbl.Length ? *Obj.StrTbl.Length
- : *Obj.StrTbl.ContentSize);
- // Copy the buffer content to the actual output stream.
- W.OS.write(Buf->getBufferStart(), Buf->getBufferSize());
- // Add zeros as padding after strings.
- if (Obj.StrTbl.ContentSize) {
- assert(*Obj.StrTbl.ContentSize >= StrTblBuilderSize &&
- "Specified ContentSize is less than the StringTableBuilder size.");
- W.OS.write_zeros(*Obj.StrTbl.ContentSize - StrTblBuilderSize);
- }
- }
- bool XCOFFWriter::writeXCOFF() {
- if (!assignAddressesAndIndices())
- return false;
- StartOffset = W.OS.tell();
- writeFileHeader();
- if (Obj.AuxHeader)
- writeAuxFileHeader();
- if (!Obj.Sections.empty()) {
- writeSectionHeader();
- if (!writeSectionData())
- return false;
- if (!writeRelocations())
- return false;
- }
- if (!Obj.Symbols.empty() && !writeSymbols())
- return false;
- writeStringTable();
- return true;
- }
- } // end anonymous namespace
- namespace llvm {
- namespace yaml {
- bool yaml2xcoff(XCOFFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
- XCOFFWriter Writer(Doc, Out, EH);
- return Writer.writeXCOFF();
- }
- } // namespace yaml
- } // namespace llvm
|