]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/MC/MCMachObjectWriter.h
Merge llvm trunk r238337 from ^/vendor/llvm/dist, resolve conflicts, and
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / MC / MCMachObjectWriter.h
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
10 #ifndef LLVM_MC_MCMACHOBJECTWRITER_H
11 #define LLVM_MC_MCMACHOBJECTWRITER_H
12
13 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCObjectWriter.h"
17 #include "llvm/MC/StringTableBuilder.h"
18 #include "llvm/Support/DataTypes.h"
19 #include "llvm/Support/MachO.h"
20 #include <vector>
21
22 namespace llvm {
23
24 class MachObjectWriter;
25
26 class MCMachObjectTargetWriter {
27   const unsigned Is64Bit : 1;
28   const uint32_t CPUType;
29   const uint32_t CPUSubtype;
30   // FIXME: Remove this, we should just always use it once we no longer care
31   // about Darwin 'as' compatibility.
32   const unsigned UseAggressiveSymbolFolding : 1;
33   unsigned LocalDifference_RIT;
34
35 protected:
36   MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_,
37                            uint32_t CPUSubtype_,
38                            bool UseAggressiveSymbolFolding_ = false);
39
40   void setLocalDifferenceRelocationType(unsigned Type) {
41     LocalDifference_RIT = Type;
42   }
43
44 public:
45   virtual ~MCMachObjectTargetWriter();
46
47   /// \name Lifetime Management
48   /// @{
49
50   virtual void reset() {};
51
52   /// @}
53
54   /// \name Accessors
55   /// @{
56
57   bool is64Bit() const { return Is64Bit; }
58   bool useAggressiveSymbolFolding() const { return UseAggressiveSymbolFolding; }
59   uint32_t getCPUType() const { return CPUType; }
60   uint32_t getCPUSubtype() const { return CPUSubtype; }
61   unsigned getLocalDifferenceRelocationType() const {
62     return LocalDifference_RIT;
63   }
64
65   /// @}
66
67   /// \name API
68   /// @{
69
70   virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
71                                 const MCAsmLayout &Layout,
72                                 const MCFragment *Fragment,
73                                 const MCFixup &Fixup, MCValue Target,
74                                 uint64_t &FixedValue) = 0;
75
76   /// @}
77 };
78
79 class MachObjectWriter : public MCObjectWriter {
80   /// MachSymbolData - Helper struct for containing some precomputed information
81   /// on symbols.
82   struct MachSymbolData {
83     const MCSymbol *Symbol;
84     uint64_t StringIndex;
85     uint8_t SectionIndex;
86
87     // Support lexicographic sorting.
88     bool operator<(const MachSymbolData &RHS) const;
89   };
90
91   /// The target specific Mach-O writer instance.
92   std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter;
93
94   /// \name Relocation Data
95   /// @{
96
97   struct RelAndSymbol {
98     const MCSymbol *Sym;
99     MachO::any_relocation_info MRE;
100     RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE)
101         : Sym(Sym), MRE(MRE) {}
102   };
103
104   llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
105   llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase;
106
107   /// @}
108   /// \name Symbol Table Data
109   /// @{
110
111   StringTableBuilder StringTable;
112   std::vector<MachSymbolData> LocalSymbolData;
113   std::vector<MachSymbolData> ExternalSymbolData;
114   std::vector<MachSymbolData> UndefinedSymbolData;
115
116   /// @}
117
118   MachSymbolData *findSymbolData(const MCSymbol &Sym);
119
120 public:
121   MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_pwrite_stream &OS,
122                    bool IsLittleEndian)
123       : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {}
124
125   const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;
126
127   /// \name Lifetime management Methods
128   /// @{
129
130   void reset() override;
131
132   /// @}
133
134   /// \name Utility Methods
135   /// @{
136
137   bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
138
139   SectionAddrMap SectionAddress;
140
141   SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
142
143   uint64_t getSectionAddress(const MCSection *Sec) const {
144     return SectionAddress.lookup(Sec);
145   }
146   uint64_t getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const;
147
148   uint64_t getFragmentAddress(const MCFragment *Fragment,
149                               const MCAsmLayout &Layout) const;
150
151   uint64_t getPaddingSize(const MCSection *SD, const MCAsmLayout &Layout) const;
152
153   bool doesSymbolRequireExternRelocation(const MCSymbol &S);
154
155   /// @}
156
157   /// \name Target Writer Proxy Accessors
158   /// @{
159
160   bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
161   bool isX86_64() const {
162     uint32_t CPUType = TargetObjectWriter->getCPUType();
163     return CPUType == MachO::CPU_TYPE_X86_64;
164   }
165
166   /// @}
167
168   void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
169                    bool SubsectionsViaSymbols);
170
171   /// WriteSegmentLoadCommand - Write a segment load command.
172   ///
173   /// \param NumSections The number of sections in this segment.
174   /// \param SectionDataSize The total size of the sections.
175   void WriteSegmentLoadCommand(unsigned NumSections,
176                                uint64_t VMSize,
177                                uint64_t SectionDataStartOffset,
178                                uint64_t SectionDataSize);
179
180   void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
181                     const MCSection &Sec, uint64_t FileOffset,
182                     uint64_t RelocationsStart, unsigned NumRelocations);
183
184   void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
185                               uint32_t StringTableOffset,
186                               uint32_t StringTableSize);
187
188   void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
189                                 uint32_t NumLocalSymbols,
190                                 uint32_t FirstExternalSymbol,
191                                 uint32_t NumExternalSymbols,
192                                 uint32_t FirstUndefinedSymbol,
193                                 uint32_t NumUndefinedSymbols,
194                                 uint32_t IndirectSymbolOffset,
195                                 uint32_t NumIndirectSymbols);
196
197   void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
198
199   void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
200                                 uint32_t DataSize);
201
202   void WriteLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
203
204   // FIXME: We really need to improve the relocation validation. Basically, we
205   // want to implement a separate computation which evaluates the relocation
206   // entry as the linker would, and verifies that the resultant fixup value is
207   // exactly what the encoder wanted. This will catch several classes of
208   // problems:
209   //
210   //  - Relocation entry bugs, the two algorithms are unlikely to have the same
211   //    exact bug.
212   //
213   //  - Relaxation issues, where we forget to relax something.
214   //
215   //  - Input errors, where something cannot be correctly encoded. 'as' allows
216   //    these through in many cases.
217
218   // Add a relocation to be output in the object file. At the time this is
219   // called, the symbol indexes are not know, so if the relocation refers
220   // to a symbol it should be passed as \p RelSymbol so that it can be updated
221   // afterwards. If the relocation doesn't refer to a symbol, nullptr should be
222   // used.
223   void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec,
224                      MachO::any_relocation_info &MRE) {
225     RelAndSymbol P(RelSymbol, MRE);
226     Relocations[Sec].push_back(P);
227   }
228
229   void RecordScatteredRelocation(const MCAssembler &Asm,
230                                  const MCAsmLayout &Layout,
231                                  const MCFragment *Fragment,
232                                  const MCFixup &Fixup, MCValue Target,
233                                  unsigned Log2Size,
234                                  uint64_t &FixedValue);
235
236   void RecordTLVPRelocation(const MCAssembler &Asm,
237                             const MCAsmLayout &Layout,
238                             const MCFragment *Fragment,
239                             const MCFixup &Fixup, MCValue Target,
240                             uint64_t &FixedValue);
241
242   void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
243                         const MCFragment *Fragment, const MCFixup &Fixup,
244                         MCValue Target, bool &IsPCRel,
245                         uint64_t &FixedValue) override;
246
247   void BindIndirectSymbols(MCAssembler &Asm);
248
249   /// ComputeSymbolTable - Compute the symbol table data
250   ///
251   void ComputeSymbolTable(MCAssembler &Asm,
252                           std::vector<MachSymbolData> &LocalSymbolData,
253                           std::vector<MachSymbolData> &ExternalSymbolData,
254                           std::vector<MachSymbolData> &UndefinedSymbolData);
255
256   void computeSectionAddresses(const MCAssembler &Asm,
257                                const MCAsmLayout &Layout);
258
259   void ExecutePostLayoutBinding(MCAssembler &Asm,
260                                 const MCAsmLayout &Layout) override;
261
262   bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
263                                               const MCSymbol &SymA,
264                                               const MCFragment &FB, bool InSet,
265                                               bool IsPCRel) const override;
266
267   void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
268 };
269
270
271 /// \brief Construct a new Mach-O writer instance.
272 ///
273 /// This routine takes ownership of the target writer subclass.
274 ///
275 /// \param MOTW - The target specific Mach-O writer subclass.
276 /// \param OS - The stream to write to.
277 /// \returns The constructed object writer.
278 MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
279                                        raw_pwrite_stream &OS,
280                                        bool IsLittleEndian);
281
282 } // End llvm namespace
283
284 #endif