LLVM 19.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"
15#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCSection.h"
20#include <cstdint>
21#include <memory>
22#include <string>
23#include <vector>
24
25namespace llvm {
26
27class MachObjectWriter;
28
30 const unsigned Is64Bit : 1;
31 const uint32_t CPUType;
32protected:
34public:
35 unsigned LocalDifference_RIT = 0;
36
37protected:
38 MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_,
39 uint32_t CPUSubtype_);
40
43 }
44
45public:
47
49 static bool classof(const MCObjectTargetWriter *W) {
50 return W->getFormat() == Triple::MachO;
51 }
52
53 /// \name Lifetime Management
54 /// @{
55
56 virtual void reset() {}
57
58 /// @}
59
60 /// \name Accessors
61 /// @{
62
63 bool is64Bit() const { return Is64Bit; }
64 uint32_t getCPUType() const { return CPUType; }
65 uint32_t getCPUSubtype() const { return CPUSubtype; }
68 }
69
70 /// @}
71
72 /// \name API
73 /// @{
74
75 virtual void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
76 const MCFragment *Fragment,
78 uint64_t &FixedValue) = 0;
79
80 /// @}
81};
82
84public:
89 };
90
91private:
92 /// Helper struct for containing some precomputed information on symbols.
93 struct MachSymbolData {
94 const MCSymbol *Symbol;
95 uint64_t StringIndex;
96 uint8_t SectionIndex;
97
98 // Support lexicographic sorting.
99 bool operator<(const MachSymbolData &RHS) const;
100 };
101
102 struct IndirectSymbolData {
103 MCSymbol *Symbol;
104 MCSection *Section;
105 };
106
107 /// The target specific Mach-O writer instance.
108 std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter;
109
110 /// \name Relocation Data
111 /// @{
112
113 struct RelAndSymbol {
114 const MCSymbol *Sym;
115 MachO::any_relocation_info MRE;
116 RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE)
117 : Sym(Sym), MRE(MRE) {}
118 };
119
120 DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
121 std::vector<IndirectSymbolData> IndirectSymbols;
122 DenseMap<const MCSection *, unsigned> IndirectSymBase;
123
124 std::vector<DataRegionData> DataRegions;
125
126 SectionAddrMap SectionAddress;
127
128 // List of sections in layout order. Virtual sections are after non-virtual
129 // sections.
130 SmallVector<MCSection *, 0> SectionOrder;
131
132 /// @}
133 /// \name Symbol Table Data
134 /// @{
135
136 StringTableBuilder StringTable;
137 std::vector<MachSymbolData> LocalSymbolData;
138 std::vector<MachSymbolData> ExternalSymbolData;
139 std::vector<MachSymbolData> UndefinedSymbolData;
140
141 /// @}
142
143 MachSymbolData *findSymbolData(const MCSymbol &Sym);
144
145 void writeWithPadding(StringRef Str, uint64_t Size);
146
147public:
148 MachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
149 raw_pwrite_stream &OS, bool IsLittleEndian)
150 : TargetObjectWriter(std::move(MOTW)),
151 StringTable(TargetObjectWriter->is64Bit() ? StringTableBuilder::MachO64
152 : StringTableBuilder::MachO),
153 W(OS,
154 IsLittleEndian ? llvm::endianness::little : llvm::endianness::big) {}
155
157
158 const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;
159
160 /// \name Lifetime management Methods
161 /// @{
162
163 void reset() override;
164
165 /// @}
166
167 /// \name Utility Methods
168 /// @{
169
170 bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
171
172 std::vector<IndirectSymbolData> &getIndirectSymbols() {
173 return IndirectSymbols;
174 }
175 std::vector<DataRegionData> &getDataRegions() { return DataRegions; }
177 return SectionOrder;
178 }
179 SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
180
182 return SectionAddress.lookup(Sec);
183 }
184 uint64_t getSymbolAddress(const MCSymbol &S, const MCAssembler &Asm) const;
185
187 const MCFragment *Fragment) const;
188
189 uint64_t getPaddingSize(const MCAssembler &Asm, const MCSection *SD) const;
190
191 const MCSymbol *getAtom(const MCSymbol &S) const;
192
194
195 /// @}
196
197 /// \name Target Writer Proxy Accessors
198 /// @{
199
200 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
201 bool isX86_64() const {
202 uint32_t CPUType = TargetObjectWriter->getCPUType();
203 return CPUType == MachO::CPU_TYPE_X86_64;
204 }
205
206 /// @}
207
208 void writeHeader(MachO::HeaderFileType Type, unsigned NumLoadCommands,
209 unsigned LoadCommandsSize, bool SubsectionsViaSymbols);
210
211 /// Write a segment load command.
212 ///
213 /// \param NumSections The number of sections in this segment.
214 /// \param SectionDataSize The total size of the sections.
215 void writeSegmentLoadCommand(StringRef Name, unsigned NumSections,
216 uint64_t VMAddr, uint64_t VMSize,
217 uint64_t SectionDataStartOffset,
218 uint64_t SectionDataSize, uint32_t MaxProt,
219 uint32_t InitProt);
220
221 void writeSection(const MCAssembler &Asm, const MCSection &Sec,
222 uint64_t VMAddr, uint64_t FileOffset, unsigned Flags,
223 uint64_t RelocationsStart, unsigned NumRelocations);
224
225 void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
226 uint32_t StringTableOffset,
227 uint32_t StringTableSize);
228
230 uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols,
231 uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols,
232 uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols,
233 uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols);
234
235 void writeNlist(MachSymbolData &MSD, const MCAssembler &Asm);
236
238 uint32_t DataSize);
239
240 void writeLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
241
242 // FIXME: We really need to improve the relocation validation. Basically, we
243 // want to implement a separate computation which evaluates the relocation
244 // entry as the linker would, and verifies that the resultant fixup value is
245 // exactly what the encoder wanted. This will catch several classes of
246 // problems:
247 //
248 // - Relocation entry bugs, the two algorithms are unlikely to have the same
249 // exact bug.
250 //
251 // - Relaxation issues, where we forget to relax something.
252 //
253 // - Input errors, where something cannot be correctly encoded. 'as' allows
254 // these through in many cases.
255
256 // Add a relocation to be output in the object file. At the time this is
257 // called, the symbol indexes are not know, so if the relocation refers
258 // to a symbol it should be passed as \p RelSymbol so that it can be updated
259 // afterwards. If the relocation doesn't refer to a symbol, nullptr should be
260 // used.
261 void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec,
263 RelAndSymbol P(RelSymbol, MRE);
264 Relocations[Sec].push_back(P);
265 }
266
267 void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment,
268 const MCFixup &Fixup, MCValue Target,
269 uint64_t &FixedValue) override;
270
272
273 /// Compute the symbol table data.
275 std::vector<MachSymbolData> &LocalSymbolData,
276 std::vector<MachSymbolData> &ExternalSymbolData,
277 std::vector<MachSymbolData> &UndefinedSymbolData);
278
279 void computeSectionAddresses(const MCAssembler &Asm);
280
281 void executePostLayoutBinding(MCAssembler &Asm) override;
282
284 const MCSymbol &SymA,
285 const MCFragment &FB, bool InSet,
286 bool IsPCRel) const override;
287
289
290 uint64_t writeObject(MCAssembler &Asm) override;
291};
292
293/// Construct a new Mach-O writer instance.
294///
295/// This routine takes ownership of the target writer subclass.
296///
297/// \param MOTW - The target specific Mach-O writer subclass.
298/// \param OS - The stream to write to.
299/// \returns The constructed object writer.
300std::unique_ptr<MCObjectWriter>
301createMachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
302 raw_pwrite_stream &OS, bool IsLittleEndian);
303
304} // end namespace llvm
305
306#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
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 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)
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
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)
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
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)
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)
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
An abstract base class for streams implementations that also support a pwrite operation.
Definition: raw_ostream.h:434
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
std::unique_ptr< MCObjectWriter > createMachObjectWriter(std::unique_ptr< MCMachObjectTargetWriter > MOTW, raw_pwrite_stream &OS, bool IsLittleEndian)
Construct a new Mach-O writer instance.
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:1849
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