2 * Copyright (c) 2007-2020 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>
34 #include <libkern/libkern.h>
35 #include <mach/machine.h>
38 #include <libkern/OSByteOrder.h>
40 /* Get machine.h from the kernel source so we can support all platforms
41 * that the kernel supports. Otherwise we're at the mercy of the host.
43 #include "../../osfmk/mach/machine.h"
46 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
47 #include <AssertMacros.h>
49 #include "kxld_array.h"
50 #include "kxld_demangle.h"
51 #include "kxld_dict.h"
52 #include "kxld_reloc.h"
53 #include "kxld_sect.h"
56 #include "kxld_symtab.h"
57 #include "kxld_util.h"
58 #include "kxld_vtable.h"
61 /* This will try to pull in mach/machine.h, so it has to come after the
62 * explicit include above.
64 #include <mach-o/loader.h>
67 /* include target-specific relocation prototypes */
68 #include <mach-o/reloc.h>
69 #if KXLD_USER_OR_X86_64
70 #include <mach-o/x86_64/reloc.h>
73 #include <mach-o/arm/reloc.h>
75 #if KXLD_USER_OR_ARM64
76 #include <mach-o/arm64/reloc.h>
79 extern uint32_t kaslr_offsets_index
;
80 extern uint32_t kaslr_offsets_count
;
81 extern uint32_t *kaslr_offsets
;
83 #define KXLD_TARGET_NONE (u_int) 0x0
84 #define KXLD_TARGET_VALUE (u_int) 0x1
85 #define KXLD_TARGET_SECTNUM (u_int) 0x2
86 #define KXLD_TARGET_SYMBOLNUM (u_int) 0x3
87 #define KXLD_TARGET_LOOKUP (u_int) 0x4
88 #define KXLD_TARGET_GOT (u_int) 0x5
90 #define ABSOLUTE_VALUE(x) (((x) < 0) ? -(x) : (x))
92 #define LO16(x) (0x0000FFFF & x)
93 #define LO16S(x) ((0x0000FFFF & x) << 16)
94 #define HI16(x) (0xFFFF0000 & x)
95 #define HI16S(x) ((0xFFFF0000 & x) >> 16)
96 #define BIT15(x) (0x00008000 & x)
97 #define BR14I(x) (0xFFFF0003 & x)
98 #define BR14D(x) (0x0000FFFC & x)
99 #define BR24I(x) (0xFC000003 & x)
100 #define BR24D(x) (0x03FFFFFC & x)
101 #define HADISP 0x00010000
102 #define BR14_LIMIT 0x00008000
103 #define BR24_LIMIT 0x02000000
104 #define IS_COND_BR_INSTR(x) ((x & 0xFC000000) == 0x40000000)
105 #define IS_NOT_ALWAYS_TAKEN(x) ((x & 0x03E00000) != 0x02800000)
106 #define FLIP_PREDICT_BIT(x) x ^= 0x00200000
108 #define SIGN_EXTEND_MASK(n) (1 << ((n) - 1))
109 #define SIGN_EXTEND(x, n) (((x) ^ SIGN_EXTEND_MASK(n)) - SIGN_EXTEND_MASK(n))
110 #define BR14_NBITS_DISPLACEMENT 16
111 #define BR24_NBITS_DISPLACEMENT 26
113 #define X86_64_RIP_RELATIVE_LIMIT 0x80000000UL
115 /*******************************************************************************
117 *******************************************************************************/
118 #if KXLD_USER_OR_I386
119 static boolean_t
generic_reloc_has_pair(u_int _type
)
120 __attribute__((const));
121 static u_int
generic_reloc_get_pair_type(u_int _prev_type
)
122 __attribute__((const));
123 static boolean_t
generic_reloc_has_got(u_int _type
)
124 __attribute__((const));
125 static kern_return_t
generic_process_reloc(const KXLDRelocator
*relocator
,
126 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
127 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
128 kxld_addr_t pair_target
, boolean_t swap
);
129 #endif /* KXLD_USER_OR_I386 */
131 #if KXLD_USER_OR_X86_64
132 static boolean_t
x86_64_reloc_has_pair(u_int _type
)
133 __attribute__((const));
134 static u_int
x86_64_reloc_get_pair_type(u_int _prev_type
)
135 __attribute__((const));
136 static boolean_t
x86_64_reloc_has_got(u_int _type
)
137 __attribute__((const));
138 static kern_return_t
x86_64_process_reloc(const KXLDRelocator
*relocator
,
139 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
140 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
141 kxld_addr_t pair_target
, boolean_t swap
);
142 static kern_return_t
calculate_displacement_x86_64(uint64_t target
,
143 uint64_t adjustment
, int32_t *instr32
);
144 #endif /* KXLD_USER_OR_X86_64 */
147 static boolean_t
arm_reloc_has_pair(u_int _type
)
148 __attribute__((const));
149 static u_int
arm_reloc_get_pair_type(u_int _prev_type
)
150 __attribute__((const));
151 static boolean_t
arm_reloc_has_got(u_int _type
)
152 __attribute__((const));
153 static kern_return_t
arm_process_reloc(const KXLDRelocator
*relocator
,
154 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
155 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
156 kxld_addr_t pair_target
, boolean_t swap
);
157 #endif /* KXLD_USER_OR_ARM */
159 #if KXLD_USER_OR_ARM64
160 static boolean_t
arm64_reloc_has_pair(u_int _type
)
161 __attribute__((const));
162 static u_int
arm64_reloc_get_pair_type(u_int _prev_type
)
163 __attribute__((const));
164 static boolean_t
arm64_reloc_has_got(u_int _type
)
165 __attribute__((const));
166 static kern_return_t
arm64_process_reloc(const KXLDRelocator
*relocator
,
167 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
168 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
169 kxld_addr_t pair_target
, boolean_t swap
);
170 #endif /* KXLD_USER_OR_ARM64 */
172 #if KXLD_USER_OR_ILP32
173 static kxld_addr_t
get_pointer_at_addr_32(const KXLDRelocator
*relocator
,
174 const u_char
*data
, u_long offset
)
175 __attribute__((pure
, nonnull
));
176 #endif /* KXLD_USER_OR_ILP32 */
177 #if KXLD_USER_OR_LP64
178 static kxld_addr_t
get_pointer_at_addr_64(const KXLDRelocator
*relocator
,
179 const u_char
*data
, u_long offset
)
180 __attribute__((pure
, nonnull
));
181 #endif /* KXLD_USER_OR_LP64 */
183 static u_int
count_relocatable_relocs(const KXLDRelocator
*relocator
,
184 const struct relocation_info
*relocs
, u_int nrelocs
)
185 __attribute__((pure
));
187 static kern_return_t
calculate_targets(KXLDRelocator
*relocator
,
188 kxld_addr_t
*_target
, kxld_addr_t
*_pair_target
, const KXLDReloc
*reloc
);
190 static kxld_addr_t
align_raw_function_address(const KXLDRelocator
*relocator
,
193 static kern_return_t
get_target_by_address_lookup(kxld_addr_t
*target
,
194 kxld_addr_t addr
, const KXLDArray
*sectarray
);
196 static kern_return_t
check_for_direct_pure_virtual_call(
197 const KXLDRelocator
*relocator
, u_long offset
);
200 static u_long
get_macho_data_size_for_array(const KXLDArray
*relocs
);
202 static kern_return_t
export_macho_for_array(const KXLDRelocator
*relocator
,
203 const KXLDArray
*relocs
, struct relocation_info
**dstp
);
204 #endif /* KXLD_PIC_KEXTS */
206 /*******************************************************************************
207 *******************************************************************************/
209 kxld_relocator_init(KXLDRelocator
*relocator
, u_char
*file
,
210 const KXLDSymtab
*symtab
, const KXLDArray
*sectarray
, cpu_type_t cputype
,
211 cpu_subtype_t cpusubtype __unused
, boolean_t swap
)
213 kern_return_t rval
= KERN_FAILURE
;
218 #if KXLD_USER_OR_I386
220 relocator
->reloc_has_pair
= generic_reloc_has_pair
;
221 relocator
->reloc_get_pair_type
= generic_reloc_get_pair_type
;
222 relocator
->reloc_has_got
= generic_reloc_has_got
;
223 relocator
->process_reloc
= generic_process_reloc
;
224 relocator
->function_align
= 0;
225 relocator
->is_32_bit
= TRUE
;
226 relocator
->may_scatter
= TRUE
;
228 #endif /* KXLD_USER_OR_I386 */
229 #if KXLD_USER_OR_X86_64
230 case CPU_TYPE_X86_64
:
231 relocator
->reloc_has_pair
= x86_64_reloc_has_pair
;
232 relocator
->reloc_get_pair_type
= x86_64_reloc_get_pair_type
;
233 relocator
->reloc_has_got
= x86_64_reloc_has_got
;
234 relocator
->process_reloc
= x86_64_process_reloc
;
235 relocator
->function_align
= 0;
236 relocator
->is_32_bit
= FALSE
;
237 relocator
->may_scatter
= FALSE
;
239 #endif /* KXLD_USER_OR_X86_64 */
242 relocator
->reloc_has_pair
= arm_reloc_has_pair
;
243 relocator
->reloc_get_pair_type
= arm_reloc_get_pair_type
;
244 relocator
->reloc_has_got
= arm_reloc_has_got
;
245 relocator
->process_reloc
= arm_process_reloc
;
246 relocator
->function_align
= 1;
247 relocator
->is_32_bit
= TRUE
;
248 relocator
->may_scatter
= FALSE
;
250 #endif /* KXLD_USER_OR_ARM */
251 #if KXLD_USER_OR_ARM64
253 relocator
->reloc_has_pair
= arm64_reloc_has_pair
;
254 relocator
->reloc_get_pair_type
= arm64_reloc_get_pair_type
;
255 relocator
->reloc_has_got
= arm64_reloc_has_got
;
256 relocator
->process_reloc
= arm64_process_reloc
;
257 relocator
->function_align
= 0;
258 relocator
->is_32_bit
= FALSE
;
259 relocator
->may_scatter
= FALSE
;
261 #endif /* KXLD_USER_OR_ARM64 */
265 kxld_log(kKxldLogLinking
, kKxldLogErr
,
266 kKxldLogArchNotSupported
, cputype
);
270 relocator
->file
= file
;
271 relocator
->symtab
= symtab
;
272 relocator
->sectarray
= sectarray
;
273 relocator
->is_32_bit
= kxld_is_32_bit(cputype
);
274 relocator
->swap
= swap
;
282 /*******************************************************************************
283 *******************************************************************************/
285 kxld_reloc_create_macho(KXLDArray
*relocarray
, const KXLDRelocator
*relocator
,
286 const struct relocation_info
*srcs
, u_int nsrcs
)
288 kern_return_t rval
= KERN_FAILURE
;
289 KXLDReloc
*reloc
= NULL
;
291 const struct relocation_info
*src
= NULL
;
292 const struct scattered_relocation_info
*scatsrc
= NULL
;
294 u_int reloc_index
= 0;
299 /* If there are no relocation entries, just return */
305 /* Count the number of non-pair relocs */
306 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
)) {
329 /* Pull out the data from the relocation entries. The target_type
330 * depends on the r_extern bit:
331 * Scattered -> Section Lookup by Address
332 * Local (not extern) -> Section by Index
333 * Extern -> Symbolnum by Index
335 reloc
= kxld_array_get_item(relocarray
, reloc_index
++);
336 if (relocator
->may_scatter
&& (src
->r_address
& R_SCATTERED
)) {
337 reloc
->address
= scatsrc
->r_address
;
338 reloc
->pcrel
= scatsrc
->r_pcrel
;
339 reloc
->length
= scatsrc
->r_length
;
340 reloc
->reloc_type
= scatsrc
->r_type
;
341 reloc
->target
= scatsrc
->r_value
;
342 reloc
->target_type
= KXLD_TARGET_LOOKUP
;
344 reloc
->address
= src
->r_address
;
345 reloc
->pcrel
= src
->r_pcrel
;
346 reloc
->length
= src
->r_length
;
347 reloc
->reloc_type
= src
->r_type
;
348 reloc
->target
= src
->r_symbolnum
;
350 if (0 == src
->r_extern
) {
351 reloc
->target_type
= KXLD_TARGET_SECTNUM
;
354 reloc
->target_type
= KXLD_TARGET_SYMBOLNUM
;
358 /* Find the pair entry if it exists */
360 if (relocator
->reloc_has_pair(reloc
->reloc_type
)) {
362 require_action(i
< nsrcs
, finish
, rval
= KERN_FAILURE
);
365 scatsrc
= (const struct scattered_relocation_info
*) src
;
367 if (relocator
->may_scatter
&& (src
->r_address
& R_SCATTERED
)) {
368 require_action(relocator
->reloc_get_pair_type(
369 reloc
->reloc_type
) == scatsrc
->r_type
,
370 finish
, rval
= KERN_FAILURE
);
371 reloc
->pair_address
= scatsrc
->r_address
;
372 reloc
->pair_target
= scatsrc
->r_value
;
373 reloc
->pair_target_type
= KXLD_TARGET_LOOKUP
;
375 require_action(relocator
->reloc_get_pair_type(
376 reloc
->reloc_type
) == scatsrc
->r_type
,
377 finish
, rval
= KERN_FAILURE
);
378 reloc
->pair_address
= scatsrc
->r_address
;
380 reloc
->pair_target
= src
->r_symbolnum
;
381 reloc
->pair_target_type
= KXLD_TARGET_SYMBOLNUM
;
383 reloc
->pair_target
= src
->r_address
;
384 reloc
->pair_target_type
= KXLD_TARGET_VALUE
;
388 reloc
->pair_target
= 0;
389 if (relocator
->reloc_has_got(reloc
->reloc_type
)) {
390 reloc
->pair_target_type
= KXLD_TARGET_GOT
;
392 reloc
->pair_target_type
= KXLD_TARGET_NONE
;
404 /*******************************************************************************
405 * Relocatable relocs :
406 * 1) Are not _PAIR_ relocs
407 * 2) Don't reference N_ABS symbols
408 *******************************************************************************/
410 count_relocatable_relocs(const KXLDRelocator
*relocator
,
411 const struct relocation_info
*relocs
, u_int nrelocs
)
413 u_int num_nonpair_relocs
= 0;
415 const struct relocation_info
*reloc
= NULL
;
416 const struct scattered_relocation_info
*sreloc
= NULL
;
421 /* Loop over all of the relocation entries */
423 num_nonpair_relocs
= 1;
424 for (i
= 1; i
< nrelocs
; ++i
) {
427 if (reloc
->r_address
& R_SCATTERED
) {
428 /* A scattered relocation entry is relocatable as long as it's not a
431 sreloc
= (const struct scattered_relocation_info
*) reloc
;
433 num_nonpair_relocs
+=
434 !relocator
->reloc_has_pair(sreloc
->r_type
);
436 /* A normal relocation entry is relocatable if it is not a pair and
437 * if it is not a section-based relocation for an absolute symbol.
439 num_nonpair_relocs
+=
440 !(relocator
->reloc_has_pair(reloc
->r_type
)
441 || (0 == reloc
->r_extern
&& R_ABS
== reloc
->r_symbolnum
));
445 return num_nonpair_relocs
;
448 /*******************************************************************************
449 *******************************************************************************/
451 kxld_relocator_clear(KXLDRelocator
*relocator
)
453 bzero(relocator
, sizeof(*relocator
));
456 /*******************************************************************************
457 *******************************************************************************/
459 kxld_relocator_has_pair(const KXLDRelocator
*relocator
, u_int r_type
)
463 return relocator
->reloc_has_pair(r_type
);
466 /*******************************************************************************
467 *******************************************************************************/
469 kxld_relocator_get_pair_type(const KXLDRelocator
*relocator
,
474 return relocator
->reloc_get_pair_type(prev_r_type
);
477 /*******************************************************************************
478 *******************************************************************************/
480 kxld_relocator_has_got(const KXLDRelocator
*relocator
, u_int r_type
)
484 return relocator
->reloc_has_got(r_type
);
487 /*******************************************************************************
488 *******************************************************************************/
490 kxld_reloc_get_symbol(const KXLDRelocator
*relocator
, const KXLDReloc
*reloc
,
494 kxld_addr_t value
= 0;
498 switch (reloc
->target_type
) {
499 case KXLD_TARGET_SYMBOLNUM
:
500 sym
= kxld_symtab_get_symbol_by_index(relocator
->symtab
, reloc
->target
);
502 case KXLD_TARGET_SECTNUM
:
504 value
= kxld_relocator_get_pointer_at_addr(relocator
, data
,
506 sym
= kxld_symtab_get_cxx_symbol_by_value(relocator
->symtab
, value
);
517 /*******************************************************************************
518 *******************************************************************************/
520 kxld_reloc_get_reloc_index_by_offset(const KXLDArray
*relocs
,
521 kxld_size_t offset
, u_int
*idx
)
523 kern_return_t rval
= KERN_FAILURE
;
524 KXLDReloc
*reloc
= NULL
;
527 for (i
= 0; i
< relocs
->nitems
; ++i
) {
528 reloc
= kxld_array_get_item(relocs
, i
);
529 if (reloc
->address
== offset
) {
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
);
560 reloc
= kxld_array_get_item(relocs
, i
);
567 /*******************************************************************************
568 *******************************************************************************/
570 kxld_reloc_get_macho_header_size()
572 return sizeof(struct dysymtab_command
);
575 /*******************************************************************************
576 *******************************************************************************/
578 kxld_reloc_get_macho_data_size(
579 const KXLDArray
*locrelocs
,
580 const KXLDArray
*extrelocs
)
584 rval
+= get_macho_data_size_for_array(locrelocs
);
585 rval
+= get_macho_data_size_for_array(extrelocs
);
590 /*******************************************************************************
591 *******************************************************************************/
593 kxld_reloc_export_macho(const KXLDRelocator
*relocator
,
594 const KXLDArray
*locrelocs
, const KXLDArray
*extrelocs
,
595 u_char
*buf
, u_long
*header_offset
, u_long header_size
,
596 u_long
*data_offset
, u_long size
)
598 kern_return_t rval
= KERN_FAILURE
;
599 struct dysymtab_command
*dysymtabhdr
= NULL
;
600 struct relocation_info
*start
= NULL
;
601 struct relocation_info
*dst
= NULL
;
603 u_long data_size
= 0;
608 check(header_offset
);
611 require_action(sizeof(*dysymtabhdr
) <= header_size
- *header_offset
, finish
, rval
= KERN_FAILURE
);
612 dysymtabhdr
= (struct dysymtab_command
*) ((void *) (buf
+ *header_offset
));
613 *header_offset
+= sizeof(*dysymtabhdr
);
615 data_size
= kxld_reloc_get_macho_data_size(locrelocs
, extrelocs
);
616 require_action((*data_offset
+ data_size
) <= size
, finish
, rval
= KERN_FAILURE
);
618 start
= dst
= (struct relocation_info
*) ((void *) (buf
+ *data_offset
));
620 if (kaslr_offsets
== NULL
) {
621 kaslr_offsets_index
= 0;
622 kaslr_offsets_count
= locrelocs
->nitems
+ extrelocs
->nitems
;
623 kaslr_offsets
= (uint32_t *)calloc(kaslr_offsets_count
, sizeof(*kaslr_offsets
));
626 // copies the reloc data into the __LINKEDIT segment
627 // data_offset is the new value for locreloff
628 rval
= export_macho_for_array(relocator
, locrelocs
, &dst
);
629 require_noerr(rval
, finish
);
631 rval
= export_macho_for_array(relocator
, extrelocs
, &dst
);
632 require_noerr(rval
, finish
);
636 memset(dysymtabhdr
, 0, sizeof(*dysymtabhdr
));
637 dysymtabhdr
->cmd
= LC_DYSYMTAB
;
638 dysymtabhdr
->cmdsize
= (uint32_t) sizeof(*dysymtabhdr
);
639 dysymtabhdr
->locreloff
= (uint32_t) *data_offset
;
640 dysymtabhdr
->nlocrel
= (uint32_t) count
;
642 *data_offset
+= count
* sizeof(struct relocation_info
);
644 #if SPLIT_KEXTS_DEBUG
645 kxld_log(kKxldLogLinking
, kKxldLogErr
,
646 "%p >>> Start of dysymtabhdr (size %lu) <%s> ",
647 (void *) dysymtabhdr
,
648 sizeof(*dysymtabhdr
),
650 kxld_log(kKxldLogLinking
, kKxldLogErr
,
651 "%p <<< End of dysymtabhdr <%s> ",
652 (void *) ((u_char
*)dysymtabhdr
+ sizeof(*dysymtabhdr
)),
655 kxld_log(kKxldLogLinking
, kKxldLogErr
,
656 "dysymtabhdr at %p: cmdsize %u indirectsymoff %u nindirectsyms %u extreloff %u nextrel %u locreloff %u nlocrel %u <%s>",
657 (void *) dysymtabhdr
,
658 dysymtabhdr
->cmdsize
,
659 dysymtabhdr
->indirectsymoff
,
660 dysymtabhdr
->nindirectsyms
,
661 dysymtabhdr
->extreloff
,
662 dysymtabhdr
->nextrel
,
663 dysymtabhdr
->locreloff
,
664 dysymtabhdr
->nlocrel
,
672 #endif /* KXLD_PIC_KEXTS */
674 /*******************************************************************************
675 *******************************************************************************/
677 kxld_relocator_get_pointer_at_addr(const KXLDRelocator
*relocator
,
678 const u_char
*data
, u_long offset
)
682 KXLD_3264_FUNC(relocator
->is_32_bit
, value
,
683 get_pointer_at_addr_32
, get_pointer_at_addr_64
,
684 relocator
, data
, offset
);
689 #if KXLD_USER_OR_ILP32
690 /*******************************************************************************
691 *******************************************************************************/
693 get_pointer_at_addr_32(const KXLDRelocator
*relocator
,
694 const u_char
*data
, u_long offset
)
700 addr
= *(const uint32_t *) ((const void *) (data
+ offset
));
702 if (relocator
->swap
) {
703 addr
= OSSwapInt32(addr
);
707 return align_raw_function_address(relocator
, addr
);
709 #endif /* KXLD_USER_OR_ILP32 */
711 #if KXLD_USER_OR_LP64
712 /*******************************************************************************
713 *******************************************************************************/
715 get_pointer_at_addr_64(const KXLDRelocator
*relocator
,
716 const u_char
*data
, u_long offset
)
722 addr
= *(const uint64_t *) ((const void *) (data
+ offset
));
725 if (relocator
->swap
) {
726 addr
= OSSwapInt64(addr
);
730 return align_raw_function_address(relocator
, addr
);
732 #endif /* KXLD_USER_OR_LP64 */
734 /*******************************************************************************
735 *******************************************************************************/
737 kxld_relocator_set_vtables(KXLDRelocator
*relocator
, const KXLDDict
*vtables
)
739 relocator
->vtables
= vtables
;
742 /*******************************************************************************
743 * When we're inspecting the raw binary and not the symbol table, value may
744 * hold a THUMB address (with bit 0 set to 1) but the index will have the real
745 * address (bit 0 set to 0). So if bit 0 is set here, we clear it. This only
746 * impacts ARM for now, but it's implemented as a generic function alignment
748 *******************************************************************************/
750 align_raw_function_address(const KXLDRelocator
*relocator
, kxld_addr_t value
)
752 if (relocator
->function_align
) {
753 value
&= ~((1ULL << relocator
->function_align
) - 1);
759 /*******************************************************************************
760 *******************************************************************************/
762 kxld_relocator_process_sect_reloc(KXLDRelocator
*relocator
,
763 const KXLDReloc
*reloc
, const KXLDSect
*sect
)
765 kern_return_t rval
= KERN_FAILURE
;
766 u_char
*instruction
= NULL
;
767 kxld_addr_t target
= 0;
768 kxld_addr_t pair_target
= 0;
769 kxld_addr_t base_pc
= 0;
770 kxld_addr_t link_pc
= 0;
771 kxld_addr_t link_disp
= 0;
777 /* Find the instruction */
779 instruction
= sect
->data
+ reloc
->address
;
781 /* Calculate the target */
783 rval
= calculate_targets(relocator
, &target
, &pair_target
, reloc
);
784 require_noerr(rval
, finish
);
786 base_pc
= reloc
->address
;
787 link_pc
= base_pc
+ sect
->link_addr
;
788 link_disp
= sect
->link_addr
- sect
->base_addr
;
792 rval
= relocator
->process_reloc(relocator
, instruction
, reloc
->length
,
793 reloc
->pcrel
, base_pc
, link_pc
, link_disp
, reloc
->reloc_type
, target
,
794 pair_target
, relocator
->swap
);
795 require_noerr(rval
, finish
);
799 relocator
->current_vtable
= NULL
;
806 /*******************************************************************************
807 *******************************************************************************/
809 kxld_reloc_update_symindex(KXLDReloc
*reloc
, u_int symindex
)
811 kern_return_t rval
= KERN_FAILURE
;
813 require_action(reloc
->target_type
== KXLD_TARGET_SYMBOLNUM
,
814 finish
, rval
= KERN_FAILURE
);
816 reloc
->target
= symindex
;
824 /*******************************************************************************
825 *******************************************************************************/
827 kxld_relocator_process_table_reloc(KXLDRelocator
*relocator
,
828 const KXLDReloc
*reloc
,
830 kxld_addr_t link_addr
)
832 kern_return_t rval
= KERN_FAILURE
;
833 u_char
*instruction
= NULL
;
834 kxld_addr_t target
= 0;
835 kxld_addr_t pair_target
= 0;
836 kxld_addr_t base_pc
= 0;
837 kxld_addr_t link_pc
= 0;
843 /* Find the instruction in original kext file we are trying to link */
845 offset
= (u_long
)(seg
->fileoff
+ (reloc
->address
- seg
->base_addr
));
846 instruction
= relocator
->file
+ offset
;
848 /* Calculate the target */
850 rval
= calculate_targets(relocator
, &target
, &pair_target
, reloc
);
851 require_noerr(rval
, finish
);
853 base_pc
= reloc
->address
;
854 link_pc
= base_pc
+ link_addr
;
855 if (kxld_seg_is_split_seg(seg
)) {
856 // link_pc for split segment special case, do not add in the base_pc
862 rval
= relocator
->process_reloc(relocator
, instruction
, reloc
->length
,
863 reloc
->pcrel
, base_pc
, link_pc
, link_addr
, reloc
->reloc_type
, target
,
864 pair_target
, relocator
->swap
);
865 require_noerr(rval
, finish
);
869 relocator
->current_vtable
= NULL
;
876 /*******************************************************************************
877 *******************************************************************************/
879 calculate_targets(KXLDRelocator
*relocator
, kxld_addr_t
*_target
,
880 kxld_addr_t
*_pair_target
, const KXLDReloc
*reloc
)
882 kern_return_t rval
= KERN_FAILURE
;
883 const KXLDSect
*sect
= NULL
;
884 const KXLDSym
*sym
= NULL
;
885 kxld_addr_t target
= 0;
886 kxld_addr_t pair_target
= 0;
887 char *demangled_name
= NULL
;
888 size_t demangled_length
= 0;
895 /* Find the target based on the lookup type */
897 switch (reloc
->target_type
) {
898 case KXLD_TARGET_LOOKUP
:
899 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
900 reloc
->pair_target_type
== KXLD_TARGET_LOOKUP
||
901 reloc
->pair_target_type
== KXLD_TARGET_VALUE
,
902 finish
, rval
= KERN_FAILURE
);
904 rval
= get_target_by_address_lookup(&target
, reloc
->target
,
905 relocator
->sectarray
);
906 require_noerr(rval
, finish
);
908 if (reloc
->pair_target_type
== KXLD_TARGET_LOOKUP
) {
909 rval
= get_target_by_address_lookup(&pair_target
,
910 reloc
->pair_target
, relocator
->sectarray
);
911 require_noerr(rval
, finish
);
912 } else if (reloc
->pair_target_type
== KXLD_TARGET_VALUE
) {
913 pair_target
= reloc
->pair_target
;
916 case KXLD_TARGET_SECTNUM
:
917 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
918 reloc
->pair_target_type
== KXLD_TARGET_VALUE
,
919 finish
, rval
= KERN_FAILURE
);
921 /* Get the target's section by section number */
922 sect
= kxld_array_get_item(relocator
->sectarray
, reloc
->target
);
923 require_action(sect
, finish
, rval
= KERN_FAILURE
);
925 /* target is the change in the section's address */
926 target
= sect
->link_addr
- sect
->base_addr
;
928 if (reloc
->pair_target_type
) {
929 pair_target
= reloc
->pair_target
;
931 /* x86_64 needs to know when we have a non-external relocation,
932 * so we hack that information in here.
937 case KXLD_TARGET_SYMBOLNUM
:
938 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
939 reloc
->pair_target_type
== KXLD_TARGET_GOT
||
940 reloc
->pair_target_type
== KXLD_TARGET_SYMBOLNUM
||
941 reloc
->pair_target_type
== KXLD_TARGET_VALUE
, finish
,
942 rval
= KERN_FAILURE
);
944 /* Get the target's symbol by symbol number */
945 sym
= kxld_symtab_get_symbol_by_index(relocator
->symtab
, reloc
->target
);
946 require_action(sym
, finish
, rval
= KERN_FAILURE
);
948 /* If this symbol is a padslot that has already been replaced, then the
949 * only way a relocation entry can still reference it is if there is a
950 * vtable that has not been patched. The vtable patcher uses the
951 * MetaClass structure to find classes for patching, so an unpatched
952 * vtable means that there is an OSObject-dervied class that is missing
953 * its OSDeclare/OSDefine macros.
955 if (kxld_sym_is_padslot(sym
) && kxld_sym_is_replaced(sym
)) {
956 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocatingPatchedSym
,
957 kxld_demangle(sym
->name
, &demangled_name
, &demangled_length
));
960 target
= sym
->link_addr
;
962 if (kxld_sym_is_vtable(sym
)) {
963 relocator
->current_vtable
= kxld_dict_find(relocator
->vtables
, sym
->name
);
966 /* Some relocation types need the GOT entry address instead of the
967 * symbol's actual address. These types don't have pair relocation
968 * entries, so we store the GOT entry address as the pair target.
970 if (reloc
->pair_target_type
== KXLD_TARGET_VALUE
) {
971 pair_target
= reloc
->pair_target
;
972 } else if (reloc
->pair_target_type
== KXLD_TARGET_SYMBOLNUM
) {
973 sym
= kxld_symtab_get_symbol_by_index(relocator
->symtab
,
975 require_action(sym
, finish
, rval
= KERN_FAILURE
);
976 pair_target
= sym
->link_addr
;
977 } else if (reloc
->pair_target_type
== KXLD_TARGET_GOT
) {
978 pair_target
= sym
->got_addr
;
987 *_pair_target
= pair_target
;
991 if (demangled_name
) {
992 kxld_free(demangled_name
, demangled_length
);
997 /*******************************************************************************
998 *******************************************************************************/
1000 get_target_by_address_lookup(kxld_addr_t
*target
, kxld_addr_t addr
,
1001 const KXLDArray
*sectarray
)
1003 kern_return_t rval
= KERN_FAILURE
;
1004 const KXLDSect
*sect
= NULL
;
1005 kxld_addr_t start
= 0;
1006 kxld_addr_t end
= 0;
1013 for (i
= 0; i
< sectarray
->nitems
; ++i
) {
1014 sect
= kxld_array_get_item(sectarray
, i
);
1015 start
= sect
->base_addr
;
1016 end
= start
+ sect
->size
;
1018 if (start
<= addr
&& addr
< end
) {
1024 require_action(sect
, finish
, rval
= KERN_FAILURE
);
1026 *target
= sect
->link_addr
- sect
->base_addr
;
1027 rval
= KERN_SUCCESS
;
1033 /*******************************************************************************
1034 *******************************************************************************/
1035 static kern_return_t
1036 check_for_direct_pure_virtual_call(const KXLDRelocator
*relocator
, u_long offset
)
1038 kern_return_t rval
= KERN_FAILURE
;
1039 const KXLDVTableEntry
*entry
= NULL
;
1041 if (relocator
->current_vtable
) {
1042 entry
= kxld_vtable_get_entry_for_offset(relocator
->current_vtable
,
1043 offset
, relocator
->is_32_bit
);
1044 require_action(!entry
|| !entry
->patched
.name
||
1045 !kxld_sym_name_is_pure_virtual(entry
->patched
.name
),
1046 finish
, rval
= KERN_FAILURE
;
1047 kxld_log(kKxldLogLinking
, kKxldLogErr
,
1048 kKxldLogDirectPureVirtualCall
));
1051 rval
= KERN_SUCCESS
;
1057 /*******************************************************************************
1058 *******************************************************************************/
1060 get_macho_data_size_for_array(const KXLDArray
*relocs
)
1062 const KXLDReloc
*reloc
= NULL
;
1068 for (i
= 0; i
< relocs
->nitems
; ++i
) {
1069 reloc
= kxld_array_get_item(relocs
, i
);
1070 if (!reloc
->pcrel
) {
1071 size
+= sizeof(struct relocation_info
);
1072 if (reloc
->pair_target_type
!= KXLD_TARGET_NONE
) {
1073 size
+= sizeof(struct relocation_info
);
1081 /*******************************************************************************
1082 *******************************************************************************/
1083 static kern_return_t
1084 export_macho_for_array(const KXLDRelocator
*relocator
,
1085 const KXLDArray
*relocs
, struct relocation_info
**dstp
)
1087 kern_return_t rval
= KERN_FAILURE
;
1088 const KXLDReloc
*reloc
= NULL
;
1089 struct relocation_info
*dst
= NULL
;
1090 struct scattered_relocation_info
*scatdst
= NULL
;
1095 for (i
= 0; i
< relocs
->nitems
; ++i
) {
1096 reloc
= kxld_array_get_item(relocs
, i
);
1097 scatdst
= (struct scattered_relocation_info
*) dst
;
1103 switch (reloc
->target_type
) {
1104 case KXLD_TARGET_LOOKUP
:
1105 if (kaslr_offsets
) {
1106 if (kaslr_offsets_index
>= kaslr_offsets_count
) {
1107 kxld_log(kKxldLogLinking
, kKxldLogErr
,
1108 "kaslr_offsets overflow %d > %d <%s> ",
1109 kaslr_offsets_index
, kaslr_offsets_count
,
1113 // reloc->address is really an offset from the start of the kext
1114 *(kaslr_offsets
+ kaslr_offsets_index
++) = reloc
->address
;
1116 scatdst
->r_address
= reloc
->address
;
1117 scatdst
->r_pcrel
= reloc
->pcrel
;
1118 scatdst
->r_length
= reloc
->length
;
1119 scatdst
->r_type
= reloc
->reloc_type
;
1120 scatdst
->r_value
= reloc
->target
;
1121 scatdst
->r_scattered
= 1;
1123 case KXLD_TARGET_SECTNUM
:
1124 if (kaslr_offsets
) {
1125 if (kaslr_offsets_index
>= kaslr_offsets_count
) {
1126 kxld_log(kKxldLogLinking
, kKxldLogErr
,
1127 "kaslr_offsets overflow <%s> ", __func__
);
1130 // reloc->address is really an offset from the start of the kext
1131 *(kaslr_offsets
+ kaslr_offsets_index
++) = reloc
->address
;
1133 dst
->r_address
= reloc
->address
;
1134 dst
->r_pcrel
= reloc
->pcrel
;
1135 dst
->r_length
= reloc
->length
;
1136 dst
->r_type
= reloc
->reloc_type
;
1137 dst
->r_symbolnum
= reloc
->target
+ 1;
1140 case KXLD_TARGET_SYMBOLNUM
:
1141 /* Assume that everything will be slid together; otherwise,
1142 * there is no sensible value for the section number.
1144 if (kaslr_offsets
) {
1145 if (kaslr_offsets_index
>= kaslr_offsets_count
) {
1146 kxld_log(kKxldLogLinking
, kKxldLogErr
,
1147 "kaslr_offsets overflow <%s> ", __func__
);
1150 // reloc->address is really an offset from the start of the kext
1151 *(kaslr_offsets
+ kaslr_offsets_index
++) = reloc
->address
;
1153 dst
->r_address
= reloc
->address
;
1154 dst
->r_pcrel
= reloc
->pcrel
;
1155 dst
->r_length
= reloc
->length
;
1156 dst
->r_type
= reloc
->reloc_type
;
1157 dst
->r_symbolnum
= 1;
1161 rval
= KERN_FAILURE
;
1167 if (reloc
->pair_target_type
!= KXLD_TARGET_NONE
) {
1169 require_action(i
< relocs
->nitems
, finish
, rval
= KERN_FAILURE
);
1170 scatdst
= (struct scattered_relocation_info
*) dst
;
1171 switch (reloc
->pair_target_type
) {
1172 case KXLD_TARGET_LOOKUP
:
1173 scatdst
->r_address
= reloc
->pair_address
;
1174 scatdst
->r_pcrel
= reloc
->pcrel
;
1175 scatdst
->r_length
= reloc
->length
;
1176 scatdst
->r_type
= relocator
->reloc_get_pair_type(reloc
->reloc_type
);
1177 scatdst
->r_value
= reloc
->pair_target
;
1178 scatdst
->r_scattered
= 1;
1180 case KXLD_TARGET_SECTNUM
:
1181 dst
->r_address
= reloc
->pair_address
;
1182 dst
->r_pcrel
= reloc
->pcrel
;
1183 dst
->r_length
= reloc
->length
;
1184 dst
->r_type
= relocator
->reloc_get_pair_type(reloc
->reloc_type
);
1185 dst
->r_symbolnum
= reloc
->pair_target
+ 1;
1188 case KXLD_TARGET_SYMBOLNUM
:
1189 dst
->r_address
= reloc
->pair_address
;
1190 dst
->r_pcrel
= reloc
->pcrel
;
1191 dst
->r_length
= reloc
->length
;
1192 dst
->r_type
= relocator
->reloc_get_pair_type(reloc
->reloc_type
);
1193 dst
->r_symbolnum
= 1;
1197 rval
= KERN_FAILURE
;
1204 rval
= KERN_SUCCESS
;
1209 #endif /* KXLD_PIC_KEXTS */
1211 #if KXLD_USER_OR_I386
1212 /*******************************************************************************
1213 *******************************************************************************/
1215 generic_reloc_has_pair(u_int _type
)
1217 enum reloc_type_generic type
= _type
;
1219 return type
== GENERIC_RELOC_SECTDIFF
||
1220 type
== GENERIC_RELOC_LOCAL_SECTDIFF
;
1223 /*******************************************************************************
1224 *******************************************************************************/
1226 generic_reloc_get_pair_type(u_int _prev_type __unused
)
1228 return GENERIC_RELOC_PAIR
;
1231 /*******************************************************************************
1232 *******************************************************************************/
1234 generic_reloc_has_got(u_int _type __unused
)
1239 /*******************************************************************************
1240 *******************************************************************************/
1241 static kern_return_t
1242 generic_process_reloc(const KXLDRelocator
*relocator
, u_char
*instruction
,
1243 u_int length
, u_int pcrel
, kxld_addr_t _base_pc
, kxld_addr_t _link_pc
,
1244 kxld_addr_t _link_disp __unused
, u_int _type
, kxld_addr_t _target
,
1245 kxld_addr_t _pair_target
, boolean_t swap __unused
)
1247 kern_return_t rval
= KERN_FAILURE
;
1248 uint32_t base_pc
= (uint32_t) _base_pc
;
1249 uint32_t link_pc
= (uint32_t) _link_pc
;
1250 uint32_t *instr_addr
= NULL
;
1251 uint32_t instr_data
= 0;
1252 uint32_t target
= (uint32_t) _target
;
1253 uint32_t pair_target
= (uint32_t) _pair_target
;
1254 enum reloc_type_generic type
= _type
;
1257 require_action(length
== 2, finish
, rval
= KERN_FAILURE
);
1260 target
= target
+ base_pc
- link_pc
;
1263 instr_addr
= (uint32_t *) ((void *) instruction
);
1264 instr_data
= *instr_addr
;
1268 instr_data
= OSSwapInt32(instr_data
);
1272 rval
= check_for_direct_pure_virtual_call(relocator
, instr_data
);
1273 require_noerr(rval
, finish
);
1276 case GENERIC_RELOC_VANILLA
:
1277 instr_data
+= target
;
1279 case GENERIC_RELOC_SECTDIFF
:
1280 case GENERIC_RELOC_LOCAL_SECTDIFF
:
1281 instr_data
= instr_data
+ target
- pair_target
;
1283 case GENERIC_RELOC_PB_LA_PTR
:
1284 rval
= KERN_FAILURE
;
1286 case GENERIC_RELOC_PAIR
:
1288 rval
= KERN_FAILURE
;
1294 instr_data
= OSSwapInt32(instr_data
);
1298 *instr_addr
= instr_data
;
1300 rval
= KERN_SUCCESS
;
1305 #endif /* KXLD_USER_OR_I386 */
1307 #if KXLD_USER_OR_X86_64
1308 /*******************************************************************************
1309 *******************************************************************************/
1311 x86_64_reloc_has_pair(u_int _type
)
1313 enum reloc_type_x86_64 type
= _type
;
1315 return type
== X86_64_RELOC_SUBTRACTOR
;
1318 /*******************************************************************************
1319 *******************************************************************************/
1321 x86_64_reloc_get_pair_type(u_int _prev_type __unused
)
1323 return X86_64_RELOC_UNSIGNED
;
1326 /*******************************************************************************
1327 *******************************************************************************/
1329 x86_64_reloc_has_got(u_int _type
)
1331 enum reloc_type_x86_64 type
= _type
;
1333 return type
== X86_64_RELOC_GOT_LOAD
|| type
== X86_64_RELOC_GOT
;
1336 /*******************************************************************************
1337 *******************************************************************************/
1338 static kern_return_t
1339 x86_64_process_reloc(const KXLDRelocator
*relocator __unused
, u_char
*instruction
,
1340 u_int length
, u_int pcrel
, kxld_addr_t _base_pc __unused
,
1341 kxld_addr_t _link_pc
, kxld_addr_t _link_disp
, u_int _type
,
1342 kxld_addr_t _target
, kxld_addr_t _pair_target
, boolean_t swap __unused
)
1344 kern_return_t rval
= KERN_FAILURE
;
1345 enum reloc_type_x86_64 type
= _type
;
1346 int32_t *instr32p
= NULL
;
1347 int32_t instr32
= 0;
1348 uint64_t *instr64p
= NULL
;
1349 uint64_t instr64
= 0;
1350 uint64_t target
= _target
;
1351 uint64_t pair_target
= _pair_target
;
1352 uint64_t link_pc
= (uint64_t) _link_pc
;
1353 uint64_t link_disp
= (uint64_t) _link_disp
;
1354 uint64_t adjustment
= 0;
1357 require_action(length
== 2 || length
== 3,
1358 finish
, rval
= KERN_FAILURE
);
1361 instr32p
= (int32_t *) ((void *) instruction
);
1362 instr32
= *instr32p
;
1366 instr32
= OSSwapInt32(instr32
);
1370 rval
= check_for_direct_pure_virtual_call(relocator
, instr32
);
1371 require_noerr(rval
, finish
);
1373 /* There are a number of different small adjustments for pc-relative
1374 * relocation entries. The general case is to subtract the size of the
1375 * relocation (represented by the length parameter), and it applies to
1376 * the GOT types and external SIGNED types. The non-external signed types
1377 * have a different adjustment corresponding to the specific type.
1380 case X86_64_RELOC_SIGNED
:
1386 case X86_64_RELOC_SIGNED_1
:
1392 case X86_64_RELOC_SIGNED_2
:
1398 case X86_64_RELOC_SIGNED_4
:
1404 case X86_64_RELOC_BRANCH
:
1405 case X86_64_RELOC_GOT
:
1406 case X86_64_RELOC_GOT_LOAD
:
1407 adjustment
= (1 << length
);
1413 /* Perform the actual relocation. All of the 32-bit relocations are
1414 * pc-relative except for SUBTRACTOR, so a good chunk of the logic is
1415 * stuck in calculate_displacement_x86_64. The signed relocations are
1416 * a special case, because when they are non-external, the instruction
1417 * already contains the pre-relocation displacement, so we only need to
1418 * find the difference between how far the PC was relocated, and how
1419 * far the target is relocated. Since the target variable already
1420 * contains the difference between the target's base and link
1421 * addresses, we add the difference between the PC's base and link
1422 * addresses to the adjustment variable. This will yield the
1423 * appropriate displacement in calculate_displacement.
1426 case X86_64_RELOC_BRANCH
:
1427 require_action(pcrel
, finish
, rval
= KERN_FAILURE
);
1428 adjustment
+= link_pc
;
1430 case X86_64_RELOC_SIGNED
:
1431 case X86_64_RELOC_SIGNED_1
:
1432 case X86_64_RELOC_SIGNED_2
:
1433 case X86_64_RELOC_SIGNED_4
:
1434 require_action(pcrel
, finish
, rval
= KERN_FAILURE
);
1435 adjustment
+= (pair_target
) ? (link_disp
) : (link_pc
);
1437 case X86_64_RELOC_GOT
:
1438 case X86_64_RELOC_GOT_LOAD
:
1439 require_action(pcrel
, finish
, rval
= KERN_FAILURE
);
1440 adjustment
+= link_pc
;
1441 target
= pair_target
;
1443 case X86_64_RELOC_SUBTRACTOR
:
1444 require_action(!pcrel
, finish
, rval
= KERN_FAILURE
);
1445 instr32
= (int32_t) (target
- pair_target
);
1447 case X86_64_RELOC_UNSIGNED
:
1449 rval
= KERN_FAILURE
;
1453 /* Call calculate_displacement for the pc-relative relocations */
1455 rval
= calculate_displacement_x86_64(target
, adjustment
, &instr32
);
1456 require_noerr(rval
, finish
);
1461 instr32
= OSSwapInt32(instr32
);
1465 *instr32p
= instr32
;
1467 instr64p
= (uint64_t *) ((void *) instruction
);
1468 instr64
= *instr64p
;
1472 instr64
= OSSwapInt64(instr64
);
1476 rval
= check_for_direct_pure_virtual_call(relocator
, (u_long
) instr64
);
1477 require_noerr(rval
, finish
);
1480 case X86_64_RELOC_UNSIGNED
:
1481 require_action(!pcrel
, finish
, rval
= KERN_FAILURE
);
1485 case X86_64_RELOC_SUBTRACTOR
:
1486 require_action(!pcrel
, finish
, rval
= KERN_FAILURE
);
1488 instr64
= target
- pair_target
;
1490 case X86_64_RELOC_SIGNED_1
:
1491 case X86_64_RELOC_SIGNED_2
:
1492 case X86_64_RELOC_SIGNED_4
:
1493 case X86_64_RELOC_GOT_LOAD
:
1494 case X86_64_RELOC_BRANCH
:
1495 case X86_64_RELOC_SIGNED
:
1496 case X86_64_RELOC_GOT
:
1498 rval
= KERN_FAILURE
;
1504 instr64
= OSSwapInt64(instr64
);
1507 *instr64p
= instr64
;
1510 rval
= KERN_SUCCESS
;
1516 /*******************************************************************************
1517 *******************************************************************************/
1518 static kern_return_t
1519 calculate_displacement_x86_64(uint64_t target
, uint64_t adjustment
,
1522 kern_return_t rval
= KERN_FAILURE
;
1523 int64_t displacement
;
1524 uint64_t difference
;
1526 displacement
= *instr32
+ target
- adjustment
;
1527 difference
= ABSOLUTE_VALUE(displacement
);
1528 require_action(difference
< X86_64_RIP_RELATIVE_LIMIT
, finish
,
1529 rval
= KERN_FAILURE
;
1530 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocationOverflow
));
1532 *instr32
= (int32_t) displacement
;
1533 rval
= KERN_SUCCESS
;
1538 #endif /* KXLD_USER_OR_X86_64 */
1540 #if KXLD_USER_OR_ARM
1541 /*******************************************************************************
1542 *******************************************************************************/
1544 arm_reloc_has_pair(u_int _type
)
1546 enum reloc_type_arm type
= _type
;
1549 case ARM_RELOC_SECTDIFF
:
1557 /*******************************************************************************
1558 *******************************************************************************/
1560 arm_reloc_get_pair_type(u_int _prev_type __unused
)
1562 return ARM_RELOC_PAIR
;
1565 /*******************************************************************************
1566 *******************************************************************************/
1568 arm_reloc_has_got(u_int _type __unused
)
1573 /*******************************************************************************
1574 *******************************************************************************/
1575 static kern_return_t
1576 arm_process_reloc(const KXLDRelocator
*relocator __unused
, u_char
*instruction
,
1577 u_int length
, u_int pcrel
, kxld_addr_t _base_pc __unused
,
1578 kxld_addr_t _link_pc __unused
, kxld_addr_t _link_disp __unused
,
1579 u_int _type __unused
, kxld_addr_t _target __unused
,
1580 kxld_addr_t _pair_target __unused
, boolean_t swap __unused
)
1582 kern_return_t rval
= KERN_FAILURE
;
1583 uint32_t *instr_addr
= NULL
;
1584 uint32_t instr_data
= 0;
1585 uint32_t base_pc
= (uint32_t) _base_pc
;
1586 uint32_t link_pc
= (uint32_t) _link_pc
;
1587 uint32_t target
= (uint32_t) _target
;
1588 int32_t displacement
= 0;
1589 enum reloc_type_arm type
= _type
;
1592 require_action(length
== 2, finish
, rval
= KERN_FAILURE
);
1595 displacement
= target
+ base_pc
- link_pc
;
1598 instr_addr
= (uint32_t *) ((void *) instruction
);
1599 instr_data
= *instr_addr
;
1603 instr_data
= OSSwapInt32(instr_data
);
1607 rval
= check_for_direct_pure_virtual_call(relocator
, instr_data
);
1608 require_noerr(rval
, finish
);
1611 case ARM_RELOC_VANILLA
:
1612 instr_data
+= target
;
1616 * If the displacement is 0 (the offset between the pc and the target has
1617 * not changed), then we don't need to do anything for BR24 and BR22
1618 * relocs. As it turns out, because kexts build with -mlong-calls all
1619 * relocations currently end up being either vanilla (handled above) or
1620 * BR22/BR24 with a displacement of 0.
1621 * We could handle other displacements here but to keep things simple, we
1622 * won't until it is needed (at which point the kernelcache will fail to
1625 case ARM_RELOC_BR24
:
1626 require_action(pcrel
, finish
, rval
= KERN_FAILURE
);
1627 require_action(displacement
== 0, finish
, rval
= KERN_FAILURE
);
1629 case ARM_THUMB_RELOC_BR22
:
1630 require_action(pcrel
, finish
, rval
= KERN_FAILURE
);
1631 require_action(displacement
== 0, finish
, rval
= KERN_FAILURE
);
1634 case ARM_RELOC_SECTDIFF
:
1635 case ARM_RELOC_LOCAL_SECTDIFF
:
1636 case ARM_RELOC_PB_LA_PTR
:
1637 rval
= KERN_FAILURE
;
1640 case ARM_RELOC_PAIR
:
1642 rval
= KERN_FAILURE
;
1648 instr_data
= OSSwapInt32(instr_data
);
1652 *instr_addr
= instr_data
;
1654 rval
= KERN_SUCCESS
;
1660 #endif /* KXLD_USER_OR_ARM */
1662 #if KXLD_USER_OR_ARM64
1663 /*******************************************************************************
1664 *******************************************************************************/
1666 arm64_reloc_has_pair(u_int _type
)
1668 return _type
== ARM64_RELOC_SUBTRACTOR
;
1671 /*******************************************************************************
1672 *******************************************************************************/
1674 arm64_reloc_get_pair_type(u_int _prev_type __unused
)
1676 if (_prev_type
== ARM64_RELOC_SUBTRACTOR
) {
1677 return ARM64_RELOC_UNSIGNED
;
1683 /*******************************************************************************
1684 *******************************************************************************/
1686 arm64_reloc_has_got(u_int _type
)
1688 return _type
== ARM64_RELOC_GOT_LOAD_PAGE21
||
1689 _type
== ARM64_RELOC_GOT_LOAD_PAGEOFF12
;
1692 /*******************************************************************************
1693 *******************************************************************************/
1695 arm64_process_reloc(const KXLDRelocator
*relocator __unused
, u_char
*instruction
,
1696 u_int length
, u_int pcrel
, kxld_addr_t _base_pc __unused
, kxld_addr_t _link_pc
,
1697 kxld_addr_t _link_disp __unused
, u_int _type
, kxld_addr_t _target
,
1698 kxld_addr_t _pair_target __unused
, boolean_t swap
)
1700 kern_return_t rval
= KERN_FAILURE
;
1701 enum reloc_type_arm64 type
= _type
;
1702 uint64_t target
= _target
;
1703 uint64_t link_pc
= (uint64_t) _link_pc
;
1704 uint64_t difference
= 0;
1705 int64_t displacement
= 0;
1706 uint32_t addend
= 0;
1709 require_action((length
== 2 || length
== 3), finish
, rval
= KERN_FAILURE
);
1712 uint32_t *instr32p
= (uint32_t *) (void *) instruction
;
1713 uint32_t instr32
= *instr32p
;
1717 instr32
= OSSwapInt32(instr32
);
1722 case ARM64_RELOC_BRANCH26
:
1723 require_action(pcrel
, finish
, rval
= KERN_FAILURE
);
1724 addend
= (instr32
& 0x03FFFFFF) << 2;
1725 addend
= SIGN_EXTEND(addend
, 27);
1726 displacement
= (target
- link_pc
+ addend
);
1727 difference
= ABSOLUTE_VALUE(displacement
);
1728 displacement
= (displacement
>> 2);
1729 require_action(difference
< (128 * 1024 * 1024), finish
,
1730 rval
= KERN_FAILURE
;
1731 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocationOverflow
));
1732 instr32
= (instr32
& 0xFC000000) | (displacement
& 0x03FFFFFF);
1736 rval
= KERN_FAILURE
;
1742 instr32
= OSSwapInt32(instr32
);
1746 *instr32p
= instr32
;
1747 } else { /* length == 3 */
1748 uint64_t *instr64p
= (uint64_t *) (void *) instruction
;
1749 uint64_t instr64
= *instr64p
;
1753 instr64
= OSSwapInt64(instr64
);
1758 case ARM64_RELOC_UNSIGNED
:
1759 require_action(!pcrel
, finish
, rval
= KERN_FAILURE
);
1763 rval
= KERN_FAILURE
;
1769 instr64
= OSSwapInt64(instr64
);
1773 *instr64p
= instr64
;
1776 rval
= KERN_SUCCESS
;
1782 #endif /* KXLD_USER_OR_ARM64 */