xref: /freebsd-src/contrib/llvm-project/llvm/lib/ObjCopy/COFF/COFFObject.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
181ad6265SDimitry Andric //===- COFFObject.h ---------------------------------------------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #ifndef LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H
1081ad6265SDimitry Andric #define LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H
1181ad6265SDimitry Andric 
1281ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h"
1381ad6265SDimitry Andric #include "llvm/ADT/DenseMap.h"
1481ad6265SDimitry Andric #include "llvm/ADT/StringRef.h"
1581ad6265SDimitry Andric #include "llvm/ADT/iterator_range.h"
1681ad6265SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
1781ad6265SDimitry Andric #include "llvm/Object/COFF.h"
1881ad6265SDimitry Andric #include <cstddef>
1981ad6265SDimitry Andric #include <cstdint>
2081ad6265SDimitry Andric #include <vector>
2181ad6265SDimitry Andric 
2281ad6265SDimitry Andric namespace llvm {
2381ad6265SDimitry Andric namespace objcopy {
2481ad6265SDimitry Andric namespace coff {
2581ad6265SDimitry Andric 
2681ad6265SDimitry Andric struct Relocation {
2781ad6265SDimitry Andric   Relocation() = default;
RelocationRelocation2881ad6265SDimitry Andric   Relocation(const object::coff_relocation &R) : Reloc(R) {}
2981ad6265SDimitry Andric 
3081ad6265SDimitry Andric   object::coff_relocation Reloc;
3181ad6265SDimitry Andric   size_t Target = 0;
3281ad6265SDimitry Andric   StringRef TargetName; // Used for diagnostics only
3381ad6265SDimitry Andric };
3481ad6265SDimitry Andric 
3581ad6265SDimitry Andric struct Section {
3681ad6265SDimitry Andric   object::coff_section Header;
3781ad6265SDimitry Andric   std::vector<Relocation> Relocs;
3881ad6265SDimitry Andric   StringRef Name;
3981ad6265SDimitry Andric   ssize_t UniqueId;
4081ad6265SDimitry Andric   size_t Index;
4181ad6265SDimitry Andric 
getContentsSection4281ad6265SDimitry Andric   ArrayRef<uint8_t> getContents() const {
4381ad6265SDimitry Andric     if (!OwnedContents.empty())
4481ad6265SDimitry Andric       return OwnedContents;
4581ad6265SDimitry Andric     return ContentsRef;
4681ad6265SDimitry Andric   }
4781ad6265SDimitry Andric 
setContentsRefSection4881ad6265SDimitry Andric   void setContentsRef(ArrayRef<uint8_t> Data) {
4981ad6265SDimitry Andric     OwnedContents.clear();
5081ad6265SDimitry Andric     ContentsRef = Data;
5181ad6265SDimitry Andric   }
5281ad6265SDimitry Andric 
setOwnedContentsSection5381ad6265SDimitry Andric   void setOwnedContents(std::vector<uint8_t> &&Data) {
5481ad6265SDimitry Andric     ContentsRef = ArrayRef<uint8_t>();
5581ad6265SDimitry Andric     OwnedContents = std::move(Data);
5681ad6265SDimitry Andric     Header.SizeOfRawData = OwnedContents.size();
5781ad6265SDimitry Andric   }
5881ad6265SDimitry Andric 
clearContentsSection5981ad6265SDimitry Andric   void clearContents() {
6081ad6265SDimitry Andric     ContentsRef = ArrayRef<uint8_t>();
6181ad6265SDimitry Andric     OwnedContents.clear();
6281ad6265SDimitry Andric   }
6381ad6265SDimitry Andric 
6481ad6265SDimitry Andric private:
6581ad6265SDimitry Andric   ArrayRef<uint8_t> ContentsRef;
6681ad6265SDimitry Andric   std::vector<uint8_t> OwnedContents;
6781ad6265SDimitry Andric };
6881ad6265SDimitry Andric 
6981ad6265SDimitry Andric struct AuxSymbol {
AuxSymbolAuxSymbol7081ad6265SDimitry Andric   AuxSymbol(ArrayRef<uint8_t> In) {
7181ad6265SDimitry Andric     assert(In.size() == sizeof(Opaque));
7281ad6265SDimitry Andric     std::copy(In.begin(), In.end(), Opaque);
7381ad6265SDimitry Andric   }
7481ad6265SDimitry Andric 
getRefAuxSymbol7581ad6265SDimitry Andric   ArrayRef<uint8_t> getRef() const {
7681ad6265SDimitry Andric     return ArrayRef<uint8_t>(Opaque, sizeof(Opaque));
7781ad6265SDimitry Andric   }
7881ad6265SDimitry Andric 
7981ad6265SDimitry Andric   uint8_t Opaque[sizeof(object::coff_symbol16)];
8081ad6265SDimitry Andric };
8181ad6265SDimitry Andric 
8281ad6265SDimitry Andric struct Symbol {
8381ad6265SDimitry Andric   object::coff_symbol32 Sym;
8481ad6265SDimitry Andric   StringRef Name;
8581ad6265SDimitry Andric   std::vector<AuxSymbol> AuxData;
8681ad6265SDimitry Andric   StringRef AuxFile;
8781ad6265SDimitry Andric   ssize_t TargetSectionId;
8881ad6265SDimitry Andric   ssize_t AssociativeComdatTargetSectionId = 0;
89*bdd1243dSDimitry Andric   std::optional<size_t> WeakTargetSymbolId;
9081ad6265SDimitry Andric   size_t UniqueId;
9181ad6265SDimitry Andric   size_t RawIndex;
9281ad6265SDimitry Andric   bool Referenced;
9381ad6265SDimitry Andric };
9481ad6265SDimitry Andric 
9581ad6265SDimitry Andric struct Object {
9681ad6265SDimitry Andric   bool IsPE = false;
9781ad6265SDimitry Andric 
9881ad6265SDimitry Andric   object::dos_header DosHeader;
9981ad6265SDimitry Andric   ArrayRef<uint8_t> DosStub;
10081ad6265SDimitry Andric 
10181ad6265SDimitry Andric   object::coff_file_header CoffFileHeader;
10281ad6265SDimitry Andric 
10381ad6265SDimitry Andric   bool Is64 = false;
10481ad6265SDimitry Andric   object::pe32plus_header PeHeader;
10581ad6265SDimitry Andric   uint32_t BaseOfData = 0; // pe32plus_header lacks this field.
10681ad6265SDimitry Andric 
10781ad6265SDimitry Andric   std::vector<object::data_directory> DataDirectories;
10881ad6265SDimitry Andric 
getSymbolsObject10981ad6265SDimitry Andric   ArrayRef<Symbol> getSymbols() const { return Symbols; }
11081ad6265SDimitry Andric   // This allows mutating individual Symbols, but not mutating the list
11181ad6265SDimitry Andric   // of symbols itself.
getMutableSymbolsObject11281ad6265SDimitry Andric   iterator_range<std::vector<Symbol>::iterator> getMutableSymbols() {
11381ad6265SDimitry Andric     return make_range(Symbols.begin(), Symbols.end());
11481ad6265SDimitry Andric   }
11581ad6265SDimitry Andric 
11681ad6265SDimitry Andric   const Symbol *findSymbol(size_t UniqueId) const;
11781ad6265SDimitry Andric 
11881ad6265SDimitry Andric   void addSymbols(ArrayRef<Symbol> NewSymbols);
11981ad6265SDimitry Andric   Error removeSymbols(function_ref<Expected<bool>(const Symbol &)> ToRemove);
12081ad6265SDimitry Andric 
12181ad6265SDimitry Andric   // Set the Referenced field on all Symbols, based on relocations in
12281ad6265SDimitry Andric   // all sections.
12381ad6265SDimitry Andric   Error markSymbols();
12481ad6265SDimitry Andric 
getSectionsObject12581ad6265SDimitry Andric   ArrayRef<Section> getSections() const { return Sections; }
12681ad6265SDimitry Andric   // This allows mutating individual Sections, but not mutating the list
12781ad6265SDimitry Andric   // of sections itself.
getMutableSectionsObject12881ad6265SDimitry Andric   iterator_range<std::vector<Section>::iterator> getMutableSections() {
12981ad6265SDimitry Andric     return make_range(Sections.begin(), Sections.end());
13081ad6265SDimitry Andric   }
13181ad6265SDimitry Andric 
13281ad6265SDimitry Andric   const Section *findSection(ssize_t UniqueId) const;
13381ad6265SDimitry Andric 
13481ad6265SDimitry Andric   void addSections(ArrayRef<Section> NewSections);
13581ad6265SDimitry Andric   void removeSections(function_ref<bool(const Section &)> ToRemove);
13681ad6265SDimitry Andric   void truncateSections(function_ref<bool(const Section &)> ToTruncate);
13781ad6265SDimitry Andric 
13881ad6265SDimitry Andric private:
13981ad6265SDimitry Andric   std::vector<Symbol> Symbols;
14081ad6265SDimitry Andric   DenseMap<size_t, Symbol *> SymbolMap;
14181ad6265SDimitry Andric 
14281ad6265SDimitry Andric   size_t NextSymbolUniqueId = 0;
14381ad6265SDimitry Andric 
14481ad6265SDimitry Andric   std::vector<Section> Sections;
14581ad6265SDimitry Andric   DenseMap<ssize_t, Section *> SectionMap;
14681ad6265SDimitry Andric 
14781ad6265SDimitry Andric   ssize_t NextSectionUniqueId = 1; // Allow a UniqueId 0 to mean undefined.
14881ad6265SDimitry Andric 
14981ad6265SDimitry Andric   // Update SymbolMap.
15081ad6265SDimitry Andric   void updateSymbols();
15181ad6265SDimitry Andric 
15281ad6265SDimitry Andric   // Update SectionMap and Index in each Section.
15381ad6265SDimitry Andric   void updateSections();
15481ad6265SDimitry Andric };
15581ad6265SDimitry Andric 
15681ad6265SDimitry Andric // Copy between coff_symbol16 and coff_symbol32.
15781ad6265SDimitry Andric // The source and destination files can use either coff_symbol16 or
15881ad6265SDimitry Andric // coff_symbol32, while we always store them as coff_symbol32 in the
15981ad6265SDimitry Andric // intermediate data structure.
16081ad6265SDimitry Andric template <class Symbol1Ty, class Symbol2Ty>
copySymbol(Symbol1Ty & Dest,const Symbol2Ty & Src)16181ad6265SDimitry Andric void copySymbol(Symbol1Ty &Dest, const Symbol2Ty &Src) {
16281ad6265SDimitry Andric   static_assert(sizeof(Dest.Name.ShortName) == sizeof(Src.Name.ShortName),
16381ad6265SDimitry Andric                 "Mismatched name sizes");
16481ad6265SDimitry Andric   memcpy(Dest.Name.ShortName, Src.Name.ShortName, sizeof(Dest.Name.ShortName));
16581ad6265SDimitry Andric   Dest.Value = Src.Value;
16681ad6265SDimitry Andric   Dest.SectionNumber = Src.SectionNumber;
16781ad6265SDimitry Andric   Dest.Type = Src.Type;
16881ad6265SDimitry Andric   Dest.StorageClass = Src.StorageClass;
16981ad6265SDimitry Andric   Dest.NumberOfAuxSymbols = Src.NumberOfAuxSymbols;
17081ad6265SDimitry Andric }
17181ad6265SDimitry Andric 
17281ad6265SDimitry Andric // Copy between pe32_header and pe32plus_header.
17381ad6265SDimitry Andric // We store the intermediate state in a pe32plus_header.
17481ad6265SDimitry Andric template <class PeHeader1Ty, class PeHeader2Ty>
copyPeHeader(PeHeader1Ty & Dest,const PeHeader2Ty & Src)17581ad6265SDimitry Andric void copyPeHeader(PeHeader1Ty &Dest, const PeHeader2Ty &Src) {
17681ad6265SDimitry Andric   Dest.Magic = Src.Magic;
17781ad6265SDimitry Andric   Dest.MajorLinkerVersion = Src.MajorLinkerVersion;
17881ad6265SDimitry Andric   Dest.MinorLinkerVersion = Src.MinorLinkerVersion;
17981ad6265SDimitry Andric   Dest.SizeOfCode = Src.SizeOfCode;
18081ad6265SDimitry Andric   Dest.SizeOfInitializedData = Src.SizeOfInitializedData;
18181ad6265SDimitry Andric   Dest.SizeOfUninitializedData = Src.SizeOfUninitializedData;
18281ad6265SDimitry Andric   Dest.AddressOfEntryPoint = Src.AddressOfEntryPoint;
18381ad6265SDimitry Andric   Dest.BaseOfCode = Src.BaseOfCode;
18481ad6265SDimitry Andric   Dest.ImageBase = Src.ImageBase;
18581ad6265SDimitry Andric   Dest.SectionAlignment = Src.SectionAlignment;
18681ad6265SDimitry Andric   Dest.FileAlignment = Src.FileAlignment;
18781ad6265SDimitry Andric   Dest.MajorOperatingSystemVersion = Src.MajorOperatingSystemVersion;
18881ad6265SDimitry Andric   Dest.MinorOperatingSystemVersion = Src.MinorOperatingSystemVersion;
18981ad6265SDimitry Andric   Dest.MajorImageVersion = Src.MajorImageVersion;
19081ad6265SDimitry Andric   Dest.MinorImageVersion = Src.MinorImageVersion;
19181ad6265SDimitry Andric   Dest.MajorSubsystemVersion = Src.MajorSubsystemVersion;
19281ad6265SDimitry Andric   Dest.MinorSubsystemVersion = Src.MinorSubsystemVersion;
19381ad6265SDimitry Andric   Dest.Win32VersionValue = Src.Win32VersionValue;
19481ad6265SDimitry Andric   Dest.SizeOfImage = Src.SizeOfImage;
19581ad6265SDimitry Andric   Dest.SizeOfHeaders = Src.SizeOfHeaders;
19681ad6265SDimitry Andric   Dest.CheckSum = Src.CheckSum;
19781ad6265SDimitry Andric   Dest.Subsystem = Src.Subsystem;
19881ad6265SDimitry Andric   Dest.DLLCharacteristics = Src.DLLCharacteristics;
19981ad6265SDimitry Andric   Dest.SizeOfStackReserve = Src.SizeOfStackReserve;
20081ad6265SDimitry Andric   Dest.SizeOfStackCommit = Src.SizeOfStackCommit;
20181ad6265SDimitry Andric   Dest.SizeOfHeapReserve = Src.SizeOfHeapReserve;
20281ad6265SDimitry Andric   Dest.SizeOfHeapCommit = Src.SizeOfHeapCommit;
20381ad6265SDimitry Andric   Dest.LoaderFlags = Src.LoaderFlags;
20481ad6265SDimitry Andric   Dest.NumberOfRvaAndSize = Src.NumberOfRvaAndSize;
20581ad6265SDimitry Andric }
20681ad6265SDimitry Andric 
20781ad6265SDimitry Andric } // end namespace coff
20881ad6265SDimitry Andric } // end namespace objcopy
20981ad6265SDimitry Andric } // end namespace llvm
21081ad6265SDimitry Andric 
21181ad6265SDimitry Andric #endif // LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H
212