COFFObject.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. #ifndef LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H
  9. #define LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H
  10. #include "llvm/ADT/ArrayRef.h"
  11. #include "llvm/ADT/DenseMap.h"
  12. #include "llvm/ADT/StringRef.h"
  13. #include "llvm/ADT/iterator_range.h"
  14. #include "llvm/BinaryFormat/COFF.h"
  15. #include "llvm/Object/COFF.h"
  16. #include <cstddef>
  17. #include <cstdint>
  18. #include <vector>
  19. namespace llvm {
  20. namespace objcopy {
  21. namespace coff {
  22. struct Relocation {
  23. Relocation() = default;
  24. Relocation(const object::coff_relocation &R) : Reloc(R) {}
  25. object::coff_relocation Reloc;
  26. size_t Target = 0;
  27. StringRef TargetName; // Used for diagnostics only
  28. };
  29. struct Section {
  30. object::coff_section Header;
  31. std::vector<Relocation> Relocs;
  32. StringRef Name;
  33. ssize_t UniqueId;
  34. size_t Index;
  35. ArrayRef<uint8_t> getContents() const {
  36. if (!OwnedContents.empty())
  37. return OwnedContents;
  38. return ContentsRef;
  39. }
  40. void setContentsRef(ArrayRef<uint8_t> Data) {
  41. OwnedContents.clear();
  42. ContentsRef = Data;
  43. }
  44. void setOwnedContents(std::vector<uint8_t> &&Data) {
  45. ContentsRef = ArrayRef<uint8_t>();
  46. OwnedContents = std::move(Data);
  47. Header.SizeOfRawData = OwnedContents.size();
  48. }
  49. void clearContents() {
  50. ContentsRef = ArrayRef<uint8_t>();
  51. OwnedContents.clear();
  52. }
  53. private:
  54. ArrayRef<uint8_t> ContentsRef;
  55. std::vector<uint8_t> OwnedContents;
  56. };
  57. struct AuxSymbol {
  58. AuxSymbol(ArrayRef<uint8_t> In) {
  59. assert(In.size() == sizeof(Opaque));
  60. std::copy(In.begin(), In.end(), Opaque);
  61. }
  62. ArrayRef<uint8_t> getRef() const {
  63. return ArrayRef<uint8_t>(Opaque, sizeof(Opaque));
  64. }
  65. uint8_t Opaque[sizeof(object::coff_symbol16)];
  66. };
  67. struct Symbol {
  68. object::coff_symbol32 Sym;
  69. StringRef Name;
  70. std::vector<AuxSymbol> AuxData;
  71. StringRef AuxFile;
  72. ssize_t TargetSectionId;
  73. ssize_t AssociativeComdatTargetSectionId = 0;
  74. std::optional<size_t> WeakTargetSymbolId;
  75. size_t UniqueId;
  76. size_t RawIndex;
  77. bool Referenced;
  78. };
  79. struct Object {
  80. bool IsPE = false;
  81. object::dos_header DosHeader;
  82. ArrayRef<uint8_t> DosStub;
  83. object::coff_file_header CoffFileHeader;
  84. bool Is64 = false;
  85. object::pe32plus_header PeHeader;
  86. uint32_t BaseOfData = 0; // pe32plus_header lacks this field.
  87. std::vector<object::data_directory> DataDirectories;
  88. ArrayRef<Symbol> getSymbols() const { return Symbols; }
  89. // This allows mutating individual Symbols, but not mutating the list
  90. // of symbols itself.
  91. iterator_range<std::vector<Symbol>::iterator> getMutableSymbols() {
  92. return make_range(Symbols.begin(), Symbols.end());
  93. }
  94. const Symbol *findSymbol(size_t UniqueId) const;
  95. void addSymbols(ArrayRef<Symbol> NewSymbols);
  96. Error removeSymbols(function_ref<Expected<bool>(const Symbol &)> ToRemove);
  97. // Set the Referenced field on all Symbols, based on relocations in
  98. // all sections.
  99. Error markSymbols();
  100. ArrayRef<Section> getSections() const { return Sections; }
  101. // This allows mutating individual Sections, but not mutating the list
  102. // of sections itself.
  103. iterator_range<std::vector<Section>::iterator> getMutableSections() {
  104. return make_range(Sections.begin(), Sections.end());
  105. }
  106. const Section *findSection(ssize_t UniqueId) const;
  107. void addSections(ArrayRef<Section> NewSections);
  108. void removeSections(function_ref<bool(const Section &)> ToRemove);
  109. void truncateSections(function_ref<bool(const Section &)> ToTruncate);
  110. private:
  111. std::vector<Symbol> Symbols;
  112. DenseMap<size_t, Symbol *> SymbolMap;
  113. size_t NextSymbolUniqueId = 0;
  114. std::vector<Section> Sections;
  115. DenseMap<ssize_t, Section *> SectionMap;
  116. ssize_t NextSectionUniqueId = 1; // Allow a UniqueId 0 to mean undefined.
  117. // Update SymbolMap.
  118. void updateSymbols();
  119. // Update SectionMap and Index in each Section.
  120. void updateSections();
  121. };
  122. // Copy between coff_symbol16 and coff_symbol32.
  123. // The source and destination files can use either coff_symbol16 or
  124. // coff_symbol32, while we always store them as coff_symbol32 in the
  125. // intermediate data structure.
  126. template <class Symbol1Ty, class Symbol2Ty>
  127. void copySymbol(Symbol1Ty &Dest, const Symbol2Ty &Src) {
  128. static_assert(sizeof(Dest.Name.ShortName) == sizeof(Src.Name.ShortName),
  129. "Mismatched name sizes");
  130. memcpy(Dest.Name.ShortName, Src.Name.ShortName, sizeof(Dest.Name.ShortName));
  131. Dest.Value = Src.Value;
  132. Dest.SectionNumber = Src.SectionNumber;
  133. Dest.Type = Src.Type;
  134. Dest.StorageClass = Src.StorageClass;
  135. Dest.NumberOfAuxSymbols = Src.NumberOfAuxSymbols;
  136. }
  137. // Copy between pe32_header and pe32plus_header.
  138. // We store the intermediate state in a pe32plus_header.
  139. template <class PeHeader1Ty, class PeHeader2Ty>
  140. void copyPeHeader(PeHeader1Ty &Dest, const PeHeader2Ty &Src) {
  141. Dest.Magic = Src.Magic;
  142. Dest.MajorLinkerVersion = Src.MajorLinkerVersion;
  143. Dest.MinorLinkerVersion = Src.MinorLinkerVersion;
  144. Dest.SizeOfCode = Src.SizeOfCode;
  145. Dest.SizeOfInitializedData = Src.SizeOfInitializedData;
  146. Dest.SizeOfUninitializedData = Src.SizeOfUninitializedData;
  147. Dest.AddressOfEntryPoint = Src.AddressOfEntryPoint;
  148. Dest.BaseOfCode = Src.BaseOfCode;
  149. Dest.ImageBase = Src.ImageBase;
  150. Dest.SectionAlignment = Src.SectionAlignment;
  151. Dest.FileAlignment = Src.FileAlignment;
  152. Dest.MajorOperatingSystemVersion = Src.MajorOperatingSystemVersion;
  153. Dest.MinorOperatingSystemVersion = Src.MinorOperatingSystemVersion;
  154. Dest.MajorImageVersion = Src.MajorImageVersion;
  155. Dest.MinorImageVersion = Src.MinorImageVersion;
  156. Dest.MajorSubsystemVersion = Src.MajorSubsystemVersion;
  157. Dest.MinorSubsystemVersion = Src.MinorSubsystemVersion;
  158. Dest.Win32VersionValue = Src.Win32VersionValue;
  159. Dest.SizeOfImage = Src.SizeOfImage;
  160. Dest.SizeOfHeaders = Src.SizeOfHeaders;
  161. Dest.CheckSum = Src.CheckSum;
  162. Dest.Subsystem = Src.Subsystem;
  163. Dest.DLLCharacteristics = Src.DLLCharacteristics;
  164. Dest.SizeOfStackReserve = Src.SizeOfStackReserve;
  165. Dest.SizeOfStackCommit = Src.SizeOfStackCommit;
  166. Dest.SizeOfHeapReserve = Src.SizeOfHeapReserve;
  167. Dest.SizeOfHeapCommit = Src.SizeOfHeapCommit;
  168. Dest.LoaderFlags = Src.LoaderFlags;
  169. Dest.NumberOfRvaAndSize = Src.NumberOfRvaAndSize;
  170. }
  171. } // end namespace coff
  172. } // end namespace objcopy
  173. } // end namespace llvm
  174. #endif // LLVM_LIB_OBJCOPY_COFF_COFFOBJECT_H