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