master
1/*
2 * Copyright (c) 2010 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#ifndef _MACHO_ARM64_RELOC_H_
25#define _MACHO_ARM64_RELOC_H_
26
27/*
28 * Relocations for arm64 are a bit different than for other architectures in
29 * Mach-O: Scattered relocations are not used. Almost all relocations produced
30 * by the compiler are external relocations. An external relocation has the
31 * r_extern bit set to 1 and the r_symbolnum field contains the symbol table
32 * index of the target label.
33 *
34 * When the assembler is generating relocations, if the target label is a local
35 * label (begins with 'L'), then the previous non-local label in the same
36 * section is used as the target of the external relocation. An addend is used
37 * with the distance from that non-local label to the target label. Only when
38 * there is no previous non-local label in the section is an internal
39 * relocation used.
40 *
41 * The addend (i.e. the 4 in _foo+4) is encoded either in the instruction or
42 * in the r_symbolnum of ARM64_RELOC_ADDEND.
43 * For ARM64_RELOC_UNSIGNED and ARM64_RELOC_AUTHENTICATED_POINTER, the addend
44 * is stored in the instruction. ARM64_RELOC_PAGE21, ARM64_RELOC_PAGEOFF12 and
45 * ARM64_RELOC_BRANCH26 must be preceded by an ARM64_RELOC_ADDEND if they need
46 * an addend. No other relocations support addends.
47 *
48 * The relocation types are:
49 *
50 * ARM64_RELOC_UNSIGNED // For pointer sized fixups
51 * ARM64_RELOC_SUBTRACTOR // must be followed by a ARM64_RELOC_UNSIGNED
52 * ARM64_RELOC_BRANCH26 // a BL instruction with pc-relative +-128MB displacement
53 * ARM64_RELOC_PAGE21 // pc-rel distance to page of target
54 * ARM64_RELOC_PAGEOFF12 // offset within page, scaled by r_length
55 * ARM64_RELOC_GOT_LOAD_PAGE21 // load with a pc-rel distance to page of a GOT entry
56 * ARM64_RELOC_GOT_LOAD_PAGEOFF12 // load with an offset within page, scaled by r_length, of GOT entry
57 * ARM64_RELOC_POINTER_TO_GOT // 32-bit pc-rel (or 64-bit absolute) offset to a GOT entry
58 * ARM64_RELOC_TLVP_LOAD_PAGE21 // tlv load with a pc-rel distance to page of a GOT entry
59 * ARM64_RELOC_TLVP_LOAD_PAGEOFF12 // tlv load with an offset within page, scaled by r_length, of GOT entry
60 * ARM64_RELOC_ADDEND // must be followed by ARM64_RELOC_BRANCH26/ARM64_RELOC_PAGE21/ARM64_RELOC_PAGEOFF12
61 * ARM64_RELOC_AUTHENTICATED_POINTER // 64-bit pointer with authentication
62 *
63 * The following are sample assembly instructions, followed by the relocation
64 * and section content they generate in an object file:
65 *
66 * (arm64_32 only)
67 * .long _foo
68 * r_type=ARM64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
69 * 00 00 00 00
70 *
71 * (arm64_32 only)
72 * .long _foo + 4
73 * r_type=ARM64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
74 * 04 00 00 00
75 *
76 * .quad _foo
77 * r_type=ARM64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
78 * 00 00 00 00 00 00 00 00
79 *
80 * .quad _foo + 16
81 * r_type=ARM64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
82 * 10 00 00 00 00 00 00 00
83 *
84 * .quad L1
85 * r_type=ARM64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
86 * 10 00 00 00 00 00 00 00
87 * // assumes _prev is the first non-local label 0x10 bytes before L1
88 * 10 00 00 00 00 00 00 00
89 *
90 * (arm64_32 only)
91 * .long _foo - _bar
92 * r_type=ARM64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_bar
93 * r_type=ARM64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
94 * 00 00 00 00
95 *
96 * (arm64_32 only)
97 * .long _foo - _bar + 4
98 * r_type=ARM64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_bar
99 * r_type=ARM64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
100 * 04 00 00 00
101 *
102 * .quad _foo - _bar
103 * r_type=ARM64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar
104 * r_type=ARM64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
105 * 00 00 00 00 00 00 00 00
106 *
107 * .quad _foo - _bar + 4
108 * r_type=ARM64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar
109 * r_type=ARM64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
110 * 04 00 00 00 00 00 00 00
111 *
112 * .long _foo - .
113 * r_type=ARM64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_prev
114 * r_type=ARM64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
115 * f8 ff ff ff
116 * // assumes _prev is the first non-local label 0x8 bytes before this
117 * // .quad
118 *
119 * .long _foo - L1
120 * r_type=ARM64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_prev
121 * r_type=ARM64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
122 * f8 ff ff ff
123 * // assumes _prev is the first non-local label 0x8 bytes before L1
124 *
125 * .quad _foo - .
126 * r_type=ARM64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
127 * r_type=ARM64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
128 * f8 ff ff ff ff ff ff ff
129 * // assumes _prev is the first non-local label 0x8 bytes before this
130 * // .quad
131 *
132 * .quad _foo - L1
133 * r_type=ARM64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
134 * r_type=ARM64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
135 * f8 ff ff ff ff ff ff ff
136 * // assumes _prev is the first non-local label 0x8 bytes before L1
137 *
138 * .long L1 - _prev
139 * // No relocations. This is an assembly time constant.
140 * 12 00 00 00 00 00 00 00
141 * // assumes _prev is the first non-local label 0x12 bytes before L1
142 *
143 * .quad L1 - _prev
144 * // No relocations. This is an assembly time constant.
145 * 12 00 00 00 00 00 00 00
146 * // assumes _prev is the first non-local label 0x12 bytes before L1
147 *
148 * bl _foo
149 * r_type=ARM64_RELOC_BRANCH26, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
150 * 0x14000000
151 *
152 * bl _foo + 4
153 * r_type=ARM64_RELOC_ADDEND, r_length=2, r_extern=0, r_pcrel=0, r_symbolnum=0x000004
154 * r_type=ARM64_RELOC_BRANCH26, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
155 * 0x14000000
156 *
157 * adrp x0, _foo@PAGE
158 * r_type=ARM64_RELOC_PAGE21, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
159 * 0x90000000
160 *
161 * ldr x0, [x0, _foo@PAGEOFF]
162 * r_type=ARM64_RELOC_PAGEOFF12, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
163 * 0xf9400000
164 *
165 * adrp x0, _foo@PAGE + 0x24
166 * r_type=ARM64_RELOC_ADDEND, r_length=2, r_extern=0, r_pcrel=0, r_symbolnum=0x000024
167 * r_type=ARM64_RELOC_PAGE21, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
168 * 0x90000000
169 *
170 * ldr x0, [x0, _foo@PAGEOFF + 0x24]
171 * r_type=ARM64_RELOC_ADDEND, r_length=2, r_extern=0, r_pcrel=0, r_symbolnum=0x000024
172 * r_type=ARM64_RELOC_PAGEOFF12, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
173 * 0xf9400000
174 *
175 * adrp x0, _foo@GOTPAGE
176 * r_type=ARM64_RELOC_GOT_LOAD_PAGE21, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
177 * 0x90000000
178 *
179 * ldr x0, [x0, _foo@GOTPAGEOFF]
180 * r_type=ARM64_RELOC_GOT_LOAD_PAGEOFF12, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
181 * 0xf9400000
182 *
183 * adrp x0, _foo@TLVPPAGE
184 * r_type=ARM64_RELOC_TLVP_LOAD_PAGE21, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
185 * 0x90000000
186 *
187 * ldr x0, [x0, _foo@TLVPPAGEOFF]
188 * r_type=ARM64_RELOC_TLVP_LOAD_PAGEOFF12, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
189 * 0xf9400000
190 *
191 * .long _foo@GOT - .
192 * r_type=ARM64_RELOC_POINTER_TO_GOT, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
193 * 00 00 00 00
194 *
195 * (arm64_32 only)
196 * .long _foo@GOT
197 * r_type=ARM64_RELOC_POINTER_TO_GOT, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
198 * 00 00 00 00
199 *
200 * .quad _foo@GOT
201 * r_type=ARM64_RELOC_POINTER_TO_GOT, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
202 * 00 00 00 00 00 00 00 00
203 *
204 * (arm64e only)
205 * .quad _foo@AUTH(da,5,addr)
206 * r_type=ARM64_RELOC_AUTHENTICATED_POINTER, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
207 * 00 00 00 00 05 00 05 80
208 *
209 * (arm64e only)
210 * .quad (_foo + 0x10)@AUTH(da,5,addr)
211 * r_type=ARM64_RELOC_AUTHENTICATED_POINTER, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
212 * 10 00 00 00 05 00 05 80
213 *
214 *
215 */
216enum reloc_type_arm64
217{
218 ARM64_RELOC_UNSIGNED, // for pointers
219 ARM64_RELOC_SUBTRACTOR, // must be followed by a ARM64_RELOC_UNSIGNED
220 ARM64_RELOC_BRANCH26, // a B/BL instruction with 26-bit displacement
221 ARM64_RELOC_PAGE21, // pc-rel distance to page of target
222 ARM64_RELOC_PAGEOFF12, // offset within page, scaled by r_length
223 ARM64_RELOC_GOT_LOAD_PAGE21, // pc-rel distance to page of GOT slot
224 ARM64_RELOC_GOT_LOAD_PAGEOFF12, // offset within page of GOT slot,
225 // scaled by r_length
226 ARM64_RELOC_POINTER_TO_GOT, // for pointers to GOT slots
227 ARM64_RELOC_TLVP_LOAD_PAGE21, // pc-rel distance to page of TLVP slot
228 ARM64_RELOC_TLVP_LOAD_PAGEOFF12, // offset within page of TLVP slot,
229 // scaled by r_length
230 ARM64_RELOC_ADDEND, // must be followed by PAGE21 or PAGEOFF12
231
232 // An arm64e authenticated pointer.
233 //
234 // Represents a pointer to a symbol (like ARM64_RELOC_UNSIGNED).
235 // Additionally, the resulting pointer is signed. The signature is
236 // specified in the target location: the addend is restricted to the lower
237 // 32 bits (instead of the full 64 bits for ARM64_RELOC_UNSIGNED):
238 //
239 // |63|62|61-51|50-49| 48 |47 - 32|31 - 0|
240 // | 1| 0| 0 | key | addr | discriminator | addend |
241 //
242 // The key is one of:
243 // IA: 00 IB: 01
244 // DA: 10 DB: 11
245 //
246 // The discriminator field is used as extra signature diversification.
247 //
248 // The addr field indicates whether the target address should be blended
249 // into the discriminator.
250 //
251 ARM64_RELOC_AUTHENTICATED_POINTER,
252};
253
254#endif /* #ifndef _MACHO_ARM64_RELOC_H_ */