LLVM 24.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 std::optional<std::string> TargetTriple;
170
171 // The list of linker options for LC_LINKER_OPTION.
172 std::vector<std::vector<std::string>> LinkerOptions;
173
174 MachSymbolData *findSymbolData(const MCSymbol &Sym);
175
176 void writeWithPadding(StringRef Str, uint64_t Size);
177
178public:
179 MachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
180 raw_pwrite_stream &OS, bool IsLittleEndian)
181 : TargetObjectWriter(std::move(MOTW)),
182 StringTable(TargetObjectWriter->is64Bit() ? StringTableBuilder::MachO64
184 W(OS,
185 IsLittleEndian ? llvm::endianness::little : llvm::endianness::big) {}
186
188
189 const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;
190
191 void reset() override;
192 void setAssembler(MCAssembler *Asm) override;
193
194 /// \name Utility Methods
195 /// @{
196
197 std::vector<IndirectSymbolData> &getIndirectSymbols() {
198 return IndirectSymbols;
199 }
200 std::vector<DataRegionData> &getDataRegions() { return DataRegions; }
202 return SectionOrder;
203 }
204 MCLOHContainer &getLOHContainer() { return LOHContainer; }
205
207 return SectionAddress.lookup(Sec);
208 }
209 uint64_t getSymbolAddress(const MCSymbol &S) const;
210
211 uint64_t getFragmentAddress(const MCAssembler &Asm,
212 const MCFragment *Fragment) const;
213
214 uint64_t getPaddingSize(const MCAssembler &Asm, const MCSection *SD) const;
215
216 const MCSymbol *getAtom(const MCSymbol &S) const;
217
218 bool doesSymbolRequireExternRelocation(const MCSymbol &S);
219
220 /// Mach-O deployment target version information.
221 void setVersionMin(MCVersionMinType Type, unsigned Major, unsigned Minor,
222 unsigned Update,
223 VersionTuple SDKVersion = VersionTuple()) {
224 VersionInfo.EmitBuildVersion = false;
225 VersionInfo.TypeOrPlatform.Type = Type;
226 VersionInfo.Major = Major;
227 VersionInfo.Minor = Minor;
228 VersionInfo.Update = Update;
229 VersionInfo.SDKVersion = SDKVersion;
230 }
231 void setBuildVersion(MachO::PlatformType Platform, unsigned Major,
232 unsigned Minor, unsigned Update,
233 VersionTuple SDKVersion = VersionTuple()) {
234 VersionInfo.EmitBuildVersion = true;
235 VersionInfo.TypeOrPlatform.Platform = Platform;
236 VersionInfo.Major = Major;
237 VersionInfo.Minor = Minor;
238 VersionInfo.Update = Update;
239 VersionInfo.SDKVersion = SDKVersion;
240 }
242 unsigned Major, unsigned Minor,
243 unsigned Update, VersionTuple SDKVersion) {
244 TargetVariantVersionInfo.EmitBuildVersion = true;
245 TargetVariantVersionInfo.TypeOrPlatform.Platform = Platform;
246 TargetVariantVersionInfo.Major = Major;
247 TargetVariantVersionInfo.Minor = Minor;
248 TargetVariantVersionInfo.Update = Update;
249 TargetVariantVersionInfo.SDKVersion = SDKVersion;
250 }
251
252 void setTargetTriple(StringRef Triple) { TargetTriple = Triple; }
253
254 std::vector<std::vector<std::string>> &getLinkerOptions() {
255 return LinkerOptions;
256 }
257
258 /// @}
259
260 /// \name Target Writer Proxy Accessors
261 /// @{
262
263 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
264 bool isX86_64() const {
265 uint32_t CPUType = TargetObjectWriter->getCPUType();
266 return CPUType == MachO::CPU_TYPE_X86_64;
267 }
268
269 /// @}
270
271 void writeHeader(MachO::HeaderFileType Type, unsigned NumLoadCommands,
272 unsigned LoadCommandsSize, bool SubsectionsViaSymbols);
273
274 /// Write a segment load command.
275 ///
276 /// \param NumSections The number of sections in this segment.
277 /// \param SectionDataSize The total size of the sections.
278 void writeSegmentLoadCommand(StringRef Name, unsigned NumSections,
279 uint64_t VMAddr, uint64_t VMSize,
280 uint64_t SectionDataStartOffset,
281 uint64_t SectionDataSize, uint32_t MaxProt,
282 uint32_t InitProt);
283
284 void writeSection(const MCAssembler &Asm, const MCSectionMachO &Sec,
285 uint64_t VMAddr, uint64_t FileOffset, unsigned Flags,
286 uint64_t RelocationsStart, unsigned NumRelocations);
287
288 void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
289 uint32_t StringTableOffset,
290 uint32_t StringTableSize);
291
292 void writeDysymtabLoadCommand(
293 uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols,
294 uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols,
295 uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols,
296 uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols);
297
298 void writeNlist(MachSymbolData &MSD, const MCAssembler &Asm);
299
300 void writeLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
301 uint32_t DataSize);
302
303 void writeLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
304
305 // FIXME: We really need to improve the relocation validation. Basically, we
306 // want to implement a separate computation which evaluates the relocation
307 // entry as the linker would, and verifies that the resultant fixup value is
308 // exactly what the encoder wanted. This will catch several classes of
309 // problems:
310 //
311 // - Relocation entry bugs, the two algorithms are unlikely to have the same
312 // exact bug.
313 //
314 // - Relaxation issues, where we forget to relax something.
315 //
316 // - Input errors, where something cannot be correctly encoded. 'as' allows
317 // these through in many cases.
318
319 // Add a relocation to be output in the object file. At the time this is
320 // called, the symbol indexes are not know, so if the relocation refers
321 // to a symbol it should be passed as \p RelSymbol so that it can be updated
322 // afterwards. If the relocation doesn't refer to a symbol, nullptr should be
323 // used.
324 void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec,
326 RelAndSymbol P(RelSymbol, MRE);
327 Relocations[Sec].push_back(P);
328 }
329
330 void recordRelocation(const MCFragment &F, const MCFixup &Fixup,
331 MCValue Target, uint64_t &FixedValue) override;
332
333 void bindIndirectSymbols(MCAssembler &Asm);
334
335 /// Compute the symbol table data.
336 void computeSymbolTable(MCAssembler &Asm,
337 std::vector<MachSymbolData> &LocalSymbolData,
338 std::vector<MachSymbolData> &ExternalSymbolData,
339 std::vector<MachSymbolData> &UndefinedSymbolData);
340
341 void computeSectionAddresses(const MCAssembler &Asm);
342
343 void executePostLayoutBinding() override;
344
345 bool isSymbolRefDifferenceFullyResolvedImpl(const MCSymbol &SymA,
346 const MCFragment &FB, bool InSet,
347 bool IsPCRel) const override;
348
349 void populateAddrSigSection(MCAssembler &Asm);
350
351 uint64_t writeObject() override;
352};
353} // end namespace llvm
354
355#endif // LLVM_MC_MCMACHOBJECTWRITER_H
#define LLVM_ABI
Definition Compiler.h:215
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:54
#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:573
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 setTargetTriple(StringRef Triple)
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...
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Utility for building string tables with deduplicated suffixes.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
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:1635
This is an optimization pass for GlobalISel generic memory operations.
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:1917
endianness
Definition bit.h:71
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
Adapter to write values to a stream in a particular byte order.