1 //===- llvm/MC/MCMachObjectWriter.h - Mach Object Writer --------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_MC_MCMACHOBJECTWRITER_H
10 #define LLVM_MC_MCMACHOBJECTWRITER_H
12 #include "llvm/ADT/DenseMap.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/BinaryFormat/MachO.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCObjectWriter.h"
17 #include "llvm/MC/MCSection.h"
18 #include "llvm/MC/StringTableBuilder.h"
26 class MachObjectWriter
;
28 class MCMachObjectTargetWriter
: public MCObjectTargetWriter
{
29 const unsigned Is64Bit
: 1;
30 const uint32_t CPUType
;
31 const uint32_t CPUSubtype
;
32 unsigned LocalDifference_RIT
;
35 MCMachObjectTargetWriter(bool Is64Bit_
, uint32_t CPUType_
,
36 uint32_t CPUSubtype_
);
38 void setLocalDifferenceRelocationType(unsigned Type
) {
39 LocalDifference_RIT
= Type
;
43 virtual ~MCMachObjectTargetWriter();
45 virtual Triple::ObjectFormatType
getFormat() const { return Triple::MachO
; }
46 static bool classof(const MCObjectTargetWriter
*W
) {
47 return W
->getFormat() == Triple::MachO
;
50 /// \name Lifetime Management
53 virtual void reset() {}
60 bool is64Bit() const { return Is64Bit
; }
61 uint32_t getCPUType() const { return CPUType
; }
62 uint32_t getCPUSubtype() const { return CPUSubtype
; }
63 unsigned getLocalDifferenceRelocationType() const {
64 return LocalDifference_RIT
;
72 virtual void recordRelocation(MachObjectWriter
*Writer
, MCAssembler
&Asm
,
73 const MCAsmLayout
&Layout
,
74 const MCFragment
*Fragment
,
75 const MCFixup
&Fixup
, MCValue Target
,
76 uint64_t &FixedValue
) = 0;
81 class MachObjectWriter
: public MCObjectWriter
{
82 /// Helper struct for containing some precomputed information on symbols.
83 struct MachSymbolData
{
84 const MCSymbol
*Symbol
;
88 // Support lexicographic sorting.
89 bool operator<(const MachSymbolData
&RHS
) const;
92 /// The target specific Mach-O writer instance.
93 std::unique_ptr
<MCMachObjectTargetWriter
> TargetObjectWriter
;
95 /// \name Relocation Data
100 MachO::any_relocation_info MRE
;
101 RelAndSymbol(const MCSymbol
*Sym
, const MachO::any_relocation_info
&MRE
)
102 : Sym(Sym
), MRE(MRE
) {}
105 DenseMap
<const MCSection
*, std::vector
<RelAndSymbol
>> Relocations
;
106 DenseMap
<const MCSection
*, unsigned> IndirectSymBase
;
108 SectionAddrMap SectionAddress
;
111 /// \name Symbol Table Data
114 StringTableBuilder StringTable
{StringTableBuilder::MachO
};
115 std::vector
<MachSymbolData
> LocalSymbolData
;
116 std::vector
<MachSymbolData
> ExternalSymbolData
;
117 std::vector
<MachSymbolData
> UndefinedSymbolData
;
121 MachSymbolData
*findSymbolData(const MCSymbol
&Sym
);
123 void writeWithPadding(StringRef Str
, uint64_t Size
);
126 MachObjectWriter(std::unique_ptr
<MCMachObjectTargetWriter
> MOTW
,
127 raw_pwrite_stream
&OS
, bool IsLittleEndian
)
128 : TargetObjectWriter(std::move(MOTW
)),
129 W(OS
, IsLittleEndian
? support::little
: support::big
) {}
131 support::endian::Writer W
;
133 const MCSymbol
&findAliasedSymbol(const MCSymbol
&Sym
) const;
135 /// \name Lifetime management Methods
138 void reset() override
;
142 /// \name Utility Methods
145 bool isFixupKindPCRel(const MCAssembler
&Asm
, unsigned Kind
);
147 SectionAddrMap
&getSectionAddressMap() { return SectionAddress
; }
149 uint64_t getSectionAddress(const MCSection
*Sec
) const {
150 return SectionAddress
.lookup(Sec
);
152 uint64_t getSymbolAddress(const MCSymbol
&S
, const MCAsmLayout
&Layout
) const;
154 uint64_t getFragmentAddress(const MCFragment
*Fragment
,
155 const MCAsmLayout
&Layout
) const;
157 uint64_t getPaddingSize(const MCSection
*SD
, const MCAsmLayout
&Layout
) const;
159 bool doesSymbolRequireExternRelocation(const MCSymbol
&S
);
163 /// \name Target Writer Proxy Accessors
166 bool is64Bit() const { return TargetObjectWriter
->is64Bit(); }
167 bool isX86_64() const {
168 uint32_t CPUType
= TargetObjectWriter
->getCPUType();
169 return CPUType
== MachO::CPU_TYPE_X86_64
;
174 void writeHeader(MachO::HeaderFileType Type
, unsigned NumLoadCommands
,
175 unsigned LoadCommandsSize
, bool SubsectionsViaSymbols
);
177 /// Write a segment load command.
179 /// \param NumSections The number of sections in this segment.
180 /// \param SectionDataSize The total size of the sections.
181 void writeSegmentLoadCommand(StringRef Name
, unsigned NumSections
,
182 uint64_t VMAddr
, uint64_t VMSize
,
183 uint64_t SectionDataStartOffset
,
184 uint64_t SectionDataSize
, uint32_t MaxProt
,
187 void writeSection(const MCAsmLayout
&Layout
, const MCSection
&Sec
,
188 uint64_t VMAddr
, uint64_t FileOffset
, unsigned Flags
,
189 uint64_t RelocationsStart
, unsigned NumRelocations
);
191 void writeSymtabLoadCommand(uint32_t SymbolOffset
, uint32_t NumSymbols
,
192 uint32_t StringTableOffset
,
193 uint32_t StringTableSize
);
195 void writeDysymtabLoadCommand(
196 uint32_t FirstLocalSymbol
, uint32_t NumLocalSymbols
,
197 uint32_t FirstExternalSymbol
, uint32_t NumExternalSymbols
,
198 uint32_t FirstUndefinedSymbol
, uint32_t NumUndefinedSymbols
,
199 uint32_t IndirectSymbolOffset
, uint32_t NumIndirectSymbols
);
201 void writeNlist(MachSymbolData
&MSD
, const MCAsmLayout
&Layout
);
203 void writeLinkeditLoadCommand(uint32_t Type
, uint32_t DataOffset
,
206 void writeLinkerOptionsLoadCommand(const std::vector
<std::string
> &Options
);
208 // FIXME: We really need to improve the relocation validation. Basically, we
209 // want to implement a separate computation which evaluates the relocation
210 // entry as the linker would, and verifies that the resultant fixup value is
211 // exactly what the encoder wanted. This will catch several classes of
214 // - Relocation entry bugs, the two algorithms are unlikely to have the same
217 // - Relaxation issues, where we forget to relax something.
219 // - Input errors, where something cannot be correctly encoded. 'as' allows
220 // these through in many cases.
222 // Add a relocation to be output in the object file. At the time this is
223 // called, the symbol indexes are not know, so if the relocation refers
224 // to a symbol it should be passed as \p RelSymbol so that it can be updated
225 // afterwards. If the relocation doesn't refer to a symbol, nullptr should be
227 void addRelocation(const MCSymbol
*RelSymbol
, const MCSection
*Sec
,
228 MachO::any_relocation_info
&MRE
) {
229 RelAndSymbol
P(RelSymbol
, MRE
);
230 Relocations
[Sec
].push_back(P
);
233 void recordScatteredRelocation(const MCAssembler
&Asm
,
234 const MCAsmLayout
&Layout
,
235 const MCFragment
*Fragment
,
236 const MCFixup
&Fixup
, MCValue Target
,
237 unsigned Log2Size
, uint64_t &FixedValue
);
239 void recordTLVPRelocation(const MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
240 const MCFragment
*Fragment
, const MCFixup
&Fixup
,
241 MCValue Target
, uint64_t &FixedValue
);
243 void recordRelocation(MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
244 const MCFragment
*Fragment
, const MCFixup
&Fixup
,
245 MCValue Target
, uint64_t &FixedValue
) override
;
247 void bindIndirectSymbols(MCAssembler
&Asm
);
249 /// Compute the symbol table data.
250 void computeSymbolTable(MCAssembler
&Asm
,
251 std::vector
<MachSymbolData
> &LocalSymbolData
,
252 std::vector
<MachSymbolData
> &ExternalSymbolData
,
253 std::vector
<MachSymbolData
> &UndefinedSymbolData
);
255 void computeSectionAddresses(const MCAssembler
&Asm
,
256 const MCAsmLayout
&Layout
);
258 void executePostLayoutBinding(MCAssembler
&Asm
,
259 const MCAsmLayout
&Layout
) override
;
261 bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler
&Asm
,
264 bool InSet
) const override
;
266 bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler
&Asm
,
267 const MCSymbol
&SymA
,
268 const MCFragment
&FB
, bool InSet
,
269 bool IsPCRel
) const override
;
271 uint64_t writeObject(MCAssembler
&Asm
, const MCAsmLayout
&Layout
) override
;
274 /// Construct a new Mach-O writer instance.
276 /// This routine takes ownership of the target writer subclass.
278 /// \param MOTW - The target specific Mach-O writer subclass.
279 /// \param OS - The stream to write to.
280 /// \returns The constructed object writer.
281 std::unique_ptr
<MCObjectWriter
>
282 createMachObjectWriter(std::unique_ptr
<MCMachObjectTargetWriter
> MOTW
,
283 raw_pwrite_stream
&OS
, bool IsLittleEndian
);
285 } // end namespace llvm
287 #endif // LLVM_MC_MCMACHOBJECTWRITER_H