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
22namespace llvm {
23namespace objcopy {
24namespace coff {
25
26struct 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
35struct 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
64private:
65 ArrayRef<uint8_t> ContentsRef;
66 std::vector<uint8_t> OwnedContents;
67};
68
69struct AuxSymbol {
70 AuxSymbol(ArrayRef<uint8_t> In) {
71 assert(In.size() == sizeof(Opaque));
72 llvm::copy(Range&: In, Out: 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
82struct 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 size_t OriginalRawIndex;
93 bool Referenced;
94};
95
96struct 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(x: Symbols.begin(), y: 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(x: Sections.begin(), y: 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
139private:
140 std::vector<Symbol> Symbols;
141 DenseMap<size_t, Symbol *> SymbolMap;
142
143 size_t NextSymbolUniqueId = 0;
144 size_t NextSymbolOriginalIndex = 0;
145
146 std::vector<Section> Sections;
147 DenseMap<ssize_t, Section *> SectionMap;
148
149 ssize_t NextSectionUniqueId = 1; // Allow a UniqueId 0 to mean undefined.
150
151 // Update SymbolMap.
152 void updateSymbols();
153
154 // Update SectionMap and Index in each Section.
155 void updateSections();
156};
157
158// Copy between coff_symbol16 and coff_symbol32.
159// The source and destination files can use either coff_symbol16 or
160// coff_symbol32, while we always store them as coff_symbol32 in the
161// intermediate data structure.
162template <class Symbol1Ty, class Symbol2Ty>
163void copySymbol(Symbol1Ty &Dest, const Symbol2Ty &Src) {
164 static_assert(sizeof(Dest.Name.ShortName) == sizeof(Src.Name.ShortName),
165 "Mismatched name sizes");
166 memcpy(Dest.Name.ShortName, Src.Name.ShortName, sizeof(Dest.Name.ShortName));
167 Dest.Value = Src.Value;
168 Dest.SectionNumber = Src.SectionNumber;
169 Dest.Type = Src.Type;
170 Dest.StorageClass = Src.StorageClass;
171 Dest.NumberOfAuxSymbols = Src.NumberOfAuxSymbols;
172}
173
174// Copy between pe32_header and pe32plus_header.
175// We store the intermediate state in a pe32plus_header.
176template <class PeHeader1Ty, class PeHeader2Ty>
177void copyPeHeader(PeHeader1Ty &Dest, const PeHeader2Ty &Src) {
178 Dest.Magic = Src.Magic;
179 Dest.MajorLinkerVersion = Src.MajorLinkerVersion;
180 Dest.MinorLinkerVersion = Src.MinorLinkerVersion;
181 Dest.SizeOfCode = Src.SizeOfCode;
182 Dest.SizeOfInitializedData = Src.SizeOfInitializedData;
183 Dest.SizeOfUninitializedData = Src.SizeOfUninitializedData;
184 Dest.AddressOfEntryPoint = Src.AddressOfEntryPoint;
185 Dest.BaseOfCode = Src.BaseOfCode;
186 Dest.ImageBase = Src.ImageBase;
187 Dest.SectionAlignment = Src.SectionAlignment;
188 Dest.FileAlignment = Src.FileAlignment;
189 Dest.MajorOperatingSystemVersion = Src.MajorOperatingSystemVersion;
190 Dest.MinorOperatingSystemVersion = Src.MinorOperatingSystemVersion;
191 Dest.MajorImageVersion = Src.MajorImageVersion;
192 Dest.MinorImageVersion = Src.MinorImageVersion;
193 Dest.MajorSubsystemVersion = Src.MajorSubsystemVersion;
194 Dest.MinorSubsystemVersion = Src.MinorSubsystemVersion;
195 Dest.Win32VersionValue = Src.Win32VersionValue;
196 Dest.SizeOfImage = Src.SizeOfImage;
197 Dest.SizeOfHeaders = Src.SizeOfHeaders;
198 Dest.CheckSum = Src.CheckSum;
199 Dest.Subsystem = Src.Subsystem;
200 Dest.DLLCharacteristics = Src.DLLCharacteristics;
201 Dest.SizeOfStackReserve = Src.SizeOfStackReserve;
202 Dest.SizeOfStackCommit = Src.SizeOfStackCommit;
203 Dest.SizeOfHeapReserve = Src.SizeOfHeapReserve;
204 Dest.SizeOfHeapCommit = Src.SizeOfHeapCommit;
205 Dest.LoaderFlags = Src.LoaderFlags;
206 Dest.NumberOfRvaAndSize = Src.NumberOfRvaAndSize;
207}
208
209} // end namespace coff
210} // end namespace objcopy
211} // end namespace llvm
212
213#endif // LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H
214