File indexing completed on 2026-05-10 08:44:14
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_MC_MCMACHOBJECTWRITER_H
0010 #define LLVM_MC_MCMACHOBJECTWRITER_H
0011
0012 #include "llvm/ADT/DenseMap.h"
0013 #include "llvm/ADT/StringRef.h"
0014 #include "llvm/BinaryFormat/MachO.h"
0015 #include "llvm/MC/MCDirectives.h"
0016 #include "llvm/MC/MCExpr.h"
0017 #include "llvm/MC/MCLinkerOptimizationHint.h"
0018 #include "llvm/MC/MCObjectWriter.h"
0019 #include "llvm/MC/MCSection.h"
0020 #include "llvm/MC/StringTableBuilder.h"
0021 #include "llvm/Support/EndianStream.h"
0022 #include "llvm/Support/VersionTuple.h"
0023 #include <cstdint>
0024 #include <memory>
0025 #include <string>
0026 #include <vector>
0027
0028 namespace llvm {
0029
0030 class MachObjectWriter;
0031
0032 class MCMachObjectTargetWriter : public MCObjectTargetWriter {
0033 const unsigned Is64Bit : 1;
0034 const uint32_t CPUType;
0035 protected:
0036 uint32_t CPUSubtype;
0037 public:
0038 unsigned LocalDifference_RIT = 0;
0039
0040 protected:
0041 MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_,
0042 uint32_t CPUSubtype_);
0043
0044 void setLocalDifferenceRelocationType(unsigned Type) {
0045 LocalDifference_RIT = Type;
0046 }
0047
0048 public:
0049 virtual ~MCMachObjectTargetWriter();
0050
0051 Triple::ObjectFormatType getFormat() const override { return Triple::MachO; }
0052 static bool classof(const MCObjectTargetWriter *W) {
0053 return W->getFormat() == Triple::MachO;
0054 }
0055
0056
0057
0058
0059 virtual void reset() {}
0060
0061
0062
0063
0064
0065
0066 bool is64Bit() const { return Is64Bit; }
0067 uint32_t getCPUType() const { return CPUType; }
0068 uint32_t getCPUSubtype() const { return CPUSubtype; }
0069 unsigned getLocalDifferenceRelocationType() const {
0070 return LocalDifference_RIT;
0071 }
0072
0073
0074
0075
0076
0077
0078 virtual void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
0079 const MCFragment *Fragment,
0080 const MCFixup &Fixup, MCValue Target,
0081 uint64_t &FixedValue) = 0;
0082
0083
0084 };
0085
0086 class MachObjectWriter final : public MCObjectWriter {
0087 public:
0088 struct DataRegionData {
0089 MachO::DataRegionType Kind;
0090 MCSymbol *Start;
0091 MCSymbol *End;
0092 };
0093
0094
0095
0096 using VersionInfoType = struct {
0097 bool EmitBuildVersion;
0098 union {
0099 MCVersionMinType Type;
0100 MachO::PlatformType Platform;
0101 } TypeOrPlatform;
0102 unsigned Major;
0103 unsigned Minor;
0104 unsigned Update;
0105
0106 VersionTuple SDKVersion;
0107 };
0108
0109 private:
0110
0111 struct MachSymbolData {
0112 const MCSymbol *Symbol;
0113 uint64_t StringIndex;
0114 uint8_t SectionIndex;
0115
0116
0117 bool operator<(const MachSymbolData &RHS) const;
0118 };
0119
0120 struct IndirectSymbolData {
0121 MCSymbol *Symbol;
0122 MCSection *Section;
0123 };
0124
0125
0126 std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter;
0127
0128
0129
0130
0131 struct RelAndSymbol {
0132 const MCSymbol *Sym;
0133 MachO::any_relocation_info MRE;
0134 RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE)
0135 : Sym(Sym), MRE(MRE) {}
0136 };
0137
0138 DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
0139 std::vector<IndirectSymbolData> IndirectSymbols;
0140 DenseMap<const MCSection *, unsigned> IndirectSymBase;
0141
0142 std::vector<DataRegionData> DataRegions;
0143
0144 SectionAddrMap SectionAddress;
0145
0146
0147
0148 SmallVector<MCSection *, 0> SectionOrder;
0149
0150
0151
0152
0153
0154 StringTableBuilder StringTable;
0155 std::vector<MachSymbolData> LocalSymbolData;
0156 std::vector<MachSymbolData> ExternalSymbolData;
0157 std::vector<MachSymbolData> UndefinedSymbolData;
0158
0159
0160
0161
0162 MCLOHContainer LOHContainer;
0163
0164 VersionInfoType VersionInfo{};
0165 VersionInfoType TargetVariantVersionInfo{};
0166
0167
0168 std::vector<std::vector<std::string>> LinkerOptions;
0169
0170 MachSymbolData *findSymbolData(const MCSymbol &Sym);
0171
0172 void writeWithPadding(StringRef Str, uint64_t Size);
0173
0174 public:
0175 MachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
0176 raw_pwrite_stream &OS, bool IsLittleEndian)
0177 : TargetObjectWriter(std::move(MOTW)),
0178 StringTable(TargetObjectWriter->is64Bit() ? StringTableBuilder::MachO64
0179 : StringTableBuilder::MachO),
0180 W(OS,
0181 IsLittleEndian ? llvm::endianness::little : llvm::endianness::big) {}
0182
0183 support::endian::Writer W;
0184
0185 const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;
0186
0187
0188
0189
0190 void reset() override;
0191
0192
0193
0194
0195
0196
0197 bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
0198
0199 std::vector<IndirectSymbolData> &getIndirectSymbols() {
0200 return IndirectSymbols;
0201 }
0202 std::vector<DataRegionData> &getDataRegions() { return DataRegions; }
0203 const llvm::SmallVectorImpl<MCSection *> &getSectionOrder() const {
0204 return SectionOrder;
0205 }
0206 SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
0207 MCLOHContainer &getLOHContainer() { return LOHContainer; }
0208
0209 uint64_t getSectionAddress(const MCSection *Sec) const {
0210 return SectionAddress.lookup(Sec);
0211 }
0212 uint64_t getSymbolAddress(const MCSymbol &S, const MCAssembler &Asm) const;
0213
0214 uint64_t getFragmentAddress(const MCAssembler &Asm,
0215 const MCFragment *Fragment) const;
0216
0217 uint64_t getPaddingSize(const MCAssembler &Asm, const MCSection *SD) const;
0218
0219 const MCSymbol *getAtom(const MCSymbol &S) const;
0220
0221 bool doesSymbolRequireExternRelocation(const MCSymbol &S);
0222
0223
0224 void setVersionMin(MCVersionMinType Type, unsigned Major, unsigned Minor,
0225 unsigned Update,
0226 VersionTuple SDKVersion = VersionTuple()) {
0227 VersionInfo.EmitBuildVersion = false;
0228 VersionInfo.TypeOrPlatform.Type = Type;
0229 VersionInfo.Major = Major;
0230 VersionInfo.Minor = Minor;
0231 VersionInfo.Update = Update;
0232 VersionInfo.SDKVersion = SDKVersion;
0233 }
0234 void setBuildVersion(MachO::PlatformType Platform, unsigned Major,
0235 unsigned Minor, unsigned Update,
0236 VersionTuple SDKVersion = VersionTuple()) {
0237 VersionInfo.EmitBuildVersion = true;
0238 VersionInfo.TypeOrPlatform.Platform = Platform;
0239 VersionInfo.Major = Major;
0240 VersionInfo.Minor = Minor;
0241 VersionInfo.Update = Update;
0242 VersionInfo.SDKVersion = SDKVersion;
0243 }
0244 void setTargetVariantBuildVersion(MachO::PlatformType Platform,
0245 unsigned Major, unsigned Minor,
0246 unsigned Update, VersionTuple SDKVersion) {
0247 TargetVariantVersionInfo.EmitBuildVersion = true;
0248 TargetVariantVersionInfo.TypeOrPlatform.Platform = Platform;
0249 TargetVariantVersionInfo.Major = Major;
0250 TargetVariantVersionInfo.Minor = Minor;
0251 TargetVariantVersionInfo.Update = Update;
0252 TargetVariantVersionInfo.SDKVersion = SDKVersion;
0253 }
0254
0255 std::vector<std::vector<std::string>> &getLinkerOptions() {
0256 return LinkerOptions;
0257 }
0258
0259
0260
0261
0262
0263
0264 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
0265 bool isX86_64() const {
0266 uint32_t CPUType = TargetObjectWriter->getCPUType();
0267 return CPUType == MachO::CPU_TYPE_X86_64;
0268 }
0269
0270
0271
0272 void writeHeader(MachO::HeaderFileType Type, unsigned NumLoadCommands,
0273 unsigned LoadCommandsSize, bool SubsectionsViaSymbols);
0274
0275
0276
0277
0278
0279 void writeSegmentLoadCommand(StringRef Name, unsigned NumSections,
0280 uint64_t VMAddr, uint64_t VMSize,
0281 uint64_t SectionDataStartOffset,
0282 uint64_t SectionDataSize, uint32_t MaxProt,
0283 uint32_t InitProt);
0284
0285 void writeSection(const MCAssembler &Asm, const MCSection &Sec,
0286 uint64_t VMAddr, uint64_t FileOffset, unsigned Flags,
0287 uint64_t RelocationsStart, unsigned NumRelocations);
0288
0289 void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
0290 uint32_t StringTableOffset,
0291 uint32_t StringTableSize);
0292
0293 void writeDysymtabLoadCommand(
0294 uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols,
0295 uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols,
0296 uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols,
0297 uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols);
0298
0299 void writeNlist(MachSymbolData &MSD, const MCAssembler &Asm);
0300
0301 void writeLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
0302 uint32_t DataSize);
0303
0304 void writeLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325 void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec,
0326 MachO::any_relocation_info &MRE) {
0327 RelAndSymbol P(RelSymbol, MRE);
0328 Relocations[Sec].push_back(P);
0329 }
0330
0331 void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment,
0332 const MCFixup &Fixup, MCValue Target,
0333 uint64_t &FixedValue) override;
0334
0335 void bindIndirectSymbols(MCAssembler &Asm);
0336
0337
0338 void computeSymbolTable(MCAssembler &Asm,
0339 std::vector<MachSymbolData> &LocalSymbolData,
0340 std::vector<MachSymbolData> &ExternalSymbolData,
0341 std::vector<MachSymbolData> &UndefinedSymbolData);
0342
0343 void computeSectionAddresses(const MCAssembler &Asm);
0344
0345 void executePostLayoutBinding(MCAssembler &Asm) override;
0346
0347 bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
0348 const MCSymbol &SymA,
0349 const MCFragment &FB, bool InSet,
0350 bool IsPCRel) const override;
0351
0352 void populateAddrSigSection(MCAssembler &Asm);
0353
0354 uint64_t writeObject(MCAssembler &Asm) override;
0355 };
0356 }
0357
0358 #endif