1 #include "CoffObjectFile.h"
2 #include <string.h>
3 #include <assert.h>
4 #include <time.h>
5 #include <algorithm>
6
7 using namespace Jitter;
8
CCoffObjectFile(CPU_ARCH cpuArch)9 CCoffObjectFile::CCoffObjectFile(CPU_ARCH cpuArch)
10 : CObjectFile(cpuArch)
11 {
12
13 }
14
~CCoffObjectFile()15 CCoffObjectFile::~CCoffObjectFile()
16 {
17
18 }
19
Write(Framework::CStream & stream)20 void CCoffObjectFile::Write(Framework::CStream& stream)
21 {
22 struct OffsetKeeper
23 {
24 OffsetKeeper()
25 {
26 currentOffset = 0;
27 }
28
29 uint32 Advance(uint32 size)
30 {
31 currentOffset += size;
32 return currentOffset;
33 }
34
35 uint32 currentOffset;
36 };
37
38 auto internalSymbolInfos = InternalSymbolInfoArray(m_internalSymbols.size());
39 auto externalSymbolInfos = ExternalSymbolInfoArray(m_externalSymbols.size());
40
41 StringTable stringTable;
42 FillStringTable(stringTable, m_internalSymbols, internalSymbolInfos);
43 FillStringTable(stringTable, m_externalSymbols, externalSymbolInfos);
44
45 auto textSection = BuildSection(m_internalSymbols, internalSymbolInfos, INTERNAL_SYMBOL_LOCATION_TEXT);
46 auto dataSection = BuildSection(m_internalSymbols, internalSymbolInfos, INTERNAL_SYMBOL_LOCATION_DATA);
47
48 auto symbols = BuildSymbols(m_internalSymbols, internalSymbolInfos,
49 m_externalSymbols, externalSymbolInfos, textSection.data.size(), dataSection.data.size());
50
51 unsigned int sectionHeaderCount = 2;
52
53 OffsetKeeper offsetKeeper;
54 uint32 textSectionDataOffset = offsetKeeper.Advance(sizeof(Coff::HEADER) + (sectionHeaderCount * sizeof(Coff::SECTION_HEADER)));
55 uint32 textSectionRelocOffset = offsetKeeper.Advance(textSection.data.size());
56 uint32 dataSectionDataOffset = offsetKeeper.Advance((textSection.symbolReferences.size() * sizeof(Coff::RELOCATION)));
57 uint32 dataSectionRelocOffset = offsetKeeper.Advance(dataSection.data.size());
58 uint32 symbolTableOffset = offsetKeeper.Advance(dataSection.symbolReferences.size() * sizeof(Coff::RELOCATION));
59
60 SectionHeaderArray sectionHeaders;
61
62 {
63 Coff::SECTION_HEADER sectionHeader = {};
64 strncpy(sectionHeader.name, ".text", 8);
65 sectionHeader.virtualSize = 0;
66 sectionHeader.virtualAddress = 0;
67 sectionHeader.sizeOfRawData = textSection.data.size();
68 sectionHeader.pointerToRawData = textSectionDataOffset;
69 sectionHeader.pointerToRelocations = (textSection.symbolReferences.size() == 0) ? 0 : textSectionRelocOffset;
70 sectionHeader.pointerToLineNumbers = 0;
71 sectionHeader.numberOfRelocations = textSection.symbolReferences.size();
72 sectionHeader.numberOfLineNumbers = 0;
73 sectionHeader.characteristics = 0x60500020;
74 sectionHeaders.push_back(sectionHeader);
75 }
76
77 {
78 Coff::SECTION_HEADER sectionHeader = {};
79 strncpy(sectionHeader.name, ".data", 8);
80 sectionHeader.virtualSize = 0;
81 sectionHeader.virtualAddress = 0;
82 sectionHeader.sizeOfRawData = dataSection.data.size();
83 sectionHeader.pointerToRawData = dataSectionDataOffset;
84 sectionHeader.pointerToRelocations = (dataSection.symbolReferences.size() == 0) ? 0 : dataSectionRelocOffset;
85 sectionHeader.pointerToLineNumbers = 0;
86 sectionHeader.numberOfRelocations = dataSection.symbolReferences.size();
87 sectionHeader.numberOfLineNumbers = 0;
88 sectionHeader.characteristics = 0xC0500040;
89 sectionHeaders.push_back(sectionHeader);
90 }
91
92 auto textSectionRelocations = BuildRelocations(textSection, internalSymbolInfos, externalSymbolInfos);
93 auto dataSectionRelocations = BuildRelocations(dataSection, internalSymbolInfos, externalSymbolInfos);
94
95 Coff::HEADER header = {};
96 header.machine = Coff::MACHINE_TYPE_I386;
97 header.numberOfSections = sectionHeaderCount;
98 header.timeDateStamp = static_cast<uint32>(time(nullptr));
99 header.pointerToSymbolTable = symbolTableOffset;
100 header.numberOfSymbols = symbols.size();
101 header.sizeOfOptionalHeader = 0;
102 header.characteristics = 0;
103
104 stream.Write(&header, sizeof(Coff::HEADER));
105 stream.Write(sectionHeaders.data(), sectionHeaders.size() * sizeof(Coff::SECTION_HEADER));
106 stream.Write(textSection.data.data(), textSection.data.size());
107 stream.Write(textSectionRelocations.data(), textSectionRelocations.size() * sizeof(Coff::RELOCATION));
108 stream.Write(dataSection.data.data(), dataSection.data.size());
109 stream.Write(dataSectionRelocations.data(), dataSectionRelocations.size() * sizeof(Coff::RELOCATION));
110 stream.Write(symbols.data(), symbols.size() * sizeof(Coff::SYMBOL));
111 stream.Write32(stringTable.size() + 4);
112 stream.Write(stringTable.data(), stringTable.size());
113 }
114
FillStringTable(StringTable & stringTable,const InternalSymbolArray & internalSymbols,InternalSymbolInfoArray & internalSymbolInfos)115 void CCoffObjectFile::FillStringTable(StringTable& stringTable, const InternalSymbolArray& internalSymbols, InternalSymbolInfoArray& internalSymbolInfos)
116 {
117 uint32 stringTableSizeIncrement = 0;
118 for(const auto& internalSymbol : internalSymbols)
119 {
120 stringTableSizeIncrement += internalSymbol.name.length() + 1;
121 }
122 stringTable.reserve(stringTable.size() + stringTableSizeIncrement);
123 for(uint32 i = 0; i < internalSymbols.size(); i++)
124 {
125 const auto& internalSymbol = internalSymbols[i];
126 auto& internalSymbolInfo = internalSymbolInfos[i];
127 internalSymbolInfo.nameOffset = stringTable.size();
128 stringTable.insert(std::end(stringTable), std::begin(internalSymbol.name), std::end(internalSymbol.name));
129 stringTable.push_back(0);
130 }
131 }
132
FillStringTable(StringTable & stringTable,const ExternalSymbolArray & externalSymbols,ExternalSymbolInfoArray & externalSymbolInfos)133 void CCoffObjectFile::FillStringTable(StringTable& stringTable, const ExternalSymbolArray& externalSymbols, ExternalSymbolInfoArray& externalSymbolInfos)
134 {
135 uint32 stringTableSizeIncrement = 0;
136 for(const auto& externalSymbol : externalSymbols)
137 {
138 stringTableSizeIncrement += externalSymbol.name.length() + 1;
139 }
140 stringTable.reserve(stringTable.size() + stringTableSizeIncrement);
141 for(uint32 i = 0; i < externalSymbols.size(); i++)
142 {
143 const auto& externalSymbol = externalSymbols[i];
144 auto& externalSymbolInfo = externalSymbolInfos[i];
145 externalSymbolInfo.nameOffset = stringTable.size();
146 stringTable.insert(std::end(stringTable), std::begin(externalSymbol.name), std::end(externalSymbol.name));
147 stringTable.push_back(0);
148 }
149 }
150
BuildSection(const InternalSymbolArray & internalSymbols,InternalSymbolInfoArray & internalSymbolInfos,INTERNAL_SYMBOL_LOCATION location)151 CCoffObjectFile::SECTION CCoffObjectFile::BuildSection(const InternalSymbolArray& internalSymbols, InternalSymbolInfoArray& internalSymbolInfos, INTERNAL_SYMBOL_LOCATION location)
152 {
153 SECTION section;
154 auto& sectionData(section.data);
155 uint32 sectionSize = 0;
156 for(const auto& internalSymbol : internalSymbols)
157 {
158 sectionSize += internalSymbol.data.size();
159 }
160 sectionData.reserve(sectionSize);
161 for(uint32 i = 0; i < internalSymbols.size(); i++)
162 {
163 const auto& internalSymbol = internalSymbols[i];
164 if(internalSymbol.location != location) continue;
165
166 auto& internalSymbolInfo = internalSymbolInfos[i];
167 internalSymbolInfo.dataOffset = sectionData.size();
168 for(const auto& symbolReference : internalSymbol.symbolReferences)
169 {
170 SYMBOL_REFERENCE newReference;
171 newReference.offset = symbolReference.offset + internalSymbolInfo.dataOffset;
172 newReference.symbolIndex = symbolReference.symbolIndex;
173 newReference.type = symbolReference.type;
174 section.symbolReferences.push_back(newReference);
175 }
176 sectionData.insert(std::end(sectionData), std::begin(internalSymbol.data), std::end(internalSymbol.data));
177 }
178 return section;
179 }
180
BuildSymbols(const InternalSymbolArray & internalSymbols,InternalSymbolInfoArray & internalSymbolInfos,const ExternalSymbolArray & externalSymbols,ExternalSymbolInfoArray & externalSymbolInfos,uint32 textSectionSize,uint32 dataSectionSize)181 CCoffObjectFile::SymbolArray CCoffObjectFile::BuildSymbols(const InternalSymbolArray& internalSymbols, InternalSymbolInfoArray& internalSymbolInfos,
182 const ExternalSymbolArray& externalSymbols, ExternalSymbolInfoArray& externalSymbolInfos,
183 uint32 textSectionSize, uint32 dataSectionSize)
184 {
185 SymbolArray symbols;
186 symbols.reserve(5 + internalSymbols.size() + externalSymbols.size());
187
188 //SafeSEH stuff
189 {
190 Coff::SYMBOL symbol = {};
191 strncpy(symbol.name.shortName, "@feat.00", 8);
192 symbol.value = 0x01;
193 symbol.sectionNumber = 0xFFFF;
194 symbol.type = 0;
195 symbol.storageClass = 0x03; //CLASS_STATIC
196 symbol.numberOfAuxSymbols = 0;
197 symbols.push_back(symbol);
198 }
199
200 //Text Section
201 {
202 Coff::SYMBOL symbol = {};
203 strncpy(symbol.name.shortName, ".text", 8);
204 symbol.value = 0;
205 symbol.sectionNumber = 1;
206 symbol.type = 0;
207 symbol.storageClass = 0x03; //CLASS_STATIC
208 symbol.numberOfAuxSymbols = 1;
209 symbols.push_back(symbol);
210 }
211
212 {
213 Coff::SYMBOL symbol = {};
214 symbol.name.offset = 0;
215 symbol.name.zeroes = textSectionSize;
216 symbols.push_back(symbol);
217 }
218
219 //Data Section
220 {
221 Coff::SYMBOL symbol = {};
222 strncpy(symbol.name.shortName, ".data", 8);
223 symbol.value = 0;
224 symbol.sectionNumber = 2;
225 symbol.type = 0;
226 symbol.storageClass = 0x03; //CLASS_STATIC
227 symbol.numberOfAuxSymbols = 1;
228 symbols.push_back(symbol);
229 }
230
231 {
232 Coff::SYMBOL symbol = {};
233 symbol.name.offset = 0;
234 symbol.name.zeroes = dataSectionSize;
235 symbols.push_back(symbol);
236 }
237
238 //Internal symbols
239 for(uint32 i = 0; i < internalSymbols.size(); i++)
240 {
241 const auto& internalSymbol = internalSymbols[i];
242 auto& internalSymbolInfo = internalSymbolInfos[i];
243 internalSymbolInfo.symbolIndex = symbols.size();
244
245 Coff::SYMBOL symbol = {};
246 symbol.name.offset = 4 + internalSymbolInfo.nameOffset;
247 symbol.value = internalSymbolInfo.dataOffset;
248 symbol.sectionNumber = (internalSymbol.location == CObjectFile::INTERNAL_SYMBOL_LOCATION_TEXT) ? 1 : 2; //.text or .data section
249 symbol.type = (internalSymbol.location == CObjectFile::INTERNAL_SYMBOL_LOCATION_TEXT) ? 0x20 : 0; //DT_FUNCTION or nothing
250 symbol.storageClass = 0x02; //CLASS_EXTERNAL
251 symbol.numberOfAuxSymbols = 0;
252 symbols.push_back(symbol);
253 }
254
255 //External symbols
256 for(uint32 i = 0; i < externalSymbols.size(); i++)
257 {
258 const auto& externalSymbol = externalSymbols[i];
259 auto& externalSymbolInfo = externalSymbolInfos[i];
260 externalSymbolInfo.symbolIndex = symbols.size();
261
262 Coff::SYMBOL symbol = {};
263 symbol.name.offset = 4 + externalSymbolInfo.nameOffset;
264 symbol.value = 0;
265 symbol.sectionNumber = 0;
266 symbol.type = 0;
267 symbol.storageClass = 0x02; //CLASS_EXTERNAL
268 symbol.numberOfAuxSymbols = 0;
269 symbols.push_back(symbol);
270 }
271
272 return symbols;
273 }
274
BuildRelocations(SECTION & section,const InternalSymbolInfoArray & internalSymbolInfos,const ExternalSymbolInfoArray & externalSymbolInfos)275 CCoffObjectFile::RelocationArray CCoffObjectFile::BuildRelocations(SECTION& section, const InternalSymbolInfoArray& internalSymbolInfos, const ExternalSymbolInfoArray& externalSymbolInfos)
276 {
277 RelocationArray relocations;
278 relocations.resize(section.symbolReferences.size());
279
280 for(uint32 i = 0; i < section.symbolReferences.size(); i++)
281 {
282 const auto& symbolReference = section.symbolReferences[i];
283 uint32 symbolIndex = (symbolReference.type == SYMBOL_TYPE_INTERNAL) ?
284 internalSymbolInfos[symbolReference.symbolIndex].symbolIndex :
285 externalSymbolInfos[symbolReference.symbolIndex].symbolIndex;
286
287 auto& relocation = relocations[i];
288 relocation.type = 0x06; //I386_DIR32
289 relocation.symbolIndex = symbolIndex;
290 relocation.rva = symbolReference.offset;
291
292 *reinterpret_cast<uint32*>(section.data.data() + symbolReference.offset) = 0;
293 }
294
295 return relocations;
296 }
297