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::() { |
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::() { |
55 | // Write the file header. |
56 | uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()); |
57 | memcpy(dest: Ptr, src: &Obj.FileHeader, n: sizeof(XCOFFFileHeader32)); |
58 | Ptr += sizeof(XCOFFFileHeader32); |
59 | |
60 | // Write the optional header. |
61 | if (Obj.FileHeader.AuxHeaderSize) { |
62 | memcpy(dest: Ptr, src: &Obj.OptionalFileHeader, n: Obj.FileHeader.AuxHeaderSize); |
63 | Ptr += Obj.FileHeader.AuxHeaderSize; |
64 | } |
65 | |
66 | // Write section headers. |
67 | for (const Section &Sec : Obj.Sections) { |
68 | memcpy(dest: Ptr, src: &Sec.SectionHeader, n: 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(dest: Ptr, src: &Rel, n: 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(dest: Ptr, src: &Sym.Sym, n: XCOFF::SymbolTableEntrySize); |
98 | Ptr += XCOFF::SymbolTableEntrySize; |
99 | // Auxiliary symbols. |
100 | memcpy(dest: Ptr, src: Sym.AuxSymbolEntries.data(), n: Sym.AuxSymbolEntries.size()); |
101 | Ptr += Sym.AuxSymbolEntries.size(); |
102 | } |
103 | // Write the string table. |
104 | memcpy(dest: Ptr, src: Obj.StringTable.data(), n: Obj.StringTable.size()); |
105 | Ptr += Obj.StringTable.size(); |
106 | } |
107 | |
108 | Error XCOFFWriter::write() { |
109 | finalize(); |
110 | Buf = WritableMemoryBuffer::getNewMemBuffer(Size: FileSize); |
111 | if (!Buf) |
112 | return createStringError(EC: errc::not_enough_memory, |
113 | S: "failed to allocate memory buffer of " + |
114 | Twine::utohexstr(Val: FileSize) + " bytes" ); |
115 | |
116 | writeHeaders(); |
117 | writeSections(); |
118 | writeSymbolStringTable(); |
119 | Out.write(Ptr: Buf->getBufferStart(), Size: Buf->getBufferSize()); |
120 | return Error::success(); |
121 | } |
122 | |
123 | } // end namespace xcoff |
124 | } // end namespace objcopy |
125 | } // end namespace llvm |
126 | |