//===- XCOFFWriter.cpp ----------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// #include "llvm/Support/Errc.h" #include "XCOFFWriter.h" namespace llvm { namespace objcopy { namespace xcoff { using namespace object; void XCOFFWriter::finalizeHeaders() { // File header. FileSize += sizeof(XCOFFFileHeader32); // Optional file header. FileSize += Obj.FileHeader.AuxHeaderSize; // Section headers. FileSize += sizeof(XCOFFSectionHeader32) * Obj.Sections.size(); } void XCOFFWriter::finalizeSections() { for (const Section &Sec : Obj.Sections) { // Section data. FileSize += Sec.Contents.size(); // Relocations. FileSize += Sec.SectionHeader.NumberOfRelocations * sizeof(XCOFFRelocation32); } } void XCOFFWriter::finalizeSymbolStringTable() { assert(Obj.FileHeader.SymbolTableOffset >= FileSize); FileSize = Obj.FileHeader.SymbolTableOffset; // Symbols and auxiliary entries. FileSize += Obj.FileHeader.NumberOfSymTableEntries * XCOFF::SymbolTableEntrySize; // String table. FileSize += Obj.StringTable.size(); } void XCOFFWriter::finalize() { FileSize = 0; finalizeHeaders(); finalizeSections(); finalizeSymbolStringTable(); } void XCOFFWriter::writeHeaders() { // Write the file header. uint8_t *Ptr = reinterpret_cast(Buf->getBufferStart()); memcpy(Ptr, &Obj.FileHeader, sizeof(XCOFFFileHeader32)); Ptr += sizeof(XCOFFFileHeader32); // Write the optional header. if (Obj.FileHeader.AuxHeaderSize) { memcpy(Ptr, &Obj.OptionalFileHeader, Obj.FileHeader.AuxHeaderSize); Ptr += Obj.FileHeader.AuxHeaderSize; } // Write section headers. for (const Section &Sec : Obj.Sections) { memcpy(Ptr, &Sec.SectionHeader, sizeof(XCOFFSectionHeader32)); Ptr += sizeof(XCOFFSectionHeader32); } } void XCOFFWriter::writeSections() { // Write section data. for (const Section &Sec : Obj.Sections) { uint8_t *Ptr = reinterpret_cast(Buf->getBufferStart()) + Sec.SectionHeader.FileOffsetToRawData; Ptr = std::copy(Sec.Contents.begin(), Sec.Contents.end(), Ptr); } // Write relocations. for (const Section &Sec : Obj.Sections) { uint8_t *Ptr = reinterpret_cast(Buf->getBufferStart()) + Sec.SectionHeader.FileOffsetToRelocationInfo; for (const XCOFFRelocation32 &Rel : Sec.Relocations) { memcpy(Ptr, &Rel, sizeof(XCOFFRelocation32)); Ptr += sizeof(XCOFFRelocation32); } } } void XCOFFWriter::writeSymbolStringTable() { // Write symbols. uint8_t *Ptr = reinterpret_cast(Buf->getBufferStart()) + Obj.FileHeader.SymbolTableOffset; for (const Symbol &Sym : Obj.Symbols) { memcpy(Ptr, &Sym.Sym, XCOFF::SymbolTableEntrySize); Ptr += XCOFF::SymbolTableEntrySize; // Auxiliary symbols. memcpy(Ptr, Sym.AuxSymbolEntries.data(), Sym.AuxSymbolEntries.size()); Ptr += Sym.AuxSymbolEntries.size(); } // Write the string table. memcpy(Ptr, Obj.StringTable.data(), Obj.StringTable.size()); Ptr += Obj.StringTable.size(); } Error XCOFFWriter::write() { finalize(); Buf = WritableMemoryBuffer::getNewMemBuffer(FileSize); if (!Buf) return createStringError(errc::not_enough_memory, "failed to allocate memory buffer of " + Twine::utohexstr(FileSize) + " bytes"); writeHeaders(); writeSections(); writeSymbolStringTable(); Out.write(Buf->getBufferStart(), Buf->getBufferSize()); return Error::success(); } } // end namespace xcoff } // end namespace objcopy } // end namespace llvm