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
23namespace llvm {
24namespace objcopy {
25namespace coff {
26
27struct 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
36struct 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  }
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    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
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  Optional<size_t> WeakTargetSymbolId;
90  size_t UniqueId;
91  size_t RawIndex;
92  bool Referenced;
93};
94
95struct 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  void removeSymbols(function_ref<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
138private:
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.
160template <class Symbol1Ty, class Symbol2Ty>
161void 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.
174template <class PeHeader1Ty, class PeHeader2Ty>
175void 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