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