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