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_ */