1*81ad6265SDimitry Andric //===- COFFWriter.cpp -----------------------------------------------------===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric 9*81ad6265SDimitry Andric #include "COFFWriter.h" 10*81ad6265SDimitry Andric #include "COFFObject.h" 11*81ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h" 12*81ad6265SDimitry Andric #include "llvm/ADT/StringRef.h" 13*81ad6265SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 14*81ad6265SDimitry Andric #include "llvm/Object/COFF.h" 15*81ad6265SDimitry Andric #include "llvm/Support/Errc.h" 16*81ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h" 17*81ad6265SDimitry Andric #include <cstddef> 18*81ad6265SDimitry Andric #include <cstdint> 19*81ad6265SDimitry Andric 20*81ad6265SDimitry Andric namespace llvm { 21*81ad6265SDimitry Andric namespace objcopy { 22*81ad6265SDimitry Andric namespace coff { 23*81ad6265SDimitry Andric 24*81ad6265SDimitry Andric using namespace object; 25*81ad6265SDimitry Andric using namespace COFF; 26*81ad6265SDimitry Andric 27*81ad6265SDimitry Andric Error COFFWriter::finalizeRelocTargets() { 28*81ad6265SDimitry Andric for (Section &Sec : Obj.getMutableSections()) { 29*81ad6265SDimitry Andric for (Relocation &R : Sec.Relocs) { 30*81ad6265SDimitry Andric const Symbol *Sym = Obj.findSymbol(R.Target); 31*81ad6265SDimitry Andric if (Sym == nullptr) 32*81ad6265SDimitry Andric return createStringError(object_error::invalid_symbol_index, 33*81ad6265SDimitry Andric "relocation target '%s' (%zu) not found", 34*81ad6265SDimitry Andric R.TargetName.str().c_str(), R.Target); 35*81ad6265SDimitry Andric R.Reloc.SymbolTableIndex = Sym->RawIndex; 36*81ad6265SDimitry Andric } 37*81ad6265SDimitry Andric } 38*81ad6265SDimitry Andric return Error::success(); 39*81ad6265SDimitry Andric } 40*81ad6265SDimitry Andric 41*81ad6265SDimitry Andric Error COFFWriter::finalizeSymbolContents() { 42*81ad6265SDimitry Andric for (Symbol &Sym : Obj.getMutableSymbols()) { 43*81ad6265SDimitry Andric if (Sym.TargetSectionId <= 0) { 44*81ad6265SDimitry Andric // Undefined, or a special kind of symbol. These negative values 45*81ad6265SDimitry Andric // are stored in the SectionNumber field which is unsigned. 46*81ad6265SDimitry Andric Sym.Sym.SectionNumber = static_cast<uint32_t>(Sym.TargetSectionId); 47*81ad6265SDimitry Andric } else { 48*81ad6265SDimitry Andric const Section *Sec = Obj.findSection(Sym.TargetSectionId); 49*81ad6265SDimitry Andric if (Sec == nullptr) 50*81ad6265SDimitry Andric return createStringError(object_error::invalid_symbol_index, 51*81ad6265SDimitry Andric "symbol '%s' points to a removed section", 52*81ad6265SDimitry Andric Sym.Name.str().c_str()); 53*81ad6265SDimitry Andric Sym.Sym.SectionNumber = Sec->Index; 54*81ad6265SDimitry Andric 55*81ad6265SDimitry Andric if (Sym.Sym.NumberOfAuxSymbols == 1 && 56*81ad6265SDimitry Andric Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC) { 57*81ad6265SDimitry Andric coff_aux_section_definition *SD = 58*81ad6265SDimitry Andric reinterpret_cast<coff_aux_section_definition *>( 59*81ad6265SDimitry Andric Sym.AuxData[0].Opaque); 60*81ad6265SDimitry Andric uint32_t SDSectionNumber; 61*81ad6265SDimitry Andric if (Sym.AssociativeComdatTargetSectionId == 0) { 62*81ad6265SDimitry Andric // Not a comdat associative section; just set the Number field to 63*81ad6265SDimitry Andric // the number of the section itself. 64*81ad6265SDimitry Andric SDSectionNumber = Sec->Index; 65*81ad6265SDimitry Andric } else { 66*81ad6265SDimitry Andric Sec = Obj.findSection(Sym.AssociativeComdatTargetSectionId); 67*81ad6265SDimitry Andric if (Sec == nullptr) 68*81ad6265SDimitry Andric return createStringError( 69*81ad6265SDimitry Andric object_error::invalid_symbol_index, 70*81ad6265SDimitry Andric "symbol '%s' is associative to a removed section", 71*81ad6265SDimitry Andric Sym.Name.str().c_str()); 72*81ad6265SDimitry Andric SDSectionNumber = Sec->Index; 73*81ad6265SDimitry Andric } 74*81ad6265SDimitry Andric // Update the section definition with the new section number. 75*81ad6265SDimitry Andric SD->NumberLowPart = static_cast<uint16_t>(SDSectionNumber); 76*81ad6265SDimitry Andric SD->NumberHighPart = static_cast<uint16_t>(SDSectionNumber >> 16); 77*81ad6265SDimitry Andric } 78*81ad6265SDimitry Andric } 79*81ad6265SDimitry Andric // Check that we actually have got AuxData to match the weak symbol target 80*81ad6265SDimitry Andric // we want to set. Only >= 1 would be required, but only == 1 makes sense. 81*81ad6265SDimitry Andric if (Sym.WeakTargetSymbolId && Sym.Sym.NumberOfAuxSymbols == 1) { 82*81ad6265SDimitry Andric coff_aux_weak_external *WE = 83*81ad6265SDimitry Andric reinterpret_cast<coff_aux_weak_external *>(Sym.AuxData[0].Opaque); 84*81ad6265SDimitry Andric const Symbol *Target = Obj.findSymbol(*Sym.WeakTargetSymbolId); 85*81ad6265SDimitry Andric if (Target == nullptr) 86*81ad6265SDimitry Andric return createStringError(object_error::invalid_symbol_index, 87*81ad6265SDimitry Andric "symbol '%s' is missing its weak target", 88*81ad6265SDimitry Andric Sym.Name.str().c_str()); 89*81ad6265SDimitry Andric WE->TagIndex = Target->RawIndex; 90*81ad6265SDimitry Andric } 91*81ad6265SDimitry Andric } 92*81ad6265SDimitry Andric return Error::success(); 93*81ad6265SDimitry Andric } 94*81ad6265SDimitry Andric 95*81ad6265SDimitry Andric void COFFWriter::layoutSections() { 96*81ad6265SDimitry Andric for (auto &S : Obj.getMutableSections()) { 97*81ad6265SDimitry Andric if (S.Header.SizeOfRawData > 0) 98*81ad6265SDimitry Andric S.Header.PointerToRawData = FileSize; 99*81ad6265SDimitry Andric FileSize += S.Header.SizeOfRawData; // For executables, this is already 100*81ad6265SDimitry Andric // aligned to FileAlignment. 101*81ad6265SDimitry Andric if (S.Relocs.size() >= 0xffff) { 102*81ad6265SDimitry Andric S.Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; 103*81ad6265SDimitry Andric S.Header.NumberOfRelocations = 0xffff; 104*81ad6265SDimitry Andric S.Header.PointerToRelocations = FileSize; 105*81ad6265SDimitry Andric FileSize += sizeof(coff_relocation); 106*81ad6265SDimitry Andric } else { 107*81ad6265SDimitry Andric S.Header.NumberOfRelocations = S.Relocs.size(); 108*81ad6265SDimitry Andric S.Header.PointerToRelocations = S.Relocs.size() ? FileSize : 0; 109*81ad6265SDimitry Andric } 110*81ad6265SDimitry Andric 111*81ad6265SDimitry Andric FileSize += S.Relocs.size() * sizeof(coff_relocation); 112*81ad6265SDimitry Andric FileSize = alignTo(FileSize, FileAlignment); 113*81ad6265SDimitry Andric 114*81ad6265SDimitry Andric if (S.Header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) 115*81ad6265SDimitry Andric SizeOfInitializedData += S.Header.SizeOfRawData; 116*81ad6265SDimitry Andric } 117*81ad6265SDimitry Andric } 118*81ad6265SDimitry Andric 119*81ad6265SDimitry Andric Expected<size_t> COFFWriter::finalizeStringTable() { 120*81ad6265SDimitry Andric for (const auto &S : Obj.getSections()) 121*81ad6265SDimitry Andric if (S.Name.size() > COFF::NameSize) 122*81ad6265SDimitry Andric StrTabBuilder.add(S.Name); 123*81ad6265SDimitry Andric 124*81ad6265SDimitry Andric for (const auto &S : Obj.getSymbols()) 125*81ad6265SDimitry Andric if (S.Name.size() > COFF::NameSize) 126*81ad6265SDimitry Andric StrTabBuilder.add(S.Name); 127*81ad6265SDimitry Andric 128*81ad6265SDimitry Andric StrTabBuilder.finalize(); 129*81ad6265SDimitry Andric 130*81ad6265SDimitry Andric for (auto &S : Obj.getMutableSections()) { 131*81ad6265SDimitry Andric memset(S.Header.Name, 0, sizeof(S.Header.Name)); 132*81ad6265SDimitry Andric if (S.Name.size() <= COFF::NameSize) { 133*81ad6265SDimitry Andric // Short names can go in the field directly. 134*81ad6265SDimitry Andric memcpy(S.Header.Name, S.Name.data(), S.Name.size()); 135*81ad6265SDimitry Andric } else { 136*81ad6265SDimitry Andric // Offset of the section name in the string table. 137*81ad6265SDimitry Andric size_t Offset = StrTabBuilder.getOffset(S.Name); 138*81ad6265SDimitry Andric if (!COFF::encodeSectionName(S.Header.Name, Offset)) 139*81ad6265SDimitry Andric return createStringError(object_error::invalid_section_index, 140*81ad6265SDimitry Andric "COFF string table is greater than 64GB, " 141*81ad6265SDimitry Andric "unable to encode section name offset"); 142*81ad6265SDimitry Andric } 143*81ad6265SDimitry Andric } 144*81ad6265SDimitry Andric for (auto &S : Obj.getMutableSymbols()) { 145*81ad6265SDimitry Andric if (S.Name.size() > COFF::NameSize) { 146*81ad6265SDimitry Andric S.Sym.Name.Offset.Zeroes = 0; 147*81ad6265SDimitry Andric S.Sym.Name.Offset.Offset = StrTabBuilder.getOffset(S.Name); 148*81ad6265SDimitry Andric } else { 149*81ad6265SDimitry Andric strncpy(S.Sym.Name.ShortName, S.Name.data(), COFF::NameSize); 150*81ad6265SDimitry Andric } 151*81ad6265SDimitry Andric } 152*81ad6265SDimitry Andric return StrTabBuilder.getSize(); 153*81ad6265SDimitry Andric } 154*81ad6265SDimitry Andric 155*81ad6265SDimitry Andric template <class SymbolTy> 156*81ad6265SDimitry Andric std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() { 157*81ad6265SDimitry Andric size_t RawSymIndex = 0; 158*81ad6265SDimitry Andric for (auto &S : Obj.getMutableSymbols()) { 159*81ad6265SDimitry Andric // Symbols normally have NumberOfAuxSymbols set correctly all the time. 160*81ad6265SDimitry Andric // For file symbols, we need to know the output file's symbol size to be 161*81ad6265SDimitry Andric // able to calculate the number of slots it occupies. 162*81ad6265SDimitry Andric if (!S.AuxFile.empty()) 163*81ad6265SDimitry Andric S.Sym.NumberOfAuxSymbols = 164*81ad6265SDimitry Andric alignTo(S.AuxFile.size(), sizeof(SymbolTy)) / sizeof(SymbolTy); 165*81ad6265SDimitry Andric S.RawIndex = RawSymIndex; 166*81ad6265SDimitry Andric RawSymIndex += 1 + S.Sym.NumberOfAuxSymbols; 167*81ad6265SDimitry Andric } 168*81ad6265SDimitry Andric return std::make_pair(RawSymIndex * sizeof(SymbolTy), sizeof(SymbolTy)); 169*81ad6265SDimitry Andric } 170*81ad6265SDimitry Andric 171*81ad6265SDimitry Andric Error COFFWriter::finalize(bool IsBigObj) { 172*81ad6265SDimitry Andric size_t SymTabSize, SymbolSize; 173*81ad6265SDimitry Andric std::tie(SymTabSize, SymbolSize) = IsBigObj 174*81ad6265SDimitry Andric ? finalizeSymbolTable<coff_symbol32>() 175*81ad6265SDimitry Andric : finalizeSymbolTable<coff_symbol16>(); 176*81ad6265SDimitry Andric 177*81ad6265SDimitry Andric if (Error E = finalizeRelocTargets()) 178*81ad6265SDimitry Andric return E; 179*81ad6265SDimitry Andric if (Error E = finalizeSymbolContents()) 180*81ad6265SDimitry Andric return E; 181*81ad6265SDimitry Andric 182*81ad6265SDimitry Andric size_t SizeOfHeaders = 0; 183*81ad6265SDimitry Andric FileAlignment = 1; 184*81ad6265SDimitry Andric size_t PeHeaderSize = 0; 185*81ad6265SDimitry Andric if (Obj.IsPE) { 186*81ad6265SDimitry Andric Obj.DosHeader.AddressOfNewExeHeader = 187*81ad6265SDimitry Andric sizeof(Obj.DosHeader) + Obj.DosStub.size(); 188*81ad6265SDimitry Andric SizeOfHeaders += Obj.DosHeader.AddressOfNewExeHeader + sizeof(PEMagic); 189*81ad6265SDimitry Andric 190*81ad6265SDimitry Andric FileAlignment = Obj.PeHeader.FileAlignment; 191*81ad6265SDimitry Andric Obj.PeHeader.NumberOfRvaAndSize = Obj.DataDirectories.size(); 192*81ad6265SDimitry Andric 193*81ad6265SDimitry Andric PeHeaderSize = Obj.Is64 ? sizeof(pe32plus_header) : sizeof(pe32_header); 194*81ad6265SDimitry Andric SizeOfHeaders += 195*81ad6265SDimitry Andric PeHeaderSize + sizeof(data_directory) * Obj.DataDirectories.size(); 196*81ad6265SDimitry Andric } 197*81ad6265SDimitry Andric Obj.CoffFileHeader.NumberOfSections = Obj.getSections().size(); 198*81ad6265SDimitry Andric SizeOfHeaders += 199*81ad6265SDimitry Andric IsBigObj ? sizeof(coff_bigobj_file_header) : sizeof(coff_file_header); 200*81ad6265SDimitry Andric SizeOfHeaders += sizeof(coff_section) * Obj.getSections().size(); 201*81ad6265SDimitry Andric SizeOfHeaders = alignTo(SizeOfHeaders, FileAlignment); 202*81ad6265SDimitry Andric 203*81ad6265SDimitry Andric Obj.CoffFileHeader.SizeOfOptionalHeader = 204*81ad6265SDimitry Andric PeHeaderSize + sizeof(data_directory) * Obj.DataDirectories.size(); 205*81ad6265SDimitry Andric 206*81ad6265SDimitry Andric FileSize = SizeOfHeaders; 207*81ad6265SDimitry Andric SizeOfInitializedData = 0; 208*81ad6265SDimitry Andric 209*81ad6265SDimitry Andric layoutSections(); 210*81ad6265SDimitry Andric 211*81ad6265SDimitry Andric if (Obj.IsPE) { 212*81ad6265SDimitry Andric Obj.PeHeader.SizeOfHeaders = SizeOfHeaders; 213*81ad6265SDimitry Andric Obj.PeHeader.SizeOfInitializedData = SizeOfInitializedData; 214*81ad6265SDimitry Andric 215*81ad6265SDimitry Andric if (!Obj.getSections().empty()) { 216*81ad6265SDimitry Andric const Section &S = Obj.getSections().back(); 217*81ad6265SDimitry Andric Obj.PeHeader.SizeOfImage = 218*81ad6265SDimitry Andric alignTo(S.Header.VirtualAddress + S.Header.VirtualSize, 219*81ad6265SDimitry Andric Obj.PeHeader.SectionAlignment); 220*81ad6265SDimitry Andric } 221*81ad6265SDimitry Andric 222*81ad6265SDimitry Andric // If the PE header had a checksum, clear it, since it isn't valid 223*81ad6265SDimitry Andric // any longer. (We don't calculate a new one.) 224*81ad6265SDimitry Andric Obj.PeHeader.CheckSum = 0; 225*81ad6265SDimitry Andric } 226*81ad6265SDimitry Andric 227*81ad6265SDimitry Andric Expected<size_t> StrTabSizeOrErr = finalizeStringTable(); 228*81ad6265SDimitry Andric if (!StrTabSizeOrErr) 229*81ad6265SDimitry Andric return StrTabSizeOrErr.takeError(); 230*81ad6265SDimitry Andric 231*81ad6265SDimitry Andric size_t StrTabSize = *StrTabSizeOrErr; 232*81ad6265SDimitry Andric 233*81ad6265SDimitry Andric size_t PointerToSymbolTable = FileSize; 234*81ad6265SDimitry Andric // StrTabSize <= 4 is the size of an empty string table, only consisting 235*81ad6265SDimitry Andric // of the length field. 236*81ad6265SDimitry Andric if (SymTabSize == 0 && StrTabSize <= 4 && Obj.IsPE) { 237*81ad6265SDimitry Andric // For executables, don't point to the symbol table and skip writing 238*81ad6265SDimitry Andric // the length field, if both the symbol and string tables are empty. 239*81ad6265SDimitry Andric PointerToSymbolTable = 0; 240*81ad6265SDimitry Andric StrTabSize = 0; 241*81ad6265SDimitry Andric } 242*81ad6265SDimitry Andric 243*81ad6265SDimitry Andric size_t NumRawSymbols = SymTabSize / SymbolSize; 244*81ad6265SDimitry Andric Obj.CoffFileHeader.PointerToSymbolTable = PointerToSymbolTable; 245*81ad6265SDimitry Andric Obj.CoffFileHeader.NumberOfSymbols = NumRawSymbols; 246*81ad6265SDimitry Andric FileSize += SymTabSize + StrTabSize; 247*81ad6265SDimitry Andric FileSize = alignTo(FileSize, FileAlignment); 248*81ad6265SDimitry Andric 249*81ad6265SDimitry Andric return Error::success(); 250*81ad6265SDimitry Andric } 251*81ad6265SDimitry Andric 252*81ad6265SDimitry Andric void COFFWriter::writeHeaders(bool IsBigObj) { 253*81ad6265SDimitry Andric uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()); 254*81ad6265SDimitry Andric if (Obj.IsPE) { 255*81ad6265SDimitry Andric memcpy(Ptr, &Obj.DosHeader, sizeof(Obj.DosHeader)); 256*81ad6265SDimitry Andric Ptr += sizeof(Obj.DosHeader); 257*81ad6265SDimitry Andric memcpy(Ptr, Obj.DosStub.data(), Obj.DosStub.size()); 258*81ad6265SDimitry Andric Ptr += Obj.DosStub.size(); 259*81ad6265SDimitry Andric memcpy(Ptr, PEMagic, sizeof(PEMagic)); 260*81ad6265SDimitry Andric Ptr += sizeof(PEMagic); 261*81ad6265SDimitry Andric } 262*81ad6265SDimitry Andric if (!IsBigObj) { 263*81ad6265SDimitry Andric memcpy(Ptr, &Obj.CoffFileHeader, sizeof(Obj.CoffFileHeader)); 264*81ad6265SDimitry Andric Ptr += sizeof(Obj.CoffFileHeader); 265*81ad6265SDimitry Andric } else { 266*81ad6265SDimitry Andric // Generate a coff_bigobj_file_header, filling it in with the values 267*81ad6265SDimitry Andric // from Obj.CoffFileHeader. All extra fields that don't exist in 268*81ad6265SDimitry Andric // coff_file_header can be set to hardcoded values. 269*81ad6265SDimitry Andric coff_bigobj_file_header BigObjHeader; 270*81ad6265SDimitry Andric BigObjHeader.Sig1 = IMAGE_FILE_MACHINE_UNKNOWN; 271*81ad6265SDimitry Andric BigObjHeader.Sig2 = 0xffff; 272*81ad6265SDimitry Andric BigObjHeader.Version = BigObjHeader::MinBigObjectVersion; 273*81ad6265SDimitry Andric BigObjHeader.Machine = Obj.CoffFileHeader.Machine; 274*81ad6265SDimitry Andric BigObjHeader.TimeDateStamp = Obj.CoffFileHeader.TimeDateStamp; 275*81ad6265SDimitry Andric memcpy(BigObjHeader.UUID, BigObjMagic, sizeof(BigObjMagic)); 276*81ad6265SDimitry Andric BigObjHeader.unused1 = 0; 277*81ad6265SDimitry Andric BigObjHeader.unused2 = 0; 278*81ad6265SDimitry Andric BigObjHeader.unused3 = 0; 279*81ad6265SDimitry Andric BigObjHeader.unused4 = 0; 280*81ad6265SDimitry Andric // The value in Obj.CoffFileHeader.NumberOfSections is truncated, thus 281*81ad6265SDimitry Andric // get the original one instead. 282*81ad6265SDimitry Andric BigObjHeader.NumberOfSections = Obj.getSections().size(); 283*81ad6265SDimitry Andric BigObjHeader.PointerToSymbolTable = Obj.CoffFileHeader.PointerToSymbolTable; 284*81ad6265SDimitry Andric BigObjHeader.NumberOfSymbols = Obj.CoffFileHeader.NumberOfSymbols; 285*81ad6265SDimitry Andric 286*81ad6265SDimitry Andric memcpy(Ptr, &BigObjHeader, sizeof(BigObjHeader)); 287*81ad6265SDimitry Andric Ptr += sizeof(BigObjHeader); 288*81ad6265SDimitry Andric } 289*81ad6265SDimitry Andric if (Obj.IsPE) { 290*81ad6265SDimitry Andric if (Obj.Is64) { 291*81ad6265SDimitry Andric memcpy(Ptr, &Obj.PeHeader, sizeof(Obj.PeHeader)); 292*81ad6265SDimitry Andric Ptr += sizeof(Obj.PeHeader); 293*81ad6265SDimitry Andric } else { 294*81ad6265SDimitry Andric pe32_header PeHeader; 295*81ad6265SDimitry Andric copyPeHeader(PeHeader, Obj.PeHeader); 296*81ad6265SDimitry Andric // The pe32plus_header (stored in Object) lacks the BaseOfData field. 297*81ad6265SDimitry Andric PeHeader.BaseOfData = Obj.BaseOfData; 298*81ad6265SDimitry Andric 299*81ad6265SDimitry Andric memcpy(Ptr, &PeHeader, sizeof(PeHeader)); 300*81ad6265SDimitry Andric Ptr += sizeof(PeHeader); 301*81ad6265SDimitry Andric } 302*81ad6265SDimitry Andric for (const auto &DD : Obj.DataDirectories) { 303*81ad6265SDimitry Andric memcpy(Ptr, &DD, sizeof(DD)); 304*81ad6265SDimitry Andric Ptr += sizeof(DD); 305*81ad6265SDimitry Andric } 306*81ad6265SDimitry Andric } 307*81ad6265SDimitry Andric for (const auto &S : Obj.getSections()) { 308*81ad6265SDimitry Andric memcpy(Ptr, &S.Header, sizeof(S.Header)); 309*81ad6265SDimitry Andric Ptr += sizeof(S.Header); 310*81ad6265SDimitry Andric } 311*81ad6265SDimitry Andric } 312*81ad6265SDimitry Andric 313*81ad6265SDimitry Andric void COFFWriter::writeSections() { 314*81ad6265SDimitry Andric for (const auto &S : Obj.getSections()) { 315*81ad6265SDimitry Andric uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + 316*81ad6265SDimitry Andric S.Header.PointerToRawData; 317*81ad6265SDimitry Andric ArrayRef<uint8_t> Contents = S.getContents(); 318*81ad6265SDimitry Andric std::copy(Contents.begin(), Contents.end(), Ptr); 319*81ad6265SDimitry Andric 320*81ad6265SDimitry Andric // For executable sections, pad the remainder of the raw data size with 321*81ad6265SDimitry Andric // 0xcc, which is int3 on x86. 322*81ad6265SDimitry Andric if ((S.Header.Characteristics & IMAGE_SCN_CNT_CODE) && 323*81ad6265SDimitry Andric S.Header.SizeOfRawData > Contents.size()) 324*81ad6265SDimitry Andric memset(Ptr + Contents.size(), 0xcc, 325*81ad6265SDimitry Andric S.Header.SizeOfRawData - Contents.size()); 326*81ad6265SDimitry Andric 327*81ad6265SDimitry Andric Ptr += S.Header.SizeOfRawData; 328*81ad6265SDimitry Andric 329*81ad6265SDimitry Andric if (S.Relocs.size() >= 0xffff) { 330*81ad6265SDimitry Andric object::coff_relocation R; 331*81ad6265SDimitry Andric R.VirtualAddress = S.Relocs.size() + 1; 332*81ad6265SDimitry Andric R.SymbolTableIndex = 0; 333*81ad6265SDimitry Andric R.Type = 0; 334*81ad6265SDimitry Andric memcpy(Ptr, &R, sizeof(R)); 335*81ad6265SDimitry Andric Ptr += sizeof(R); 336*81ad6265SDimitry Andric } 337*81ad6265SDimitry Andric for (const auto &R : S.Relocs) { 338*81ad6265SDimitry Andric memcpy(Ptr, &R.Reloc, sizeof(R.Reloc)); 339*81ad6265SDimitry Andric Ptr += sizeof(R.Reloc); 340*81ad6265SDimitry Andric } 341*81ad6265SDimitry Andric } 342*81ad6265SDimitry Andric } 343*81ad6265SDimitry Andric 344*81ad6265SDimitry Andric template <class SymbolTy> void COFFWriter::writeSymbolStringTables() { 345*81ad6265SDimitry Andric uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + 346*81ad6265SDimitry Andric Obj.CoffFileHeader.PointerToSymbolTable; 347*81ad6265SDimitry Andric for (const auto &S : Obj.getSymbols()) { 348*81ad6265SDimitry Andric // Convert symbols back to the right size, from coff_symbol32. 349*81ad6265SDimitry Andric copySymbol<SymbolTy, coff_symbol32>(*reinterpret_cast<SymbolTy *>(Ptr), 350*81ad6265SDimitry Andric S.Sym); 351*81ad6265SDimitry Andric Ptr += sizeof(SymbolTy); 352*81ad6265SDimitry Andric if (!S.AuxFile.empty()) { 353*81ad6265SDimitry Andric // For file symbols, just write the string into the aux symbol slots, 354*81ad6265SDimitry Andric // assuming that the unwritten parts are initialized to zero in the memory 355*81ad6265SDimitry Andric // mapped file. 356*81ad6265SDimitry Andric std::copy(S.AuxFile.begin(), S.AuxFile.end(), Ptr); 357*81ad6265SDimitry Andric Ptr += S.Sym.NumberOfAuxSymbols * sizeof(SymbolTy); 358*81ad6265SDimitry Andric } else { 359*81ad6265SDimitry Andric // For other auxillary symbols, write their opaque payload into one symbol 360*81ad6265SDimitry Andric // table slot each. For big object files, the symbols are larger than the 361*81ad6265SDimitry Andric // opaque auxillary symbol struct and we leave padding at the end of each 362*81ad6265SDimitry Andric // entry. 363*81ad6265SDimitry Andric for (const AuxSymbol &AuxSym : S.AuxData) { 364*81ad6265SDimitry Andric ArrayRef<uint8_t> Ref = AuxSym.getRef(); 365*81ad6265SDimitry Andric std::copy(Ref.begin(), Ref.end(), Ptr); 366*81ad6265SDimitry Andric Ptr += sizeof(SymbolTy); 367*81ad6265SDimitry Andric } 368*81ad6265SDimitry Andric } 369*81ad6265SDimitry Andric } 370*81ad6265SDimitry Andric if (StrTabBuilder.getSize() > 4 || !Obj.IsPE) { 371*81ad6265SDimitry Andric // Always write a string table in object files, even an empty one. 372*81ad6265SDimitry Andric StrTabBuilder.write(Ptr); 373*81ad6265SDimitry Andric Ptr += StrTabBuilder.getSize(); 374*81ad6265SDimitry Andric } 375*81ad6265SDimitry Andric } 376*81ad6265SDimitry Andric 377*81ad6265SDimitry Andric Error COFFWriter::write(bool IsBigObj) { 378*81ad6265SDimitry Andric if (Error E = finalize(IsBigObj)) 379*81ad6265SDimitry Andric return E; 380*81ad6265SDimitry Andric 381*81ad6265SDimitry Andric Buf = WritableMemoryBuffer::getNewMemBuffer(FileSize); 382*81ad6265SDimitry Andric if (!Buf) 383*81ad6265SDimitry Andric return createStringError(llvm::errc::not_enough_memory, 384*81ad6265SDimitry Andric "failed to allocate memory buffer of " + 385*81ad6265SDimitry Andric Twine::utohexstr(FileSize) + " bytes."); 386*81ad6265SDimitry Andric 387*81ad6265SDimitry Andric writeHeaders(IsBigObj); 388*81ad6265SDimitry Andric writeSections(); 389*81ad6265SDimitry Andric if (IsBigObj) 390*81ad6265SDimitry Andric writeSymbolStringTables<coff_symbol32>(); 391*81ad6265SDimitry Andric else 392*81ad6265SDimitry Andric writeSymbolStringTables<coff_symbol16>(); 393*81ad6265SDimitry Andric 394*81ad6265SDimitry Andric if (Obj.IsPE) 395*81ad6265SDimitry Andric if (Error E = patchDebugDirectory()) 396*81ad6265SDimitry Andric return E; 397*81ad6265SDimitry Andric 398*81ad6265SDimitry Andric // TODO: Implement direct writing to the output stream (without intermediate 399*81ad6265SDimitry Andric // memory buffer Buf). 400*81ad6265SDimitry Andric Out.write(Buf->getBufferStart(), Buf->getBufferSize()); 401*81ad6265SDimitry Andric return Error::success(); 402*81ad6265SDimitry Andric } 403*81ad6265SDimitry Andric 404*81ad6265SDimitry Andric Expected<uint32_t> COFFWriter::virtualAddressToFileAddress(uint32_t RVA) { 405*81ad6265SDimitry Andric for (const auto &S : Obj.getSections()) { 406*81ad6265SDimitry Andric if (RVA >= S.Header.VirtualAddress && 407*81ad6265SDimitry Andric RVA < S.Header.VirtualAddress + S.Header.SizeOfRawData) 408*81ad6265SDimitry Andric return S.Header.PointerToRawData + RVA - S.Header.VirtualAddress; 409*81ad6265SDimitry Andric } 410*81ad6265SDimitry Andric return createStringError(object_error::parse_failed, 411*81ad6265SDimitry Andric "debug directory payload not found"); 412*81ad6265SDimitry Andric } 413*81ad6265SDimitry Andric 414*81ad6265SDimitry Andric // Locate which sections contain the debug directories, iterate over all 415*81ad6265SDimitry Andric // the debug_directory structs in there, and set the PointerToRawData field 416*81ad6265SDimitry Andric // in all of them, according to their new physical location in the file. 417*81ad6265SDimitry Andric Error COFFWriter::patchDebugDirectory() { 418*81ad6265SDimitry Andric if (Obj.DataDirectories.size() <= DEBUG_DIRECTORY) 419*81ad6265SDimitry Andric return Error::success(); 420*81ad6265SDimitry Andric const data_directory *Dir = &Obj.DataDirectories[DEBUG_DIRECTORY]; 421*81ad6265SDimitry Andric if (Dir->Size <= 0) 422*81ad6265SDimitry Andric return Error::success(); 423*81ad6265SDimitry Andric for (const auto &S : Obj.getSections()) { 424*81ad6265SDimitry Andric if (Dir->RelativeVirtualAddress >= S.Header.VirtualAddress && 425*81ad6265SDimitry Andric Dir->RelativeVirtualAddress < 426*81ad6265SDimitry Andric S.Header.VirtualAddress + S.Header.SizeOfRawData) { 427*81ad6265SDimitry Andric if (Dir->RelativeVirtualAddress + Dir->Size > 428*81ad6265SDimitry Andric S.Header.VirtualAddress + S.Header.SizeOfRawData) 429*81ad6265SDimitry Andric return createStringError(object_error::parse_failed, 430*81ad6265SDimitry Andric "debug directory extends past end of section"); 431*81ad6265SDimitry Andric 432*81ad6265SDimitry Andric size_t Offset = Dir->RelativeVirtualAddress - S.Header.VirtualAddress; 433*81ad6265SDimitry Andric uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + 434*81ad6265SDimitry Andric S.Header.PointerToRawData + Offset; 435*81ad6265SDimitry Andric uint8_t *End = Ptr + Dir->Size; 436*81ad6265SDimitry Andric while (Ptr < End) { 437*81ad6265SDimitry Andric debug_directory *Debug = reinterpret_cast<debug_directory *>(Ptr); 438*81ad6265SDimitry Andric if (Debug->PointerToRawData) { 439*81ad6265SDimitry Andric if (Expected<uint32_t> FilePosOrErr = 440*81ad6265SDimitry Andric virtualAddressToFileAddress(Debug->AddressOfRawData)) 441*81ad6265SDimitry Andric Debug->PointerToRawData = *FilePosOrErr; 442*81ad6265SDimitry Andric else 443*81ad6265SDimitry Andric return FilePosOrErr.takeError(); 444*81ad6265SDimitry Andric } 445*81ad6265SDimitry Andric Ptr += sizeof(debug_directory); 446*81ad6265SDimitry Andric Offset += sizeof(debug_directory); 447*81ad6265SDimitry Andric } 448*81ad6265SDimitry Andric // Debug directory found and patched, all done. 449*81ad6265SDimitry Andric return Error::success(); 450*81ad6265SDimitry Andric } 451*81ad6265SDimitry Andric } 452*81ad6265SDimitry Andric return createStringError(object_error::parse_failed, 453*81ad6265SDimitry Andric "debug directory not found"); 454*81ad6265SDimitry Andric } 455*81ad6265SDimitry Andric 456*81ad6265SDimitry Andric Error COFFWriter::write() { 457*81ad6265SDimitry Andric bool IsBigObj = Obj.getSections().size() > MaxNumberOfSections16; 458*81ad6265SDimitry Andric if (IsBigObj && Obj.IsPE) 459*81ad6265SDimitry Andric return createStringError(object_error::parse_failed, 460*81ad6265SDimitry Andric "too many sections for executable"); 461*81ad6265SDimitry Andric return write(IsBigObj); 462*81ad6265SDimitry Andric } 463*81ad6265SDimitry Andric 464*81ad6265SDimitry Andric } // end namespace coff 465*81ad6265SDimitry Andric } // end namespace objcopy 466*81ad6265SDimitry Andric } // end namespace llvm 467