1 //===- XCOFFWriter.cpp ----------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Support/Errc.h" 10 #include "XCOFFWriter.h" 11 12 namespace llvm { 13 namespace objcopy { 14 namespace xcoff { 15 16 using namespace object; 17 18 void XCOFFWriter::finalizeHeaders() { 19 // File header. 20 FileSize += sizeof(XCOFFFileHeader32); 21 // Optional file header. 22 FileSize += Obj.FileHeader.AuxHeaderSize; 23 // Section headers. 24 FileSize += sizeof(XCOFFSectionHeader32) * Obj.Sections.size(); 25 } 26 27 void XCOFFWriter::finalizeSections() { 28 for (const Section &Sec : Obj.Sections) { 29 // Section data. 30 FileSize += Sec.Contents.size(); 31 // Relocations. 32 FileSize += 33 Sec.SectionHeader.NumberOfRelocations * sizeof(XCOFFRelocation32); 34 } 35 } 36 37 void XCOFFWriter::finalizeSymbolStringTable() { 38 assert(Obj.FileHeader.SymbolTableOffset >= FileSize); 39 FileSize = Obj.FileHeader.SymbolTableOffset; 40 // Symbols and auxiliary entries. 41 FileSize += 42 Obj.FileHeader.NumberOfSymTableEntries * XCOFF::SymbolTableEntrySize; 43 // String table. 44 FileSize += Obj.StringTable.size(); 45 } 46 47 void XCOFFWriter::finalize() { 48 FileSize = 0; 49 finalizeHeaders(); 50 finalizeSections(); 51 finalizeSymbolStringTable(); 52 } 53 54 void XCOFFWriter::writeHeaders() { 55 // Write the file header. 56 uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()); 57 memcpy(Ptr, &Obj.FileHeader, sizeof(XCOFFFileHeader32)); 58 Ptr += sizeof(XCOFFFileHeader32); 59 60 // Write the optional header. 61 if (Obj.FileHeader.AuxHeaderSize) { 62 memcpy(Ptr, &Obj.OptionalFileHeader, Obj.FileHeader.AuxHeaderSize); 63 Ptr += Obj.FileHeader.AuxHeaderSize; 64 } 65 66 // Write section headers. 67 for (const Section &Sec : Obj.Sections) { 68 memcpy(Ptr, &Sec.SectionHeader, sizeof(XCOFFSectionHeader32)); 69 Ptr += sizeof(XCOFFSectionHeader32); 70 } 71 } 72 73 void XCOFFWriter::writeSections() { 74 // Write section data. 75 for (const Section &Sec : Obj.Sections) { 76 uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + 77 Sec.SectionHeader.FileOffsetToRawData; 78 Ptr = std::copy(Sec.Contents.begin(), Sec.Contents.end(), Ptr); 79 } 80 81 // Write relocations. 82 for (const Section &Sec : Obj.Sections) { 83 uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + 84 Sec.SectionHeader.FileOffsetToRelocationInfo; 85 for (const XCOFFRelocation32 &Rel : Sec.Relocations) { 86 memcpy(Ptr, &Rel, sizeof(XCOFFRelocation32)); 87 Ptr += sizeof(XCOFFRelocation32); 88 } 89 } 90 } 91 92 void XCOFFWriter::writeSymbolStringTable() { 93 // Write symbols. 94 uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + 95 Obj.FileHeader.SymbolTableOffset; 96 for (const Symbol &Sym : Obj.Symbols) { 97 memcpy(Ptr, &Sym.Sym, XCOFF::SymbolTableEntrySize); 98 Ptr += XCOFF::SymbolTableEntrySize; 99 // Auxiliary symbols. 100 memcpy(Ptr, Sym.AuxSymbolEntries.data(), Sym.AuxSymbolEntries.size()); 101 Ptr += Sym.AuxSymbolEntries.size(); 102 } 103 // Write the string table. 104 memcpy(Ptr, Obj.StringTable.data(), Obj.StringTable.size()); 105 Ptr += Obj.StringTable.size(); 106 } 107 108 Error XCOFFWriter::write() { 109 finalize(); 110 Buf = WritableMemoryBuffer::getNewMemBuffer(FileSize); 111 if (!Buf) 112 return createStringError(errc::not_enough_memory, 113 "failed to allocate memory buffer of " + 114 Twine::utohexstr(FileSize) + " bytes"); 115 116 writeHeaders(); 117 writeSections(); 118 writeSymbolStringTable(); 119 Out.write(Buf->getBufferStart(), Buf->getBufferSize()); 120 return Error::success(); 121 } 122 123 } // end namespace xcoff 124 } // end namespace objcopy 125 } // end namespace llvm 126