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