27 Error COFFWriter::finalizeRelocTargets() {
28 for (Section &Sec : Obj.getMutableSections()) {
29 for (Relocation &R : Sec.Relocs) {
30 const Symbol *Sym = Obj.findSymbol(
R.Target);
33 "relocation target '%s' (%zu) not found",
34 R.TargetName.str().c_str(),
R.Target);
35 R.Reloc.SymbolTableIndex = Sym->RawIndex;
41 Error COFFWriter::finalizeSymbolContents() {
42 for (
Symbol &Sym : Obj.getMutableSymbols()) {
43 if (Sym.TargetSectionId <= 0) {
46 Sym.Sym.SectionNumber =
static_cast<uint32_t>(Sym.TargetSectionId);
48 const Section *Sec = Obj.findSection(Sym.TargetSectionId);
51 "symbol '%s' points to a removed section",
52 Sym.Name.str().c_str());
53 Sym.Sym.SectionNumber = Sec->Index;
55 if (Sym.Sym.NumberOfAuxSymbols == 1 &&
57 coff_aux_section_definition *SD =
58 reinterpret_cast<coff_aux_section_definition *
>(
59 Sym.AuxData[0].Opaque);
61 if (Sym.AssociativeComdatTargetSectionId == 0) {
64 SDSectionNumber = Sec->Index;
66 Sec = Obj.findSection(Sym.AssociativeComdatTargetSectionId);
69 object_error::invalid_symbol_index,
70 "symbol '%s' is associative to a removed section",
71 Sym.Name.str().c_str());
72 SDSectionNumber = Sec->Index;
75 SD->NumberLowPart =
static_cast<uint16_t>(SDSectionNumber);
76 SD->NumberHighPart =
static_cast<uint16_t>(SDSectionNumber >> 16);
81 if (Sym.WeakTargetSymbolId && Sym.Sym.NumberOfAuxSymbols == 1) {
82 coff_aux_weak_external *WE =
83 reinterpret_cast<coff_aux_weak_external *
>(Sym.AuxData[0].Opaque);
84 const Symbol *
Target = Obj.findSymbol(*Sym.WeakTargetSymbolId);
85 if (Target ==
nullptr)
87 "symbol '%s' is missing its weak target",
88 Sym.Name.str().c_str());
89 WE->TagIndex =
Target->RawIndex;
95 void COFFWriter::layoutSections() {
96 for (
auto &
S : Obj.getMutableSections()) {
97 if (
S.Header.SizeOfRawData > 0)
98 S.Header.PointerToRawData = FileSize;
99 FileSize +=
S.Header.SizeOfRawData;
101 if (
S.Relocs.size() >= 0xffff) {
103 S.Header.NumberOfRelocations = 0xffff;
104 S.Header.PointerToRelocations = FileSize;
105 FileSize +=
sizeof(coff_relocation);
107 S.Header.NumberOfRelocations =
S.Relocs.size();
108 S.Header.PointerToRelocations =
S.Relocs.size() ? FileSize : 0;
111 FileSize +=
S.Relocs.size() *
sizeof(coff_relocation);
112 FileSize =
alignTo(FileSize, FileAlignment);
115 SizeOfInitializedData +=
S.Header.SizeOfRawData;
119 Expected<size_t> COFFWriter::finalizeStringTable() {
120 for (
const auto &
S : Obj.getSections())
122 StrTabBuilder.add(
S.Name);
124 for (
const auto &
S : Obj.getSymbols())
126 StrTabBuilder.add(
S.Name);
128 StrTabBuilder.finalize();
130 for (
auto &
S : Obj.getMutableSections()) {
131 memset(
S.Header.Name, 0,
sizeof(
S.Header.Name));
134 memcpy(
S.Header.Name,
S.Name.data(),
S.Name.size());
137 size_t Offset = StrTabBuilder.getOffset(
S.Name);
140 "COFF string table is greater than 64GB, "
141 "unable to encode section name offset");
144 for (
auto &
S : Obj.getMutableSymbols()) {
146 S.Sym.Name.Offset.Zeroes = 0;
147 S.Sym.Name.Offset.Offset = StrTabBuilder.getOffset(
S.Name);
152 return StrTabBuilder.getSize();
155 template <
class SymbolTy>
156 std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() {
157 size_t RawSymIndex = 0;
158 for (
auto &
S : Obj.getMutableSymbols()) {
162 if (!
S.AuxFile.empty())
163 S.Sym.NumberOfAuxSymbols =
164 alignTo(
S.AuxFile.size(),
sizeof(SymbolTy)) /
sizeof(SymbolTy);
165 S.RawIndex = RawSymIndex;
166 RawSymIndex += 1 +
S.Sym.NumberOfAuxSymbols;
168 return std::make_pair(RawSymIndex *
sizeof(SymbolTy),
sizeof(SymbolTy));
171 Error COFFWriter::finalize(
bool IsBigObj) {
172 size_t SymTabSize, SymbolSize;
173 std::tie(SymTabSize, SymbolSize) = IsBigObj
174 ? finalizeSymbolTable<coff_symbol32>()
177 if (Error
E = finalizeRelocTargets())
179 if (Error
E = finalizeSymbolContents())
182 size_t SizeOfHeaders = 0;
184 size_t PeHeaderSize = 0;
186 Obj.DosHeader.AddressOfNewExeHeader =
187 sizeof(Obj.DosHeader) + Obj.DosStub.size();
188 SizeOfHeaders += Obj.DosHeader.AddressOfNewExeHeader +
sizeof(
PEMagic);
190 FileAlignment = Obj.PeHeader.FileAlignment;
191 Obj.PeHeader.NumberOfRvaAndSize = Obj.DataDirectories.size();
193 PeHeaderSize = Obj.Is64 ?
sizeof(pe32plus_header) :
sizeof(pe32_header);
195 PeHeaderSize +
sizeof(data_directory) * Obj.DataDirectories.size();
197 Obj.CoffFileHeader.NumberOfSections = Obj.getSections().size();
199 IsBigObj ?
sizeof(coff_bigobj_file_header) :
sizeof(coff_file_header);
200 SizeOfHeaders +=
sizeof(coff_section) * Obj.getSections().size();
201 SizeOfHeaders =
alignTo(SizeOfHeaders, FileAlignment);
203 Obj.CoffFileHeader.SizeOfOptionalHeader =
204 PeHeaderSize +
sizeof(data_directory) * Obj.DataDirectories.size();
206 FileSize = SizeOfHeaders;
207 SizeOfInitializedData = 0;
212 Obj.PeHeader.SizeOfHeaders = SizeOfHeaders;
213 Obj.PeHeader.SizeOfInitializedData = SizeOfInitializedData;
215 if (!Obj.getSections().empty()) {
216 const Section &
S = Obj.getSections().back();
217 Obj.PeHeader.SizeOfImage =
218 alignTo(
S.Header.VirtualAddress +
S.Header.VirtualSize,
219 Obj.PeHeader.SectionAlignment);
224 Obj.PeHeader.CheckSum = 0;
227 Expected<size_t> StrTabSizeOrErr = finalizeStringTable();
228 if (!StrTabSizeOrErr)
229 return StrTabSizeOrErr.takeError();
231 size_t StrTabSize = *StrTabSizeOrErr;
233 size_t PointerToSymbolTable = FileSize;
236 if (SymTabSize == 0 && StrTabSize <= 4 && Obj.IsPE) {
239 PointerToSymbolTable = 0;
243 size_t NumRawSymbols = SymTabSize / SymbolSize;
244 Obj.CoffFileHeader.PointerToSymbolTable = PointerToSymbolTable;
245 Obj.CoffFileHeader.NumberOfSymbols = NumRawSymbols;
246 FileSize += SymTabSize + StrTabSize;
247 FileSize =
alignTo(FileSize, FileAlignment);
252 void COFFWriter::writeHeaders(
bool IsBigObj) {
253 uint8_t *
Ptr =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart());
255 memcpy(
Ptr, &Obj.DosHeader,
sizeof(Obj.DosHeader));
256 Ptr +=
sizeof(Obj.DosHeader);
257 memcpy(
Ptr, Obj.DosStub.data(), Obj.DosStub.size());
258 Ptr += Obj.DosStub.size();
263 memcpy(
Ptr, &Obj.CoffFileHeader,
sizeof(Obj.CoffFileHeader));
264 Ptr +=
sizeof(Obj.CoffFileHeader);
269 coff_bigobj_file_header BigObjHeader;
271 BigObjHeader.Sig2 = 0xffff;
273 BigObjHeader.Machine = Obj.CoffFileHeader.Machine;
274 BigObjHeader.TimeDateStamp = Obj.CoffFileHeader.TimeDateStamp;
276 BigObjHeader.unused1 = 0;
277 BigObjHeader.unused2 = 0;
278 BigObjHeader.unused3 = 0;
279 BigObjHeader.unused4 = 0;
282 BigObjHeader.NumberOfSections = Obj.getSections().size();
283 BigObjHeader.PointerToSymbolTable = Obj.CoffFileHeader.PointerToSymbolTable;
284 BigObjHeader.NumberOfSymbols = Obj.CoffFileHeader.NumberOfSymbols;
286 memcpy(
Ptr, &BigObjHeader,
sizeof(BigObjHeader));
287 Ptr +=
sizeof(BigObjHeader);
291 memcpy(
Ptr, &Obj.PeHeader,
sizeof(Obj.PeHeader));
292 Ptr +=
sizeof(Obj.PeHeader);
294 pe32_header PeHeader;
297 PeHeader.BaseOfData = Obj.BaseOfData;
299 memcpy(
Ptr, &PeHeader,
sizeof(PeHeader));
300 Ptr +=
sizeof(PeHeader);
302 for (
const auto &DD : Obj.DataDirectories) {
307 for (
const auto &
S : Obj.getSections()) {
309 Ptr +=
sizeof(
S.Header);
313 void COFFWriter::writeSections() {
314 for (
const auto &
S : Obj.getSections()) {
315 uint8_t *
Ptr =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) +
316 S.Header.PointerToRawData;
317 ArrayRef<uint8_t> Contents =
S.getContents();
323 S.Header.SizeOfRawData > Contents.size())
324 memset(
Ptr + Contents.size(), 0xcc,
325 S.Header.SizeOfRawData - Contents.size());
327 Ptr +=
S.Header.SizeOfRawData;
329 if (
S.Relocs.size() >= 0xffff) {
330 object::coff_relocation
R;
331 R.VirtualAddress =
S.Relocs.size() + 1;
332 R.SymbolTableIndex = 0;
337 for (
const auto &R :
S.Relocs) {
339 Ptr +=
sizeof(
R.Reloc);
344 template <
class SymbolTy>
void COFFWriter::writeSymbolStringTables() {
345 uint8_t *
Ptr =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) +
346 Obj.CoffFileHeader.PointerToSymbolTable;
347 for (
const auto &
S : Obj.getSymbols()) {
349 copySymbol<SymbolTy, coff_symbol32>(*
reinterpret_cast<SymbolTy *
>(
Ptr),
351 Ptr +=
sizeof(SymbolTy);
352 if (!
S.AuxFile.empty()) {
357 Ptr +=
S.Sym.NumberOfAuxSymbols *
sizeof(SymbolTy);
363 for (
const AuxSymbol &AuxSym :
S.AuxData) {
364 ArrayRef<uint8_t>
Ref = AuxSym.getRef();
366 Ptr +=
sizeof(SymbolTy);
370 if (StrTabBuilder.getSize() > 4 || !Obj.IsPE) {
372 StrTabBuilder.write(
Ptr);
373 Ptr += StrTabBuilder.getSize();
384 "failed to allocate memory buffer of " +
387 writeHeaders(IsBigObj);
390 writeSymbolStringTables<coff_symbol32>();
392 writeSymbolStringTables<coff_symbol16>();
395 if (Error
E = patchDebugDirectory())
400 Out.write(Buf->getBufferStart(), Buf->getBufferSize());
404 Expected<uint32_t> COFFWriter::virtualAddressToFileAddress(
uint32_t RVA) {
405 for (
const auto &
S : Obj.getSections()) {
406 if (RVA >=
S.Header.VirtualAddress &&
407 RVA <
S.Header.VirtualAddress +
S.Header.SizeOfRawData)
408 return S.Header.PointerToRawData + RVA -
S.Header.VirtualAddress;
411 "debug directory payload not found");
417 Error COFFWriter::patchDebugDirectory() {
423 for (
const auto &
S : Obj.getSections()) {
424 if (Dir->RelativeVirtualAddress >=
S.Header.VirtualAddress &&
425 Dir->RelativeVirtualAddress <
426 S.Header.VirtualAddress +
S.Header.SizeOfRawData) {
427 if (Dir->RelativeVirtualAddress + Dir->Size >
428 S.Header.VirtualAddress +
S.Header.SizeOfRawData)
430 "debug directory extends past end of section");
432 size_t Offset = Dir->RelativeVirtualAddress -
S.Header.VirtualAddress;
433 uint8_t *
Ptr =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) +
434 S.Header.PointerToRawData + Offset;
435 uint8_t *End =
Ptr + Dir->Size;
437 debug_directory *
Debug =
reinterpret_cast<debug_directory *
>(
Ptr);
438 if (
Debug->PointerToRawData) {
439 if (Expected<uint32_t> FilePosOrErr =
440 virtualAddressToFileAddress(
Debug->AddressOfRawData))
441 Debug->PointerToRawData = *FilePosOrErr;
443 return FilePosOrErr.takeError();
445 Ptr +=
sizeof(debug_directory);
446 Offset +=
sizeof(debug_directory);
453 "debug directory not found");
458 if (IsBigObj && Obj.IsPE)
460 "too many sections for executable");
461 return write(IsBigObj);