| //===- 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<uint8_t *>(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<uint8_t *>(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<uint8_t *>(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<uint8_t *>(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 |