xref: /freebsd/contrib/llvm-project/llvm/lib/ObjCopy/COFF/COFFObject.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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