1 //===- Object.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_TOOLS_OBJCOPY_COFF_OBJECT_H
10 #define LLVM_TOOLS_OBJCOPY_COFF_OBJECT_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;
RelocationRelocation29 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
getContentsSection43 ArrayRef<uint8_t> getContents() const {
44 if (!OwnedContents.empty())
45 return OwnedContents;
46 return ContentsRef;
47 }
48
setContentsRefSection49 void setContentsRef(ArrayRef<uint8_t> Data) {
50 OwnedContents.clear();
51 ContentsRef = Data;
52 }
53
setOwnedContentsSection54 void setOwnedContents(std::vector<uint8_t> &&Data) {
55 ContentsRef = ArrayRef<uint8_t>();
56 OwnedContents = std::move(Data);
57 }
58
clearContentsSection59 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 {
AuxSymbolAuxSymbol70 AuxSymbol(ArrayRef<uint8_t> In) {
71 assert(In.size() == sizeof(Opaque));
72 std::copy(In.begin(), In.end(), Opaque);
73 }
74
getRefAuxSymbol75 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 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
getSymbolsObject109 ArrayRef<Symbol> getSymbols() const { return Symbols; }
110 // This allows mutating individual Symbols, but not mutating the list
111 // of symbols itself.
getMutableSymbolsObject112 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
getSectionsObject125 ArrayRef<Section> getSections() const { return Sections; }
126 // This allows mutating individual Sections, but not mutating the list
127 // of sections itself.
getMutableSectionsObject128 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>
copySymbol(Symbol1Ty & Dest,const Symbol2Ty & Src)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>
copyPeHeader(PeHeader1Ty & Dest,const PeHeader2Ty & Src)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_TOOLS_OBJCOPY_COFF_OBJECT_H
212