2 * Copyright (c) 2007-2008 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach/boolean.h>
30 #include <sys/types.h>
33 #include <libkern/libkern.h>
34 #include <mach/machine.h>
37 #include <libkern/OSByteOrder.h>
39 /* Get machine.h from the kernel source so we can support all platforms
40 * that the kernel supports. Otherwise we're at the mercy of the host.
42 #include "../../osfmk/mach/machine.h"
45 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
46 #include <AssertMacros.h>
48 #include "kxld_array.h"
49 #include "kxld_demangle.h"
50 #include "kxld_dict.h"
51 #include "kxld_reloc.h"
52 #include "kxld_sect.h"
55 #include "kxld_symtab.h"
56 #include "kxld_util.h"
57 #include "kxld_vtable.h"
60 /* This will try to pull in mach/machine.h, so it has to come after the
61 * explicit include above.
63 #include <mach-o/loader.h>
66 /* include target-specific relocation prototypes */
67 #include <mach-o/reloc.h>
68 #if KXLD_USER_OR_X86_64
69 #include <mach-o/x86_64/reloc.h>
72 #include <mach-o/arm/reloc.h>
74 #if KXLD_USER_OR_ARM64
75 #include <mach-o/arm64/reloc.h>
78 extern uint32_t kaslr_offsets_index
;
79 extern uint32_t kaslr_offsets_count
;
80 extern uint32_t *kaslr_offsets
;
82 #define KXLD_TARGET_NONE (u_int) 0x0
83 #define KXLD_TARGET_VALUE (u_int) 0x1
84 #define KXLD_TARGET_SECTNUM (u_int) 0x2
85 #define KXLD_TARGET_SYMBOLNUM (u_int) 0x3
86 #define KXLD_TARGET_LOOKUP (u_int) 0x4
87 #define KXLD_TARGET_GOT (u_int) 0x5
89 #define ABSOLUTE_VALUE(x) (((x) < 0) ? -(x) : (x))
91 #define LO16(x) (0x0000FFFF & x)
92 #define LO16S(x) ((0x0000FFFF & x) << 16)
93 #define HI16(x) (0xFFFF0000 & x)
94 #define HI16S(x) ((0xFFFF0000 & x) >> 16)
95 #define BIT15(x) (0x00008000 & x)
96 #define BR14I(x) (0xFFFF0003 & x)
97 #define BR14D(x) (0x0000FFFC & x)
98 #define BR24I(x) (0xFC000003 & x)
99 #define BR24D(x) (0x03FFFFFC & x)
100 #define HADISP 0x00010000
101 #define BR14_LIMIT 0x00008000
102 #define BR24_LIMIT 0x02000000
103 #define IS_COND_BR_INSTR(x) ((x & 0xFC000000) == 0x40000000)
104 #define IS_NOT_ALWAYS_TAKEN(x) ((x & 0x03E00000) != 0x02800000)
105 #define FLIP_PREDICT_BIT(x) x ^= 0x00200000
107 #define SIGN_EXTEND_MASK(n) (1 << ((n) - 1))
108 #define SIGN_EXTEND(x,n) (((x) ^ SIGN_EXTEND_MASK(n)) - SIGN_EXTEND_MASK(n))
109 #define BR14_NBITS_DISPLACEMENT 16
110 #define BR24_NBITS_DISPLACEMENT 26
112 #define X86_64_RIP_RELATIVE_LIMIT 0x80000000UL
114 /*******************************************************************************
116 *******************************************************************************/
117 #if KXLD_USER_OR_I386
118 static boolean_t
generic_reloc_has_pair(u_int _type
)
119 __attribute__((const));
120 static u_int
generic_reloc_get_pair_type(u_int _prev_type
)
121 __attribute__((const));
122 static boolean_t
generic_reloc_has_got(u_int _type
)
123 __attribute__((const));
124 static kern_return_t
generic_process_reloc(const KXLDRelocator
*relocator
,
125 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
126 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
127 kxld_addr_t pair_target
, boolean_t swap
);
128 #endif /* KXLD_USER_OR_I386 */
130 #if KXLD_USER_OR_X86_64
131 static boolean_t
x86_64_reloc_has_pair(u_int _type
)
132 __attribute__((const));
133 static u_int
x86_64_reloc_get_pair_type(u_int _prev_type
)
134 __attribute__((const));
135 static boolean_t
x86_64_reloc_has_got(u_int _type
)
136 __attribute__((const));
137 static kern_return_t
x86_64_process_reloc(const KXLDRelocator
*relocator
,
138 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
139 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
140 kxld_addr_t pair_target
, boolean_t swap
);
141 static kern_return_t
calculate_displacement_x86_64(uint64_t target
,
142 uint64_t adjustment
, int32_t *instr32
);
143 #endif /* KXLD_USER_OR_X86_64 */
146 static boolean_t
arm_reloc_has_pair(u_int _type
)
147 __attribute__((const));
148 static u_int
arm_reloc_get_pair_type(u_int _prev_type
)
149 __attribute__((const));
150 static boolean_t
arm_reloc_has_got(u_int _type
)
151 __attribute__((const));
152 static kern_return_t
arm_process_reloc(const KXLDRelocator
*relocator
,
153 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
154 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
155 kxld_addr_t pair_target
, boolean_t swap
);
156 #endif /* KXLD_USER_OR_ARM */
158 #if KXLD_USER_OR_ARM64
159 static boolean_t
arm64_reloc_has_pair(u_int _type
)
160 __attribute__((const));
161 static u_int
arm64_reloc_get_pair_type(u_int _prev_type
)
162 __attribute__((const));
163 static boolean_t
arm64_reloc_has_got(u_int _type
)
164 __attribute__((const));
165 static kern_return_t
arm64_process_reloc(const KXLDRelocator
*relocator
,
166 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
167 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
168 kxld_addr_t pair_target
, boolean_t swap
);
169 #endif /* KXLD_USER_OR_ARM64 */
171 #if KXLD_USER_OR_ILP32
172 static kxld_addr_t
get_pointer_at_addr_32(const KXLDRelocator
*relocator
,
173 const u_char
*data
, u_long offset
)
174 __attribute__((pure
, nonnull
));
175 #endif /* KXLD_USER_OR_ILP32 */
176 #if KXLD_USER_OR_LP64
177 static kxld_addr_t
get_pointer_at_addr_64(const KXLDRelocator
*relocator
,
178 const u_char
*data
, u_long offset
)
179 __attribute__((pure
, nonnull
));
180 #endif /* KXLD_USER_OR_LP64 */
182 static u_int
count_relocatable_relocs(const KXLDRelocator
*relocator
,
183 const struct relocation_info
*relocs
, u_int nrelocs
)
184 __attribute__((pure
));
186 static kern_return_t
calculate_targets(KXLDRelocator
*relocator
,
187 kxld_addr_t
*_target
, kxld_addr_t
*_pair_target
, const KXLDReloc
*reloc
);
189 static kxld_addr_t
align_raw_function_address(const KXLDRelocator
*relocator
,
192 static kern_return_t
get_target_by_address_lookup(kxld_addr_t
*target
,
193 kxld_addr_t addr
, const KXLDArray
*sectarray
);
195 static kern_return_t
check_for_direct_pure_virtual_call(
196 const KXLDRelocator
*relocator
, u_long offset
);
199 static u_long
get_macho_data_size_for_array(const KXLDArray
*relocs
);
201 static kern_return_t
export_macho_for_array(const KXLDRelocator
*relocator
,
202 const KXLDArray
*relocs
, struct relocation_info
**dstp
);
203 #endif /* KXLD_PIC_KEXTS */
205 /*******************************************************************************
206 *******************************************************************************/
208 kxld_relocator_init(KXLDRelocator
*relocator
, u_char
*file
,
209 const KXLDSymtab
*symtab
, const KXLDArray
*sectarray
, cpu_type_t cputype
,
210 cpu_subtype_t cpusubtype __unused
, boolean_t swap
)
212 kern_return_t rval
= KERN_FAILURE
;
217 #if KXLD_USER_OR_I386
219 relocator
->reloc_has_pair
= generic_reloc_has_pair
;
220 relocator
->reloc_get_pair_type
= generic_reloc_get_pair_type
;
221 relocator
->reloc_has_got
= generic_reloc_has_got
;
222 relocator
->process_reloc
= generic_process_reloc
;
223 relocator
->function_align
= 0;
224 relocator
->is_32_bit
= TRUE
;
225 relocator
->may_scatter
= TRUE
;
227 #endif /* KXLD_USER_OR_I386 */
228 #if KXLD_USER_OR_X86_64
229 case CPU_TYPE_X86_64
:
230 relocator
->reloc_has_pair
= x86_64_reloc_has_pair
;
231 relocator
->reloc_get_pair_type
= x86_64_reloc_get_pair_type
;
232 relocator
->reloc_has_got
= x86_64_reloc_has_got
;
233 relocator
->process_reloc
= x86_64_process_reloc
;
234 relocator
->function_align
= 0;
235 relocator
->is_32_bit
= FALSE
;
236 relocator
->may_scatter
= FALSE
;
238 #endif /* KXLD_USER_OR_X86_64 */
241 relocator
->reloc_has_pair
= arm_reloc_has_pair
;
242 relocator
->reloc_get_pair_type
= arm_reloc_get_pair_type
;
243 relocator
->reloc_has_got
= arm_reloc_has_got
;
244 relocator
->process_reloc
= arm_process_reloc
;
245 relocator
->function_align
= 1;
246 relocator
->is_32_bit
= TRUE
;
247 relocator
->may_scatter
= FALSE
;
249 #endif /* KXLD_USER_OR_ARM */
250 #if KXLD_USER_OR_ARM64
252 relocator
->reloc_has_pair
= arm64_reloc_has_pair
;
253 relocator
->reloc_get_pair_type
= arm64_reloc_get_pair_type
;
254 relocator
->reloc_has_got
= arm64_reloc_has_got
;
255 relocator
->process_reloc
= arm64_process_reloc
;
256 relocator
->function_align
= 0;
257 relocator
->is_32_bit
= FALSE
;
258 relocator
->may_scatter
= FALSE
;
260 #endif /* KXLD_USER_OR_ARM64 */
264 kxld_log(kKxldLogLinking
, kKxldLogErr
,
265 kKxldLogArchNotSupported
, cputype
);
269 relocator
->file
= file
;
270 relocator
->symtab
= symtab
;
271 relocator
->sectarray
= sectarray
;
272 relocator
->is_32_bit
= kxld_is_32_bit(cputype
);
273 relocator
->swap
= swap
;
281 /*******************************************************************************
282 *******************************************************************************/
284 kxld_reloc_create_macho(KXLDArray
*relocarray
, const KXLDRelocator
*relocator
,
285 const struct relocation_info
*srcs
, u_int nsrcs
)
287 kern_return_t rval
= KERN_FAILURE
;
288 KXLDReloc
*reloc
= NULL
;
290 const struct relocation_info
*src
= NULL
;
291 const struct scattered_relocation_info
*scatsrc
= NULL
;
293 u_int reloc_index
= 0;
298 /* If there are no relocation entries, just return */
304 /* Count the number of non-pair relocs */
305 nrelocs
= count_relocatable_relocs(relocator
, srcs
, nsrcs
);
309 /* Allocate the array of relocation entries */
311 rval
= kxld_array_init(relocarray
, sizeof(KXLDReloc
), nrelocs
);
312 require_noerr(rval
, finish
);
314 /* Initialize the relocation entries */
316 for (i
= 0; i
< nsrcs
; ++i
) {
318 scatsrc
= (const struct scattered_relocation_info
*) src
;
320 /* A section-based relocation entry can be skipped for absolute
324 if (!(relocator
->may_scatter
&& (src
->r_address
& R_SCATTERED
)) &&
325 !(src
->r_extern
) && (R_ABS
== src
->r_symbolnum
))
330 /* Pull out the data from the relocation entries. The target_type
331 * depends on the r_extern bit:
332 * Scattered -> Section Lookup by Address
333 * Local (not extern) -> Section by Index
334 * Extern -> Symbolnum by Index
336 reloc
= kxld_array_get_item(relocarray
, reloc_index
++);
337 if (relocator
->may_scatter
&& (src
->r_address
& R_SCATTERED
)) {
338 reloc
->address
= scatsrc
->r_address
;
339 reloc
->pcrel
= scatsrc
->r_pcrel
;
340 reloc
->length
= scatsrc
->r_length
;
341 reloc
->reloc_type
= scatsrc
->r_type
;
342 reloc
->target
= scatsrc
->r_value
;
343 reloc
->target_type
= KXLD_TARGET_LOOKUP
;
345 reloc
->address
= src
->r_address
;
346 reloc
->pcrel
= src
->r_pcrel
;
347 reloc
->length
= src
->r_length
;
348 reloc
->reloc_type
= src
->r_type
;
349 reloc
->target
= src
->r_symbolnum
;
351 if (0 == src
->r_extern
) {
352 reloc
->target_type
= KXLD_TARGET_SECTNUM
;
355 reloc
->target_type
= KXLD_TARGET_SYMBOLNUM
;
359 /* Find the pair entry if it exists */
361 if (relocator
->reloc_has_pair(reloc
->reloc_type
)) {
363 require_action(i
< nsrcs
, finish
, rval
=KERN_FAILURE
);
366 scatsrc
= (const struct scattered_relocation_info
*) src
;
368 if (relocator
->may_scatter
&& (src
->r_address
& R_SCATTERED
)) {
369 require_action(relocator
->reloc_get_pair_type(
370 reloc
->reloc_type
) == scatsrc
->r_type
,
371 finish
, rval
=KERN_FAILURE
);
372 reloc
->pair_address
= scatsrc
->r_address
;
373 reloc
->pair_target
= scatsrc
->r_value
;
374 reloc
->pair_target_type
= KXLD_TARGET_LOOKUP
;
376 require_action(relocator
->reloc_get_pair_type(
377 reloc
->reloc_type
) == scatsrc
->r_type
,
378 finish
, rval
=KERN_FAILURE
);
379 reloc
->pair_address
= scatsrc
->r_address
;
381 reloc
->pair_target
= src
->r_symbolnum
;
382 reloc
->pair_target_type
= KXLD_TARGET_SYMBOLNUM
;
384 reloc
->pair_target
= src
->r_address
;
385 reloc
->pair_target_type
= KXLD_TARGET_VALUE
;
389 reloc
->pair_target
= 0;
390 if (relocator
->reloc_has_got(reloc
->reloc_type
)) {
391 reloc
->pair_target_type
= KXLD_TARGET_GOT
;
393 reloc
->pair_target_type
= KXLD_TARGET_NONE
;
405 /*******************************************************************************
406 * Relocatable relocs :
407 * 1) Are not _PAIR_ relocs
408 * 2) Don't reference N_ABS symbols
409 *******************************************************************************/
411 count_relocatable_relocs(const KXLDRelocator
*relocator
,
412 const struct relocation_info
*relocs
, u_int nrelocs
)
414 u_int num_nonpair_relocs
= 0;
416 const struct relocation_info
*reloc
= NULL
;
417 const struct scattered_relocation_info
*sreloc
= NULL
;
422 /* Loop over all of the relocation entries */
424 num_nonpair_relocs
= 1;
425 for (i
= 1; i
< nrelocs
; ++i
) {
428 if (reloc
->r_address
& R_SCATTERED
) {
429 /* A scattered relocation entry is relocatable as long as it's not a
432 sreloc
= (const struct scattered_relocation_info
*) reloc
;
434 num_nonpair_relocs
+=
435 !relocator
->reloc_has_pair(sreloc
->r_type
);
437 /* A normal relocation entry is relocatable if it is not a pair and
438 * if it is not a section-based relocation for an absolute symbol.
440 num_nonpair_relocs
+=
441 !(relocator
->reloc_has_pair(reloc
->r_type
)
442 || (0 == reloc
->r_extern
&& R_ABS
== reloc
->r_symbolnum
));
447 return num_nonpair_relocs
;
450 /*******************************************************************************
451 *******************************************************************************/
453 kxld_relocator_clear(KXLDRelocator
*relocator
)
455 bzero(relocator
, sizeof(*relocator
));
458 /*******************************************************************************
459 *******************************************************************************/
461 kxld_relocator_has_pair(const KXLDRelocator
*relocator
, u_int r_type
)
465 return relocator
->reloc_has_pair(r_type
);
468 /*******************************************************************************
469 *******************************************************************************/
471 kxld_relocator_get_pair_type(const KXLDRelocator
*relocator
,
476 return relocator
->reloc_get_pair_type(prev_r_type
);
479 /*******************************************************************************
480 *******************************************************************************/
482 kxld_relocator_has_got(const KXLDRelocator
*relocator
, u_int r_type
)
486 return relocator
->reloc_has_got(r_type
);
489 /*******************************************************************************
490 *******************************************************************************/
492 kxld_reloc_get_symbol(const KXLDRelocator
*relocator
, const KXLDReloc
*reloc
,
496 kxld_addr_t value
= 0;
500 switch (reloc
->target_type
) {
501 case KXLD_TARGET_SYMBOLNUM
:
502 sym
= kxld_symtab_get_symbol_by_index(relocator
->symtab
, reloc
->target
);
504 case KXLD_TARGET_SECTNUM
:
506 value
= kxld_relocator_get_pointer_at_addr(relocator
, data
,
508 sym
= kxld_symtab_get_cxx_symbol_by_value(relocator
->symtab
, value
);
519 /*******************************************************************************
520 *******************************************************************************/
522 kxld_reloc_get_reloc_index_by_offset(const KXLDArray
*relocs
,
523 kxld_size_t offset
, u_int
*idx
)
525 kern_return_t rval
= KERN_FAILURE
;
526 KXLDReloc
*reloc
= NULL
;
529 for (i
= 0; i
< relocs
->nitems
; ++i
) {
530 reloc
= kxld_array_get_item(relocs
, i
);
531 if (reloc
->address
== offset
) break;
534 if (i
>= relocs
->nitems
) {
546 /*******************************************************************************
547 *******************************************************************************/
549 kxld_reloc_get_reloc_by_offset(const KXLDArray
*relocs
, kxld_addr_t offset
)
551 kern_return_t rval
= KERN_FAILURE
;
552 KXLDReloc
*reloc
= NULL
;
555 rval
= kxld_reloc_get_reloc_index_by_offset(relocs
, offset
, &i
);
556 if (rval
) goto finish
;
558 reloc
= kxld_array_get_item(relocs
, i
);
565 /*******************************************************************************
566 *******************************************************************************/
568 kxld_reloc_get_macho_header_size()
570 return sizeof(struct dysymtab_command
);
573 /*******************************************************************************
574 *******************************************************************************/
576 kxld_reloc_get_macho_data_size(
577 const KXLDArray
*locrelocs
,
578 const KXLDArray
*extrelocs
)
582 rval
+= get_macho_data_size_for_array(locrelocs
);
583 rval
+= get_macho_data_size_for_array(extrelocs
);
588 /*******************************************************************************
589 *******************************************************************************/
591 kxld_reloc_export_macho(const KXLDRelocator
*relocator
,
592 const KXLDArray
*locrelocs
, const KXLDArray
*extrelocs
,
593 u_char
*buf
, u_long
*header_offset
, u_long header_size
,
594 u_long
*data_offset
, u_long size
)
596 kern_return_t rval
= KERN_FAILURE
;
597 struct dysymtab_command
*dysymtabhdr
= NULL
;
598 struct relocation_info
*start
= NULL
;
599 struct relocation_info
*dst
= NULL
;
601 u_long data_size
= 0;
606 check(header_offset
);
609 require_action(sizeof(*dysymtabhdr
) <= header_size
- *header_offset
, finish
, rval
=KERN_FAILURE
);
610 dysymtabhdr
= (struct dysymtab_command
*) ((void *) (buf
+ *header_offset
));
611 *header_offset
+= sizeof(*dysymtabhdr
);
613 data_size
= kxld_reloc_get_macho_data_size(locrelocs
, extrelocs
);
614 require_action((*data_offset
+ data_size
) <= size
, finish
, rval
=KERN_FAILURE
);
616 start
= dst
= (struct relocation_info
*) ((void *) (buf
+ *data_offset
));
618 if (kaslr_offsets
== NULL
) {
619 kaslr_offsets_index
= 0;
620 kaslr_offsets_count
= locrelocs
->nitems
+ extrelocs
->nitems
;
621 kaslr_offsets
= (uint32_t *)malloc(kaslr_offsets_count
* sizeof(*kaslr_offsets
));
622 bzero(kaslr_offsets
, kaslr_offsets_count
* sizeof(*kaslr_offsets
));
625 // copies the reloc data into the __LINKEDIT segment
626 // data_offset is the new value for locreloff
627 rval
= export_macho_for_array(relocator
, locrelocs
, &dst
);
628 require_noerr(rval
, finish
);
630 rval
= export_macho_for_array(relocator
, extrelocs
, &dst
);
631 require_noerr(rval
, finish
);
635 memset(dysymtabhdr
, 0, sizeof(*dysymtabhdr
));
636 dysymtabhdr
->cmd
= LC_DYSYMTAB
;
637 dysymtabhdr
->cmdsize
= (uint32_t) sizeof(*dysymtabhdr
);
638 dysymtabhdr
->locreloff
= (uint32_t) *data_offset
;
639 dysymtabhdr
->nlocrel
= (uint32_t) count
;
641 *data_offset
+= count
* sizeof(struct relocation_info
);
643 #if SPLIT_KEXTS_DEBUG
644 kxld_log(kKxldLogLinking
, kKxldLogErr
,
645 "%p >>> Start of dysymtabhdr (size %lu) <%s> ",
646 (void *) dysymtabhdr
,
647 sizeof(*dysymtabhdr
),
649 kxld_log(kKxldLogLinking
, kKxldLogErr
,
650 "%p <<< End of dysymtabhdr <%s> ",
651 (void *) ((u_char
*)dysymtabhdr
+ sizeof(*dysymtabhdr
)),
654 kxld_log(kKxldLogLinking
, kKxldLogErr
,
655 "dysymtabhdr at %p: cmdsize %u indirectsymoff %u nindirectsyms %u extreloff %u nextrel %u locreloff %u nlocrel %u <%s>",
656 (void *) dysymtabhdr
,
657 dysymtabhdr
->cmdsize
,
658 dysymtabhdr
->indirectsymoff
,
659 dysymtabhdr
->nindirectsyms
,
660 dysymtabhdr
->extreloff
,
661 dysymtabhdr
->nextrel
,
662 dysymtabhdr
->locreloff
,
663 dysymtabhdr
->nlocrel
,
671 #endif /* KXLD_PIC_KEXTS */
673 /*******************************************************************************
674 *******************************************************************************/
676 kxld_relocator_get_pointer_at_addr(const KXLDRelocator
*relocator
,
677 const u_char
*data
, u_long offset
)
681 KXLD_3264_FUNC(relocator
->is_32_bit
, value
,
682 get_pointer_at_addr_32
, get_pointer_at_addr_64
,
683 relocator
, data
, offset
);
688 #if KXLD_USER_OR_ILP32
689 /*******************************************************************************
690 *******************************************************************************/
692 get_pointer_at_addr_32(const KXLDRelocator
*relocator
,
693 const u_char
*data
, u_long offset
)
699 addr
= *(const uint32_t *) ((const void *) (data
+ offset
));
701 if (relocator
->swap
) {
702 addr
= OSSwapInt32(addr
);
706 return align_raw_function_address(relocator
, addr
);
708 #endif /* KXLD_USER_OR_ILP32 */
710 #if KXLD_USER_OR_LP64
711 /*******************************************************************************
712 *******************************************************************************/
714 get_pointer_at_addr_64(const KXLDRelocator
*relocator
,
715 const u_char
*data
, u_long offset
)
721 addr
= *(const uint64_t *) ((const void *) (data
+ offset
));
724 if (relocator
->swap
) {
725 addr
= OSSwapInt64(addr
);
729 return align_raw_function_address(relocator
, addr
);
731 #endif /* KXLD_USER_OR_LP64 */
733 /*******************************************************************************
734 *******************************************************************************/
736 kxld_relocator_set_vtables(KXLDRelocator
*relocator
, const KXLDDict
*vtables
)
738 relocator
->vtables
= vtables
;
741 /*******************************************************************************
742 * When we're inspecting the raw binary and not the symbol table, value may
743 * hold a THUMB address (with bit 0 set to 1) but the index will have the real
744 * address (bit 0 set to 0). So if bit 0 is set here, we clear it. This only
745 * impacts ARM for now, but it's implemented as a generic function alignment
747 *******************************************************************************/
749 align_raw_function_address(const KXLDRelocator
*relocator
, kxld_addr_t value
)
751 if (relocator
->function_align
) {
752 value
&= ~((1ULL << relocator
->function_align
) - 1);
758 /*******************************************************************************
759 *******************************************************************************/
761 kxld_relocator_process_sect_reloc(KXLDRelocator
*relocator
,
762 const KXLDReloc
*reloc
, const KXLDSect
*sect
)
764 kern_return_t rval
= KERN_FAILURE
;
765 u_char
*instruction
= NULL
;
766 kxld_addr_t target
= 0;
767 kxld_addr_t pair_target
= 0;
768 kxld_addr_t base_pc
= 0;
769 kxld_addr_t link_pc
= 0;
770 kxld_addr_t link_disp
= 0;
776 /* Find the instruction */
778 instruction
= sect
->data
+ reloc
->address
;
780 /* Calculate the target */
782 rval
= calculate_targets(relocator
, &target
, &pair_target
, reloc
);
783 require_noerr(rval
, finish
);
785 base_pc
= reloc
->address
;
786 link_pc
= base_pc
+ sect
->link_addr
;
787 link_disp
= sect
->link_addr
- sect
->base_addr
;
791 rval
= relocator
->process_reloc(relocator
, instruction
, reloc
->length
,
792 reloc
->pcrel
, base_pc
, link_pc
, link_disp
, reloc
->reloc_type
, target
,
793 pair_target
, relocator
->swap
);
794 require_noerr(rval
, finish
);
798 relocator
->current_vtable
= NULL
;
805 /*******************************************************************************
806 *******************************************************************************/
808 kxld_reloc_update_symindex(KXLDReloc
*reloc
, u_int symindex
)
810 kern_return_t rval
= KERN_FAILURE
;
812 require_action(reloc
->target_type
== KXLD_TARGET_SYMBOLNUM
,
813 finish
, rval
= KERN_FAILURE
);
815 reloc
->target
= symindex
;
823 /*******************************************************************************
824 *******************************************************************************/
826 kxld_relocator_process_table_reloc(KXLDRelocator
*relocator
,
827 const KXLDReloc
*reloc
,
829 kxld_addr_t link_addr
)
831 kern_return_t rval
= KERN_FAILURE
;
832 u_char
*instruction
= NULL
;
833 kxld_addr_t target
= 0;
834 kxld_addr_t pair_target
= 0;
835 kxld_addr_t base_pc
= 0;
836 kxld_addr_t link_pc
= 0;
842 /* Find the instruction in original kext file we are trying to link */
844 offset
= (u_long
)(seg
->fileoff
+ (reloc
->address
- seg
->base_addr
));
845 instruction
= relocator
->file
+ offset
;
847 /* Calculate the target */
849 rval
= calculate_targets(relocator
, &target
, &pair_target
, reloc
);
850 require_noerr(rval
, finish
);
852 base_pc
= reloc
->address
;
853 link_pc
= base_pc
+ link_addr
;
854 if (kxld_seg_is_split_seg(seg
)) {
855 // link_pc for split segment special case, do not add in the base_pc
861 rval
= relocator
->process_reloc(relocator
, instruction
, reloc
->length
,
862 reloc
->pcrel
, base_pc
, link_pc
, link_addr
, reloc
->reloc_type
, target
,
863 pair_target
, relocator
->swap
);
864 require_noerr(rval
, finish
);
868 relocator
->current_vtable
= NULL
;
875 /*******************************************************************************
876 *******************************************************************************/
878 calculate_targets(KXLDRelocator
*relocator
, kxld_addr_t
*_target
,
879 kxld_addr_t
*_pair_target
, const KXLDReloc
*reloc
)
881 kern_return_t rval
= KERN_FAILURE
;
882 const KXLDSect
*sect
= NULL
;
883 const KXLDSym
*sym
= NULL
;
884 kxld_addr_t target
= 0;
885 kxld_addr_t pair_target
= 0;
886 char *demangled_name
= NULL
;
887 size_t demangled_length
= 0;
894 /* Find the target based on the lookup type */
896 switch(reloc
->target_type
) {
897 case KXLD_TARGET_LOOKUP
:
898 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
899 reloc
->pair_target_type
== KXLD_TARGET_LOOKUP
||
900 reloc
->pair_target_type
== KXLD_TARGET_VALUE
,
901 finish
, rval
=KERN_FAILURE
);
903 rval
= get_target_by_address_lookup(&target
, reloc
->target
,
904 relocator
->sectarray
);
905 require_noerr(rval
, finish
);
907 if (reloc
->pair_target_type
== KXLD_TARGET_LOOKUP
) {
908 rval
= get_target_by_address_lookup(&pair_target
,
909 reloc
->pair_target
, relocator
->sectarray
);
910 require_noerr(rval
, finish
);
911 } else if (reloc
->pair_target_type
== KXLD_TARGET_VALUE
) {
912 pair_target
= reloc
->pair_target
;
915 case KXLD_TARGET_SECTNUM
:
916 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
917 reloc
->pair_target_type
== KXLD_TARGET_VALUE
,
918 finish
, rval
=KERN_FAILURE
);
920 /* Get the target's section by section number */
921 sect
= kxld_array_get_item(relocator
->sectarray
, reloc
->target
);
922 require_action(sect
, finish
, rval
=KERN_FAILURE
);
924 /* target is the change in the section's address */
925 target
= sect
->link_addr
- sect
->base_addr
;
927 if (reloc
->pair_target_type
) {
928 pair_target
= reloc
->pair_target
;
930 /* x86_64 needs to know when we have a non-external relocation,
931 * so we hack that information in here.
936 case KXLD_TARGET_SYMBOLNUM
:
937 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
938 reloc
->pair_target_type
== KXLD_TARGET_GOT
||
939 reloc
->pair_target_type
== KXLD_TARGET_SYMBOLNUM
||
940 reloc
->pair_target_type
== KXLD_TARGET_VALUE
, finish
,
943 /* Get the target's symbol by symbol number */
944 sym
= kxld_symtab_get_symbol_by_index(relocator
->symtab
, reloc
->target
);
945 require_action(sym
, finish
, rval
=KERN_FAILURE
);
947 /* If this symbol is a padslot that has already been replaced, then the
948 * only way a relocation entry can still reference it is if there is a
949 * vtable that has not been patched. The vtable patcher uses the
950 * MetaClass structure to find classes for patching, so an unpatched
951 * vtable means that there is an OSObject-dervied class that is missing
952 * its OSDeclare/OSDefine macros.
954 require_action(!kxld_sym_is_padslot(sym
) || !kxld_sym_is_replaced(sym
),
955 finish
, rval
=KERN_FAILURE
;
956 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocatingPatchedSym
,
957 kxld_demangle(sym
->name
, &demangled_name
, &demangled_length
)));
959 target
= sym
->link_addr
;
961 if (kxld_sym_is_vtable(sym
)) {
962 relocator
->current_vtable
= kxld_dict_find(relocator
->vtables
, sym
->name
);
965 /* Some relocation types need the GOT entry address instead of the
966 * symbol's actual address. These types don't have pair relocation
967 * entries, so we store the GOT entry address as the pair target.
969 if (reloc
->pair_target_type
== KXLD_TARGET_VALUE
) {
970 pair_target
= reloc
->pair_target
;
971 } else if (reloc
->pair_target_type
== KXLD_TARGET_SYMBOLNUM
) {
972 sym
= kxld_symtab_get_symbol_by_index(relocator
->symtab
,
974 require_action(sym
, finish
, rval
=KERN_FAILURE
);
975 pair_target
= sym
->link_addr
;
976 } else if (reloc
->pair_target_type
== KXLD_TARGET_GOT
) {
977 pair_target
= sym
->got_addr
;
986 *_pair_target
= pair_target
;
990 if (demangled_name
) kxld_free(demangled_name
, demangled_length
);
994 /*******************************************************************************
995 *******************************************************************************/
997 get_target_by_address_lookup(kxld_addr_t
*target
, kxld_addr_t addr
,
998 const KXLDArray
*sectarray
)
1000 kern_return_t rval
= KERN_FAILURE
;
1001 const KXLDSect
*sect
= NULL
;
1002 kxld_addr_t start
= 0;
1003 kxld_addr_t end
= 0;
1010 for (i
= 0; i
< sectarray
->nitems
; ++i
) {
1011 sect
= kxld_array_get_item(sectarray
, i
);
1012 start
= sect
->base_addr
;
1013 end
= start
+ sect
->size
;
1015 if (start
<= addr
&& addr
< end
) break;
1019 require_action(sect
, finish
, rval
=KERN_FAILURE
);
1021 *target
= sect
->link_addr
- sect
->base_addr
;
1022 rval
= KERN_SUCCESS
;
1028 /*******************************************************************************
1029 *******************************************************************************/
1030 static kern_return_t
1031 check_for_direct_pure_virtual_call(const KXLDRelocator
*relocator
, u_long offset
)
1033 kern_return_t rval
= KERN_FAILURE
;
1034 const KXLDVTableEntry
*entry
= NULL
;
1036 if (relocator
->current_vtable
) {
1037 entry
= kxld_vtable_get_entry_for_offset(relocator
->current_vtable
,
1038 offset
, relocator
->is_32_bit
);
1039 require_action(!entry
|| !entry
->patched
.name
||
1040 !kxld_sym_name_is_pure_virtual(entry
->patched
.name
),
1041 finish
, rval
=KERN_FAILURE
;
1042 kxld_log(kKxldLogLinking
, kKxldLogErr
,
1043 kKxldLogDirectPureVirtualCall
));
1046 rval
= KERN_SUCCESS
;
1052 /*******************************************************************************
1053 *******************************************************************************/
1055 get_macho_data_size_for_array(const KXLDArray
*relocs
)
1057 const KXLDReloc
*reloc
= NULL
;
1063 for (i
= 0; i
< relocs
->nitems
; ++i
) {
1064 reloc
= kxld_array_get_item(relocs
, i
);
1065 if (!reloc
->pcrel
) {
1066 size
+= sizeof(struct relocation_info
);
1067 if(reloc
->pair_target_type
!= KXLD_TARGET_NONE
) {
1068 size
+= sizeof(struct relocation_info
);
1076 /*******************************************************************************
1077 *******************************************************************************/
1078 static kern_return_t
1079 export_macho_for_array(const KXLDRelocator
*relocator
,
1080 const KXLDArray
*relocs
, struct relocation_info
**dstp
)
1082 kern_return_t rval
= KERN_FAILURE
;
1083 const KXLDReloc
*reloc
= NULL
;
1084 struct relocation_info
*dst
= NULL
;
1085 struct scattered_relocation_info
*scatdst
= NULL
;
1090 for (i
= 0; i
< relocs
->nitems
; ++i
) {
1091 reloc
= kxld_array_get_item(relocs
, i
);
1092 scatdst
= (struct scattered_relocation_info
*) dst
;
1098 switch (reloc
->target_type
) {
1099 case KXLD_TARGET_LOOKUP
:
1100 if (kaslr_offsets
) {
1101 if (kaslr_offsets_index
>= kaslr_offsets_count
) {
1102 kxld_log(kKxldLogLinking
, kKxldLogErr
,
1103 "kaslr_offsets overflow %d > %d <%s> ",
1104 kaslr_offsets_index
, kaslr_offsets_count
,
1108 // reloc->address is really an offset from the start of the kext
1109 *(kaslr_offsets
+ kaslr_offsets_index
++) = reloc
->address
;
1111 scatdst
->r_address
= reloc
->address
;
1112 scatdst
->r_pcrel
= reloc
->pcrel
;
1113 scatdst
->r_length
= reloc
->length
;
1114 scatdst
->r_type
= reloc
->reloc_type
;
1115 scatdst
->r_value
= reloc
->target
;
1116 scatdst
->r_scattered
= 1;
1118 case KXLD_TARGET_SECTNUM
:
1119 if (kaslr_offsets
) {
1120 if (kaslr_offsets_index
>= kaslr_offsets_count
) {
1121 kxld_log(kKxldLogLinking
, kKxldLogErr
,
1122 "kaslr_offsets overflow <%s> ", __func__
);
1125 // reloc->address is really an offset from the start of the kext
1126 *(kaslr_offsets
+ kaslr_offsets_index
++) = reloc
->address
;
1128 dst
->r_address
= reloc
->address
;
1129 dst
->r_pcrel
= reloc
->pcrel
;
1130 dst
->r_length
= reloc
->length
;
1131 dst
->r_type
= reloc
->reloc_type
;
1132 dst
->r_symbolnum
= reloc
->target
+ 1;
1135 case KXLD_TARGET_SYMBOLNUM
:
1136 /* Assume that everything will be slid together; otherwise,
1137 * there is no sensible value for the section number.
1139 if (kaslr_offsets
) {
1140 if (kaslr_offsets_index
>= kaslr_offsets_count
) {
1141 kxld_log(kKxldLogLinking
, kKxldLogErr
,
1142 "kaslr_offsets overflow <%s> ", __func__
);
1145 // reloc->address is really an offset from the start of the kext
1146 *(kaslr_offsets
+ kaslr_offsets_index
++) = reloc
->address
;
1148 dst
->r_address
= reloc
->address
;
1149 dst
->r_pcrel
= reloc
->pcrel
;
1150 dst
->r_length
= reloc
->length
;
1151 dst
->r_type
= reloc
->reloc_type
;
1152 dst
->r_symbolnum
= 1;
1156 rval
= KERN_FAILURE
;
1162 if(reloc
->pair_target_type
!= KXLD_TARGET_NONE
) {
1164 require_action(i
< relocs
->nitems
, finish
, rval
=KERN_FAILURE
);
1165 scatdst
= (struct scattered_relocation_info
*) dst
;
1166 switch (reloc
->pair_target_type
) {
1167 case KXLD_TARGET_LOOKUP
:
1168 scatdst
->r_address
= reloc
->pair_address
;
1169 scatdst
->r_pcrel
= reloc
->pcrel
;
1170 scatdst
->r_length
= reloc
->length
;
1171 scatdst
->r_type
= relocator
->reloc_get_pair_type(reloc
->reloc_type
);
1172 scatdst
->r_value
= reloc
->pair_target
;
1173 scatdst
->r_scattered
= 1;
1175 case KXLD_TARGET_SECTNUM
:
1176 dst
->r_address
= reloc
->pair_address
;
1177 dst
->r_pcrel
= reloc
->pcrel
;
1178 dst
->r_length
= reloc
->length
;
1179 dst
->r_type
= relocator
->reloc_get_pair_type(reloc
->reloc_type
);
1180 dst
->r_symbolnum
= reloc
->pair_target
+ 1;
1183 case KXLD_TARGET_SYMBOLNUM
:
1184 dst
->r_address
= reloc
->pair_address
;
1185 dst
->r_pcrel
= reloc
->pcrel
;
1186 dst
->r_length
= reloc
->length
;
1187 dst
->r_type
= relocator
->reloc_get_pair_type(reloc
->reloc_type
);
1188 dst
->r_symbolnum
= 1;
1192 rval
= KERN_FAILURE
;
1199 rval
= KERN_SUCCESS
;
1204 #endif /* KXLD_PIC_KEXTS */
1206 #if KXLD_USER_OR_I386
1207 /*******************************************************************************
1208 *******************************************************************************/
1210 generic_reloc_has_pair(u_int _type
)
1212 enum reloc_type_generic type
= _type
;
1214 return (type
== GENERIC_RELOC_SECTDIFF
||
1215 type
== GENERIC_RELOC_LOCAL_SECTDIFF
);
1218 /*******************************************************************************
1219 *******************************************************************************/
1221 generic_reloc_get_pair_type(u_int _prev_type __unused
)
1223 return GENERIC_RELOC_PAIR
;
1226 /*******************************************************************************
1227 *******************************************************************************/
1228 static boolean_t
generic_reloc_has_got(u_int _type __unused
)
1233 /*******************************************************************************
1234 *******************************************************************************/
1235 static kern_return_t
1236 generic_process_reloc(const KXLDRelocator
*relocator
, u_char
*instruction
,
1237 u_int length
, u_int pcrel
, kxld_addr_t _base_pc
, kxld_addr_t _link_pc
,
1238 kxld_addr_t _link_disp __unused
, u_int _type
, kxld_addr_t _target
,
1239 kxld_addr_t _pair_target
, boolean_t swap __unused
)
1241 kern_return_t rval
= KERN_FAILURE
;
1242 uint32_t base_pc
= (uint32_t) _base_pc
;
1243 uint32_t link_pc
= (uint32_t) _link_pc
;
1244 uint32_t *instr_addr
= NULL
;
1245 uint32_t instr_data
= 0;
1246 uint32_t target
= (uint32_t) _target
;
1247 uint32_t pair_target
= (uint32_t) _pair_target
;
1248 enum reloc_type_generic type
= _type
;
1251 require_action(length
== 2, finish
, rval
=KERN_FAILURE
);
1253 if (pcrel
) target
= target
+ base_pc
- link_pc
;
1255 instr_addr
= (uint32_t *) ((void *) instruction
);
1256 instr_data
= *instr_addr
;
1259 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1262 rval
= check_for_direct_pure_virtual_call(relocator
, instr_data
);
1263 require_noerr(rval
, finish
);
1266 case GENERIC_RELOC_VANILLA
:
1267 instr_data
+= target
;
1269 case GENERIC_RELOC_SECTDIFF
:
1270 case GENERIC_RELOC_LOCAL_SECTDIFF
:
1271 instr_data
= instr_data
+ target
- pair_target
;
1273 case GENERIC_RELOC_PB_LA_PTR
:
1274 rval
= KERN_FAILURE
;
1276 case GENERIC_RELOC_PAIR
:
1278 rval
= KERN_FAILURE
;
1283 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1286 *instr_addr
= instr_data
;
1288 rval
= KERN_SUCCESS
;
1293 #endif /* KXLD_USER_OR_I386 */
1295 #if KXLD_USER_OR_X86_64
1296 /*******************************************************************************
1297 *******************************************************************************/
1299 x86_64_reloc_has_pair(u_int _type
)
1301 enum reloc_type_x86_64 type
= _type
;
1303 return (type
== X86_64_RELOC_SUBTRACTOR
);
1306 /*******************************************************************************
1307 *******************************************************************************/
1309 x86_64_reloc_get_pair_type(u_int _prev_type __unused
)
1311 return X86_64_RELOC_UNSIGNED
;
1314 /*******************************************************************************
1315 *******************************************************************************/
1317 x86_64_reloc_has_got(u_int _type
)
1319 enum reloc_type_x86_64 type
= _type
;
1321 return (type
== X86_64_RELOC_GOT_LOAD
|| type
== X86_64_RELOC_GOT
);
1324 /*******************************************************************************
1325 *******************************************************************************/
1326 static kern_return_t
1327 x86_64_process_reloc(const KXLDRelocator
*relocator __unused
, u_char
*instruction
,
1328 u_int length
, u_int pcrel
, kxld_addr_t _base_pc __unused
,
1329 kxld_addr_t _link_pc
, kxld_addr_t _link_disp
, u_int _type
,
1330 kxld_addr_t _target
, kxld_addr_t _pair_target
, boolean_t swap __unused
)
1332 kern_return_t rval
= KERN_FAILURE
;
1333 enum reloc_type_x86_64 type
= _type
;
1334 int32_t *instr32p
= NULL
;
1335 int32_t instr32
= 0;
1336 uint64_t *instr64p
= NULL
;
1337 uint64_t instr64
= 0;
1338 uint64_t target
= _target
;
1339 uint64_t pair_target
= _pair_target
;
1340 uint64_t link_pc
= (uint64_t) _link_pc
;
1341 uint64_t link_disp
= (uint64_t) _link_disp
;
1342 uint64_t adjustment
= 0;
1345 require_action(length
== 2 || length
== 3,
1346 finish
, rval
=KERN_FAILURE
);
1349 instr32p
= (int32_t *) ((void *) instruction
);
1350 instr32
= *instr32p
;
1353 if (swap
) instr32
= OSSwapInt32(instr32
);
1356 rval
= check_for_direct_pure_virtual_call(relocator
, instr32
);
1357 require_noerr(rval
, finish
);
1359 /* There are a number of different small adjustments for pc-relative
1360 * relocation entries. The general case is to subtract the size of the
1361 * relocation (represented by the length parameter), and it applies to
1362 * the GOT types and external SIGNED types. The non-external signed types
1363 * have a different adjustment corresponding to the specific type.
1366 case X86_64_RELOC_SIGNED
:
1372 case X86_64_RELOC_SIGNED_1
:
1378 case X86_64_RELOC_SIGNED_2
:
1384 case X86_64_RELOC_SIGNED_4
:
1390 case X86_64_RELOC_BRANCH
:
1391 case X86_64_RELOC_GOT
:
1392 case X86_64_RELOC_GOT_LOAD
:
1393 adjustment
= (1 << length
);
1399 /* Perform the actual relocation. All of the 32-bit relocations are
1400 * pc-relative except for SUBTRACTOR, so a good chunk of the logic is
1401 * stuck in calculate_displacement_x86_64. The signed relocations are
1402 * a special case, because when they are non-external, the instruction
1403 * already contains the pre-relocation displacement, so we only need to
1404 * find the difference between how far the PC was relocated, and how
1405 * far the target is relocated. Since the target variable already
1406 * contains the difference between the target's base and link
1407 * addresses, we add the difference between the PC's base and link
1408 * addresses to the adjustment variable. This will yield the
1409 * appropriate displacement in calculate_displacement.
1412 case X86_64_RELOC_BRANCH
:
1413 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1414 adjustment
+= link_pc
;
1416 case X86_64_RELOC_SIGNED
:
1417 case X86_64_RELOC_SIGNED_1
:
1418 case X86_64_RELOC_SIGNED_2
:
1419 case X86_64_RELOC_SIGNED_4
:
1420 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1421 adjustment
+= (pair_target
) ? (link_disp
) : (link_pc
);
1423 case X86_64_RELOC_GOT
:
1424 case X86_64_RELOC_GOT_LOAD
:
1425 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1426 adjustment
+= link_pc
;
1427 target
= pair_target
;
1429 case X86_64_RELOC_SUBTRACTOR
:
1430 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1431 instr32
= (int32_t) (target
- pair_target
);
1433 case X86_64_RELOC_UNSIGNED
:
1435 rval
= KERN_FAILURE
;
1439 /* Call calculate_displacement for the pc-relative relocations */
1441 rval
= calculate_displacement_x86_64(target
, adjustment
, &instr32
);
1442 require_noerr(rval
, finish
);
1446 if (swap
) instr32
= OSSwapInt32(instr32
);
1449 *instr32p
= instr32
;
1451 instr64p
= (uint64_t *) ((void *) instruction
);
1452 instr64
= *instr64p
;
1455 if (swap
) instr64
= OSSwapInt64(instr64
);
1458 rval
= check_for_direct_pure_virtual_call(relocator
, (u_long
) instr64
);
1459 require_noerr(rval
, finish
);
1462 case X86_64_RELOC_UNSIGNED
:
1463 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1467 case X86_64_RELOC_SUBTRACTOR
:
1468 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1470 instr64
= target
- pair_target
;
1472 case X86_64_RELOC_SIGNED_1
:
1473 case X86_64_RELOC_SIGNED_2
:
1474 case X86_64_RELOC_SIGNED_4
:
1475 case X86_64_RELOC_GOT_LOAD
:
1476 case X86_64_RELOC_BRANCH
:
1477 case X86_64_RELOC_SIGNED
:
1478 case X86_64_RELOC_GOT
:
1480 rval
= KERN_FAILURE
;
1485 if (swap
) instr64
= OSSwapInt64(instr64
);
1487 *instr64p
= instr64
;
1490 rval
= KERN_SUCCESS
;
1496 /*******************************************************************************
1497 *******************************************************************************/
1498 static kern_return_t
1499 calculate_displacement_x86_64(uint64_t target
, uint64_t adjustment
,
1502 kern_return_t rval
= KERN_FAILURE
;
1503 int64_t displacement
;
1504 uint64_t difference
;
1506 displacement
= *instr32
+ target
- adjustment
;
1507 difference
= ABSOLUTE_VALUE(displacement
);
1508 require_action(difference
< X86_64_RIP_RELATIVE_LIMIT
, finish
,
1510 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocationOverflow
));
1512 *instr32
= (int32_t) displacement
;
1513 rval
= KERN_SUCCESS
;
1518 #endif /* KXLD_USER_OR_X86_64 */
1520 #if KXLD_USER_OR_ARM
1521 /*******************************************************************************
1522 *******************************************************************************/
1524 arm_reloc_has_pair(u_int _type
)
1526 enum reloc_type_arm type
= _type
;
1529 case ARM_RELOC_SECTDIFF
:
1537 /*******************************************************************************
1538 *******************************************************************************/
1540 arm_reloc_get_pair_type(u_int _prev_type __unused
)
1542 return ARM_RELOC_PAIR
;
1545 /*******************************************************************************
1546 *******************************************************************************/
1548 arm_reloc_has_got(u_int _type __unused
)
1553 /*******************************************************************************
1554 *******************************************************************************/
1555 static kern_return_t
1556 arm_process_reloc(const KXLDRelocator
*relocator __unused
, u_char
*instruction
,
1557 u_int length
, u_int pcrel
, kxld_addr_t _base_pc __unused
,
1558 kxld_addr_t _link_pc __unused
, kxld_addr_t _link_disp __unused
,
1559 u_int _type __unused
, kxld_addr_t _target __unused
,
1560 kxld_addr_t _pair_target __unused
, boolean_t swap __unused
)
1562 kern_return_t rval
= KERN_FAILURE
;
1563 uint32_t *instr_addr
= NULL
;
1564 uint32_t instr_data
= 0;
1565 uint32_t base_pc
= (uint32_t) _base_pc
;
1566 uint32_t link_pc
= (uint32_t) _link_pc
;
1567 uint32_t target
= (uint32_t) _target
;
1568 int32_t displacement
= 0;
1569 enum reloc_type_arm type
= _type
;
1572 require_action(length
== 2, finish
, rval
=KERN_FAILURE
);
1574 if (pcrel
) displacement
= target
+ base_pc
- link_pc
;
1576 instr_addr
= (uint32_t *) ((void *) instruction
);
1577 instr_data
= *instr_addr
;
1580 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1583 rval
= check_for_direct_pure_virtual_call(relocator
, instr_data
);
1584 require_noerr(rval
, finish
);
1587 case ARM_RELOC_VANILLA
:
1588 instr_data
+= target
;
1592 * If the displacement is 0 (the offset between the pc and the target has
1593 * not changed), then we don't need to do anything for BR24 and BR22
1594 * relocs. As it turns out, because kexts build with -mlong-calls all
1595 * relocations currently end up being either vanilla (handled above) or
1596 * BR22/BR24 with a displacement of 0.
1597 * We could handle other displacements here but to keep things simple, we
1598 * won't until it is needed (at which point the kernelcache will fail to
1601 case ARM_RELOC_BR24
:
1602 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1603 require_action(displacement
== 0, finish
, rval
=KERN_FAILURE
);
1605 case ARM_THUMB_RELOC_BR22
:
1606 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1607 require_action(displacement
== 0, finish
, rval
=KERN_FAILURE
);
1610 case ARM_RELOC_SECTDIFF
:
1611 case ARM_RELOC_LOCAL_SECTDIFF
:
1612 case ARM_RELOC_PB_LA_PTR
:
1613 rval
= KERN_FAILURE
;
1616 case ARM_RELOC_PAIR
:
1618 rval
= KERN_FAILURE
;
1623 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1626 *instr_addr
= instr_data
;
1628 rval
= KERN_SUCCESS
;
1634 #endif /* KXLD_USER_OR_ARM */
1636 #if KXLD_USER_OR_ARM64
1637 /*******************************************************************************
1638 *******************************************************************************/
1640 arm64_reloc_has_pair(u_int _type
)
1642 return (_type
== ARM64_RELOC_SUBTRACTOR
);
1645 /*******************************************************************************
1646 *******************************************************************************/
1648 arm64_reloc_get_pair_type(u_int _prev_type __unused
)
1650 if (_prev_type
== ARM64_RELOC_SUBTRACTOR
) {
1651 return ARM64_RELOC_UNSIGNED
;
1657 /*******************************************************************************
1658 *******************************************************************************/
1660 arm64_reloc_has_got(u_int _type
)
1662 return (_type
== ARM64_RELOC_GOT_LOAD_PAGE21
||
1663 _type
== ARM64_RELOC_GOT_LOAD_PAGEOFF12
);
1666 /*******************************************************************************
1667 *******************************************************************************/
1669 arm64_process_reloc(const KXLDRelocator
*relocator __unused
, u_char
*instruction
,
1670 u_int length
, u_int pcrel
, kxld_addr_t _base_pc __unused
, kxld_addr_t _link_pc
,
1671 kxld_addr_t _link_disp __unused
, u_int _type
, kxld_addr_t _target
,
1672 kxld_addr_t _pair_target __unused
, boolean_t swap
)
1674 kern_return_t rval
= KERN_FAILURE
;
1675 enum reloc_type_arm64 type
= _type
;
1676 uint64_t target
= _target
;
1677 uint64_t link_pc
= (uint64_t) _link_pc
;
1678 uint64_t difference
= 0;
1679 int64_t displacement
= 0;
1680 uint32_t addend
= 0;
1683 require_action((length
== 2 || length
== 3), finish
, rval
=KERN_FAILURE
);
1686 uint32_t *instr32p
= (uint32_t *) (void *) instruction
;
1687 uint32_t instr32
= *instr32p
;
1690 if (swap
) instr32
= OSSwapInt32(instr32
);
1694 case ARM64_RELOC_BRANCH26
:
1695 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1696 addend
= (instr32
& 0x03FFFFFF) << 2;
1697 addend
= SIGN_EXTEND(addend
, 27);
1698 displacement
= (target
- link_pc
+ addend
);
1699 difference
= ABSOLUTE_VALUE(displacement
);
1700 displacement
= (displacement
>> 2);
1701 require_action(difference
< (128 * 1024 * 1024), finish
,
1702 rval
= KERN_FAILURE
;
1703 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocationOverflow
));
1704 instr32
= (instr32
& 0xFC000000) | (displacement
& 0x03FFFFFF);
1708 rval
= KERN_FAILURE
;
1713 if (swap
) instr32
= OSSwapInt32(instr32
);
1716 *instr32p
= instr32
;
1717 } else { /* length == 3 */
1718 uint64_t *instr64p
= (uint64_t *) (void *) instruction
;
1719 uint64_t instr64
= *instr64p
;
1722 if (swap
) instr64
= OSSwapInt64(instr64
);
1726 case ARM64_RELOC_UNSIGNED
:
1727 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1731 rval
= KERN_FAILURE
;
1736 if (swap
) instr64
= OSSwapInt64(instr64
);
1739 *instr64p
= instr64
;
1742 rval
= KERN_SUCCESS
;
1748 #endif /* KXLD_USER_OR_ARM64 */