LLVM 22.0.0git
MCMachObjectWriter.h
Go to the documentation of this file.
1//===- llvm/MC/MCMachObjectWriter.h - Mach Object Writer --------*- 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
9#ifndef LLVM_MC_MCMACHOBJECTWRITER_H
10#define LLVM_MC_MCMACHOBJECTWRITER_H
11
12#include "llvm/ADT/DenseMap.h"
13#include "llvm/ADT/StringRef.h"
16#include "llvm/MC/MCExpr.h"
25#include <cstdint>
26#include <memory>
27#include <string>
28#include <vector>
29
30namespace llvm {
31
33
35 const unsigned Is64Bit : 1;
36 const uint32_t CPUType;
37protected:
39public:
40 unsigned LocalDifference_RIT = 0;
41
42protected:
43 MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_,
44 uint32_t CPUSubtype_);
45
49
50public:
52
54 static bool classof(const MCObjectTargetWriter *W) {
55 return W->getFormat() == Triple::MachO;
56 }
57
58 /// \name Lifetime Management
59 /// @{
60
61 virtual void reset() {}
62
63 /// @}
64
65 /// \name Accessors
66 /// @{
67
68 bool is64Bit() const { return Is64Bit; }
69 uint32_t getCPUType() const { return CPUType; }
70 uint32_t getCPUSubtype() const { return CPUSubtype; }
73 }
74
75 /// @}
76
77 /// \name API
78 /// @{
79
81 const MCFragment *Fragment,
83 uint64_t &FixedValue) = 0;
84
85 /// @}
86};
87
89public:
95
96 // A Major version of 0 indicates that no version information was supplied
97 // and so the corresponding load command should not be emitted.
98 using VersionInfoType = struct {
99 bool EmitBuildVersion;
100 union {
101 MCVersionMinType Type; ///< Used when EmitBuildVersion==false.
102 MachO::PlatformType Platform; ///< Used when EmitBuildVersion==true.
103 } TypeOrPlatform;
104 unsigned Major;
105 unsigned Minor;
106 unsigned Update;
107 /// An optional version of the SDK that was used to build the source.
108 VersionTuple SDKVersion;
109 };
110
111private:
112 /// Helper struct for containing some precomputed information on symbols.
113 struct MachSymbolData {
114 const MCSymbolMachO *Symbol;
115 uint64_t StringIndex;
116 uint8_t SectionIndex;
117
118 // Support lexicographic sorting.
119 LLVM_ABI bool operator<(const MachSymbolData &RHS) const;
120 };
121
122 struct IndirectSymbolData {
123 MCSymbolMachO *Symbol;
124 MCSection *Section;
125 };
126
127 /// The target specific Mach-O writer instance.
128 std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter;
129
130 /// \name Relocation Data
131 /// @{
132
133 struct RelAndSymbol {
134 const MCSymbol *Sym;
135 MachO::any_relocation_info MRE;
136 RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE)
137 : Sym(Sym), MRE(MRE) {}
138 };
139
140 DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
141 std::vector<IndirectSymbolData> IndirectSymbols;
142 DenseMap<const MCSection *, unsigned> IndirectSymBase;
143
144 std::vector<DataRegionData> DataRegions;
145
146 DenseMap<const MCSection *, uint64_t> SectionAddress;
147
148 // List of sections in layout order. Virtual sections are after non-virtual
149 // sections.
150 SmallVector<MCSection *, 0> SectionOrder;
151
152 /// @}
153 /// \name Symbol Table Data
154 /// @{
155
156 StringTableBuilder StringTable;
157 std::vector<MachSymbolData> LocalSymbolData;
158 std::vector<MachSymbolData> ExternalSymbolData;
159 std::vector<MachSymbolData> UndefinedSymbolData;
160
161 /// @}
162
163 // Used to communicate Linker Optimization Hint information.
164 MCLOHContainer LOHContainer;
165
166 VersionInfoType VersionInfo{};
167 VersionInfoType TargetVariantVersionInfo{};
168
169 // The list of linker options for LC_LINKER_OPTION.
170 std::vector<std::vector<std::string>> LinkerOptions;
171
172 MachSymbolData *findSymbolData(const MCSymbol &Sym);
173
174 void writeWithPadding(StringRef Str, uint64_t Size);
175
176public:
177 MachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
178 raw_pwrite_stream &OS, bool IsLittleEndian)
179 : TargetObjectWriter(std::move(MOTW)),
180 StringTable(TargetObjectWriter->is64Bit() ? StringTableBuilder::MachO64
182 W(OS,
183 IsLittleEndian ? llvm::endianness::little : llvm::endianness::big) {}
184
186
187 const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;
188
189 void reset() override;
190 void setAssembler(MCAssembler *Asm) override;
191
192 /// \name Utility Methods
193 /// @{
194
195 std::vector<IndirectSymbolData> &getIndirectSymbols() {
196 return IndirectSymbols;
197 }
198 std::vector<DataRegionData> &getDataRegions() { return DataRegions; }
200 return SectionOrder;
201 }
202 MCLOHContainer &getLOHContainer() { return LOHContainer; }
203
205 return SectionAddress.lookup(Sec);
206 }
207 uint64_t getSymbolAddress(const MCSymbol &S) const;
208
209 uint64_t getFragmentAddress(const MCAssembler &Asm,
210 const MCFragment *Fragment) const;
211
212 uint64_t getPaddingSize(const MCAssembler &Asm, const MCSection *SD) const;
213
214 const MCSymbol *getAtom(const MCSymbol &S) const;
215
216 bool doesSymbolRequireExternRelocation(const MCSymbol &S);
217
218 /// Mach-O deployment target version information.
219 void setVersionMin(MCVersionMinType Type, unsigned Major, unsigned Minor,
220 unsigned Update,
221 VersionTuple SDKVersion = VersionTuple()) {
222 VersionInfo.EmitBuildVersion = false;
223 VersionInfo.TypeOrPlatform.Type = Type;
224 VersionInfo.Major = Major;
225 VersionInfo.Minor = Minor;
226 VersionInfo.Update = Update;
227 VersionInfo.SDKVersion = SDKVersion;
228 }
229 void setBuildVersion(MachO::PlatformType Platform, unsigned Major,
230 unsigned Minor, unsigned Update,
231 VersionTuple SDKVersion = VersionTuple()) {
232 VersionInfo.EmitBuildVersion = true;
233 VersionInfo.TypeOrPlatform.Platform = Platform;
234 VersionInfo.Major = Major;
235 VersionInfo.Minor = Minor;
236 VersionInfo.Update = Update;
237 VersionInfo.SDKVersion = SDKVersion;
238 }
240 unsigned Major, unsigned Minor,
241 unsigned Update, VersionTuple SDKVersion) {
242 TargetVariantVersionInfo.EmitBuildVersion = true;
243 TargetVariantVersionInfo.TypeOrPlatform.Platform = Platform;
244 TargetVariantVersionInfo.Major = Major;
245 TargetVariantVersionInfo.Minor = Minor;
246 TargetVariantVersionInfo.Update = Update;
247 TargetVariantVersionInfo.SDKVersion = SDKVersion;
248 }
249
250 std::vector<std::vector<std::string>> &getLinkerOptions() {
251 return LinkerOptions;
252 }
253
254 /// @}
255
256 /// \name Target Writer Proxy Accessors
257 /// @{
258
259 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
260 bool isX86_64() const {
261 uint32_t CPUType = TargetObjectWriter->getCPUType();
262 return CPUType == MachO::CPU_TYPE_X86_64;
263 }
264
265 /// @}
266
267 void writeHeader(MachO::HeaderFileType Type, unsigned NumLoadCommands,
268 unsigned LoadCommandsSize, bool SubsectionsViaSymbols);
269
270 /// Write a segment load command.
271 ///
272 /// \param NumSections The number of sections in this segment.
273 /// \param SectionDataSize The total size of the sections.
274 void writeSegmentLoadCommand(StringRef Name, unsigned NumSections,
275 uint64_t VMAddr, uint64_t VMSize,
276 uint64_t SectionDataStartOffset,
277 uint64_t SectionDataSize, uint32_t MaxProt,
278 uint32_t InitProt);
279
280 void writeSection(const MCAssembler &Asm, const MCSectionMachO &Sec,
281 uint64_t VMAddr, uint64_t FileOffset, unsigned Flags,
282 uint64_t RelocationsStart, unsigned NumRelocations);
283
284 void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
285 uint32_t StringTableOffset,
286 uint32_t StringTableSize);
287
288 void writeDysymtabLoadCommand(
289 uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols,
290 uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols,
291 uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols,
292 uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols);
293
294 void writeNlist(MachSymbolData &MSD, const MCAssembler &Asm);
295
296 void writeLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
298
299 void writeLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
300
301 // FIXME: We really need to improve the relocation validation. Basically, we
302 // want to implement a separate computation which evaluates the relocation
303 // entry as the linker would, and verifies that the resultant fixup value is
304 // exactly what the encoder wanted. This will catch several classes of
305 // problems:
306 //
307 // - Relocation entry bugs, the two algorithms are unlikely to have the same
308 // exact bug.
309 //
310 // - Relaxation issues, where we forget to relax something.
311 //
312 // - Input errors, where something cannot be correctly encoded. 'as' allows
313 // these through in many cases.
314
315 // Add a relocation to be output in the object file. At the time this is
316 // called, the symbol indexes are not know, so if the relocation refers
317 // to a symbol it should be passed as \p RelSymbol so that it can be updated
318 // afterwards. If the relocation doesn't refer to a symbol, nullptr should be
319 // used.
320 void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec,
322 RelAndSymbol P(RelSymbol, MRE);
323 Relocations[Sec].push_back(P);
324 }
325
326 void recordRelocation(const MCFragment &F, const MCFixup &Fixup,
327 MCValue Target, uint64_t &FixedValue) override;
328
329 void bindIndirectSymbols(MCAssembler &Asm);
330
331 /// Compute the symbol table data.
332 void computeSymbolTable(MCAssembler &Asm,
333 std::vector<MachSymbolData> &LocalSymbolData,
334 std::vector<MachSymbolData> &ExternalSymbolData,
335 std::vector<MachSymbolData> &UndefinedSymbolData);
336
337 void computeSectionAddresses(const MCAssembler &Asm);
338
339 void executePostLayoutBinding() override;
340
341 bool isSymbolRefDifferenceFullyResolvedImpl(const MCSymbol &SymA,
342 const MCFragment &FB, bool InSet,
343 bool IsPCRel) const override;
344
345 void populateAddrSigSection(MCAssembler &Asm);
346
347 uint64_t writeObject() override;
348};
349} // end namespace llvm
350
351#endif // LLVM_MC_MCMACHOBJECTWRITER_H
#define LLVM_ABI
Definition Compiler.h:213
This file defines the DenseMap class.
static LVOptions Options
Definition LVOptions.cpp:25
bool operator<(const DeltaInfo &LHS, int64_t Delta)
Definition LineTable.cpp:30
#define F(x, y, z)
Definition MD5.cpp:55
#define P(N)
PowerPC TLS Dynamic Call Fixup
Defines the llvm::VersionTuple class, which represents a version in the form major[....
Value * RHS
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition MCFixup.h:61
virtual void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue)=0
void setLocalDifferenceRelocationType(unsigned Type)
static bool classof(const MCObjectTargetWriter *W)
Triple::ObjectFormatType getFormat() const override
MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_, uint32_t CPUSubtype_)
unsigned getLocalDifferenceRelocationType() const
Base class for classes that define behaviour that is specific to both the target and the object forma...
MCObjectWriter()=default
This represents a section on a Mach-O system (used by Mac OS X).
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition MCSection.h:496
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
void setTargetVariantBuildVersion(MachO::PlatformType Platform, unsigned Major, unsigned Minor, unsigned Update, VersionTuple SDKVersion)
MCLOHContainer & getLOHContainer()
uint64_t getSectionAddress(const MCSection *Sec) const
void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec, MachO::any_relocation_info &MRE)
const llvm::SmallVectorImpl< MCSection * > & getSectionOrder() const
std::vector< DataRegionData > & getDataRegions()
support::endian::Writer W
const MCSymbol & findAliasedSymbol(const MCSymbol &Sym) const
std::vector< IndirectSymbolData > & getIndirectSymbols()
void setAssembler(MCAssembler *Asm) override
void reset() override
lifetime management
void setVersionMin(MCVersionMinType Type, unsigned Major, unsigned Minor, unsigned Update, VersionTuple SDKVersion=VersionTuple())
Mach-O deployment target version information.
void setBuildVersion(MachO::PlatformType Platform, unsigned Major, unsigned Minor, unsigned Update, VersionTuple SDKVersion=VersionTuple())
MachObjectWriter(std::unique_ptr< MCMachObjectTargetWriter > MOTW, raw_pwrite_stream &OS, bool IsLittleEndian)
std::vector< std::vector< std::string > > & getLinkerOptions()
struct { bool EmitBuildVersion; union { MCVersionMinType Type; MachO::PlatformType Platform; } TypeOrPlatform; unsigned Major; unsigned Minor; unsigned Update; VersionTuple SDKVersion; } VersionInfoType
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Utility for building string tables with deduplicated suffixes.
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
Represents a version number in the form major[.minor[.subminor[.build]]].
An abstract base class for streams implementations that also support a pwrite operation.
HeaderFileType
Definition MachO.h:40
@ CPU_TYPE_X86_64
Definition MachO.h:1566
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr uintptr_t uintptr_t DataSize
Definition InstrProf.h:267
MCVersionMinType
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1869
endianness
Definition bit.h:71
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:851
Adapter to write values to a stream in a particular byte order.