15ffd83dbSDimitry Andric //===- Target.h -------------------------------------------------*- C++ -*-===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #ifndef LLD_MACHO_TARGET_H 105ffd83dbSDimitry Andric #define LLD_MACHO_TARGET_H 115ffd83dbSDimitry Andric 12fe6060f1SDimitry Andric #include "MachOStructs.h" 13fe6060f1SDimitry Andric #include "Relocations.h" 14fe6060f1SDimitry Andric 15fe6060f1SDimitry Andric #include "llvm/ADT/BitmaskEnum.h" 165ffd83dbSDimitry Andric #include "llvm/BinaryFormat/MachO.h" 1781ad6265SDimitry Andric #include "llvm/Support/MathExtras.h" 185ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h" 195ffd83dbSDimitry Andric 205ffd83dbSDimitry Andric #include <cstddef> 215ffd83dbSDimitry Andric #include <cstdint> 225ffd83dbSDimitry Andric 23bdd1243dSDimitry Andric #include "mach-o/compact_unwind_encoding.h" 24bdd1243dSDimitry Andric 25bdd1243dSDimitry Andric namespace lld::macho { 26fe6060f1SDimitry Andric LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 275ffd83dbSDimitry Andric 285ffd83dbSDimitry Andric class Symbol; 29fe6060f1SDimitry Andric class Defined; 305ffd83dbSDimitry Andric class DylibSymbol; 315ffd83dbSDimitry Andric class InputSection; 32bdd1243dSDimitry Andric class ObjFile; 33bdd1243dSDimitry Andric 34bdd1243dSDimitry Andric static_assert(static_cast<uint32_t>(UNWIND_X86_64_MODE_MASK) == 35bdd1243dSDimitry Andric static_cast<uint32_t>(UNWIND_X86_MODE_MASK) && 36bdd1243dSDimitry Andric static_cast<uint32_t>(UNWIND_ARM64_MODE_MASK) == 37bdd1243dSDimitry Andric static_cast<uint32_t>(UNWIND_X86_64_MODE_MASK)); 38bdd1243dSDimitry Andric 39bdd1243dSDimitry Andric // Since the mode masks have the same value on all targets, define 40bdd1243dSDimitry Andric // a common one for convenience. 41bdd1243dSDimitry Andric constexpr uint32_t UNWIND_MODE_MASK = UNWIND_X86_64_MODE_MASK; 425ffd83dbSDimitry Andric 435ffd83dbSDimitry Andric class TargetInfo { 445ffd83dbSDimitry Andric public: TargetInfo(LP)45fe6060f1SDimitry Andric template <class LP> TargetInfo(LP) { 46fe6060f1SDimitry Andric // Having these values available in TargetInfo allows us to access them 47fe6060f1SDimitry Andric // without having to resort to templates. 48fe6060f1SDimitry Andric magic = LP::magic; 49fe6060f1SDimitry Andric pageZeroSize = LP::pageZeroSize; 50fe6060f1SDimitry Andric headerSize = sizeof(typename LP::mach_header); 51fe6060f1SDimitry Andric wordSize = LP::wordSize; 5281ad6265SDimitry Andric p2WordSize = llvm::CTLog2<LP::wordSize>(); 53fe6060f1SDimitry Andric } 54fe6060f1SDimitry Andric 555ffd83dbSDimitry Andric virtual ~TargetInfo() = default; 565ffd83dbSDimitry Andric 575ffd83dbSDimitry Andric // Validate the relocation structure and get its addend. 58fe6060f1SDimitry Andric virtual int64_t 59fe6060f1SDimitry Andric getEmbeddedAddend(llvm::MemoryBufferRef, uint64_t offset, 60fe6060f1SDimitry Andric const llvm::MachO::relocation_info) const = 0; 61fe6060f1SDimitry Andric virtual void relocateOne(uint8_t *loc, const Reloc &, uint64_t va, 62fe6060f1SDimitry Andric uint64_t relocVA) const = 0; 635ffd83dbSDimitry Andric 645ffd83dbSDimitry Andric // Write code for lazy binding. See the comments on StubsSection for more 655ffd83dbSDimitry Andric // details. 66bdd1243dSDimitry Andric virtual void writeStub(uint8_t *buf, const Symbol &, 67bdd1243dSDimitry Andric uint64_t pointerVA) const = 0; 685ffd83dbSDimitry Andric virtual void writeStubHelperHeader(uint8_t *buf) const = 0; 6981ad6265SDimitry Andric virtual void writeStubHelperEntry(uint8_t *buf, const Symbol &, 705ffd83dbSDimitry Andric uint64_t entryAddr) const = 0; 715ffd83dbSDimitry Andric 72bdd1243dSDimitry Andric virtual void writeObjCMsgSendStub(uint8_t *buf, Symbol *sym, 73*7a6dacacSDimitry Andric uint64_t stubsAddr, uint64_t &stubOffset, 74bdd1243dSDimitry Andric uint64_t selrefsVA, uint64_t selectorIndex, 75*7a6dacacSDimitry Andric Symbol *objcMsgSend) const = 0; 76bdd1243dSDimitry Andric 775ffd83dbSDimitry Andric // Symbols may be referenced via either the GOT or the stubs section, 785ffd83dbSDimitry Andric // depending on the relocation type. prepareSymbolRelocation() will set up the 79e8d8bef9SDimitry Andric // GOT/stubs entries, and resolveSymbolVA() will return the addresses of those 80e8d8bef9SDimitry Andric // entries. resolveSymbolVA() may also relax the target instructions to save 81e8d8bef9SDimitry Andric // on a level of address indirection. 82fe6060f1SDimitry Andric virtual void relaxGotLoad(uint8_t *loc, uint8_t type) const = 0; 835ffd83dbSDimitry Andric 84fe6060f1SDimitry Andric virtual uint64_t getPageSize() const = 0; 85fe6060f1SDimitry Andric populateThunk(InputSection * thunk,Symbol * funcSym)86fe6060f1SDimitry Andric virtual void populateThunk(InputSection *thunk, Symbol *funcSym) { 87fe6060f1SDimitry Andric llvm_unreachable("target does not use thunks"); 88fe6060f1SDimitry Andric } 89fe6060f1SDimitry Andric getRelocAttrs(uint8_t type)90fcaf7f86SDimitry Andric const RelocAttrs &getRelocAttrs(uint8_t type) const { 91fcaf7f86SDimitry Andric assert(type < relocAttrs.size() && "invalid relocation type"); 92fcaf7f86SDimitry Andric if (type >= relocAttrs.size()) 93fcaf7f86SDimitry Andric return invalidRelocAttrs; 94fcaf7f86SDimitry Andric return relocAttrs[type]; 95fcaf7f86SDimitry Andric } 96fcaf7f86SDimitry Andric hasAttr(uint8_t type,RelocAttrBits bit)97fe6060f1SDimitry Andric bool hasAttr(uint8_t type, RelocAttrBits bit) const { 98fe6060f1SDimitry Andric return getRelocAttrs(type).hasAttr(bit); 99fe6060f1SDimitry Andric } 100fe6060f1SDimitry Andric usesThunks()101fe6060f1SDimitry Andric bool usesThunks() const { return thunkSize > 0; } 102fe6060f1SDimitry Andric 103753f127fSDimitry Andric // For now, handleDtraceReloc only implements -no_dtrace_dof, and ensures 104753f127fSDimitry Andric // that the linking would not fail even when there are user-provided dtrace 105753f127fSDimitry Andric // symbols. However, unlike ld64, lld currently does not emit __dof sections. handleDtraceReloc(const Symbol * sym,const Reloc & r,uint8_t * loc)106753f127fSDimitry Andric virtual void handleDtraceReloc(const Symbol *sym, const Reloc &r, 107753f127fSDimitry Andric uint8_t *loc) const { 108753f127fSDimitry Andric llvm_unreachable("Unsupported architecture for dtrace symbols"); 109753f127fSDimitry Andric } 110753f127fSDimitry Andric applyOptimizationHints(uint8_t *,const ObjFile &)111bdd1243dSDimitry Andric virtual void applyOptimizationHints(uint8_t *, const ObjFile &) const {}; 11281ad6265SDimitry Andric 113fe6060f1SDimitry Andric uint32_t magic; 114fe6060f1SDimitry Andric llvm::MachO::CPUType cpuType; 1155ffd83dbSDimitry Andric uint32_t cpuSubtype; 1165ffd83dbSDimitry Andric 117fe6060f1SDimitry Andric uint64_t pageZeroSize; 118fe6060f1SDimitry Andric size_t headerSize; 1195ffd83dbSDimitry Andric size_t stubSize; 1205ffd83dbSDimitry Andric size_t stubHelperHeaderSize; 1215ffd83dbSDimitry Andric size_t stubHelperEntrySize; 122bdd1243dSDimitry Andric size_t objcStubsFastSize; 123*7a6dacacSDimitry Andric size_t objcStubsSmallSize; 124*7a6dacacSDimitry Andric size_t objcStubsFastAlignment; 125*7a6dacacSDimitry Andric size_t objcStubsSmallAlignment; 12681ad6265SDimitry Andric uint8_t p2WordSize; 127fe6060f1SDimitry Andric size_t wordSize; 128fe6060f1SDimitry Andric 129fe6060f1SDimitry Andric size_t thunkSize = 0; 130349cc55cSDimitry Andric uint64_t forwardBranchRange = 0; 131349cc55cSDimitry Andric uint64_t backwardBranchRange = 0; 132fe6060f1SDimitry Andric 13381ad6265SDimitry Andric uint32_t modeDwarfEncoding; 13481ad6265SDimitry Andric uint8_t subtractorRelocType; 13581ad6265SDimitry Andric uint8_t unsignedRelocType; 13681ad6265SDimitry Andric 137fcaf7f86SDimitry Andric llvm::ArrayRef<RelocAttrs> relocAttrs; 138fcaf7f86SDimitry Andric 139fe6060f1SDimitry Andric // We contrive this value as sufficiently far from any valid address that it 140fe6060f1SDimitry Andric // will always be out-of-range for any architecture. UINT64_MAX is not a 141fe6060f1SDimitry Andric // good choice because it is (a) only 1 away from wrapping to 0, and (b) the 142fe6060f1SDimitry Andric // tombstone value for DenseMap<> and caused weird assertions for me. 143fe6060f1SDimitry Andric static constexpr uint64_t outOfRangeVA = 0xfull << 60; 1445ffd83dbSDimitry Andric }; 1455ffd83dbSDimitry Andric 1465ffd83dbSDimitry Andric TargetInfo *createX86_64TargetInfo(); 147fe6060f1SDimitry Andric TargetInfo *createARM64TargetInfo(); 148fe6060f1SDimitry Andric TargetInfo *createARM64_32TargetInfo(); 149fe6060f1SDimitry Andric 150fe6060f1SDimitry Andric struct LP64 { 151fe6060f1SDimitry Andric using mach_header = llvm::MachO::mach_header_64; 152fe6060f1SDimitry Andric using nlist = structs::nlist_64; 153fe6060f1SDimitry Andric using segment_command = llvm::MachO::segment_command_64; 154fe6060f1SDimitry Andric using section = llvm::MachO::section_64; 155fe6060f1SDimitry Andric using encryption_info_command = llvm::MachO::encryption_info_command_64; 156fe6060f1SDimitry Andric 157fe6060f1SDimitry Andric static constexpr uint32_t magic = llvm::MachO::MH_MAGIC_64; 158fe6060f1SDimitry Andric static constexpr uint32_t segmentLCType = llvm::MachO::LC_SEGMENT_64; 159fe6060f1SDimitry Andric static constexpr uint32_t encryptionInfoLCType = 160fe6060f1SDimitry Andric llvm::MachO::LC_ENCRYPTION_INFO_64; 161fe6060f1SDimitry Andric 162fe6060f1SDimitry Andric static constexpr uint64_t pageZeroSize = 1ull << 32; 163fe6060f1SDimitry Andric static constexpr size_t wordSize = 8; 164fe6060f1SDimitry Andric }; 165fe6060f1SDimitry Andric 166fe6060f1SDimitry Andric struct ILP32 { 167fe6060f1SDimitry Andric using mach_header = llvm::MachO::mach_header; 168fe6060f1SDimitry Andric using nlist = structs::nlist; 169fe6060f1SDimitry Andric using segment_command = llvm::MachO::segment_command; 170fe6060f1SDimitry Andric using section = llvm::MachO::section; 171fe6060f1SDimitry Andric using encryption_info_command = llvm::MachO::encryption_info_command; 172fe6060f1SDimitry Andric 173fe6060f1SDimitry Andric static constexpr uint32_t magic = llvm::MachO::MH_MAGIC; 174fe6060f1SDimitry Andric static constexpr uint32_t segmentLCType = llvm::MachO::LC_SEGMENT; 175fe6060f1SDimitry Andric static constexpr uint32_t encryptionInfoLCType = 176fe6060f1SDimitry Andric llvm::MachO::LC_ENCRYPTION_INFO; 177fe6060f1SDimitry Andric 178fe6060f1SDimitry Andric static constexpr uint64_t pageZeroSize = 1ull << 12; 179fe6060f1SDimitry Andric static constexpr size_t wordSize = 4; 180fe6060f1SDimitry Andric }; 1815ffd83dbSDimitry Andric 1825ffd83dbSDimitry Andric extern TargetInfo *target; 1835ffd83dbSDimitry Andric 184bdd1243dSDimitry Andric } // namespace lld::macho 1855ffd83dbSDimitry Andric 1865ffd83dbSDimitry Andric #endif 187