master
1/*
2 * Copyright (c) 2006 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_X86_64_RELOC_H_
25#define _MACHO_X86_64_RELOC_H_
26
27/*
28 * Relocations for x86_64 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 in the instruction (Mach-O does
42 * not have RELA relocations). For PC-relative relocations, the addend is
43 * stored directly in the instruction. This is different from other Mach-O
44 * architectures, which encode the addend minus the current section offset.
45 *
46 * The relocation types are:
47 *
48 * X86_64_RELOC_UNSIGNED // for absolute addresses
49 * X86_64_RELOC_SIGNED // for signed 32-bit displacement
50 * X86_64_RELOC_BRANCH // a CALL/JMP instruction with 32-bit displacement
51 * X86_64_RELOC_GOT_LOAD // a MOVQ load of a GOT entry
52 * X86_64_RELOC_GOT // other GOT references
53 * X86_64_RELOC_SUBTRACTOR // must be followed by a X86_64_RELOC_UNSIGNED
54 *
55 * The following are sample assembly instructions, followed by the relocation
56 * and section content they generate in an object file:
57 *
58 * call _foo
59 * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
60 * E8 00 00 00 00
61 *
62 * call _foo+4
63 * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
64 * E8 04 00 00 00
65 *
66 * movq _foo@GOTPCREL(%rip), %rax
67 * r_type=X86_64_RELOC_GOT_LOAD, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
68 * 48 8B 05 00 00 00 00
69 *
70 * pushq _foo@GOTPCREL(%rip)
71 * r_type=X86_64_RELOC_GOT, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
72 * FF 35 00 00 00 00
73 *
74 * movl _foo(%rip), %eax
75 * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
76 * 8B 05 00 00 00 00
77 *
78 * movl _foo+4(%rip), %eax
79 * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
80 * 8B 05 04 00 00 00
81 *
82 * movb $0x12, _foo(%rip)
83 * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
84 * C6 05 FF FF FF FF 12
85 *
86 * movl $0x12345678, _foo(%rip)
87 * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
88 * C7 05 FC FF FF FF 78 56 34 12
89 *
90 * .quad _foo
91 * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
92 * 00 00 00 00 00 00 00 00
93 *
94 * .quad _foo+4
95 * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
96 * 04 00 00 00 00 00 00 00
97 *
98 * .quad _foo - _bar
99 * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar
100 * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
101 * 00 00 00 00 00 00 00 00
102 *
103 * .quad _foo - _bar + 4
104 * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar
105 * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
106 * 04 00 00 00 00 00 00 00
107 *
108 * .long _foo - _bar
109 * r_type=X86_64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_bar
110 * r_type=X86_64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
111 * 00 00 00 00
112 *
113 * lea L1(%rip), %rax
114 * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_prev
115 * 48 8d 05 12 00 00 00
116 * // assumes _prev is the first non-local label 0x12 bytes before L1
117 *
118 * lea L0(%rip), %rax
119 * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3
120 * 48 8d 05 56 00 00 00
121 * // assumes L0 is in third section and there is no previous non-local label.
122 * // The rip-relative-offset of 0x00000056 is L0-address_of_next_instruction.
123 * // address_of_next_instruction is the address of the relocation + 4.
124 *
125 * add $6,L0(%rip)
126 * r_type=X86_64_RELOC_SIGNED_1, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3
127 * 83 05 18 00 00 00 06
128 * // assumes L0 is in third section and there is no previous non-local label.
129 * // The rip-relative-offset of 0x00000018 is L0-address_of_next_instruction.
130 * // address_of_next_instruction is the address of the relocation + 4 + 1.
131 * // The +1 comes from SIGNED_1. This is used because the relocation is not
132 * // at the end of the instruction.
133 *
134 * .quad L1
135 * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
136 * 12 00 00 00 00 00 00 00
137 * // assumes _prev is the first non-local label 0x12 bytes before L1
138 *
139 * .quad L0
140 * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=0, r_pcrel=0, r_symbolnum=3
141 * 56 00 00 00 00 00 00 00
142 * // assumes L0 is in third section, has an address of 0x00000056 in .o
143 * // file, and there is no previous non-local label
144 *
145 * .quad _foo - .
146 * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
147 * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
148 * EE FF FF FF FF FF FF FF
149 * // assumes _prev is the first non-local label 0x12 bytes before this
150 * // .quad
151 *
152 * .quad _foo - L1
153 * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
154 * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
155 * EE FF FF FF FF FF FF FF
156 * // assumes _prev is the first non-local label 0x12 bytes before L1
157 *
158 * .quad L1 - _prev
159 * // No relocations. This is an assembly time constant.
160 * 12 00 00 00 00 00 00 00
161 * // assumes _prev is the first non-local label 0x12 bytes before L1
162 *
163 *
164 *
165 * In final linked images, there are only two valid relocation kinds:
166 *
167 * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=1, r_symbolnum=sym_index
168 * This tells dyld to add the address of a symbol to a pointer sized (8-byte)
169 * piece of data (i.e on disk the 8-byte piece of data contains the addend). The
170 * r_symbolnum contains the index into the symbol table of the target symbol.
171 *
172 * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=0, r_symbolnum=0
173 * This tells dyld to adjust the pointer sized (8-byte) piece of data by the amount
174 * the containing image was loaded from its base address (e.g. slide).
175 *
176 */
177enum reloc_type_x86_64
178{
179 X86_64_RELOC_UNSIGNED, // for absolute addresses
180 X86_64_RELOC_SIGNED, // for signed 32-bit displacement
181 X86_64_RELOC_BRANCH, // a CALL/JMP instruction with 32-bit displacement
182 X86_64_RELOC_GOT_LOAD, // a MOVQ load of a GOT entry
183 X86_64_RELOC_GOT, // other GOT references
184 X86_64_RELOC_SUBTRACTOR, // must be followed by a X86_64_RELOC_UNSIGNED
185 X86_64_RELOC_SIGNED_1, // for signed 32-bit displacement with a -1 addend
186 X86_64_RELOC_SIGNED_2, // for signed 32-bit displacement with a -2 addend
187 X86_64_RELOC_SIGNED_4, // for signed 32-bit displacement with a -4 addend
188 X86_64_RELOC_TLV, // for thread local variables
189};
190
191#endif /* #ifndef _MACHO_X86_64_RELOC_H_ */