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
84 /// Helper struct for containing some precomputed information on symbols.
85 struct MachSymbolData {
86 const MCSymbol *Symbol;
87 uint64_t StringIndex;
88 uint8_t SectionIndex;
89
90 // Support lexicographic sorting.
91 bool operator<(const MachSymbolData &RHS) const;
92 };
93
94 /// The target specific Mach-O writer instance.
95 std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter;
96
97 /// \name Relocation Data
98 /// @{
99
100 struct RelAndSymbol {
101 const MCSymbol *Sym;
103 RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE)
104 : Sym(Sym), MRE(MRE) {}
105 };
106
109
110 SectionAddrMap SectionAddress;
111
112 /// @}
113 /// \name Symbol Table Data
114 /// @{
115
116 StringTableBuilder StringTable;
117 std::vector<MachSymbolData> LocalSymbolData;
118 std::vector<MachSymbolData> ExternalSymbolData;
119 std::vector<MachSymbolData> UndefinedSymbolData;
120
121 /// @}
122
123 MachSymbolData *findSymbolData(const MCSymbol &Sym);
124
125 void writeWithPadding(StringRef Str, uint64_t Size);
126
127public:
128 MachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
129 raw_pwrite_stream &OS, bool IsLittleEndian)
130 : TargetObjectWriter(std::move(MOTW)),
131 StringTable(TargetObjectWriter->is64Bit() ? StringTableBuilder::MachO64
132 : StringTableBuilder::MachO),
133 W(OS,
134 IsLittleEndian ? llvm::endianness::little : llvm::endianness::big) {}
135
137
138 const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;
139
140 /// \name Lifetime management Methods
141 /// @{
142
143 void reset() override;
144
145 /// @}
146
147 /// \name Utility Methods
148 /// @{
149
150 bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
151
152 SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
153
155 return SectionAddress.lookup(Sec);
156 }
157 uint64_t getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const;
158
159 uint64_t getFragmentAddress(const MCFragment *Fragment,
160 const MCAsmLayout &Layout) const;
161
162 uint64_t getPaddingSize(const MCSection *SD, const MCAsmLayout &Layout) const;
163
164 const MCSymbol *getAtom(const MCSymbol &S) const;
165
167
168 /// @}
169
170 /// \name Target Writer Proxy Accessors
171 /// @{
172
173 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
174 bool isX86_64() const {
175 uint32_t CPUType = TargetObjectWriter->getCPUType();
176 return CPUType == MachO::CPU_TYPE_X86_64;
177 }
178
179 /// @}
180
181 void writeHeader(MachO::HeaderFileType Type, unsigned NumLoadCommands,
182 unsigned LoadCommandsSize, bool SubsectionsViaSymbols);
183
184 /// Write a segment load command.
185 ///
186 /// \param NumSections The number of sections in this segment.
187 /// \param SectionDataSize The total size of the sections.
188 void writeSegmentLoadCommand(StringRef Name, unsigned NumSections,
189 uint64_t VMAddr, uint64_t VMSize,
190 uint64_t SectionDataStartOffset,
191 uint64_t SectionDataSize, uint32_t MaxProt,
192 uint32_t InitProt);
193
194 void writeSection(const MCAsmLayout &Layout, const MCSection &Sec,
195 uint64_t VMAddr, uint64_t FileOffset, unsigned Flags,
196 uint64_t RelocationsStart, unsigned NumRelocations);
197
198 void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
199 uint32_t StringTableOffset,
200 uint32_t StringTableSize);
201
203 uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols,
204 uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols,
205 uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols,
206 uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols);
207
208 void writeNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
209
211 uint32_t DataSize);
212
213 void writeLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
214
215 // FIXME: We really need to improve the relocation validation. Basically, we
216 // want to implement a separate computation which evaluates the relocation
217 // entry as the linker would, and verifies that the resultant fixup value is
218 // exactly what the encoder wanted. This will catch several classes of
219 // problems:
220 //
221 // - Relocation entry bugs, the two algorithms are unlikely to have the same
222 // exact bug.
223 //
224 // - Relaxation issues, where we forget to relax something.
225 //
226 // - Input errors, where something cannot be correctly encoded. 'as' allows
227 // these through in many cases.
228
229 // Add a relocation to be output in the object file. At the time this is
230 // called, the symbol indexes are not know, so if the relocation refers
231 // to a symbol it should be passed as \p RelSymbol so that it can be updated
232 // afterwards. If the relocation doesn't refer to a symbol, nullptr should be
233 // used.
234 void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec,
236 RelAndSymbol P(RelSymbol, MRE);
237 Relocations[Sec].push_back(P);
238 }
239
240 void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment,
241 const MCFixup &Fixup, MCValue Target,
242 uint64_t &FixedValue) override;
243
245
246 /// Compute the symbol table data.
248 std::vector<MachSymbolData> &LocalSymbolData,
249 std::vector<MachSymbolData> &ExternalSymbolData,
250 std::vector<MachSymbolData> &UndefinedSymbolData);
251
252 void computeSectionAddresses(const MCAssembler &Asm,
253 const MCAsmLayout &Layout);
254
256 const MCAsmLayout &Layout) override;
257
259 const MCSymbol &SymA,
260 const MCFragment &FB, bool InSet,
261 bool IsPCRel) const override;
262
264
265 uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
266};
267
268/// Construct a new Mach-O writer instance.
269///
270/// This routine takes ownership of the target writer subclass.
271///
272/// \param MOTW - The target specific Mach-O writer subclass.
273/// \param OS - The stream to write to.
274/// \returns The constructed object writer.
275std::unique_ptr<MCObjectWriter>
276createMachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
277 raw_pwrite_stream &OS, bool IsLittleEndian);
278
279} // end namespace llvm
280
281#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
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition: DenseMap.h:202
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:28
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
bool doesSymbolRequireExternRelocation(const MCSymbol &S)
uint64_t getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const
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 getSectionAddress(const MCSection *Sec) const
void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec, MachO::any_relocation_info &MRE)
uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override
Write the object file and returns the number of bytes written.
void populateAddrSigSection(MCAssembler &Asm)
bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind)
support::endian::Writer W
void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override
Perform any late binding of symbols (for example, to assign symbol indices for use when generating re...
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.
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)
void writeNlist(MachSymbolData &MSD, const MCAsmLayout &Layout)
const MCSymbol & findAliasedSymbol(const MCSymbol &Sym) const
void writeSection(const MCAsmLayout &Layout, const MCSection &Sec, uint64_t VMAddr, uint64_t FileOffset, unsigned Flags, uint64_t RelocationsStart, unsigned NumRelocations)
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)
uint64_t getFragmentAddress(const MCFragment *Fragment, const MCAsmLayout &Layout) const
void reset() override
lifetime management
void computeSectionAddresses(const MCAssembler &Asm, const MCAsmLayout &Layout)
void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, uint32_t StringTableOffset, uint32_t StringTableSize)
void bindIndirectSymbols(MCAssembler &Asm)
uint64_t getPaddingSize(const MCSection *SD, const MCAsmLayout &Layout) const
MachObjectWriter(std::unique_ptr< MCMachObjectTargetWriter > MOTW, raw_pwrite_stream &OS, bool IsLittleEndian)
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:445
HeaderFileType
Definition: MachO.h:40
@ 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.
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