201 lines · c
1//===- Target.h -------------------------------------------------*- 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLD_MACHO_TARGET_H10#define LLD_MACHO_TARGET_H11 12#include "MachOStructs.h"13#include "Relocations.h"14 15#include "llvm/ADT/BitmaskEnum.h"16#include "llvm/BinaryFormat/MachO.h"17#include "llvm/Support/MathExtras.h"18#include "llvm/Support/MemoryBuffer.h"19 20#include <cstddef>21#include <cstdint>22 23#include "mach-o/compact_unwind_encoding.h"24 25namespace lld::macho {26LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();27 28class Symbol;29class Defined;30class DylibSymbol;31class InputSection;32class ObjFile;33 34static_assert(static_cast<uint32_t>(UNWIND_X86_64_MODE_MASK) ==35 static_cast<uint32_t>(UNWIND_X86_MODE_MASK) &&36 static_cast<uint32_t>(UNWIND_ARM64_MODE_MASK) ==37 static_cast<uint32_t>(UNWIND_X86_64_MODE_MASK));38 39// Since the mode masks have the same value on all targets, define40// a common one for convenience.41constexpr uint32_t UNWIND_MODE_MASK = UNWIND_X86_64_MODE_MASK;42 43class TargetInfo {44public:45 template <class LP> TargetInfo(LP) {46 // Having these values available in TargetInfo allows us to access them47 // without having to resort to templates.48 magic = LP::magic;49 pageZeroSize = LP::pageZeroSize;50 headerSize = sizeof(typename LP::mach_header);51 wordSize = LP::wordSize;52 p2WordSize = llvm::ConstantLog2<LP::wordSize>();53 }54 55 virtual ~TargetInfo() = default;56 57 // Validate the relocation structure and get its addend.58 virtual int64_t59 getEmbeddedAddend(llvm::MemoryBufferRef, uint64_t offset,60 const llvm::MachO::relocation_info) const = 0;61 virtual void relocateOne(uint8_t *loc, const Reloc &, uint64_t va,62 uint64_t relocVA) const = 0;63 64 // Write code for lazy binding. See the comments on StubsSection for more65 // details.66 virtual void writeStub(uint8_t *buf, const Symbol &,67 uint64_t pointerVA) const = 0;68 virtual void writeStubHelperHeader(uint8_t *buf) const = 0;69 virtual void writeStubHelperEntry(uint8_t *buf, const Symbol &,70 uint64_t entryAddr) const = 0;71 72 virtual void writeObjCMsgSendStub(uint8_t *buf, Symbol *sym,73 uint64_t stubsAddr, uint64_t &stubOffset,74 uint64_t selrefVA,75 Symbol *objcMsgSend) const = 0;76 77 // Init 'thunk' so that it be a direct jump to 'branchTarget'.78 virtual void initICFSafeThunkBody(InputSection *thunk,79 Symbol *targetSym) const {80 llvm_unreachable("target does not support ICF safe thunks");81 }82 83 // Given a thunk for which `initICFSafeThunkBody` was called, return the84 // branchTarget it was initialized with.85 virtual Symbol *getThunkBranchTarget(InputSection *thunk) const {86 llvm_unreachable("target does not support ICF safe thunks");87 }88 89 virtual uint32_t getICFSafeThunkSize() const {90 llvm_unreachable("target does not support ICF safe thunks");91 }92 93 // Symbols may be referenced via either the GOT or the stubs section,94 // depending on the relocation type. prepareSymbolRelocation() will set up the95 // GOT/stubs entries, and resolveSymbolVA() will return the addresses of those96 // entries. resolveSymbolVA() may also relax the target instructions to save97 // on a level of address indirection.98 virtual void relaxGotLoad(uint8_t *loc, uint8_t type) const = 0;99 100 virtual uint64_t getPageSize() const = 0;101 102 virtual void populateThunk(InputSection *thunk, Symbol *funcSym) {103 llvm_unreachable("target does not use thunks");104 }105 106 const RelocAttrs &getRelocAttrs(uint8_t type) const {107 assert(type < relocAttrs.size() && "invalid relocation type");108 if (type >= relocAttrs.size())109 return invalidRelocAttrs;110 return relocAttrs[type];111 }112 113 bool hasAttr(uint8_t type, RelocAttrBits bit) const {114 return getRelocAttrs(type).hasAttr(bit);115 }116 117 bool usesThunks() const { return thunkSize > 0; }118 119 // For now, handleDtraceReloc only implements -no_dtrace_dof, and ensures120 // that the linking would not fail even when there are user-provided dtrace121 // symbols. However, unlike ld64, lld currently does not emit __dof sections.122 virtual void handleDtraceReloc(const Symbol *sym, const Reloc &r,123 uint8_t *loc) const {124 llvm_unreachable("Unsupported architecture for dtrace symbols");125 }126 127 uint32_t magic;128 llvm::MachO::CPUType cpuType;129 uint32_t cpuSubtype;130 131 uint64_t pageZeroSize;132 size_t headerSize;133 size_t stubSize;134 size_t stubHelperHeaderSize;135 size_t stubHelperEntrySize;136 size_t objcStubsFastSize;137 size_t objcStubsSmallSize;138 size_t objcStubsFastAlignment;139 size_t objcStubsSmallAlignment;140 uint8_t p2WordSize;141 size_t wordSize;142 143 size_t thunkSize = 0;144 uint64_t forwardBranchRange = 0;145 uint64_t backwardBranchRange = 0;146 147 uint32_t modeDwarfEncoding;148 uint8_t subtractorRelocType;149 uint8_t unsignedRelocType;150 151 llvm::ArrayRef<RelocAttrs> relocAttrs;152 153 // We contrive this value as sufficiently far from any valid address that it154 // will always be out-of-range for any architecture. UINT64_MAX is not a155 // good choice because it is (a) only 1 away from wrapping to 0, and (b) the156 // tombstone value for DenseMap<> and caused weird assertions for me.157 static constexpr uint64_t outOfRangeVA = 0xfull << 60;158};159 160TargetInfo *createX86_64TargetInfo();161TargetInfo *createARM64TargetInfo();162TargetInfo *createARM64_32TargetInfo();163 164struct LP64 {165 using mach_header = llvm::MachO::mach_header_64;166 using nlist = structs::nlist_64;167 using segment_command = llvm::MachO::segment_command_64;168 using section = llvm::MachO::section_64;169 using encryption_info_command = llvm::MachO::encryption_info_command_64;170 171 static constexpr uint32_t magic = llvm::MachO::MH_MAGIC_64;172 static constexpr uint32_t segmentLCType = llvm::MachO::LC_SEGMENT_64;173 static constexpr uint32_t encryptionInfoLCType =174 llvm::MachO::LC_ENCRYPTION_INFO_64;175 176 static constexpr uint64_t pageZeroSize = 1ull << 32;177 static constexpr size_t wordSize = 8;178};179 180struct ILP32 {181 using mach_header = llvm::MachO::mach_header;182 using nlist = structs::nlist;183 using segment_command = llvm::MachO::segment_command;184 using section = llvm::MachO::section;185 using encryption_info_command = llvm::MachO::encryption_info_command;186 187 static constexpr uint32_t magic = llvm::MachO::MH_MAGIC;188 static constexpr uint32_t segmentLCType = llvm::MachO::LC_SEGMENT;189 static constexpr uint32_t encryptionInfoLCType =190 llvm::MachO::LC_ENCRYPTION_INFO;191 192 static constexpr uint64_t pageZeroSize = 1ull << 12;193 static constexpr size_t wordSize = 4;194};195 196extern TargetInfo *target;197 198} // namespace lld::macho199 200#endif201