xref: /llvm-project/llvm/lib/ObjCopy/COFF/COFFObject.h (revision 6eb0b0a0452a4c53ceb1156afd17764fbff51111)
125d7b4fbSAlexey Lapshin //===- COFFObject.h ---------------------------------------------*- C++ -*-===//
225d7b4fbSAlexey Lapshin //
325d7b4fbSAlexey Lapshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
425d7b4fbSAlexey Lapshin // See https://llvm.org/LICENSE.txt for license information.
525d7b4fbSAlexey Lapshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
625d7b4fbSAlexey Lapshin //
725d7b4fbSAlexey Lapshin //===----------------------------------------------------------------------===//
825d7b4fbSAlexey Lapshin 
925d7b4fbSAlexey Lapshin #ifndef LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H
1025d7b4fbSAlexey Lapshin #define LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H
1125d7b4fbSAlexey Lapshin 
1225d7b4fbSAlexey Lapshin #include "llvm/ADT/ArrayRef.h"
1325d7b4fbSAlexey Lapshin #include "llvm/ADT/DenseMap.h"
1425d7b4fbSAlexey Lapshin #include "llvm/ADT/StringRef.h"
1525d7b4fbSAlexey Lapshin #include "llvm/ADT/iterator_range.h"
1625d7b4fbSAlexey Lapshin #include "llvm/BinaryFormat/COFF.h"
1725d7b4fbSAlexey Lapshin #include "llvm/Object/COFF.h"
1825d7b4fbSAlexey Lapshin #include <cstddef>
1925d7b4fbSAlexey Lapshin #include <cstdint>
2025d7b4fbSAlexey Lapshin #include <vector>
2125d7b4fbSAlexey Lapshin 
2225d7b4fbSAlexey Lapshin namespace llvm {
2325d7b4fbSAlexey Lapshin namespace objcopy {
2425d7b4fbSAlexey Lapshin namespace coff {
2525d7b4fbSAlexey Lapshin 
2625d7b4fbSAlexey Lapshin struct Relocation {
2725d7b4fbSAlexey Lapshin   Relocation() = default;
RelocationRelocation2825d7b4fbSAlexey Lapshin   Relocation(const object::coff_relocation &R) : Reloc(R) {}
2925d7b4fbSAlexey Lapshin 
3025d7b4fbSAlexey Lapshin   object::coff_relocation Reloc;
3125d7b4fbSAlexey Lapshin   size_t Target = 0;
3225d7b4fbSAlexey Lapshin   StringRef TargetName; // Used for diagnostics only
3325d7b4fbSAlexey Lapshin };
3425d7b4fbSAlexey Lapshin 
3525d7b4fbSAlexey Lapshin struct Section {
3625d7b4fbSAlexey Lapshin   object::coff_section Header;
3725d7b4fbSAlexey Lapshin   std::vector<Relocation> Relocs;
3825d7b4fbSAlexey Lapshin   StringRef Name;
3925d7b4fbSAlexey Lapshin   ssize_t UniqueId;
4025d7b4fbSAlexey Lapshin   size_t Index;
4125d7b4fbSAlexey Lapshin 
getContentsSection4225d7b4fbSAlexey Lapshin   ArrayRef<uint8_t> getContents() const {
4325d7b4fbSAlexey Lapshin     if (!OwnedContents.empty())
4425d7b4fbSAlexey Lapshin       return OwnedContents;
4525d7b4fbSAlexey Lapshin     return ContentsRef;
4625d7b4fbSAlexey Lapshin   }
4725d7b4fbSAlexey Lapshin 
setContentsRefSection4825d7b4fbSAlexey Lapshin   void setContentsRef(ArrayRef<uint8_t> Data) {
4925d7b4fbSAlexey Lapshin     OwnedContents.clear();
5025d7b4fbSAlexey Lapshin     ContentsRef = Data;
5125d7b4fbSAlexey Lapshin   }
5225d7b4fbSAlexey Lapshin 
setOwnedContentsSection5325d7b4fbSAlexey Lapshin   void setOwnedContents(std::vector<uint8_t> &&Data) {
5425d7b4fbSAlexey Lapshin     ContentsRef = ArrayRef<uint8_t>();
5525d7b4fbSAlexey Lapshin     OwnedContents = std::move(Data);
5625d7b4fbSAlexey Lapshin     Header.SizeOfRawData = OwnedContents.size();
5725d7b4fbSAlexey Lapshin   }
5825d7b4fbSAlexey Lapshin 
clearContentsSection5925d7b4fbSAlexey Lapshin   void clearContents() {
6025d7b4fbSAlexey Lapshin     ContentsRef = ArrayRef<uint8_t>();
6125d7b4fbSAlexey Lapshin     OwnedContents.clear();
6225d7b4fbSAlexey Lapshin   }
6325d7b4fbSAlexey Lapshin 
6425d7b4fbSAlexey Lapshin private:
6525d7b4fbSAlexey Lapshin   ArrayRef<uint8_t> ContentsRef;
6625d7b4fbSAlexey Lapshin   std::vector<uint8_t> OwnedContents;
6725d7b4fbSAlexey Lapshin };
6825d7b4fbSAlexey Lapshin 
6925d7b4fbSAlexey Lapshin struct AuxSymbol {
AuxSymbolAuxSymbol7025d7b4fbSAlexey Lapshin   AuxSymbol(ArrayRef<uint8_t> In) {
7125d7b4fbSAlexey Lapshin     assert(In.size() == sizeof(Opaque));
7225d7b4fbSAlexey Lapshin     std::copy(In.begin(), In.end(), Opaque);
7325d7b4fbSAlexey Lapshin   }
7425d7b4fbSAlexey Lapshin 
getRefAuxSymbol7525d7b4fbSAlexey Lapshin   ArrayRef<uint8_t> getRef() const {
7625d7b4fbSAlexey Lapshin     return ArrayRef<uint8_t>(Opaque, sizeof(Opaque));
7725d7b4fbSAlexey Lapshin   }
7825d7b4fbSAlexey Lapshin 
7925d7b4fbSAlexey Lapshin   uint8_t Opaque[sizeof(object::coff_symbol16)];
8025d7b4fbSAlexey Lapshin };
8125d7b4fbSAlexey Lapshin 
8225d7b4fbSAlexey Lapshin struct Symbol {
8325d7b4fbSAlexey Lapshin   object::coff_symbol32 Sym;
8425d7b4fbSAlexey Lapshin   StringRef Name;
8525d7b4fbSAlexey Lapshin   std::vector<AuxSymbol> AuxData;
8625d7b4fbSAlexey Lapshin   StringRef AuxFile;
8725d7b4fbSAlexey Lapshin   ssize_t TargetSectionId;
8825d7b4fbSAlexey Lapshin   ssize_t AssociativeComdatTargetSectionId = 0;
89*ec941432SFangrui Song   std::optional<size_t> WeakTargetSymbolId;
9025d7b4fbSAlexey Lapshin   size_t UniqueId;
9125d7b4fbSAlexey Lapshin   size_t RawIndex;
9225d7b4fbSAlexey Lapshin   bool Referenced;
9325d7b4fbSAlexey Lapshin };
9425d7b4fbSAlexey Lapshin 
9525d7b4fbSAlexey Lapshin struct Object {
9625d7b4fbSAlexey Lapshin   bool IsPE = false;
9725d7b4fbSAlexey Lapshin 
9825d7b4fbSAlexey Lapshin   object::dos_header DosHeader;
9925d7b4fbSAlexey Lapshin   ArrayRef<uint8_t> DosStub;
10025d7b4fbSAlexey Lapshin 
10125d7b4fbSAlexey Lapshin   object::coff_file_header CoffFileHeader;
10225d7b4fbSAlexey Lapshin 
10325d7b4fbSAlexey Lapshin   bool Is64 = false;
10425d7b4fbSAlexey Lapshin   object::pe32plus_header PeHeader;
10525d7b4fbSAlexey Lapshin   uint32_t BaseOfData = 0; // pe32plus_header lacks this field.
10625d7b4fbSAlexey Lapshin 
10725d7b4fbSAlexey Lapshin   std::vector<object::data_directory> DataDirectories;
10825d7b4fbSAlexey Lapshin 
getSymbolsObject10925d7b4fbSAlexey Lapshin   ArrayRef<Symbol> getSymbols() const { return Symbols; }
11025d7b4fbSAlexey Lapshin   // This allows mutating individual Symbols, but not mutating the list
11125d7b4fbSAlexey Lapshin   // of symbols itself.
getMutableSymbolsObject11225d7b4fbSAlexey Lapshin   iterator_range<std::vector<Symbol>::iterator> getMutableSymbols() {
11325d7b4fbSAlexey Lapshin     return make_range(Symbols.begin(), Symbols.end());
11425d7b4fbSAlexey Lapshin   }
11525d7b4fbSAlexey Lapshin 
11625d7b4fbSAlexey Lapshin   const Symbol *findSymbol(size_t UniqueId) const;
11725d7b4fbSAlexey Lapshin 
11825d7b4fbSAlexey Lapshin   void addSymbols(ArrayRef<Symbol> NewSymbols);
11925d7b4fbSAlexey Lapshin   Error removeSymbols(function_ref<Expected<bool>(const Symbol &)> ToRemove);
12025d7b4fbSAlexey Lapshin 
12125d7b4fbSAlexey Lapshin   // Set the Referenced field on all Symbols, based on relocations in
12225d7b4fbSAlexey Lapshin   // all sections.
12325d7b4fbSAlexey Lapshin   Error markSymbols();
12425d7b4fbSAlexey Lapshin 
getSectionsObject12525d7b4fbSAlexey Lapshin   ArrayRef<Section> getSections() const { return Sections; }
12625d7b4fbSAlexey Lapshin   // This allows mutating individual Sections, but not mutating the list
12725d7b4fbSAlexey Lapshin   // of sections itself.
getMutableSectionsObject12825d7b4fbSAlexey Lapshin   iterator_range<std::vector<Section>::iterator> getMutableSections() {
12925d7b4fbSAlexey Lapshin     return make_range(Sections.begin(), Sections.end());
13025d7b4fbSAlexey Lapshin   }
13125d7b4fbSAlexey Lapshin 
13225d7b4fbSAlexey Lapshin   const Section *findSection(ssize_t UniqueId) const;
13325d7b4fbSAlexey Lapshin 
13425d7b4fbSAlexey Lapshin   void addSections(ArrayRef<Section> NewSections);
13525d7b4fbSAlexey Lapshin   void removeSections(function_ref<bool(const Section &)> ToRemove);
13625d7b4fbSAlexey Lapshin   void truncateSections(function_ref<bool(const Section &)> ToTruncate);
13725d7b4fbSAlexey Lapshin 
13825d7b4fbSAlexey Lapshin private:
13925d7b4fbSAlexey Lapshin   std::vector<Symbol> Symbols;
14025d7b4fbSAlexey Lapshin   DenseMap<size_t, Symbol *> SymbolMap;
14125d7b4fbSAlexey Lapshin 
14225d7b4fbSAlexey Lapshin   size_t NextSymbolUniqueId = 0;
14325d7b4fbSAlexey Lapshin 
14425d7b4fbSAlexey Lapshin   std::vector<Section> Sections;
14525d7b4fbSAlexey Lapshin   DenseMap<ssize_t, Section *> SectionMap;
14625d7b4fbSAlexey Lapshin 
14725d7b4fbSAlexey Lapshin   ssize_t NextSectionUniqueId = 1; // Allow a UniqueId 0 to mean undefined.
14825d7b4fbSAlexey Lapshin 
14925d7b4fbSAlexey Lapshin   // Update SymbolMap.
15025d7b4fbSAlexey Lapshin   void updateSymbols();
15125d7b4fbSAlexey Lapshin 
15225d7b4fbSAlexey Lapshin   // Update SectionMap and Index in each Section.
15325d7b4fbSAlexey Lapshin   void updateSections();
15425d7b4fbSAlexey Lapshin };
15525d7b4fbSAlexey Lapshin 
15625d7b4fbSAlexey Lapshin // Copy between coff_symbol16 and coff_symbol32.
15725d7b4fbSAlexey Lapshin // The source and destination files can use either coff_symbol16 or
15825d7b4fbSAlexey Lapshin // coff_symbol32, while we always store them as coff_symbol32 in the
15925d7b4fbSAlexey Lapshin // intermediate data structure.
16025d7b4fbSAlexey Lapshin template <class Symbol1Ty, class Symbol2Ty>
copySymbol(Symbol1Ty & Dest,const Symbol2Ty & Src)16125d7b4fbSAlexey Lapshin void copySymbol(Symbol1Ty &Dest, const Symbol2Ty &Src) {
16225d7b4fbSAlexey Lapshin   static_assert(sizeof(Dest.Name.ShortName) == sizeof(Src.Name.ShortName),
16325d7b4fbSAlexey Lapshin                 "Mismatched name sizes");
16425d7b4fbSAlexey Lapshin   memcpy(Dest.Name.ShortName, Src.Name.ShortName, sizeof(Dest.Name.ShortName));
16525d7b4fbSAlexey Lapshin   Dest.Value = Src.Value;
16625d7b4fbSAlexey Lapshin   Dest.SectionNumber = Src.SectionNumber;
16725d7b4fbSAlexey Lapshin   Dest.Type = Src.Type;
16825d7b4fbSAlexey Lapshin   Dest.StorageClass = Src.StorageClass;
16925d7b4fbSAlexey Lapshin   Dest.NumberOfAuxSymbols = Src.NumberOfAuxSymbols;
17025d7b4fbSAlexey Lapshin }
17125d7b4fbSAlexey Lapshin 
17225d7b4fbSAlexey Lapshin // Copy between pe32_header and pe32plus_header.
17325d7b4fbSAlexey Lapshin // We store the intermediate state in a pe32plus_header.
17425d7b4fbSAlexey Lapshin template <class PeHeader1Ty, class PeHeader2Ty>
copyPeHeader(PeHeader1Ty & Dest,const PeHeader2Ty & Src)17525d7b4fbSAlexey Lapshin void copyPeHeader(PeHeader1Ty &Dest, const PeHeader2Ty &Src) {
17625d7b4fbSAlexey Lapshin   Dest.Magic = Src.Magic;
17725d7b4fbSAlexey Lapshin   Dest.MajorLinkerVersion = Src.MajorLinkerVersion;
17825d7b4fbSAlexey Lapshin   Dest.MinorLinkerVersion = Src.MinorLinkerVersion;
17925d7b4fbSAlexey Lapshin   Dest.SizeOfCode = Src.SizeOfCode;
18025d7b4fbSAlexey Lapshin   Dest.SizeOfInitializedData = Src.SizeOfInitializedData;
18125d7b4fbSAlexey Lapshin   Dest.SizeOfUninitializedData = Src.SizeOfUninitializedData;
18225d7b4fbSAlexey Lapshin   Dest.AddressOfEntryPoint = Src.AddressOfEntryPoint;
18325d7b4fbSAlexey Lapshin   Dest.BaseOfCode = Src.BaseOfCode;
18425d7b4fbSAlexey Lapshin   Dest.ImageBase = Src.ImageBase;
18525d7b4fbSAlexey Lapshin   Dest.SectionAlignment = Src.SectionAlignment;
18625d7b4fbSAlexey Lapshin   Dest.FileAlignment = Src.FileAlignment;
18725d7b4fbSAlexey Lapshin   Dest.MajorOperatingSystemVersion = Src.MajorOperatingSystemVersion;
18825d7b4fbSAlexey Lapshin   Dest.MinorOperatingSystemVersion = Src.MinorOperatingSystemVersion;
18925d7b4fbSAlexey Lapshin   Dest.MajorImageVersion = Src.MajorImageVersion;
19025d7b4fbSAlexey Lapshin   Dest.MinorImageVersion = Src.MinorImageVersion;
19125d7b4fbSAlexey Lapshin   Dest.MajorSubsystemVersion = Src.MajorSubsystemVersion;
19225d7b4fbSAlexey Lapshin   Dest.MinorSubsystemVersion = Src.MinorSubsystemVersion;
19325d7b4fbSAlexey Lapshin   Dest.Win32VersionValue = Src.Win32VersionValue;
19425d7b4fbSAlexey Lapshin   Dest.SizeOfImage = Src.SizeOfImage;
19525d7b4fbSAlexey Lapshin   Dest.SizeOfHeaders = Src.SizeOfHeaders;
19625d7b4fbSAlexey Lapshin   Dest.CheckSum = Src.CheckSum;
19725d7b4fbSAlexey Lapshin   Dest.Subsystem = Src.Subsystem;
19825d7b4fbSAlexey Lapshin   Dest.DLLCharacteristics = Src.DLLCharacteristics;
19925d7b4fbSAlexey Lapshin   Dest.SizeOfStackReserve = Src.SizeOfStackReserve;
20025d7b4fbSAlexey Lapshin   Dest.SizeOfStackCommit = Src.SizeOfStackCommit;
20125d7b4fbSAlexey Lapshin   Dest.SizeOfHeapReserve = Src.SizeOfHeapReserve;
20225d7b4fbSAlexey Lapshin   Dest.SizeOfHeapCommit = Src.SizeOfHeapCommit;
20325d7b4fbSAlexey Lapshin   Dest.LoaderFlags = Src.LoaderFlags;
20425d7b4fbSAlexey Lapshin   Dest.NumberOfRvaAndSize = Src.NumberOfRvaAndSize;
20525d7b4fbSAlexey Lapshin }
20625d7b4fbSAlexey Lapshin 
20725d7b4fbSAlexey Lapshin } // end namespace coff
20825d7b4fbSAlexey Lapshin } // end namespace objcopy
20925d7b4fbSAlexey Lapshin } // end namespace llvm
21025d7b4fbSAlexey Lapshin 
21125d7b4fbSAlexey Lapshin #endif // LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H
212