1 //===- Writer.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 //===----------------------------------------------------------------------===//
11 #include "llvm-objcopy.h"
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/BinaryFormat/COFF.h"
15 #include "llvm/Object/COFF.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 make_error
<StringError
>("Relocation target " + R
.TargetName
+
33 " (" + Twine(R
.Target
) +
35 object_error::invalid_symbol_index
);
36 R
.Reloc
.SymbolTableIndex
= Sym
->RawIndex
;
39 return Error::success();
42 Error
COFFWriter::finalizeSectionNumbers() {
43 for (Symbol
&Sym
: Obj
.getMutableSymbols()) {
44 if (Sym
.TargetSectionId
<= 0) {
45 // Undefined, or a special kind of symbol. These negative values
46 // are stored in the SectionNumber field which is unsigned.
47 Sym
.Sym
.SectionNumber
= static_cast<uint32_t>(Sym
.TargetSectionId
);
49 const Section
*Sec
= Obj
.findSection(Sym
.TargetSectionId
);
51 return make_error
<StringError
>("Symbol " + Sym
.Name
+
52 " points to a removed section",
53 object_error::invalid_symbol_index
);
54 Sym
.Sym
.SectionNumber
= Sec
->Index
;
56 if (Sym
.Sym
.NumberOfAuxSymbols
== 1 &&
57 Sym
.Sym
.StorageClass
== IMAGE_SYM_CLASS_STATIC
) {
58 coff_aux_section_definition
*SD
=
59 reinterpret_cast<coff_aux_section_definition
*>(Sym
.AuxData
.data());
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 make_error
<StringError
>(
69 "Symbol " + Sym
.Name
+ " is associative to a removed section",
70 object_error::invalid_symbol_index
);
71 SDSectionNumber
= Sec
->Index
;
73 // Update the section definition with the new section number.
74 SD
->NumberLowPart
= static_cast<uint16_t>(SDSectionNumber
);
75 SD
->NumberHighPart
= static_cast<uint16_t>(SDSectionNumber
>> 16);
79 return Error::success();
82 void COFFWriter::layoutSections() {
83 for (auto &S
: Obj
.getMutableSections()) {
84 if (S
.Header
.SizeOfRawData
> 0)
85 S
.Header
.PointerToRawData
= FileSize
;
86 FileSize
+= S
.Header
.SizeOfRawData
; // For executables, this is already
87 // aligned to FileAlignment.
88 S
.Header
.NumberOfRelocations
= S
.Relocs
.size();
89 S
.Header
.PointerToRelocations
=
90 S
.Header
.NumberOfRelocations
> 0 ? FileSize
: 0;
91 FileSize
+= S
.Relocs
.size() * sizeof(coff_relocation
);
92 FileSize
= alignTo(FileSize
, FileAlignment
);
94 if (S
.Header
.Characteristics
& IMAGE_SCN_CNT_INITIALIZED_DATA
)
95 SizeOfInitializedData
+= S
.Header
.SizeOfRawData
;
99 size_t COFFWriter::finalizeStringTable() {
100 for (const auto &S
: Obj
.getSections())
101 if (S
.Name
.size() > COFF::NameSize
)
102 StrTabBuilder
.add(S
.Name
);
104 for (const auto &S
: Obj
.getSymbols())
105 if (S
.Name
.size() > COFF::NameSize
)
106 StrTabBuilder
.add(S
.Name
);
108 StrTabBuilder
.finalize();
110 for (auto &S
: Obj
.getMutableSections()) {
111 if (S
.Name
.size() > COFF::NameSize
) {
112 snprintf(S
.Header
.Name
, sizeof(S
.Header
.Name
), "/%d",
113 (int)StrTabBuilder
.getOffset(S
.Name
));
115 strncpy(S
.Header
.Name
, S
.Name
.data(), COFF::NameSize
);
118 for (auto &S
: Obj
.getMutableSymbols()) {
119 if (S
.Name
.size() > COFF::NameSize
) {
120 S
.Sym
.Name
.Offset
.Zeroes
= 0;
121 S
.Sym
.Name
.Offset
.Offset
= StrTabBuilder
.getOffset(S
.Name
);
123 strncpy(S
.Sym
.Name
.ShortName
, S
.Name
.data(), COFF::NameSize
);
126 return StrTabBuilder
.getSize();
129 template <class SymbolTy
>
130 std::pair
<size_t, size_t> COFFWriter::finalizeSymbolTable() {
131 size_t SymTabSize
= Obj
.getSymbols().size() * sizeof(SymbolTy
);
132 for (const auto &S
: Obj
.getSymbols())
133 SymTabSize
+= S
.AuxData
.size();
134 return std::make_pair(SymTabSize
, sizeof(SymbolTy
));
137 Error
COFFWriter::finalize(bool IsBigObj
) {
138 if (Error E
= finalizeRelocTargets())
140 if (Error E
= finalizeSectionNumbers())
143 size_t SizeOfHeaders
= 0;
145 size_t PeHeaderSize
= 0;
147 Obj
.DosHeader
.AddressOfNewExeHeader
=
148 sizeof(Obj
.DosHeader
) + Obj
.DosStub
.size();
149 SizeOfHeaders
+= Obj
.DosHeader
.AddressOfNewExeHeader
+ sizeof(PEMagic
);
151 FileAlignment
= Obj
.PeHeader
.FileAlignment
;
152 Obj
.PeHeader
.NumberOfRvaAndSize
= Obj
.DataDirectories
.size();
154 PeHeaderSize
= Obj
.Is64
? sizeof(pe32plus_header
) : sizeof(pe32_header
);
156 PeHeaderSize
+ sizeof(data_directory
) * Obj
.DataDirectories
.size();
158 Obj
.CoffFileHeader
.NumberOfSections
= Obj
.getSections().size();
160 IsBigObj
? sizeof(coff_bigobj_file_header
) : sizeof(coff_file_header
);
161 SizeOfHeaders
+= sizeof(coff_section
) * Obj
.getSections().size();
162 SizeOfHeaders
= alignTo(SizeOfHeaders
, FileAlignment
);
164 Obj
.CoffFileHeader
.SizeOfOptionalHeader
=
165 PeHeaderSize
+ sizeof(data_directory
) * Obj
.DataDirectories
.size();
167 FileSize
= SizeOfHeaders
;
168 SizeOfInitializedData
= 0;
173 Obj
.PeHeader
.SizeOfHeaders
= SizeOfHeaders
;
174 Obj
.PeHeader
.SizeOfInitializedData
= SizeOfInitializedData
;
176 if (!Obj
.getSections().empty()) {
177 const Section
&S
= Obj
.getSections().back();
178 Obj
.PeHeader
.SizeOfImage
=
179 alignTo(S
.Header
.VirtualAddress
+ S
.Header
.VirtualSize
,
180 Obj
.PeHeader
.SectionAlignment
);
183 // If the PE header had a checksum, clear it, since it isn't valid
184 // any longer. (We don't calculate a new one.)
185 Obj
.PeHeader
.CheckSum
= 0;
188 size_t StrTabSize
= finalizeStringTable();
189 size_t SymTabSize
, SymbolSize
;
190 std::tie(SymTabSize
, SymbolSize
) = IsBigObj
191 ? finalizeSymbolTable
<coff_symbol32
>()
192 : finalizeSymbolTable
<coff_symbol16
>();
194 size_t PointerToSymbolTable
= FileSize
;
195 // StrTabSize <= 4 is the size of an empty string table, only consisting
196 // of the length field.
197 if (SymTabSize
== 0 && StrTabSize
<= 4 && Obj
.IsPE
) {
198 // For executables, don't point to the symbol table and skip writing
199 // the length field, if both the symbol and string tables are empty.
200 PointerToSymbolTable
= 0;
204 size_t NumRawSymbols
= SymTabSize
/ SymbolSize
;
205 Obj
.CoffFileHeader
.PointerToSymbolTable
= PointerToSymbolTable
;
206 Obj
.CoffFileHeader
.NumberOfSymbols
= NumRawSymbols
;
207 FileSize
+= SymTabSize
+ StrTabSize
;
208 FileSize
= alignTo(FileSize
, FileAlignment
);
210 return Error::success();
213 void COFFWriter::writeHeaders(bool IsBigObj
) {
214 uint8_t *Ptr
= Buf
.getBufferStart();
216 memcpy(Ptr
, &Obj
.DosHeader
, sizeof(Obj
.DosHeader
));
217 Ptr
+= sizeof(Obj
.DosHeader
);
218 memcpy(Ptr
, Obj
.DosStub
.data(), Obj
.DosStub
.size());
219 Ptr
+= Obj
.DosStub
.size();
220 memcpy(Ptr
, PEMagic
, sizeof(PEMagic
));
221 Ptr
+= sizeof(PEMagic
);
224 memcpy(Ptr
, &Obj
.CoffFileHeader
, sizeof(Obj
.CoffFileHeader
));
225 Ptr
+= sizeof(Obj
.CoffFileHeader
);
227 // Generate a coff_bigobj_file_header, filling it in with the values
228 // from Obj.CoffFileHeader. All extra fields that don't exist in
229 // coff_file_header can be set to hardcoded values.
230 coff_bigobj_file_header BigObjHeader
;
231 BigObjHeader
.Sig1
= IMAGE_FILE_MACHINE_UNKNOWN
;
232 BigObjHeader
.Sig2
= 0xffff;
233 BigObjHeader
.Version
= BigObjHeader::MinBigObjectVersion
;
234 BigObjHeader
.Machine
= Obj
.CoffFileHeader
.Machine
;
235 BigObjHeader
.TimeDateStamp
= Obj
.CoffFileHeader
.TimeDateStamp
;
236 memcpy(BigObjHeader
.UUID
, BigObjMagic
, sizeof(BigObjMagic
));
237 BigObjHeader
.unused1
= 0;
238 BigObjHeader
.unused2
= 0;
239 BigObjHeader
.unused3
= 0;
240 BigObjHeader
.unused4
= 0;
241 // The value in Obj.CoffFileHeader.NumberOfSections is truncated, thus
242 // get the original one instead.
243 BigObjHeader
.NumberOfSections
= Obj
.getSections().size();
244 BigObjHeader
.PointerToSymbolTable
= Obj
.CoffFileHeader
.PointerToSymbolTable
;
245 BigObjHeader
.NumberOfSymbols
= Obj
.CoffFileHeader
.NumberOfSymbols
;
247 memcpy(Ptr
, &BigObjHeader
, sizeof(BigObjHeader
));
248 Ptr
+= sizeof(BigObjHeader
);
252 memcpy(Ptr
, &Obj
.PeHeader
, sizeof(Obj
.PeHeader
));
253 Ptr
+= sizeof(Obj
.PeHeader
);
255 pe32_header PeHeader
;
256 copyPeHeader(PeHeader
, Obj
.PeHeader
);
257 // The pe32plus_header (stored in Object) lacks the BaseOfData field.
258 PeHeader
.BaseOfData
= Obj
.BaseOfData
;
260 memcpy(Ptr
, &PeHeader
, sizeof(PeHeader
));
261 Ptr
+= sizeof(PeHeader
);
263 for (const auto &DD
: Obj
.DataDirectories
) {
264 memcpy(Ptr
, &DD
, sizeof(DD
));
268 for (const auto &S
: Obj
.getSections()) {
269 memcpy(Ptr
, &S
.Header
, sizeof(S
.Header
));
270 Ptr
+= sizeof(S
.Header
);
274 void COFFWriter::writeSections() {
275 for (const auto &S
: Obj
.getSections()) {
276 uint8_t *Ptr
= Buf
.getBufferStart() + S
.Header
.PointerToRawData
;
277 std::copy(S
.Contents
.begin(), S
.Contents
.end(), Ptr
);
279 // For executable sections, pad the remainder of the raw data size with
280 // 0xcc, which is int3 on x86.
281 if ((S
.Header
.Characteristics
& IMAGE_SCN_CNT_CODE
) &&
282 S
.Header
.SizeOfRawData
> S
.Contents
.size())
283 memset(Ptr
+ S
.Contents
.size(), 0xcc,
284 S
.Header
.SizeOfRawData
- S
.Contents
.size());
286 Ptr
+= S
.Header
.SizeOfRawData
;
287 for (const auto &R
: S
.Relocs
) {
288 memcpy(Ptr
, &R
.Reloc
, sizeof(R
.Reloc
));
289 Ptr
+= sizeof(R
.Reloc
);
294 template <class SymbolTy
> void COFFWriter::writeSymbolStringTables() {
295 uint8_t *Ptr
= Buf
.getBufferStart() + Obj
.CoffFileHeader
.PointerToSymbolTable
;
296 for (const auto &S
: Obj
.getSymbols()) {
297 // Convert symbols back to the right size, from coff_symbol32.
298 copySymbol
<SymbolTy
, coff_symbol32
>(*reinterpret_cast<SymbolTy
*>(Ptr
),
300 Ptr
+= sizeof(SymbolTy
);
301 std::copy(S
.AuxData
.begin(), S
.AuxData
.end(), Ptr
);
302 Ptr
+= S
.AuxData
.size();
304 if (StrTabBuilder
.getSize() > 4 || !Obj
.IsPE
) {
305 // Always write a string table in object files, even an empty one.
306 StrTabBuilder
.write(Ptr
);
307 Ptr
+= StrTabBuilder
.getSize();
311 Error
COFFWriter::write(bool IsBigObj
) {
312 if (Error E
= finalize(IsBigObj
))
315 Buf
.allocate(FileSize
);
317 writeHeaders(IsBigObj
);
320 writeSymbolStringTables
<coff_symbol32
>();
322 writeSymbolStringTables
<coff_symbol16
>();
325 if (Error E
= patchDebugDirectory())
331 // Locate which sections contain the debug directories, iterate over all
332 // the debug_directory structs in there, and set the PointerToRawData field
333 // in all of them, according to their new physical location in the file.
334 Error
COFFWriter::patchDebugDirectory() {
335 if (Obj
.DataDirectories
.size() < DEBUG_DIRECTORY
)
336 return Error::success();
337 const data_directory
*Dir
= &Obj
.DataDirectories
[DEBUG_DIRECTORY
];
339 return Error::success();
340 for (const auto &S
: Obj
.getSections()) {
341 if (Dir
->RelativeVirtualAddress
>= S
.Header
.VirtualAddress
&&
342 Dir
->RelativeVirtualAddress
<
343 S
.Header
.VirtualAddress
+ S
.Header
.SizeOfRawData
) {
344 if (Dir
->RelativeVirtualAddress
+ Dir
->Size
>
345 S
.Header
.VirtualAddress
+ S
.Header
.SizeOfRawData
)
346 return make_error
<StringError
>(
347 "Debug directory extends past end of section",
348 object_error::parse_failed
);
350 size_t Offset
= Dir
->RelativeVirtualAddress
- S
.Header
.VirtualAddress
;
351 uint8_t *Ptr
= Buf
.getBufferStart() + S
.Header
.PointerToRawData
+ Offset
;
352 uint8_t *End
= Ptr
+ Dir
->Size
;
354 debug_directory
*Debug
= reinterpret_cast<debug_directory
*>(Ptr
);
355 Debug
->PointerToRawData
=
356 S
.Header
.PointerToRawData
+ Offset
+ sizeof(debug_directory
);
357 Ptr
+= sizeof(debug_directory
) + Debug
->SizeOfData
;
358 Offset
+= sizeof(debug_directory
) + Debug
->SizeOfData
;
360 // Debug directory found and patched, all done.
361 return Error::success();
364 return make_error
<StringError
>("Debug directory not found",
365 object_error::parse_failed
);
368 Error
COFFWriter::write() {
369 bool IsBigObj
= Obj
.getSections().size() > MaxNumberOfSections16
;
370 if (IsBigObj
&& Obj
.IsPE
)
371 return make_error
<StringError
>("Too many sections for executable",
372 object_error::parse_failed
);
373 return write(IsBigObj
);
376 } // end namespace coff
377 } // end namespace objcopy
378 } // end namespace llvm