MCMachObjectWriter.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. //===-- llvm/MC/MCMachObjectWriter.h - Mach Object Writer -------*- 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. #ifndef LLVM_MC_MCMACHOBJECTWRITER_H
  10. #define LLVM_MC_MCMACHOBJECTWRITER_H
  11. #include "llvm/ADT/DenseMap.h"
  12. #include "llvm/ADT/SmallString.h"
  13. #include "llvm/MC/MCExpr.h"
  14. #include "llvm/MC/MCObjectWriter.h"
  15. #include "llvm/MC/StringTableBuilder.h"
  16. #include "llvm/Support/DataTypes.h"
  17. #include "llvm/Support/MachO.h"
  18. #include <vector>
  19. namespace llvm {
  20. class MachObjectWriter;
  21. class MCMachObjectTargetWriter {
  22. const unsigned Is64Bit : 1;
  23. const uint32_t CPUType;
  24. const uint32_t CPUSubtype;
  25. unsigned LocalDifference_RIT;
  26. protected:
  27. MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_,
  28. uint32_t CPUSubtype_);
  29. void setLocalDifferenceRelocationType(unsigned Type) {
  30. LocalDifference_RIT = Type;
  31. }
  32. public:
  33. virtual ~MCMachObjectTargetWriter();
  34. /// \name Lifetime Management
  35. /// @{
  36. virtual void reset() {}
  37. /// @}
  38. /// \name Accessors
  39. /// @{
  40. bool is64Bit() const { return Is64Bit; }
  41. uint32_t getCPUType() const { return CPUType; }
  42. uint32_t getCPUSubtype() const { return CPUSubtype; }
  43. unsigned getLocalDifferenceRelocationType() const {
  44. return LocalDifference_RIT;
  45. }
  46. /// @}
  47. /// \name API
  48. /// @{
  49. virtual void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
  50. const MCAsmLayout &Layout,
  51. const MCFragment *Fragment,
  52. const MCFixup &Fixup, MCValue Target,
  53. uint64_t &FixedValue) = 0;
  54. /// @}
  55. };
  56. class MachObjectWriter : public MCObjectWriter {
  57. /// Helper struct for containing some precomputed information on symbols.
  58. struct MachSymbolData {
  59. const MCSymbol *Symbol;
  60. uint64_t StringIndex;
  61. uint8_t SectionIndex;
  62. // Support lexicographic sorting.
  63. bool operator<(const MachSymbolData &RHS) const;
  64. };
  65. /// The target specific Mach-O writer instance.
  66. std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter;
  67. /// \name Relocation Data
  68. /// @{
  69. struct RelAndSymbol {
  70. const MCSymbol *Sym;
  71. MachO::any_relocation_info MRE;
  72. RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE)
  73. : Sym(Sym), MRE(MRE) {}
  74. };
  75. llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
  76. llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase;
  77. SectionAddrMap SectionAddress;
  78. /// @}
  79. /// \name Symbol Table Data
  80. /// @{
  81. StringTableBuilder StringTable;
  82. std::vector<MachSymbolData> LocalSymbolData;
  83. std::vector<MachSymbolData> ExternalSymbolData;
  84. std::vector<MachSymbolData> UndefinedSymbolData;
  85. /// @}
  86. MachSymbolData *findSymbolData(const MCSymbol &Sym);
  87. public:
  88. MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_pwrite_stream &OS,
  89. bool IsLittleEndian)
  90. : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {}
  91. const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;
  92. /// \name Lifetime management Methods
  93. /// @{
  94. void reset() override;
  95. /// @}
  96. /// \name Utility Methods
  97. /// @{
  98. bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
  99. SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
  100. uint64_t getSectionAddress(const MCSection *Sec) const {
  101. return SectionAddress.lookup(Sec);
  102. }
  103. uint64_t getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const;
  104. uint64_t getFragmentAddress(const MCFragment *Fragment,
  105. const MCAsmLayout &Layout) const;
  106. uint64_t getPaddingSize(const MCSection *SD, const MCAsmLayout &Layout) const;
  107. bool doesSymbolRequireExternRelocation(const MCSymbol &S);
  108. /// @}
  109. /// \name Target Writer Proxy Accessors
  110. /// @{
  111. bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
  112. bool isX86_64() const {
  113. uint32_t CPUType = TargetObjectWriter->getCPUType();
  114. return CPUType == MachO::CPU_TYPE_X86_64;
  115. }
  116. /// @}
  117. void writeHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
  118. bool SubsectionsViaSymbols);
  119. /// Write a segment load command.
  120. ///
  121. /// \param NumSections The number of sections in this segment.
  122. /// \param SectionDataSize The total size of the sections.
  123. void writeSegmentLoadCommand(unsigned NumSections, uint64_t VMSize,
  124. uint64_t SectionDataStartOffset,
  125. uint64_t SectionDataSize);
  126. void writeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
  127. const MCSection &Sec, uint64_t FileOffset,
  128. uint64_t RelocationsStart, unsigned NumRelocations);
  129. void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
  130. uint32_t StringTableOffset,
  131. uint32_t StringTableSize);
  132. void writeDysymtabLoadCommand(
  133. uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols,
  134. uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols,
  135. uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols,
  136. uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols);
  137. void writeNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
  138. void writeLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
  139. uint32_t DataSize);
  140. void writeLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
  141. // FIXME: We really need to improve the relocation validation. Basically, we
  142. // want to implement a separate computation which evaluates the relocation
  143. // entry as the linker would, and verifies that the resultant fixup value is
  144. // exactly what the encoder wanted. This will catch several classes of
  145. // problems:
  146. //
  147. // - Relocation entry bugs, the two algorithms are unlikely to have the same
  148. // exact bug.
  149. //
  150. // - Relaxation issues, where we forget to relax something.
  151. //
  152. // - Input errors, where something cannot be correctly encoded. 'as' allows
  153. // these through in many cases.
  154. // Add a relocation to be output in the object file. At the time this is
  155. // called, the symbol indexes are not know, so if the relocation refers
  156. // to a symbol it should be passed as \p RelSymbol so that it can be updated
  157. // afterwards. If the relocation doesn't refer to a symbol, nullptr should be
  158. // used.
  159. void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec,
  160. MachO::any_relocation_info &MRE) {
  161. RelAndSymbol P(RelSymbol, MRE);
  162. Relocations[Sec].push_back(P);
  163. }
  164. void recordScatteredRelocation(const MCAssembler &Asm,
  165. const MCAsmLayout &Layout,
  166. const MCFragment *Fragment,
  167. const MCFixup &Fixup, MCValue Target,
  168. unsigned Log2Size, uint64_t &FixedValue);
  169. void recordTLVPRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
  170. const MCFragment *Fragment, const MCFixup &Fixup,
  171. MCValue Target, uint64_t &FixedValue);
  172. void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
  173. const MCFragment *Fragment, const MCFixup &Fixup,
  174. MCValue Target, bool &IsPCRel,
  175. uint64_t &FixedValue) override;
  176. void bindIndirectSymbols(MCAssembler &Asm);
  177. /// Compute the symbol table data.
  178. void computeSymbolTable(MCAssembler &Asm,
  179. std::vector<MachSymbolData> &LocalSymbolData,
  180. std::vector<MachSymbolData> &ExternalSymbolData,
  181. std::vector<MachSymbolData> &UndefinedSymbolData);
  182. void computeSectionAddresses(const MCAssembler &Asm,
  183. const MCAsmLayout &Layout);
  184. void executePostLayoutBinding(MCAssembler &Asm,
  185. const MCAsmLayout &Layout) override;
  186. bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
  187. const MCSymbol &SymA,
  188. const MCFragment &FB, bool InSet,
  189. bool IsPCRel) const override;
  190. void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
  191. };
  192. /// Construct a new Mach-O writer instance.
  193. ///
  194. /// This routine takes ownership of the target writer subclass.
  195. ///
  196. /// \param MOTW - The target specific Mach-O writer subclass.
  197. /// \param OS - The stream to write to.
  198. /// \returns The constructed object writer.
  199. MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
  200. raw_pwrite_stream &OS,
  201. bool IsLittleEndian);
  202. } // End llvm namespace
  203. #endif