1 //===- COFFWriter.cpp -----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "COFFWriter.h"
10 #include "COFFObject.h"
11 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/BinaryFormat/COFF.h"
14 #include "llvm/Object/COFF.h"
15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/ErrorHandling.h"
24 using namespace object
;
27 Error
COFFWriter::finalizeRelocTargets() {
28 for (Section
&Sec
: Obj
.getMutableSections()) {
29 for (Relocation
&R
: Sec
.Relocs
) {
30 const Symbol
*Sym
= Obj
.findSymbol(R
.Target
);
32 return createStringError(object_error::invalid_symbol_index
,
33 "relocation target '%s' (%zu) not found",
34 R
.TargetName
.str().c_str(), R
.Target
);
35 R
.Reloc
.SymbolTableIndex
= Sym
->RawIndex
;
38 return Error::success();
41 Error
COFFWriter::finalizeSymbolContents() {
42 for (Symbol
&Sym
: Obj
.getMutableSymbols()) {
43 if (Sym
.TargetSectionId
<= 0) {
44 // Undefined, or a special kind of symbol. These negative values
45 // are stored in the SectionNumber field which is unsigned.
46 Sym
.Sym
.SectionNumber
= static_cast<uint32_t>(Sym
.TargetSectionId
);
48 const Section
*Sec
= Obj
.findSection(Sym
.TargetSectionId
);
50 return createStringError(object_error::invalid_symbol_index
,
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 &&
56 Sym
.Sym
.StorageClass
== IMAGE_SYM_CLASS_STATIC
) {
57 coff_aux_section_definition
*SD
=
58 reinterpret_cast<coff_aux_section_definition
*>(
59 Sym
.AuxData
[0].Opaque
);
60 uint32_t SDSectionNumber
;
61 if (Sym
.AssociativeComdatTargetSectionId
== 0) {
62 // Not a comdat associative section; just set the Number field to
63 // the number of the section itself.
64 SDSectionNumber
= Sec
->Index
;
66 Sec
= Obj
.findSection(Sym
.AssociativeComdatTargetSectionId
);
68 return createStringError(
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
;
74 // Update the section definition with the new section number.
75 SD
->NumberLowPart
= static_cast<uint16_t>(SDSectionNumber
);
76 SD
->NumberHighPart
= static_cast<uint16_t>(SDSectionNumber
>> 16);
79 // Check that we actually have got AuxData to match the weak symbol target
80 // we want to set. Only >= 1 would be required, but only == 1 makes sense.
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)
86 return createStringError(object_error::invalid_symbol_index
,
87 "symbol '%s' is missing its weak target",
88 Sym
.Name
.str().c_str());
89 WE
->TagIndex
= Target
->RawIndex
;
92 return Error::success();
95 void COFFWriter::layoutSections() {
96 for (auto &S
: Obj
.getMutableSections()) {
97 if (S
.Header
.SizeOfRawData
> 0)
98 S
.Header
.PointerToRawData
= FileSize
;
100 S
.Header
.PointerToRawData
= 0;
101 FileSize
+= S
.Header
.SizeOfRawData
; // For executables, this is already
102 // aligned to FileAlignment.
103 if (S
.Relocs
.size() >= 0xffff) {
104 S
.Header
.Characteristics
|= COFF::IMAGE_SCN_LNK_NRELOC_OVFL
;
105 S
.Header
.NumberOfRelocations
= 0xffff;
106 S
.Header
.PointerToRelocations
= FileSize
;
107 FileSize
+= sizeof(coff_relocation
);
109 S
.Header
.NumberOfRelocations
= S
.Relocs
.size();
110 S
.Header
.PointerToRelocations
= S
.Relocs
.size() ? FileSize
: 0;
113 FileSize
+= S
.Relocs
.size() * sizeof(coff_relocation
);
114 FileSize
= alignTo(FileSize
, FileAlignment
);
116 if (S
.Header
.Characteristics
& IMAGE_SCN_CNT_INITIALIZED_DATA
)
117 SizeOfInitializedData
+= S
.Header
.SizeOfRawData
;
121 Expected
<size_t> COFFWriter::finalizeStringTable() {
122 for (const auto &S
: Obj
.getSections())
123 if (S
.Name
.size() > COFF::NameSize
)
124 StrTabBuilder
.add(S
.Name
);
126 for (const auto &S
: Obj
.getSymbols())
127 if (S
.Name
.size() > COFF::NameSize
)
128 StrTabBuilder
.add(S
.Name
);
130 StrTabBuilder
.finalize();
132 for (auto &S
: Obj
.getMutableSections()) {
133 memset(S
.Header
.Name
, 0, sizeof(S
.Header
.Name
));
134 if (S
.Name
.size() <= COFF::NameSize
) {
135 // Short names can go in the field directly.
136 memcpy(S
.Header
.Name
, S
.Name
.data(), S
.Name
.size());
138 // Offset of the section name in the string table.
139 size_t Offset
= StrTabBuilder
.getOffset(S
.Name
);
140 if (!COFF::encodeSectionName(S
.Header
.Name
, Offset
))
141 return createStringError(object_error::invalid_section_index
,
142 "COFF string table is greater than 64GB, "
143 "unable to encode section name offset");
146 for (auto &S
: Obj
.getMutableSymbols()) {
147 if (S
.Name
.size() > COFF::NameSize
) {
148 S
.Sym
.Name
.Offset
.Zeroes
= 0;
149 S
.Sym
.Name
.Offset
.Offset
= StrTabBuilder
.getOffset(S
.Name
);
151 strncpy(S
.Sym
.Name
.ShortName
, S
.Name
.data(), COFF::NameSize
);
154 return StrTabBuilder
.getSize();
157 template <class SymbolTy
>
158 std::pair
<size_t, size_t> COFFWriter::finalizeSymbolTable() {
159 size_t RawSymIndex
= 0;
160 for (auto &S
: Obj
.getMutableSymbols()) {
161 // Symbols normally have NumberOfAuxSymbols set correctly all the time.
162 // For file symbols, we need to know the output file's symbol size to be
163 // able to calculate the number of slots it occupies.
164 if (!S
.AuxFile
.empty())
165 S
.Sym
.NumberOfAuxSymbols
=
166 alignTo(S
.AuxFile
.size(), sizeof(SymbolTy
)) / sizeof(SymbolTy
);
167 S
.RawIndex
= RawSymIndex
;
168 RawSymIndex
+= 1 + S
.Sym
.NumberOfAuxSymbols
;
170 return std::make_pair(RawSymIndex
* sizeof(SymbolTy
), sizeof(SymbolTy
));
173 Error
COFFWriter::finalize(bool IsBigObj
) {
174 size_t SymTabSize
, SymbolSize
;
175 std::tie(SymTabSize
, SymbolSize
) = IsBigObj
176 ? finalizeSymbolTable
<coff_symbol32
>()
177 : finalizeSymbolTable
<coff_symbol16
>();
179 if (Error E
= finalizeRelocTargets())
181 if (Error E
= finalizeSymbolContents())
184 size_t SizeOfHeaders
= 0;
186 size_t PeHeaderSize
= 0;
188 Obj
.DosHeader
.AddressOfNewExeHeader
=
189 sizeof(Obj
.DosHeader
) + Obj
.DosStub
.size();
190 SizeOfHeaders
+= Obj
.DosHeader
.AddressOfNewExeHeader
+ sizeof(PEMagic
);
192 FileAlignment
= Obj
.PeHeader
.FileAlignment
;
193 Obj
.PeHeader
.NumberOfRvaAndSize
= Obj
.DataDirectories
.size();
195 PeHeaderSize
= Obj
.Is64
? sizeof(pe32plus_header
) : sizeof(pe32_header
);
197 PeHeaderSize
+ sizeof(data_directory
) * Obj
.DataDirectories
.size();
199 Obj
.CoffFileHeader
.NumberOfSections
= Obj
.getSections().size();
201 IsBigObj
? sizeof(coff_bigobj_file_header
) : sizeof(coff_file_header
);
202 SizeOfHeaders
+= sizeof(coff_section
) * Obj
.getSections().size();
203 SizeOfHeaders
= alignTo(SizeOfHeaders
, FileAlignment
);
205 Obj
.CoffFileHeader
.SizeOfOptionalHeader
=
206 PeHeaderSize
+ sizeof(data_directory
) * Obj
.DataDirectories
.size();
208 FileSize
= SizeOfHeaders
;
209 SizeOfInitializedData
= 0;
214 Obj
.PeHeader
.SizeOfHeaders
= SizeOfHeaders
;
215 Obj
.PeHeader
.SizeOfInitializedData
= SizeOfInitializedData
;
217 if (!Obj
.getSections().empty()) {
218 const Section
&S
= Obj
.getSections().back();
219 Obj
.PeHeader
.SizeOfImage
=
220 alignTo(S
.Header
.VirtualAddress
+ S
.Header
.VirtualSize
,
221 Obj
.PeHeader
.SectionAlignment
);
224 // If the PE header had a checksum, clear it, since it isn't valid
225 // any longer. (We don't calculate a new one.)
226 Obj
.PeHeader
.CheckSum
= 0;
229 Expected
<size_t> StrTabSizeOrErr
= finalizeStringTable();
230 if (!StrTabSizeOrErr
)
231 return StrTabSizeOrErr
.takeError();
233 size_t StrTabSize
= *StrTabSizeOrErr
;
235 size_t PointerToSymbolTable
= FileSize
;
236 // StrTabSize <= 4 is the size of an empty string table, only consisting
237 // of the length field.
238 if (SymTabSize
== 0 && StrTabSize
<= 4 && Obj
.IsPE
) {
239 // For executables, don't point to the symbol table and skip writing
240 // the length field, if both the symbol and string tables are empty.
241 PointerToSymbolTable
= 0;
245 size_t NumRawSymbols
= SymTabSize
/ SymbolSize
;
246 Obj
.CoffFileHeader
.PointerToSymbolTable
= PointerToSymbolTable
;
247 Obj
.CoffFileHeader
.NumberOfSymbols
= NumRawSymbols
;
248 FileSize
+= SymTabSize
+ StrTabSize
;
249 FileSize
= alignTo(FileSize
, FileAlignment
);
251 return Error::success();
254 void COFFWriter::writeHeaders(bool IsBigObj
) {
255 uint8_t *Ptr
= reinterpret_cast<uint8_t *>(Buf
->getBufferStart());
257 memcpy(Ptr
, &Obj
.DosHeader
, sizeof(Obj
.DosHeader
));
258 Ptr
+= sizeof(Obj
.DosHeader
);
259 memcpy(Ptr
, Obj
.DosStub
.data(), Obj
.DosStub
.size());
260 Ptr
+= Obj
.DosStub
.size();
261 memcpy(Ptr
, PEMagic
, sizeof(PEMagic
));
262 Ptr
+= sizeof(PEMagic
);
265 memcpy(Ptr
, &Obj
.CoffFileHeader
, sizeof(Obj
.CoffFileHeader
));
266 Ptr
+= sizeof(Obj
.CoffFileHeader
);
268 // Generate a coff_bigobj_file_header, filling it in with the values
269 // from Obj.CoffFileHeader. All extra fields that don't exist in
270 // coff_file_header can be set to hardcoded values.
271 coff_bigobj_file_header BigObjHeader
;
272 BigObjHeader
.Sig1
= IMAGE_FILE_MACHINE_UNKNOWN
;
273 BigObjHeader
.Sig2
= 0xffff;
274 BigObjHeader
.Version
= BigObjHeader::MinBigObjectVersion
;
275 BigObjHeader
.Machine
= Obj
.CoffFileHeader
.Machine
;
276 BigObjHeader
.TimeDateStamp
= Obj
.CoffFileHeader
.TimeDateStamp
;
277 memcpy(BigObjHeader
.UUID
, BigObjMagic
, sizeof(BigObjMagic
));
278 BigObjHeader
.unused1
= 0;
279 BigObjHeader
.unused2
= 0;
280 BigObjHeader
.unused3
= 0;
281 BigObjHeader
.unused4
= 0;
282 // The value in Obj.CoffFileHeader.NumberOfSections is truncated, thus
283 // get the original one instead.
284 BigObjHeader
.NumberOfSections
= Obj
.getSections().size();
285 BigObjHeader
.PointerToSymbolTable
= Obj
.CoffFileHeader
.PointerToSymbolTable
;
286 BigObjHeader
.NumberOfSymbols
= Obj
.CoffFileHeader
.NumberOfSymbols
;
288 memcpy(Ptr
, &BigObjHeader
, sizeof(BigObjHeader
));
289 Ptr
+= sizeof(BigObjHeader
);
293 memcpy(Ptr
, &Obj
.PeHeader
, sizeof(Obj
.PeHeader
));
294 Ptr
+= sizeof(Obj
.PeHeader
);
296 pe32_header PeHeader
;
297 copyPeHeader(PeHeader
, Obj
.PeHeader
);
298 // The pe32plus_header (stored in Object) lacks the BaseOfData field.
299 PeHeader
.BaseOfData
= Obj
.BaseOfData
;
301 memcpy(Ptr
, &PeHeader
, sizeof(PeHeader
));
302 Ptr
+= sizeof(PeHeader
);
304 for (const auto &DD
: Obj
.DataDirectories
) {
305 memcpy(Ptr
, &DD
, sizeof(DD
));
309 for (const auto &S
: Obj
.getSections()) {
310 memcpy(Ptr
, &S
.Header
, sizeof(S
.Header
));
311 Ptr
+= sizeof(S
.Header
);
315 void COFFWriter::writeSections() {
316 for (const auto &S
: Obj
.getSections()) {
317 uint8_t *Ptr
= reinterpret_cast<uint8_t *>(Buf
->getBufferStart()) +
318 S
.Header
.PointerToRawData
;
319 ArrayRef
<uint8_t> Contents
= S
.getContents();
320 std::copy(Contents
.begin(), Contents
.end(), Ptr
);
322 // For executable sections, pad the remainder of the raw data size with
323 // 0xcc, which is int3 on x86.
324 if ((S
.Header
.Characteristics
& IMAGE_SCN_CNT_CODE
) &&
325 S
.Header
.SizeOfRawData
> Contents
.size())
326 memset(Ptr
+ Contents
.size(), 0xcc,
327 S
.Header
.SizeOfRawData
- Contents
.size());
329 Ptr
+= S
.Header
.SizeOfRawData
;
331 if (S
.Relocs
.size() >= 0xffff) {
332 object::coff_relocation R
;
333 R
.VirtualAddress
= S
.Relocs
.size() + 1;
334 R
.SymbolTableIndex
= 0;
336 memcpy(Ptr
, &R
, sizeof(R
));
339 for (const auto &R
: S
.Relocs
) {
340 memcpy(Ptr
, &R
.Reloc
, sizeof(R
.Reloc
));
341 Ptr
+= sizeof(R
.Reloc
);
346 template <class SymbolTy
> void COFFWriter::writeSymbolStringTables() {
347 uint8_t *Ptr
= reinterpret_cast<uint8_t *>(Buf
->getBufferStart()) +
348 Obj
.CoffFileHeader
.PointerToSymbolTable
;
349 for (const auto &S
: Obj
.getSymbols()) {
350 // Convert symbols back to the right size, from coff_symbol32.
351 copySymbol
<SymbolTy
, coff_symbol32
>(*reinterpret_cast<SymbolTy
*>(Ptr
),
353 Ptr
+= sizeof(SymbolTy
);
354 if (!S
.AuxFile
.empty()) {
355 // For file symbols, just write the string into the aux symbol slots,
356 // assuming that the unwritten parts are initialized to zero in the memory
358 std::copy(S
.AuxFile
.begin(), S
.AuxFile
.end(), Ptr
);
359 Ptr
+= S
.Sym
.NumberOfAuxSymbols
* sizeof(SymbolTy
);
361 // For other auxillary symbols, write their opaque payload into one symbol
362 // table slot each. For big object files, the symbols are larger than the
363 // opaque auxillary symbol struct and we leave padding at the end of each
365 for (const AuxSymbol
&AuxSym
: S
.AuxData
) {
366 ArrayRef
<uint8_t> Ref
= AuxSym
.getRef();
367 std::copy(Ref
.begin(), Ref
.end(), Ptr
);
368 Ptr
+= sizeof(SymbolTy
);
372 if (StrTabBuilder
.getSize() > 4 || !Obj
.IsPE
) {
373 // Always write a string table in object files, even an empty one.
374 StrTabBuilder
.write(Ptr
);
375 Ptr
+= StrTabBuilder
.getSize();
379 Error
COFFWriter::write(bool IsBigObj
) {
380 if (Error E
= finalize(IsBigObj
))
383 Buf
= WritableMemoryBuffer::getNewMemBuffer(FileSize
);
385 return createStringError(llvm::errc::not_enough_memory
,
386 "failed to allocate memory buffer of " +
387 Twine::utohexstr(FileSize
) + " bytes.");
389 writeHeaders(IsBigObj
);
392 writeSymbolStringTables
<coff_symbol32
>();
394 writeSymbolStringTables
<coff_symbol16
>();
397 if (Error E
= patchDebugDirectory())
400 // TODO: Implement direct writing to the output stream (without intermediate
401 // memory buffer Buf).
402 Out
.write(Buf
->getBufferStart(), Buf
->getBufferSize());
403 return Error::success();
406 Expected
<uint32_t> COFFWriter::virtualAddressToFileAddress(uint32_t RVA
) {
407 for (const auto &S
: Obj
.getSections()) {
408 if (RVA
>= S
.Header
.VirtualAddress
&&
409 RVA
< S
.Header
.VirtualAddress
+ S
.Header
.SizeOfRawData
)
410 return S
.Header
.PointerToRawData
+ RVA
- S
.Header
.VirtualAddress
;
412 return createStringError(object_error::parse_failed
,
413 "debug directory payload not found");
416 // Locate which sections contain the debug directories, iterate over all
417 // the debug_directory structs in there, and set the PointerToRawData field
418 // in all of them, according to their new physical location in the file.
419 Error
COFFWriter::patchDebugDirectory() {
420 if (Obj
.DataDirectories
.size() <= DEBUG_DIRECTORY
)
421 return Error::success();
422 const data_directory
*Dir
= &Obj
.DataDirectories
[DEBUG_DIRECTORY
];
424 return Error::success();
425 for (const auto &S
: Obj
.getSections()) {
426 if (Dir
->RelativeVirtualAddress
>= S
.Header
.VirtualAddress
&&
427 Dir
->RelativeVirtualAddress
<
428 S
.Header
.VirtualAddress
+ S
.Header
.SizeOfRawData
) {
429 if (Dir
->RelativeVirtualAddress
+ Dir
->Size
>
430 S
.Header
.VirtualAddress
+ S
.Header
.SizeOfRawData
)
431 return createStringError(object_error::parse_failed
,
432 "debug directory extends past end of section");
434 size_t Offset
= Dir
->RelativeVirtualAddress
- S
.Header
.VirtualAddress
;
435 uint8_t *Ptr
= reinterpret_cast<uint8_t *>(Buf
->getBufferStart()) +
436 S
.Header
.PointerToRawData
+ Offset
;
437 uint8_t *End
= Ptr
+ Dir
->Size
;
439 debug_directory
*Debug
= reinterpret_cast<debug_directory
*>(Ptr
);
440 if (Debug
->PointerToRawData
) {
441 if (Expected
<uint32_t> FilePosOrErr
=
442 virtualAddressToFileAddress(Debug
->AddressOfRawData
))
443 Debug
->PointerToRawData
= *FilePosOrErr
;
445 return FilePosOrErr
.takeError();
447 Ptr
+= sizeof(debug_directory
);
448 Offset
+= sizeof(debug_directory
);
450 // Debug directory found and patched, all done.
451 return Error::success();
454 return createStringError(object_error::parse_failed
,
455 "debug directory not found");
458 Error
COFFWriter::write() {
459 bool IsBigObj
= Obj
.getSections().size() > MaxNumberOfSections16
;
460 if (IsBigObj
&& Obj
.IsPE
)
461 return createStringError(object_error::parse_failed
,
462 "too many sections for executable");
463 return write(IsBigObj
);
466 } // end namespace coff
467 } // end namespace objcopy
468 } // end namespace llvm