1 //===- Object.h -------------------------------------------------*- C++ -*-===//
2 //
3 //                      The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H
11 #define LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H
12 
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/DenseMap.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 {
RelocationRelocation28   Relocation() {}
RelocationRelocation29   Relocation(const object::coff_relocation& R) : Reloc(R) {}
30 
31   object::coff_relocation Reloc;
32   size_t Target;
33   StringRef TargetName; // Used for diagnostics only
34 };
35 
36 struct Section {
37   object::coff_section Header;
38   ArrayRef<uint8_t> Contents;
39   std::vector<Relocation> Relocs;
40   StringRef Name;
41 };
42 
43 struct Symbol {
44   object::coff_symbol32 Sym;
45   StringRef Name;
46   ArrayRef<uint8_t> AuxData;
47   size_t UniqueId;
48   size_t RawIndex;
49   bool Referenced;
50 };
51 
52 struct Object {
53   bool IsPE = false;
54 
55   object::dos_header DosHeader;
56   ArrayRef<uint8_t> DosStub;
57 
58   object::coff_file_header CoffFileHeader;
59 
60   bool Is64 = false;
61   object::pe32plus_header PeHeader;
62   uint32_t BaseOfData = 0; // pe32plus_header lacks this field.
63 
64   std::vector<object::data_directory> DataDirectories;
65   std::vector<Section> Sections;
66 
getSymbolsObject67   ArrayRef<Symbol> getSymbols() const { return Symbols; }
68   // This allows mutating individual Symbols, but not mutating the list
69   // of symbols itself.
getMutableSymbolsObject70   iterator_range<std::vector<Symbol>::iterator> getMutableSymbols() {
71     return make_range(Symbols.begin(), Symbols.end());
72   }
73 
74   const Symbol *findSymbol(size_t UniqueId) const;
75 
76   void addSymbols(ArrayRef<Symbol> NewSymbols);
77   void removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
78 
79   // Set the Referenced field on all Symbols, based on relocations in
80   // all sections.
81   Error markSymbols();
82 
83 private:
84   std::vector<Symbol> Symbols;
85   DenseMap<size_t, Symbol *> SymbolMap;
86 
87   size_t NextSymbolUniqueId = 0;
88 
89   // Update SymbolMap and RawIndex in each Symbol.
90   void updateSymbols();
91 };
92 
93 // Copy between coff_symbol16 and coff_symbol32.
94 // The source and destination files can use either coff_symbol16 or
95 // coff_symbol32, while we always store them as coff_symbol32 in the
96 // intermediate data structure.
97 template <class Symbol1Ty, class Symbol2Ty>
copySymbol(Symbol1Ty & Dest,const Symbol2Ty & Src)98 void copySymbol(Symbol1Ty &Dest, const Symbol2Ty &Src) {
99   static_assert(sizeof(Dest.Name.ShortName) == sizeof(Src.Name.ShortName),
100                 "Mismatched name sizes");
101   memcpy(Dest.Name.ShortName, Src.Name.ShortName, sizeof(Dest.Name.ShortName));
102   Dest.Value = Src.Value;
103   Dest.SectionNumber = Src.SectionNumber;
104   Dest.Type = Src.Type;
105   Dest.StorageClass = Src.StorageClass;
106   Dest.NumberOfAuxSymbols = Src.NumberOfAuxSymbols;
107 }
108 
109 // Copy between pe32_header and pe32plus_header.
110 // We store the intermediate state in a pe32plus_header.
111 template <class PeHeader1Ty, class PeHeader2Ty>
copyPeHeader(PeHeader1Ty & Dest,const PeHeader2Ty & Src)112 void copyPeHeader(PeHeader1Ty &Dest, const PeHeader2Ty &Src) {
113   Dest.Magic = Src.Magic;
114   Dest.MajorLinkerVersion = Src.MajorLinkerVersion;
115   Dest.MinorLinkerVersion = Src.MinorLinkerVersion;
116   Dest.SizeOfCode = Src.SizeOfCode;
117   Dest.SizeOfInitializedData = Src.SizeOfInitializedData;
118   Dest.SizeOfUninitializedData = Src.SizeOfUninitializedData;
119   Dest.AddressOfEntryPoint = Src.AddressOfEntryPoint;
120   Dest.BaseOfCode = Src.BaseOfCode;
121   Dest.ImageBase = Src.ImageBase;
122   Dest.SectionAlignment = Src.SectionAlignment;
123   Dest.FileAlignment = Src.FileAlignment;
124   Dest.MajorOperatingSystemVersion = Src.MajorOperatingSystemVersion;
125   Dest.MinorOperatingSystemVersion = Src.MinorOperatingSystemVersion;
126   Dest.MajorImageVersion = Src.MajorImageVersion;
127   Dest.MinorImageVersion = Src.MinorImageVersion;
128   Dest.MajorSubsystemVersion = Src.MajorSubsystemVersion;
129   Dest.MinorSubsystemVersion = Src.MinorSubsystemVersion;
130   Dest.Win32VersionValue = Src.Win32VersionValue;
131   Dest.SizeOfImage = Src.SizeOfImage;
132   Dest.SizeOfHeaders = Src.SizeOfHeaders;
133   Dest.CheckSum = Src.CheckSum;
134   Dest.Subsystem = Src.Subsystem;
135   Dest.DLLCharacteristics = Src.DLLCharacteristics;
136   Dest.SizeOfStackReserve = Src.SizeOfStackReserve;
137   Dest.SizeOfStackCommit = Src.SizeOfStackCommit;
138   Dest.SizeOfHeapReserve = Src.SizeOfHeapReserve;
139   Dest.SizeOfHeapCommit = Src.SizeOfHeapCommit;
140   Dest.LoaderFlags = Src.LoaderFlags;
141   Dest.NumberOfRvaAndSize = Src.NumberOfRvaAndSize;
142 }
143 
144 } // end namespace coff
145 } // end namespace objcopy
146 } // end namespace llvm
147 
148 #endif // LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H
149