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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_MACHO_TARGET_H
10#define LLD_MACHO_TARGET_H
11
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
23namespace lld::macho {
24LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
25
26class Symbol;
27class Defined;
28class DylibSymbol;
29class InputSection;
30class ConcatInputSection;
31
32class TargetInfo {
33public:
34 template <class LP> TargetInfo(LP) {
35 // Having these values available in TargetInfo allows us to access them
36 // without having to resort to templates.
37 magic = LP::magic;
38 pageZeroSize = LP::pageZeroSize;
39 headerSize = sizeof(typename LP::mach_header);
40 wordSize = LP::wordSize;
41 p2WordSize = llvm::CTLog2<LP::wordSize>();
42 }
43
44 virtual ~TargetInfo() = default;
45
46 // Validate the relocation structure and get its addend.
47 virtual int64_t
48 getEmbeddedAddend(llvm::MemoryBufferRef, uint64_t offset,
49 const llvm::MachO::relocation_info) const = 0;
50 virtual void relocateOne(uint8_t *loc, const Reloc &, uint64_t va,
51 uint64_t relocVA) const = 0;
52
53 // Write code for lazy binding. See the comments on StubsSection for more
54 // details.
55 virtual void writeStub(uint8_t *buf, const Symbol &) const = 0;
56 virtual void writeStubHelperHeader(uint8_t *buf) const = 0;
57 virtual void writeStubHelperEntry(uint8_t *buf, const Symbol &,
58 uint64_t entryAddr) const = 0;
59
60 virtual void writeObjCMsgSendStub(uint8_t *buf, Symbol *sym,
61 uint64_t stubsAddr, uint64_t stubOffset,
62 uint64_t selrefsVA, uint64_t selectorIndex,
63 uint64_t gotAddr,
64 uint64_t msgSendIndex) const = 0;
65
66 // Symbols may be referenced via either the GOT or the stubs section,
67 // depending on the relocation type. prepareSymbolRelocation() will set up the
68 // GOT/stubs entries, and resolveSymbolVA() will return the addresses of those
69 // entries. resolveSymbolVA() may also relax the target instructions to save
70 // on a level of address indirection.
71 virtual void relaxGotLoad(uint8_t *loc, uint8_t type) const = 0;
72
73 virtual uint64_t getPageSize() const = 0;
74
75 virtual void populateThunk(InputSection *thunk, Symbol *funcSym) {
76 llvm_unreachable("target does not use thunks");
77 }
78
79 const RelocAttrs &getRelocAttrs(uint8_t type) const {
80 assert(type < relocAttrs.size() && "invalid relocation type");
81 if (type >= relocAttrs.size())
82 return invalidRelocAttrs;
83 return relocAttrs[type];
84 }
85
86 bool hasAttr(uint8_t type, RelocAttrBits bit) const {
87 return getRelocAttrs(type).hasAttr(bit);
88 }
89
90 bool usesThunks() const { return thunkSize > 0; }
91
92 // For now, handleDtraceReloc only implements -no_dtrace_dof, and ensures
93 // that the linking would not fail even when there are user-provided dtrace
94 // symbols. However, unlike ld64, lld currently does not emit __dof sections.
95 virtual void handleDtraceReloc(const Symbol *sym, const Reloc &r,
96 uint8_t *loc) const {
97 llvm_unreachable("Unsupported architecture for dtrace symbols");
98 }
99
100
101 virtual void applyOptimizationHints(uint8_t *buf, const ConcatInputSection *,
102 llvm::ArrayRef<uint64_t>) const {};
103
104 uint32_t magic;
105 llvm::MachO::CPUType cpuType;
106 uint32_t cpuSubtype;
107
108 uint64_t pageZeroSize;
109 size_t headerSize;
110 size_t stubSize;
111 size_t stubHelperHeaderSize;
112 size_t stubHelperEntrySize;
113 size_t objcStubsFastSize;
114 size_t objcStubsAlignment;
115 uint8_t p2WordSize;
116 size_t wordSize;
117
118 size_t thunkSize = 0;
119 uint64_t forwardBranchRange = 0;
120 uint64_t backwardBranchRange = 0;
121
122 uint32_t modeDwarfEncoding;
123 uint8_t subtractorRelocType;
124 uint8_t unsignedRelocType;
125
126 llvm::ArrayRef<RelocAttrs> relocAttrs;
127
128 // We contrive this value as sufficiently far from any valid address that it
129 // will always be out-of-range for any architecture. UINT64_MAX is not a
130 // good choice because it is (a) only 1 away from wrapping to 0, and (b) the
131 // tombstone value for DenseMap<> and caused weird assertions for me.
132 static constexpr uint64_t outOfRangeVA = 0xfull << 60;
133};
134
135TargetInfo *createX86_64TargetInfo();
136TargetInfo *createARM64TargetInfo();
137TargetInfo *createARM64_32TargetInfo();
138TargetInfo *createARMTargetInfo(uint32_t cpuSubtype);
139
140struct LP64 {
141 using mach_header = llvm::MachO::mach_header_64;
142 using nlist = structs::nlist_64;
143 using segment_command = llvm::MachO::segment_command_64;
144 using section = llvm::MachO::section_64;
145 using encryption_info_command = llvm::MachO::encryption_info_command_64;
146
147 static constexpr uint32_t magic = llvm::MachO::MH_MAGIC_64;
148 static constexpr uint32_t segmentLCType = llvm::MachO::LC_SEGMENT_64;
149 static constexpr uint32_t encryptionInfoLCType =
150 llvm::MachO::LC_ENCRYPTION_INFO_64;
151
152 static constexpr uint64_t pageZeroSize = 1ull << 32;
153 static constexpr size_t wordSize = 8;
154};
155
156struct ILP32 {
157 using mach_header = llvm::MachO::mach_header;
158 using nlist = structs::nlist;
159 using segment_command = llvm::MachO::segment_command;
160 using section = llvm::MachO::section;
161 using encryption_info_command = llvm::MachO::encryption_info_command;
162
163 static constexpr uint32_t magic = llvm::MachO::MH_MAGIC;
164 static constexpr uint32_t segmentLCType = llvm::MachO::LC_SEGMENT;
165 static constexpr uint32_t encryptionInfoLCType =
166 llvm::MachO::LC_ENCRYPTION_INFO;
167
168 static constexpr uint64_t pageZeroSize = 1ull << 12;
169 static constexpr size_t wordSize = 4;
170};
171
172extern TargetInfo *target;
173
174} // namespace lld::macho
175
176#endif
177

source code of lld/MachO/Target.h