26using namespace object;
29Error COFFWriter::finalizeRelocTargets() {
30 for (
Section &Sec : Obj.getMutableSections()) {
31 for (Relocation &R : Sec.Relocs) {
32 const Symbol *Sym = Obj.findSymbol(
R.Target);
35 "relocation target '%s' (%zu) not found",
36 R.TargetName.str().c_str(),
R.Target);
37 R.Reloc.SymbolTableIndex = Sym->RawIndex;
43Error COFFWriter::finalizeSymbolContents() {
44 for (Symbol &Sym : Obj.getMutableSymbols()) {
45 if (Sym.TargetSectionId <= 0) {
48 Sym.Sym.SectionNumber =
static_cast<uint32_t
>(Sym.TargetSectionId);
50 const Section *Sec = Obj.findSection(Sym.TargetSectionId);
53 "symbol '%s' points to a removed section",
54 Sym.Name.str().c_str());
55 Sym.Sym.SectionNumber = Sec->Index;
57 if (Sym.Sym.NumberOfAuxSymbols == 1 &&
59 coff_aux_section_definition *SD =
60 reinterpret_cast<coff_aux_section_definition *
>(
61 Sym.AuxData[0].Opaque);
62 uint32_t SDSectionNumber;
63 if (Sym.AssociativeComdatTargetSectionId == 0) {
66 SDSectionNumber = Sec->Index;
68 Sec = Obj.findSection(Sym.AssociativeComdatTargetSectionId);
71 object_error::invalid_symbol_index,
72 "symbol '%s' is associative to a removed section",
73 Sym.Name.str().c_str());
74 SDSectionNumber = Sec->Index;
77 SD->NumberLowPart =
static_cast<uint16_t
>(SDSectionNumber);
78 SD->NumberHighPart =
static_cast<uint16_t
>(SDSectionNumber >> 16);
83 if (Sym.WeakTargetSymbolId && Sym.Sym.NumberOfAuxSymbols == 1) {
84 coff_aux_weak_external *WE =
85 reinterpret_cast<coff_aux_weak_external *
>(Sym.AuxData[0].Opaque);
86 const Symbol *
Target = Obj.findSymbol(*Sym.WeakTargetSymbolId);
87 if (Target ==
nullptr)
89 "symbol '%s' is missing its weak target",
90 Sym.Name.str().c_str());
91 WE->TagIndex =
Target->RawIndex;
97Error COFFWriter::finalizeSymIdxContents() {
105 auto IsSymIdxSection = [](StringRef
Name) {
106 return Name ==
".gljmp$y" ||
Name ==
".giats$y" ||
Name ==
".gfids$y" ||
107 Name ==
".gehcont$y";
110 DenseMap<size_t, size_t> SymIdMap;
111 SmallDenseMap<ssize_t, coff_aux_section_definition *, 4> SecIdMap;
112 for (Symbol &Sym : Obj.getMutableSymbols()) {
113 SymIdMap[Sym.OriginalRawIndex] = Sym.RawIndex;
118 Sym.Sym.NumberOfAuxSymbols == 1 && Sym.Sym.Value == 0 &&
119 IsSymIdxSection(Sym.Name))
120 SecIdMap[Sym.TargetSectionId] =
121 reinterpret_cast<coff_aux_section_definition *
>(
122 Sym.AuxData[0].Opaque);
125 for (
Section &Sec : Obj.getMutableSections()) {
126 if (!IsSymIdxSection(Sec.Name))
129 ArrayRef<uint8_t> RawIds = Sec.getContents();
132 if (RawIds.size() == 0)
135 auto SecDefIt = SecIdMap.find(Sec.UniqueId);
136 if (SecDefIt == SecIdMap.end())
138 "section '%s' does not have the corresponding "
139 "symbol or the symbol has unexpected format",
140 Sec.Name.str().c_str());
146 std::vector<support::ulittle32_t> NewIds;
148 auto SymIdIt = SymIdMap.find(Id);
149 if (SymIdIt == SymIdMap.end())
151 "section '%s' contains a .symidx (%d) that is "
152 "incorrect or was stripped",
153 Sec.Name.str().c_str(),
Id.value());
156 ArrayRef<uint8_t> NewRawIds(
reinterpret_cast<uint8_t *
>(NewIds.data()),
160 JC.update(NewRawIds);
161 SecDefIt->getSecond()->CheckSum = JC.getCRC();
163 Sec.setOwnedContents(NewRawIds.vec());
168void COFFWriter::layoutSections() {
169 for (
auto &S : Obj.getMutableSections()) {
170 if (S.Header.SizeOfRawData > 0)
171 S.Header.PointerToRawData = FileSize;
173 S.Header.PointerToRawData = 0;
174 FileSize += S.Header.SizeOfRawData;
176 if (S.Relocs.size() >= 0xffff) {
178 S.Header.NumberOfRelocations = 0xffff;
179 S.Header.PointerToRelocations = FileSize;
180 FileSize +=
sizeof(coff_relocation);
182 S.Header.NumberOfRelocations = S.Relocs.size();
183 S.Header.PointerToRelocations = S.Relocs.size() ? FileSize : 0;
186 FileSize += S.Relocs.size() *
sizeof(coff_relocation);
187 FileSize =
alignTo(FileSize, FileAlignment);
190 SizeOfInitializedData += S.Header.SizeOfRawData;
194Expected<size_t> COFFWriter::finalizeStringTable() {
195 for (
const auto &S : Obj.getSections())
199 StrTabBuilder.add(S.Name, UINT8_MAX);
202 for (
const auto &S : Obj.getSymbols())
204 StrTabBuilder.add(S.Name);
206 StrTabBuilder.finalize();
208 for (
auto &S : Obj.getMutableSections()) {
209 memset(S.Header.Name, 0,
sizeof(S.Header.Name));
212 memcpy(S.Header.Name, S.Name.data(), S.Name.size());
215 size_t Offset = StrTabBuilder.getOffset(S.Name);
218 "COFF string table is greater than 64GB, "
219 "unable to encode section name offset");
222 for (
auto &S : Obj.getMutableSymbols()) {
224 S.Sym.Name.Offset.Zeroes = 0;
225 S.Sym.Name.Offset.Offset = StrTabBuilder.getOffset(S.Name);
230 return StrTabBuilder.getSize();
233template <
class SymbolTy>
234std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() {
235 size_t RawSymIndex = 0;
236 for (
auto &S : Obj.getMutableSymbols()) {
240 if (!S.AuxFile.empty())
241 S.Sym.NumberOfAuxSymbols =
242 alignTo(S.AuxFile.size(),
sizeof(SymbolTy)) /
sizeof(SymbolTy);
243 S.RawIndex = RawSymIndex;
244 RawSymIndex += 1 + S.Sym.NumberOfAuxSymbols;
246 return std::make_pair(RawSymIndex *
sizeof(SymbolTy),
sizeof(SymbolTy));
249Error COFFWriter::finalize(
bool IsBigObj) {
250 size_t SymTabSize, SymbolSize;
251 std::tie(SymTabSize, SymbolSize) = IsBigObj
252 ? finalizeSymbolTable<coff_symbol32>()
255 if (
Error E = finalizeRelocTargets())
257 if (
Error E = finalizeSymbolContents())
259 if (
Error E = finalizeSymIdxContents())
262 size_t SizeOfHeaders = 0;
264 size_t PeHeaderSize = 0;
266 Obj.DosHeader.AddressOfNewExeHeader =
267 sizeof(Obj.DosHeader) + Obj.DosStub.size();
268 SizeOfHeaders += Obj.DosHeader.AddressOfNewExeHeader + sizeof(PEMagic);
270 FileAlignment = Obj.PeHeader.FileAlignment;
271 Obj.PeHeader.NumberOfRvaAndSize = Obj.DataDirectories.size();
273 PeHeaderSize = Obj.Is64 ? sizeof(pe32plus_header) : sizeof(pe32_header);
275 PeHeaderSize + sizeof(data_directory) * Obj.DataDirectories.size();
277 Obj.CoffFileHeader.NumberOfSections = Obj.getSections().size();
279 IsBigObj ?
sizeof(coff_bigobj_file_header) :
sizeof(coff_file_header);
280 SizeOfHeaders +=
sizeof(coff_section) * Obj.getSections().size();
281 SizeOfHeaders =
alignTo(SizeOfHeaders, FileAlignment);
283 Obj.CoffFileHeader.SizeOfOptionalHeader =
284 PeHeaderSize +
sizeof(data_directory) * Obj.DataDirectories.size();
286 FileSize = SizeOfHeaders;
287 SizeOfInitializedData = 0;
292 Obj.PeHeader.SizeOfHeaders = SizeOfHeaders;
293 Obj.PeHeader.SizeOfInitializedData = SizeOfInitializedData;
295 if (!Obj.getSections().empty()) {
296 const Section &S = Obj.getSections().back();
297 Obj.PeHeader.SizeOfImage =
298 alignTo(S.Header.VirtualAddress + S.Header.VirtualSize,
299 Obj.PeHeader.SectionAlignment);
304 Obj.PeHeader.CheckSum = 0;
307 Expected<size_t> StrTabSizeOrErr = finalizeStringTable();
308 if (!StrTabSizeOrErr)
309 return StrTabSizeOrErr.takeError();
311 size_t StrTabSize = *StrTabSizeOrErr;
313 size_t PointerToSymbolTable = FileSize;
316 if (SymTabSize == 0 && StrTabSize <= 4 && Obj.IsPE) {
319 PointerToSymbolTable = 0;
323 size_t NumRawSymbols = SymTabSize / SymbolSize;
324 Obj.CoffFileHeader.PointerToSymbolTable = PointerToSymbolTable;
325 Obj.CoffFileHeader.NumberOfSymbols = NumRawSymbols;
326 FileSize += SymTabSize + StrTabSize;
327 FileSize =
alignTo(FileSize, FileAlignment);
332void COFFWriter::writeHeaders(
bool IsBigObj) {
333 uint8_t *
Ptr =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart());
335 memcpy(
Ptr, &Obj.DosHeader,
sizeof(Obj.DosHeader));
336 Ptr +=
sizeof(Obj.DosHeader);
337 memcpy(
Ptr, Obj.DosStub.data(), Obj.DosStub.size());
338 Ptr += Obj.DosStub.size();
343 memcpy(
Ptr, &Obj.CoffFileHeader,
sizeof(Obj.CoffFileHeader));
344 Ptr +=
sizeof(Obj.CoffFileHeader);
349 coff_bigobj_file_header BigObjHeader;
351 BigObjHeader.Sig2 = 0xffff;
353 BigObjHeader.Machine = Obj.CoffFileHeader.Machine;
354 BigObjHeader.TimeDateStamp = Obj.CoffFileHeader.TimeDateStamp;
356 BigObjHeader.unused1 = 0;
357 BigObjHeader.unused2 = 0;
358 BigObjHeader.unused3 = 0;
359 BigObjHeader.unused4 = 0;
362 BigObjHeader.NumberOfSections = Obj.getSections().size();
363 BigObjHeader.PointerToSymbolTable = Obj.CoffFileHeader.PointerToSymbolTable;
364 BigObjHeader.NumberOfSymbols = Obj.CoffFileHeader.NumberOfSymbols;
366 memcpy(
Ptr, &BigObjHeader,
sizeof(BigObjHeader));
367 Ptr +=
sizeof(BigObjHeader);
371 memcpy(
Ptr, &Obj.PeHeader,
sizeof(Obj.PeHeader));
372 Ptr +=
sizeof(Obj.PeHeader);
374 pe32_header PeHeader;
377 PeHeader.BaseOfData = Obj.BaseOfData;
379 memcpy(
Ptr, &PeHeader,
sizeof(PeHeader));
380 Ptr +=
sizeof(PeHeader);
382 for (
const auto &DD : Obj.DataDirectories) {
383 memcpy(
Ptr, &DD,
sizeof(DD));
387 for (
const auto &S : Obj.getSections()) {
388 memcpy(
Ptr, &S.Header,
sizeof(S.Header));
389 Ptr +=
sizeof(S.Header);
393void COFFWriter::writeSections() {
394 for (
const auto &S : Obj.getSections()) {
395 uint8_t *
Ptr =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) +
396 S.Header.PointerToRawData;
397 ArrayRef<uint8_t> Contents = S.getContents();
403 S.Header.SizeOfRawData > Contents.size())
404 memset(
Ptr + Contents.size(), 0xcc,
405 S.Header.SizeOfRawData - Contents.size());
407 Ptr += S.Header.SizeOfRawData;
409 if (S.Relocs.size() >= 0xffff) {
410 object::coff_relocation
R;
411 R.VirtualAddress = S.Relocs.size() + 1;
412 R.SymbolTableIndex = 0;
414 memcpy(
Ptr, &R,
sizeof(R));
417 for (
const auto &R : S.Relocs) {
418 memcpy(
Ptr, &
R.Reloc,
sizeof(
R.Reloc));
419 Ptr +=
sizeof(
R.Reloc);
424template <
class SymbolTy>
void COFFWriter::writeSymbolStringTables() {
425 uint8_t *
Ptr =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) +
426 Obj.CoffFileHeader.PointerToSymbolTable;
427 for (
const auto &S : Obj.getSymbols()) {
431 Ptr +=
sizeof(SymbolTy);
432 if (!S.AuxFile.empty()) {
437 Ptr += S.Sym.NumberOfAuxSymbols *
sizeof(SymbolTy);
443 for (
const AuxSymbol &AuxSym : S.AuxData) {
444 ArrayRef<uint8_t>
Ref = AuxSym.getRef();
446 Ptr +=
sizeof(SymbolTy);
450 if (StrTabBuilder.getSize() > 4 || !Obj.IsPE) {
452 StrTabBuilder.write(
Ptr);
453 Ptr += StrTabBuilder.getSize();
464 "failed to allocate memory buffer of " +
467 writeHeaders(IsBigObj);
470 writeSymbolStringTables<coff_symbol32>();
472 writeSymbolStringTables<coff_symbol16>();
475 if (
Error E = patchDebugDirectory())
480 Out.write(Buf->getBufferStart(), Buf->getBufferSize());
484Expected<uint32_t> COFFWriter::virtualAddressToFileAddress(uint32_t RVA) {
485 for (
const auto &S : Obj.getSections()) {
486 if (RVA >= S.Header.VirtualAddress &&
487 RVA < S.Header.VirtualAddress + S.Header.SizeOfRawData)
488 return S.Header.PointerToRawData + RVA - S.Header.VirtualAddress;
491 "debug directory payload not found");
497Error COFFWriter::patchDebugDirectory() {
503 for (
const auto &S : Obj.getSections()) {
504 if (Dir->RelativeVirtualAddress >= S.Header.VirtualAddress &&
505 Dir->RelativeVirtualAddress <
506 S.Header.VirtualAddress + S.Header.SizeOfRawData) {
507 if (Dir->RelativeVirtualAddress + Dir->Size >
508 S.Header.VirtualAddress + S.Header.SizeOfRawData)
510 "debug directory extends past end of section");
512 size_t Offset = Dir->RelativeVirtualAddress - S.Header.VirtualAddress;
513 uint8_t *
Ptr =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) +
514 S.Header.PointerToRawData +
Offset;
515 uint8_t *End =
Ptr + Dir->Size;
517 debug_directory *
Debug =
reinterpret_cast<debug_directory *
>(
Ptr);
518 if (
Debug->PointerToRawData) {
519 if (Expected<uint32_t> FilePosOrErr =
520 virtualAddressToFileAddress(
Debug->AddressOfRawData))
521 Debug->PointerToRawData = *FilePosOrErr;
523 return FilePosOrErr.takeError();
525 Ptr +=
sizeof(debug_directory);
526 Offset +=
sizeof(debug_directory);
533 "debug directory not found");
538 if (IsBigObj && Obj.IsPE)
540 "too many sections for executable");
541 return write(IsBigObj);
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
static Twine utohexstr(uint64_t Val)
static LLVM_ABI std::unique_ptr< WritableMemoryBuffer > getNewMemBuffer(size_t Size, const Twine &BufferName="")
Allocate a new zero-initialized MemoryBuffer of the specified size.
@ IMAGE_FILE_MACHINE_UNKNOWN
@ IMAGE_SCN_CNT_INITIALIZED_DATA
@ IMAGE_SCN_LNK_NRELOC_OVFL
@ IMAGE_SYM_CLASS_STATIC
Static.
LLVM_ABI bool encodeSectionName(char *Out, uint64_t Offset)
Encode section name based on string table offset.
const int32_t MaxNumberOfSections16
static const char BigObjMagic[]
static const char PEMagic[]
void copySymbol(Symbol1Ty &Dest, const Symbol2Ty &Src)
void copyPeHeader(PeHeader1Ty &Dest, const PeHeader2Ty &Src)
coff_symbol< support::ulittle16_t > coff_symbol16
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
This is an optimization pass for GlobalISel generic memory operations.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
@ Ref
The access may reference the value stored in memory.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)