1*81ad6265SDimitry Andric //===- COFFObject.h ---------------------------------------------*- C++ -*-===// 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 #ifndef LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H 10*81ad6265SDimitry Andric #define LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H 11*81ad6265SDimitry Andric 12*81ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h" 13*81ad6265SDimitry Andric #include "llvm/ADT/DenseMap.h" 14*81ad6265SDimitry Andric #include "llvm/ADT/Optional.h" 15*81ad6265SDimitry Andric #include "llvm/ADT/StringRef.h" 16*81ad6265SDimitry Andric #include "llvm/ADT/iterator_range.h" 17*81ad6265SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 18*81ad6265SDimitry Andric #include "llvm/Object/COFF.h" 19*81ad6265SDimitry Andric #include <cstddef> 20*81ad6265SDimitry Andric #include <cstdint> 21*81ad6265SDimitry Andric #include <vector> 22*81ad6265SDimitry Andric 23*81ad6265SDimitry Andric namespace llvm { 24*81ad6265SDimitry Andric namespace objcopy { 25*81ad6265SDimitry Andric namespace coff { 26*81ad6265SDimitry Andric 27*81ad6265SDimitry Andric struct Relocation { 28*81ad6265SDimitry Andric Relocation() = default; 29*81ad6265SDimitry Andric Relocation(const object::coff_relocation &R) : Reloc(R) {} 30*81ad6265SDimitry Andric 31*81ad6265SDimitry Andric object::coff_relocation Reloc; 32*81ad6265SDimitry Andric size_t Target = 0; 33*81ad6265SDimitry Andric StringRef TargetName; // Used for diagnostics only 34*81ad6265SDimitry Andric }; 35*81ad6265SDimitry Andric 36*81ad6265SDimitry Andric struct Section { 37*81ad6265SDimitry Andric object::coff_section Header; 38*81ad6265SDimitry Andric std::vector<Relocation> Relocs; 39*81ad6265SDimitry Andric StringRef Name; 40*81ad6265SDimitry Andric ssize_t UniqueId; 41*81ad6265SDimitry Andric size_t Index; 42*81ad6265SDimitry Andric 43*81ad6265SDimitry Andric ArrayRef<uint8_t> getContents() const { 44*81ad6265SDimitry Andric if (!OwnedContents.empty()) 45*81ad6265SDimitry Andric return OwnedContents; 46*81ad6265SDimitry Andric return ContentsRef; 47*81ad6265SDimitry Andric } 48*81ad6265SDimitry Andric 49*81ad6265SDimitry Andric void setContentsRef(ArrayRef<uint8_t> Data) { 50*81ad6265SDimitry Andric OwnedContents.clear(); 51*81ad6265SDimitry Andric ContentsRef = Data; 52*81ad6265SDimitry Andric } 53*81ad6265SDimitry Andric 54*81ad6265SDimitry Andric void setOwnedContents(std::vector<uint8_t> &&Data) { 55*81ad6265SDimitry Andric ContentsRef = ArrayRef<uint8_t>(); 56*81ad6265SDimitry Andric OwnedContents = std::move(Data); 57*81ad6265SDimitry Andric Header.SizeOfRawData = OwnedContents.size(); 58*81ad6265SDimitry Andric } 59*81ad6265SDimitry Andric 60*81ad6265SDimitry Andric void clearContents() { 61*81ad6265SDimitry Andric ContentsRef = ArrayRef<uint8_t>(); 62*81ad6265SDimitry Andric OwnedContents.clear(); 63*81ad6265SDimitry Andric } 64*81ad6265SDimitry Andric 65*81ad6265SDimitry Andric private: 66*81ad6265SDimitry Andric ArrayRef<uint8_t> ContentsRef; 67*81ad6265SDimitry Andric std::vector<uint8_t> OwnedContents; 68*81ad6265SDimitry Andric }; 69*81ad6265SDimitry Andric 70*81ad6265SDimitry Andric struct AuxSymbol { 71*81ad6265SDimitry Andric AuxSymbol(ArrayRef<uint8_t> In) { 72*81ad6265SDimitry Andric assert(In.size() == sizeof(Opaque)); 73*81ad6265SDimitry Andric std::copy(In.begin(), In.end(), Opaque); 74*81ad6265SDimitry Andric } 75*81ad6265SDimitry Andric 76*81ad6265SDimitry Andric ArrayRef<uint8_t> getRef() const { 77*81ad6265SDimitry Andric return ArrayRef<uint8_t>(Opaque, sizeof(Opaque)); 78*81ad6265SDimitry Andric } 79*81ad6265SDimitry Andric 80*81ad6265SDimitry Andric uint8_t Opaque[sizeof(object::coff_symbol16)]; 81*81ad6265SDimitry Andric }; 82*81ad6265SDimitry Andric 83*81ad6265SDimitry Andric struct Symbol { 84*81ad6265SDimitry Andric object::coff_symbol32 Sym; 85*81ad6265SDimitry Andric StringRef Name; 86*81ad6265SDimitry Andric std::vector<AuxSymbol> AuxData; 87*81ad6265SDimitry Andric StringRef AuxFile; 88*81ad6265SDimitry Andric ssize_t TargetSectionId; 89*81ad6265SDimitry Andric ssize_t AssociativeComdatTargetSectionId = 0; 90*81ad6265SDimitry Andric Optional<size_t> WeakTargetSymbolId; 91*81ad6265SDimitry Andric size_t UniqueId; 92*81ad6265SDimitry Andric size_t RawIndex; 93*81ad6265SDimitry Andric bool Referenced; 94*81ad6265SDimitry Andric }; 95*81ad6265SDimitry Andric 96*81ad6265SDimitry Andric struct Object { 97*81ad6265SDimitry Andric bool IsPE = false; 98*81ad6265SDimitry Andric 99*81ad6265SDimitry Andric object::dos_header DosHeader; 100*81ad6265SDimitry Andric ArrayRef<uint8_t> DosStub; 101*81ad6265SDimitry Andric 102*81ad6265SDimitry Andric object::coff_file_header CoffFileHeader; 103*81ad6265SDimitry Andric 104*81ad6265SDimitry Andric bool Is64 = false; 105*81ad6265SDimitry Andric object::pe32plus_header PeHeader; 106*81ad6265SDimitry Andric uint32_t BaseOfData = 0; // pe32plus_header lacks this field. 107*81ad6265SDimitry Andric 108*81ad6265SDimitry Andric std::vector<object::data_directory> DataDirectories; 109*81ad6265SDimitry Andric 110*81ad6265SDimitry Andric ArrayRef<Symbol> getSymbols() const { return Symbols; } 111*81ad6265SDimitry Andric // This allows mutating individual Symbols, but not mutating the list 112*81ad6265SDimitry Andric // of symbols itself. 113*81ad6265SDimitry Andric iterator_range<std::vector<Symbol>::iterator> getMutableSymbols() { 114*81ad6265SDimitry Andric return make_range(Symbols.begin(), Symbols.end()); 115*81ad6265SDimitry Andric } 116*81ad6265SDimitry Andric 117*81ad6265SDimitry Andric const Symbol *findSymbol(size_t UniqueId) const; 118*81ad6265SDimitry Andric 119*81ad6265SDimitry Andric void addSymbols(ArrayRef<Symbol> NewSymbols); 120*81ad6265SDimitry Andric Error removeSymbols(function_ref<Expected<bool>(const Symbol &)> ToRemove); 121*81ad6265SDimitry Andric 122*81ad6265SDimitry Andric // Set the Referenced field on all Symbols, based on relocations in 123*81ad6265SDimitry Andric // all sections. 124*81ad6265SDimitry Andric Error markSymbols(); 125*81ad6265SDimitry Andric 126*81ad6265SDimitry Andric ArrayRef<Section> getSections() const { return Sections; } 127*81ad6265SDimitry Andric // This allows mutating individual Sections, but not mutating the list 128*81ad6265SDimitry Andric // of sections itself. 129*81ad6265SDimitry Andric iterator_range<std::vector<Section>::iterator> getMutableSections() { 130*81ad6265SDimitry Andric return make_range(Sections.begin(), Sections.end()); 131*81ad6265SDimitry Andric } 132*81ad6265SDimitry Andric 133*81ad6265SDimitry Andric const Section *findSection(ssize_t UniqueId) const; 134*81ad6265SDimitry Andric 135*81ad6265SDimitry Andric void addSections(ArrayRef<Section> NewSections); 136*81ad6265SDimitry Andric void removeSections(function_ref<bool(const Section &)> ToRemove); 137*81ad6265SDimitry Andric void truncateSections(function_ref<bool(const Section &)> ToTruncate); 138*81ad6265SDimitry Andric 139*81ad6265SDimitry Andric private: 140*81ad6265SDimitry Andric std::vector<Symbol> Symbols; 141*81ad6265SDimitry Andric DenseMap<size_t, Symbol *> SymbolMap; 142*81ad6265SDimitry Andric 143*81ad6265SDimitry Andric size_t NextSymbolUniqueId = 0; 144*81ad6265SDimitry Andric 145*81ad6265SDimitry Andric std::vector<Section> Sections; 146*81ad6265SDimitry Andric DenseMap<ssize_t, Section *> SectionMap; 147*81ad6265SDimitry Andric 148*81ad6265SDimitry Andric ssize_t NextSectionUniqueId = 1; // Allow a UniqueId 0 to mean undefined. 149*81ad6265SDimitry Andric 150*81ad6265SDimitry Andric // Update SymbolMap. 151*81ad6265SDimitry Andric void updateSymbols(); 152*81ad6265SDimitry Andric 153*81ad6265SDimitry Andric // Update SectionMap and Index in each Section. 154*81ad6265SDimitry Andric void updateSections(); 155*81ad6265SDimitry Andric }; 156*81ad6265SDimitry Andric 157*81ad6265SDimitry Andric // Copy between coff_symbol16 and coff_symbol32. 158*81ad6265SDimitry Andric // The source and destination files can use either coff_symbol16 or 159*81ad6265SDimitry Andric // coff_symbol32, while we always store them as coff_symbol32 in the 160*81ad6265SDimitry Andric // intermediate data structure. 161*81ad6265SDimitry Andric template <class Symbol1Ty, class Symbol2Ty> 162*81ad6265SDimitry Andric void copySymbol(Symbol1Ty &Dest, const Symbol2Ty &Src) { 163*81ad6265SDimitry Andric static_assert(sizeof(Dest.Name.ShortName) == sizeof(Src.Name.ShortName), 164*81ad6265SDimitry Andric "Mismatched name sizes"); 165*81ad6265SDimitry Andric memcpy(Dest.Name.ShortName, Src.Name.ShortName, sizeof(Dest.Name.ShortName)); 166*81ad6265SDimitry Andric Dest.Value = Src.Value; 167*81ad6265SDimitry Andric Dest.SectionNumber = Src.SectionNumber; 168*81ad6265SDimitry Andric Dest.Type = Src.Type; 169*81ad6265SDimitry Andric Dest.StorageClass = Src.StorageClass; 170*81ad6265SDimitry Andric Dest.NumberOfAuxSymbols = Src.NumberOfAuxSymbols; 171*81ad6265SDimitry Andric } 172*81ad6265SDimitry Andric 173*81ad6265SDimitry Andric // Copy between pe32_header and pe32plus_header. 174*81ad6265SDimitry Andric // We store the intermediate state in a pe32plus_header. 175*81ad6265SDimitry Andric template <class PeHeader1Ty, class PeHeader2Ty> 176*81ad6265SDimitry Andric void copyPeHeader(PeHeader1Ty &Dest, const PeHeader2Ty &Src) { 177*81ad6265SDimitry Andric Dest.Magic = Src.Magic; 178*81ad6265SDimitry Andric Dest.MajorLinkerVersion = Src.MajorLinkerVersion; 179*81ad6265SDimitry Andric Dest.MinorLinkerVersion = Src.MinorLinkerVersion; 180*81ad6265SDimitry Andric Dest.SizeOfCode = Src.SizeOfCode; 181*81ad6265SDimitry Andric Dest.SizeOfInitializedData = Src.SizeOfInitializedData; 182*81ad6265SDimitry Andric Dest.SizeOfUninitializedData = Src.SizeOfUninitializedData; 183*81ad6265SDimitry Andric Dest.AddressOfEntryPoint = Src.AddressOfEntryPoint; 184*81ad6265SDimitry Andric Dest.BaseOfCode = Src.BaseOfCode; 185*81ad6265SDimitry Andric Dest.ImageBase = Src.ImageBase; 186*81ad6265SDimitry Andric Dest.SectionAlignment = Src.SectionAlignment; 187*81ad6265SDimitry Andric Dest.FileAlignment = Src.FileAlignment; 188*81ad6265SDimitry Andric Dest.MajorOperatingSystemVersion = Src.MajorOperatingSystemVersion; 189*81ad6265SDimitry Andric Dest.MinorOperatingSystemVersion = Src.MinorOperatingSystemVersion; 190*81ad6265SDimitry Andric Dest.MajorImageVersion = Src.MajorImageVersion; 191*81ad6265SDimitry Andric Dest.MinorImageVersion = Src.MinorImageVersion; 192*81ad6265SDimitry Andric Dest.MajorSubsystemVersion = Src.MajorSubsystemVersion; 193*81ad6265SDimitry Andric Dest.MinorSubsystemVersion = Src.MinorSubsystemVersion; 194*81ad6265SDimitry Andric Dest.Win32VersionValue = Src.Win32VersionValue; 195*81ad6265SDimitry Andric Dest.SizeOfImage = Src.SizeOfImage; 196*81ad6265SDimitry Andric Dest.SizeOfHeaders = Src.SizeOfHeaders; 197*81ad6265SDimitry Andric Dest.CheckSum = Src.CheckSum; 198*81ad6265SDimitry Andric Dest.Subsystem = Src.Subsystem; 199*81ad6265SDimitry Andric Dest.DLLCharacteristics = Src.DLLCharacteristics; 200*81ad6265SDimitry Andric Dest.SizeOfStackReserve = Src.SizeOfStackReserve; 201*81ad6265SDimitry Andric Dest.SizeOfStackCommit = Src.SizeOfStackCommit; 202*81ad6265SDimitry Andric Dest.SizeOfHeapReserve = Src.SizeOfHeapReserve; 203*81ad6265SDimitry Andric Dest.SizeOfHeapCommit = Src.SizeOfHeapCommit; 204*81ad6265SDimitry Andric Dest.LoaderFlags = Src.LoaderFlags; 205*81ad6265SDimitry Andric Dest.NumberOfRvaAndSize = Src.NumberOfRvaAndSize; 206*81ad6265SDimitry Andric } 207*81ad6265SDimitry Andric 208*81ad6265SDimitry Andric } // end namespace coff 209*81ad6265SDimitry Andric } // end namespace objcopy 210*81ad6265SDimitry Andric } // end namespace llvm 211*81ad6265SDimitry Andric 212*81ad6265SDimitry Andric #endif // LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H 213