1 //===-- llvm/MC/MCMachObjectWriter.h - Mach Object Writer -------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_MC_MCMACHOBJECTWRITER_H
11 #define LLVM_MC_MCMACHOBJECTWRITER_H
13 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/ADT/OwningPtr.h"
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCObjectWriter.h"
18 #include "llvm/Object/MachOFormat.h"
19 #include "llvm/Support/DataTypes.h"
25 class MachObjectWriter;
27 class MCMachObjectTargetWriter {
28 const unsigned Is64Bit : 1;
29 const uint32_t CPUType;
30 const uint32_t CPUSubtype;
31 // FIXME: Remove this, we should just always use it once we no longer care
32 // about Darwin 'as' compatibility.
33 const unsigned UseAggressiveSymbolFolding : 1;
34 unsigned LocalDifference_RIT;
37 MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_,
39 bool UseAggressiveSymbolFolding_ = false);
41 void setLocalDifferenceRelocationType(unsigned Type) {
42 LocalDifference_RIT = Type;
46 virtual ~MCMachObjectTargetWriter();
51 bool is64Bit() const { return Is64Bit; }
52 bool useAggressiveSymbolFolding() const { return UseAggressiveSymbolFolding; }
53 uint32_t getCPUType() const { return CPUType; }
54 uint32_t getCPUSubtype() const { return CPUSubtype; }
55 unsigned getLocalDifferenceRelocationType() const {
56 return LocalDifference_RIT;
64 virtual void RecordRelocation(MachObjectWriter *Writer,
65 const MCAssembler &Asm,
66 const MCAsmLayout &Layout,
67 const MCFragment *Fragment,
70 uint64_t &FixedValue) = 0;
75 class MachObjectWriter : public MCObjectWriter {
76 /// MachSymbolData - Helper struct for containing some precomputed information
78 struct MachSymbolData {
79 MCSymbolData *SymbolData;
83 // Support lexicographic sorting.
84 bool operator<(const MachSymbolData &RHS) const;
87 /// The target specific Mach-O writer instance.
88 llvm::OwningPtr<MCMachObjectTargetWriter> TargetObjectWriter;
90 /// @name Relocation Data
93 llvm::DenseMap<const MCSectionData*,
94 std::vector<object::macho::RelocationEntry> > Relocations;
95 llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase;
98 /// @name Symbol Table Data
101 SmallString<256> StringTable;
102 std::vector<MachSymbolData> LocalSymbolData;
103 std::vector<MachSymbolData> ExternalSymbolData;
104 std::vector<MachSymbolData> UndefinedSymbolData;
109 MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS,
110 bool _IsLittleEndian)
111 : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) {
114 /// @name Utility Methods
117 bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
119 SectionAddrMap SectionAddress;
121 SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
123 uint64_t getSectionAddress(const MCSectionData* SD) const {
124 return SectionAddress.lookup(SD);
126 uint64_t getSymbolAddress(const MCSymbolData* SD,
127 const MCAsmLayout &Layout) const;
129 uint64_t getFragmentAddress(const MCFragment *Fragment,
130 const MCAsmLayout &Layout) const;
132 uint64_t getPaddingSize(const MCSectionData *SD,
133 const MCAsmLayout &Layout) const;
135 bool doesSymbolRequireExternRelocation(const MCSymbolData *SD);
139 /// @name Target Writer Proxy Accessors
142 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
144 uint32_t CPUType = TargetObjectWriter->getCPUType() &
145 ~object::mach::CTFM_ArchMask;
146 return CPUType == object::mach::CTM_ARM;
151 void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
152 bool SubsectionsViaSymbols);
154 /// WriteSegmentLoadCommand - Write a segment load command.
156 /// \param NumSections The number of sections in this segment.
157 /// \param SectionDataSize The total size of the sections.
158 void WriteSegmentLoadCommand(unsigned NumSections,
160 uint64_t SectionDataStartOffset,
161 uint64_t SectionDataSize);
163 void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
164 const MCSectionData &SD, uint64_t FileOffset,
165 uint64_t RelocationsStart, unsigned NumRelocations);
167 void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
168 uint32_t StringTableOffset,
169 uint32_t StringTableSize);
171 void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
172 uint32_t NumLocalSymbols,
173 uint32_t FirstExternalSymbol,
174 uint32_t NumExternalSymbols,
175 uint32_t FirstUndefinedSymbol,
176 uint32_t NumUndefinedSymbols,
177 uint32_t IndirectSymbolOffset,
178 uint32_t NumIndirectSymbols);
180 void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
182 void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
185 // FIXME: We really need to improve the relocation validation. Basically, we
186 // want to implement a separate computation which evaluates the relocation
187 // entry as the linker would, and verifies that the resultant fixup value is
188 // exactly what the encoder wanted. This will catch several classes of
191 // - Relocation entry bugs, the two algorithms are unlikely to have the same
194 // - Relaxation issues, where we forget to relax something.
196 // - Input errors, where something cannot be correctly encoded. 'as' allows
197 // these through in many cases.
199 void addRelocation(const MCSectionData *SD,
200 object::macho::RelocationEntry &MRE) {
201 Relocations[SD].push_back(MRE);
204 void RecordScatteredRelocation(const MCAssembler &Asm,
205 const MCAsmLayout &Layout,
206 const MCFragment *Fragment,
207 const MCFixup &Fixup, MCValue Target,
209 uint64_t &FixedValue);
211 void RecordTLVPRelocation(const MCAssembler &Asm,
212 const MCAsmLayout &Layout,
213 const MCFragment *Fragment,
214 const MCFixup &Fixup, MCValue Target,
215 uint64_t &FixedValue);
217 void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
218 const MCFragment *Fragment, const MCFixup &Fixup,
219 MCValue Target, uint64_t &FixedValue);
221 void BindIndirectSymbols(MCAssembler &Asm);
223 /// ComputeSymbolTable - Compute the symbol table data
225 /// \param StringTable [out] - The string table data.
226 /// \param StringIndexMap [out] - Map from symbol names to offsets in the
228 void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
229 std::vector<MachSymbolData> &LocalSymbolData,
230 std::vector<MachSymbolData> &ExternalSymbolData,
231 std::vector<MachSymbolData> &UndefinedSymbolData);
233 void computeSectionAddresses(const MCAssembler &Asm,
234 const MCAsmLayout &Layout);
236 void markAbsoluteVariableSymbols(MCAssembler &Asm,
237 const MCAsmLayout &Layout);
238 void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout);
240 virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
241 const MCSymbolData &DataA,
242 const MCFragment &FB,
246 void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
250 /// \brief Construct a new Mach-O writer instance.
252 /// This routine takes ownership of the target writer subclass.
254 /// \param MOTW - The target specific Mach-O writer subclass.
255 /// \param OS - The stream to write to.
256 /// \returns The constructed object writer.
257 MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
258 raw_ostream &OS, bool IsLittleEndian);
260 } // End llvm namespace