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 <mach/machine.h>
31 #include <sys/types.h>
34 #include <libkern/libkern.h>
36 #include <libkern/OSByteOrder.h>
40 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
41 #include <AssertMacros.h>
43 #include "kxld_array.h"
44 #include "kxld_demangle.h"
45 #include "kxld_dict.h"
46 #include "kxld_reloc.h"
47 #include "kxld_sect.h"
50 #include "kxld_symtab.h"
51 #include "kxld_util.h"
52 #include "kxld_vtable.h"
54 /* include target-specific relocation prototypes */
55 #include <mach-o/reloc.h>
57 #include <mach-o/ppc/reloc.h>
59 #if KXLD_USER_OR_X86_64
60 #include <mach-o/x86_64/reloc.h>
63 #include <mach-o/arm/reloc.h>
66 #define KXLD_TARGET_NONE (u_int) 0x0
67 #define KXLD_TARGET_VALUE (u_int) 0x1
68 #define KXLD_TARGET_SECTNUM (u_int) 0x2
69 #define KXLD_TARGET_SYMBOLNUM (u_int) 0x3
70 #define KXLD_TARGET_LOOKUP (u_int) 0x4
71 #define KXLD_TARGET_GOT (u_int) 0x5
73 #define ABSOLUTE_VALUE(x) (((x) < 0) ? -(x) : (x))
75 #define LO16(x) (0x0000FFFF & x)
76 #define LO16S(x) ((0x0000FFFF & x) << 16)
77 #define HI16(x) (0xFFFF0000 & x)
78 #define HI16S(x) ((0xFFFF0000 & x) >> 16)
79 #define BIT15(x) (0x00008000 & x)
80 #define BR14I(x) (0xFFFF0003 & x)
81 #define BR14D(x) (0x0000FFFC & x)
82 #define BR24I(x) (0xFC000003 & x)
83 #define BR24D(x) (0x03FFFFFC & x)
84 #define HADISP 0x00010000
85 #define BR14_LIMIT 0x00008000
86 #define BR24_LIMIT 0x02000000
87 #define IS_COND_BR_INSTR(x) ((x & 0xFC000000) == 0x40000000)
88 #define IS_NOT_ALWAYS_TAKEN(x) ((x & 0x03E00000) != 0x02800000)
89 #define FLIP_PREDICT_BIT(x) x ^= 0x00200000
91 #define SIGN_EXTEND_MASK(n) (1 << ((n) - 1))
92 #define SIGN_EXTEND(x,n) (((x) ^ SIGN_EXTEND_MASK(n)) - SIGN_EXTEND_MASK(n))
93 #define BR14_NBITS_DISPLACEMENT 16
94 #define BR24_NBITS_DISPLACEMENT 26
96 #define X86_64_RIP_RELATIVE_LIMIT 0x80000000UL
98 /*******************************************************************************
100 *******************************************************************************/
101 #if KXLD_USER_OR_I386
102 static boolean_t
generic_reloc_has_pair(u_int _type
)
103 __attribute__((const));
104 static boolean_t
generic_reloc_is_pair(u_int _type
, u_int _prev_type
)
105 __attribute__((const));
106 static boolean_t
generic_reloc_has_got(u_int _type
)
107 __attribute__((const));
108 static kern_return_t
generic_process_reloc(const KXLDRelocator
*relocator
,
109 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
110 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
111 kxld_addr_t pair_target
, boolean_t swap
);
112 #endif /* KXLD_USER_OR_I386 */
115 static boolean_t
ppc_reloc_has_pair(u_int _type
)
116 __attribute__((const));
117 static boolean_t
ppc_reloc_is_pair(u_int _type
, u_int _prev_type
)
118 __attribute__((const));
119 static boolean_t
ppc_reloc_has_got(u_int _type
)
120 __attribute__((const));
121 static kern_return_t
ppc_process_reloc(const KXLDRelocator
*relocator
,
122 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
123 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
124 kxld_addr_t pair_target
, boolean_t swap
);
125 #endif /* KXLD_USER_OR_PPC */
127 #if KXLD_USER_OR_X86_64
128 static boolean_t
x86_64_reloc_has_pair(u_int _type
)
129 __attribute__((const));
130 static boolean_t
x86_64_reloc_is_pair(u_int _type
, u_int _prev_type
)
131 __attribute__((const));
132 static boolean_t
x86_64_reloc_has_got(u_int _type
)
133 __attribute__((const));
134 static kern_return_t
x86_64_process_reloc(const KXLDRelocator
*relocator
,
135 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
136 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
137 kxld_addr_t pair_target
, boolean_t swap
);
138 static kern_return_t
calculate_displacement_x86_64(uint64_t target
,
139 uint64_t adjustment
, int32_t *instr32
);
140 #endif /* KXLD_USER_OR_X86_64 */
143 static boolean_t
arm_reloc_has_pair(u_int _type
)
144 __attribute__((const));
145 static boolean_t
arm_reloc_is_pair(u_int _type
, u_int _prev_type
)
146 __attribute__((const));
147 static boolean_t
arm_reloc_has_got(u_int _type
)
148 __attribute__((const));
149 static kern_return_t
arm_process_reloc(const KXLDRelocator
*relocator
,
150 u_char
*instruction
, u_int length
, u_int pcrel
, kxld_addr_t base_pc
,
151 kxld_addr_t link_pc
, kxld_addr_t link_disp
, u_int type
, kxld_addr_t target
,
152 kxld_addr_t pair_target
, boolean_t swap
);
153 #endif /* KXLD_USER_OR_ARM */
155 #if KXLD_USER_OR_ILP32
156 static kxld_addr_t
get_pointer_at_addr_32(const KXLDRelocator
*relocator
,
157 const u_char
*data
, u_long offset
)
158 __attribute__((pure
, nonnull
));
159 #endif /* KXLD_USER_OR_ILP32 */
160 #if KXLD_USER_OR_LP64
161 static kxld_addr_t
get_pointer_at_addr_64(const KXLDRelocator
*relocator
,
162 const u_char
*data
, u_long offset
)
163 __attribute__((pure
, nonnull
));
164 #endif /* KXLD_USER_OR_LP64 */
166 static u_int
count_relocatable_relocs(const KXLDRelocator
*relocator
,
167 const struct relocation_info
*relocs
, u_int nrelocs
)
168 __attribute__((pure
));
170 static kern_return_t
calculate_targets(KXLDRelocator
*relocator
,
171 kxld_addr_t
*_target
, kxld_addr_t
*_pair_target
, const KXLDReloc
*reloc
);
173 static kxld_addr_t
align_raw_function_address(const KXLDRelocator
*relocator
,
176 static kern_return_t
get_target_by_address_lookup(kxld_addr_t
*target
,
177 kxld_addr_t addr
, const KXLDArray
*sectarray
);
179 static kern_return_t
check_for_direct_pure_virtual_call(
180 const KXLDRelocator
*relocator
, u_long offset
);
182 /*******************************************************************************
183 *******************************************************************************/
185 kxld_relocator_init(KXLDRelocator
*relocator
, u_char
*file
,
186 const KXLDSymtab
*symtab
, const KXLDArray
*sectarray
, cpu_type_t cputype
,
187 cpu_subtype_t cpusubtype __unused
, boolean_t swap
)
189 kern_return_t rval
= KERN_FAILURE
;
194 #if KXLD_USER_OR_I386
196 relocator
->reloc_has_pair
= generic_reloc_has_pair
;
197 relocator
->reloc_is_pair
= generic_reloc_is_pair
;
198 relocator
->reloc_has_got
= generic_reloc_has_got
;
199 relocator
->process_reloc
= generic_process_reloc
;
200 relocator
->function_align
= 0;
201 relocator
->is_32_bit
= TRUE
;
203 #endif /* KXLD_USER_OR_I386 */
205 case CPU_TYPE_POWERPC
:
206 relocator
->reloc_has_pair
= ppc_reloc_has_pair
;
207 relocator
->reloc_is_pair
= ppc_reloc_is_pair
;
208 relocator
->reloc_has_got
= ppc_reloc_has_got
;
209 relocator
->process_reloc
= ppc_process_reloc
;
210 relocator
->function_align
= 0;
211 relocator
->is_32_bit
= TRUE
;
213 #endif /* KXLD_USER_OR_PPC */
214 #if KXLD_USER_OR_X86_64
215 case CPU_TYPE_X86_64
:
216 relocator
->reloc_has_pair
= x86_64_reloc_has_pair
;
217 relocator
->reloc_is_pair
= x86_64_reloc_is_pair
;
218 relocator
->reloc_has_got
= x86_64_reloc_has_got
;
219 relocator
->process_reloc
= x86_64_process_reloc
;
220 relocator
->function_align
= 0;
221 relocator
->is_32_bit
= FALSE
;
223 #endif /* KXLD_USER_OR_X86_64 */
226 relocator
->reloc_has_pair
= arm_reloc_has_pair
;
227 relocator
->reloc_is_pair
= arm_reloc_is_pair
;
228 relocator
->reloc_has_got
= arm_reloc_has_got
;
229 relocator
->process_reloc
= arm_process_reloc
;
230 relocator
->function_align
= 1;
231 relocator
->is_32_bit
= TRUE
;
233 #endif /* KXLD_USER_OR_ARM */
236 kxld_log(kKxldLogLinking
, kKxldLogErr
,
237 kKxldLogArchNotSupported
, cputype
);
241 relocator
->file
= file
;
242 relocator
->symtab
= symtab
;
243 relocator
->sectarray
= sectarray
;
244 relocator
->is_32_bit
= kxld_is_32_bit(cputype
);
245 relocator
->swap
= swap
;
253 /*******************************************************************************
254 *******************************************************************************/
256 kxld_reloc_create_macho(KXLDArray
*relocarray
, const KXLDRelocator
*relocator
,
257 const struct relocation_info
*srcs
, u_int nsrcs
)
259 kern_return_t rval
= KERN_FAILURE
;
260 KXLDReloc
*reloc
= NULL
;
262 const struct relocation_info
*src
= NULL
;
263 const struct scattered_relocation_info
*scatsrc
= NULL
;
265 u_int reloc_index
= 0;
270 /* If there are no relocation entries, just return */
276 /* Count the number of non-pair relocs */
277 nrelocs
= count_relocatable_relocs(relocator
, srcs
, nsrcs
);
281 /* Allocate the array of relocation entries */
283 rval
= kxld_array_init(relocarray
, sizeof(KXLDReloc
), nrelocs
);
284 require_noerr(rval
, finish
);
286 /* Initialize the relocation entries */
288 for (i
= 0; i
< nsrcs
; ++i
) {
290 scatsrc
= (const struct scattered_relocation_info
*) src
;
292 /* A section-based relocation entry can be skipped for absolute
296 if (!(src
->r_address
& R_SCATTERED
) && !(src
->r_extern
) &&
297 (R_ABS
== src
->r_symbolnum
))
302 /* Pull out the data from the relocation entries. The target_type
303 * depends on the r_extern bit:
304 * Scattered -> Section Lookup by Address
305 * Local (not extern) -> Section by Index
306 * Extern -> Symbolnum by Index
308 reloc
= kxld_array_get_item(relocarray
, reloc_index
++);
309 if (src
->r_address
& R_SCATTERED
) {
310 reloc
->address
= scatsrc
->r_address
;
311 reloc
->pcrel
= scatsrc
->r_pcrel
;
312 reloc
->length
= scatsrc
->r_length
;
313 reloc
->reloc_type
= scatsrc
->r_type
;
314 reloc
->target
= scatsrc
->r_value
;
315 reloc
->target_type
= KXLD_TARGET_LOOKUP
;
317 reloc
->address
= src
->r_address
;
318 reloc
->pcrel
= src
->r_pcrel
;
319 reloc
->length
= src
->r_length
;
320 reloc
->reloc_type
= src
->r_type
;
321 reloc
->target
= src
->r_symbolnum
;
323 if (0 == src
->r_extern
) {
324 reloc
->target_type
= KXLD_TARGET_SECTNUM
;
327 reloc
->target_type
= KXLD_TARGET_SYMBOLNUM
;
331 /* Find the pair entry if it exists */
333 if (relocator
->reloc_has_pair(reloc
->reloc_type
)) {
335 require_action(i
< nsrcs
, finish
, rval
=KERN_FAILURE
);
338 scatsrc
= (const struct scattered_relocation_info
*) src
;
340 if (src
->r_address
& R_SCATTERED
) {
341 require_action(relocator
->reloc_is_pair(
342 scatsrc
->r_type
, reloc
->reloc_type
),
343 finish
, rval
=KERN_FAILURE
);
344 reloc
->pair_target
= scatsrc
->r_value
;
345 reloc
->pair_target_type
= KXLD_TARGET_LOOKUP
;
347 require_action(relocator
->reloc_is_pair(src
->r_type
,
348 reloc
->reloc_type
), finish
, rval
=KERN_FAILURE
);
351 reloc
->pair_target
= src
->r_symbolnum
;
352 reloc
->pair_target_type
= KXLD_TARGET_SYMBOLNUM
;
354 reloc
->pair_target
= src
->r_address
;
355 reloc
->pair_target_type
= KXLD_TARGET_VALUE
;
359 reloc
->pair_target
= 0;
360 if (relocator
->reloc_has_got(reloc
->reloc_type
)) {
361 reloc
->pair_target_type
= KXLD_TARGET_GOT
;
363 reloc
->pair_target_type
= KXLD_TARGET_NONE
;
376 /*******************************************************************************
377 * Relocatable relocs :
378 * 1) Are not _PAIR_ relocs
379 * 2) Don't reference N_ABS symbols
380 *******************************************************************************/
382 count_relocatable_relocs(const KXLDRelocator
*relocator
,
383 const struct relocation_info
*relocs
, u_int nrelocs
)
385 u_int num_nonpair_relocs
= 0;
388 const struct relocation_info
*reloc
= NULL
;
389 const struct scattered_relocation_info
*sreloc
= NULL
;
394 /* Loop over all of the relocation entries */
396 num_nonpair_relocs
= 1;
397 prev_type
= relocs
->r_type
;
398 for (i
= 1; i
< nrelocs
; ++i
) {
401 if (reloc
->r_address
& R_SCATTERED
) {
402 /* A scattered relocation entry is relocatable as long as it's not a
405 sreloc
= (const struct scattered_relocation_info
*) reloc
;
407 num_nonpair_relocs
+=
408 (!relocator
->reloc_is_pair(sreloc
->r_type
, prev_type
));
410 prev_type
= sreloc
->r_type
;
412 /* A normal relocation entry is relocatable if it is not a pair and
413 * if it is not a section-based relocation for an absolute symbol.
415 num_nonpair_relocs
+=
416 !(relocator
->reloc_is_pair(reloc
->r_type
, prev_type
)
417 || (0 == reloc
->r_extern
&& R_ABS
== reloc
->r_symbolnum
));
419 prev_type
= reloc
->r_type
;
424 return num_nonpair_relocs
;
427 /*******************************************************************************
428 *******************************************************************************/
430 kxld_relocator_clear(KXLDRelocator
*relocator
)
432 bzero(relocator
, sizeof(*relocator
));
435 /*******************************************************************************
436 *******************************************************************************/
438 kxld_relocator_has_pair(const KXLDRelocator
*relocator
, u_int r_type
)
442 return relocator
->reloc_has_pair(r_type
);
445 /*******************************************************************************
446 *******************************************************************************/
448 kxld_relocator_is_pair(const KXLDRelocator
*relocator
, u_int r_type
,
453 return relocator
->reloc_is_pair(r_type
, prev_r_type
);
456 /*******************************************************************************
457 *******************************************************************************/
459 kxld_relocator_has_got(const KXLDRelocator
*relocator
, u_int r_type
)
463 return relocator
->reloc_has_got(r_type
);
466 /*******************************************************************************
467 *******************************************************************************/
469 kxld_reloc_get_symbol(const KXLDRelocator
*relocator
, const KXLDReloc
*reloc
,
473 kxld_addr_t value
= 0;
477 switch (reloc
->target_type
) {
478 case KXLD_TARGET_SYMBOLNUM
:
479 sym
= kxld_symtab_get_symbol_by_index(relocator
->symtab
, reloc
->target
);
481 case KXLD_TARGET_SECTNUM
:
483 value
= kxld_relocator_get_pointer_at_addr(relocator
, data
,
485 sym
= kxld_symtab_get_cxx_symbol_by_value(relocator
->symtab
, value
);
496 /*******************************************************************************
497 *******************************************************************************/
499 kxld_reloc_get_reloc_index_by_offset(const KXLDArray
*relocs
,
500 kxld_size_t offset
, u_int
*idx
)
502 kern_return_t rval
= KERN_FAILURE
;
503 KXLDReloc
*reloc
= NULL
;
506 for (i
= 0; i
< relocs
->nitems
; ++i
) {
507 reloc
= kxld_array_get_item(relocs
, i
);
508 if (reloc
->address
== offset
) break;
511 if (i
>= relocs
->nitems
) {
523 /*******************************************************************************
524 *******************************************************************************/
526 kxld_reloc_get_reloc_by_offset(const KXLDArray
*relocs
, kxld_addr_t offset
)
528 kern_return_t rval
= KERN_FAILURE
;
529 KXLDReloc
*reloc
= NULL
;
532 rval
= kxld_reloc_get_reloc_index_by_offset(relocs
, offset
, &i
);
533 if (rval
) goto finish
;
535 reloc
= kxld_array_get_item(relocs
, i
);
541 /*******************************************************************************
542 *******************************************************************************/
544 kxld_relocator_get_pointer_at_addr(const KXLDRelocator
*relocator
,
545 const u_char
*data
, u_long offset
)
549 KXLD_3264_FUNC(relocator
->is_32_bit
, value
,
550 get_pointer_at_addr_32
, get_pointer_at_addr_64
,
551 relocator
, data
, offset
);
556 #if KXLD_USER_OR_ILP32
557 /*******************************************************************************
558 *******************************************************************************/
560 get_pointer_at_addr_32(const KXLDRelocator
*relocator
,
561 const u_char
*data
, u_long offset
)
567 addr
= *(const uint32_t *) (data
+ offset
);
569 if (relocator
->swap
) {
570 addr
= OSSwapInt32(addr
);
574 return align_raw_function_address(relocator
, addr
);
576 #endif /* KXLD_USER_OR_ILP32 */
578 #if KXLD_USER_OR_LP64
579 /*******************************************************************************
580 *******************************************************************************/
582 get_pointer_at_addr_64(const KXLDRelocator
*relocator
,
583 const u_char
*data
, u_long offset
)
589 addr
= *(const uint64_t *) (data
+ offset
);
591 if (relocator
->swap
) {
592 addr
= OSSwapInt64(addr
);
596 return align_raw_function_address(relocator
, addr
);
598 #endif /* KXLD_USER_OR_LP64 */
600 /*******************************************************************************
601 *******************************************************************************/
603 kxld_relocator_set_vtables(KXLDRelocator
*relocator
,
604 const struct kxld_dict
*vtables
)
606 relocator
->vtables
= vtables
;
609 /*******************************************************************************
610 * When we're inspecting the raw binary and not the symbol table, value may
611 * hold a THUMB address (with bit 0 set to 1) but the index will have the real
612 * address (bit 0 set to 0). So if bit 0 is set here, we clear it. This only
613 * impacts ARM for now, but it's implemented as a generic function alignment
615 *******************************************************************************/
617 align_raw_function_address(const KXLDRelocator
*relocator
, kxld_addr_t value
)
619 if (relocator
->function_align
) {
620 value
&= ~((1ULL << relocator
->function_align
) - 1);
626 /*******************************************************************************
627 *******************************************************************************/
629 kxld_relocator_process_sect_reloc(KXLDRelocator
*relocator
,
630 const KXLDReloc
*reloc
, const struct kxld_sect
*sect
)
632 kern_return_t rval
= KERN_FAILURE
;
633 u_char
*instruction
= NULL
;
634 kxld_addr_t target
= 0;
635 kxld_addr_t pair_target
= 0;
636 kxld_addr_t base_pc
= 0;
637 kxld_addr_t link_pc
= 0;
638 kxld_addr_t link_disp
= 0;
644 /* Find the instruction */
646 instruction
= sect
->data
+ reloc
->address
;
648 /* Calculate the target */
650 rval
= calculate_targets(relocator
, &target
, &pair_target
, reloc
);
651 require_noerr(rval
, finish
);
653 base_pc
= reloc
->address
;
654 link_pc
= base_pc
+ sect
->link_addr
;
655 link_disp
= sect
->link_addr
- sect
->base_addr
;
659 rval
= relocator
->process_reloc(relocator
, instruction
, reloc
->length
,
660 reloc
->pcrel
, base_pc
, link_pc
, link_disp
, reloc
->reloc_type
, target
,
661 pair_target
, relocator
->swap
);
662 require_noerr(rval
, finish
);
666 relocator
->current_vtable
= NULL
;
673 /*******************************************************************************
674 *******************************************************************************/
676 kxld_reloc_update_symindex(KXLDReloc
*reloc
, u_int symindex
)
678 kern_return_t rval
= KERN_FAILURE
;
680 require_action(reloc
->target_type
== KXLD_TARGET_SYMBOLNUM
,
681 finish
, rval
= KERN_FAILURE
);
683 reloc
->target
= symindex
;
691 /*******************************************************************************
692 *******************************************************************************/
694 kxld_relocator_process_table_reloc(KXLDRelocator
*relocator
,
695 const KXLDReloc
*reloc
, const KXLDSeg
*seg
, kxld_addr_t link_addr
)
697 kern_return_t rval
= KERN_FAILURE
;
698 u_char
*instruction
= NULL
;
699 kxld_addr_t target
= 0;
700 kxld_addr_t pair_target
= 0;
701 kxld_addr_t base_pc
= 0;
702 kxld_addr_t link_pc
= 0;
708 /* Find the instruction */
710 offset
= (u_long
)(seg
->fileoff
+ (reloc
->address
- seg
->base_addr
));
711 instruction
= relocator
->file
+ offset
;
713 /* Calculate the target */
715 rval
= calculate_targets(relocator
, &target
, &pair_target
, reloc
);
716 require_noerr(rval
, finish
);
718 base_pc
= reloc
->address
;
719 link_pc
= base_pc
+ link_addr
;
723 rval
= relocator
->process_reloc(relocator
, instruction
, reloc
->length
,
724 reloc
->pcrel
, base_pc
, link_pc
, link_addr
, reloc
->reloc_type
, target
,
725 pair_target
, relocator
->swap
);
726 require_noerr(rval
, finish
);
730 relocator
->current_vtable
= NULL
;
737 /*******************************************************************************
738 *******************************************************************************/
740 calculate_targets(KXLDRelocator
*relocator
, kxld_addr_t
*_target
,
741 kxld_addr_t
*_pair_target
, const KXLDReloc
*reloc
)
743 kern_return_t rval
= KERN_FAILURE
;
744 const KXLDSect
*sect
= NULL
;
745 const KXLDSym
*sym
= NULL
;
746 kxld_addr_t target
= 0;
747 kxld_addr_t pair_target
= 0;
748 char *demangled_name
= NULL
;
749 size_t demangled_length
= 0;
756 /* Find the target based on the lookup type */
758 switch(reloc
->target_type
) {
759 case KXLD_TARGET_LOOKUP
:
760 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
761 reloc
->pair_target_type
== KXLD_TARGET_LOOKUP
||
762 reloc
->pair_target_type
== KXLD_TARGET_VALUE
,
763 finish
, rval
=KERN_FAILURE
);
765 rval
= get_target_by_address_lookup(&target
, reloc
->target
,
766 relocator
->sectarray
);
767 require_noerr(rval
, finish
);
769 if (reloc
->pair_target_type
== KXLD_TARGET_LOOKUP
) {
770 rval
= get_target_by_address_lookup(&pair_target
,
771 reloc
->pair_target
, relocator
->sectarray
);
772 require_noerr(rval
, finish
);
773 } else if (reloc
->pair_target_type
== KXLD_TARGET_VALUE
) {
774 pair_target
= reloc
->pair_target
;
777 case KXLD_TARGET_SECTNUM
:
778 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
779 reloc
->pair_target_type
== KXLD_TARGET_VALUE
,
780 finish
, rval
=KERN_FAILURE
);
782 /* Get the target's section by section number */
783 sect
= kxld_array_get_item(relocator
->sectarray
, reloc
->target
);
784 require_action(sect
, finish
, rval
=KERN_FAILURE
);
786 /* target is the change in the section's address */
787 target
= sect
->link_addr
- sect
->base_addr
;
789 if (reloc
->pair_target_type
) {
790 pair_target
= reloc
->pair_target
;
792 /* x86_64 needs to know when we have a non-external relocation,
793 * so we hack that information in here.
798 case KXLD_TARGET_SYMBOLNUM
:
799 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
800 reloc
->pair_target_type
== KXLD_TARGET_GOT
||
801 reloc
->pair_target_type
== KXLD_TARGET_SYMBOLNUM
||
802 reloc
->pair_target_type
== KXLD_TARGET_VALUE
, finish
,
805 /* Get the target's symbol by symbol number */
806 sym
= kxld_symtab_get_symbol_by_index(relocator
->symtab
, reloc
->target
);
807 require_action(sym
, finish
, rval
=KERN_FAILURE
);
809 /* If this symbol is a padslot that has already been replaced, then the
810 * only way a relocation entry can still reference it is if there is a
811 * vtable that has not been patched. The vtable patcher uses the
812 * MetaClass structure to find classes for patching, so an unpatched
813 * vtable means that there is an OSObject-dervied class that is missing
814 * its OSDeclare/OSDefine macros.
816 require_action(!kxld_sym_is_padslot(sym
) || !kxld_sym_is_replaced(sym
),
817 finish
, rval
=KERN_FAILURE
;
818 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocatingPatchedSym
,
819 kxld_demangle(sym
->name
, &demangled_name
, &demangled_length
)));
821 target
= sym
->link_addr
;
823 if (kxld_sym_is_vtable(sym
)) {
824 relocator
->current_vtable
= kxld_dict_find(relocator
->vtables
, sym
->name
);
827 /* Some relocation types need the GOT entry address instead of the
828 * symbol's actual address. These types don't have pair relocation
829 * entries, so we store the GOT entry address as the pair target.
831 if (reloc
->pair_target_type
== KXLD_TARGET_VALUE
) {
832 pair_target
= reloc
->pair_target
;
833 } else if (reloc
->pair_target_type
== KXLD_TARGET_SYMBOLNUM
) {
834 sym
= kxld_symtab_get_symbol_by_index(relocator
->symtab
,
836 require_action(sym
, finish
, rval
=KERN_FAILURE
);
837 pair_target
= sym
->link_addr
;
838 } else if (reloc
->pair_target_type
== KXLD_TARGET_GOT
) {
839 pair_target
= sym
->got_addr
;
848 *_pair_target
= pair_target
;
852 if (demangled_name
) kxld_free(demangled_name
, demangled_length
);
856 /*******************************************************************************
857 *******************************************************************************/
859 get_target_by_address_lookup(kxld_addr_t
*target
, kxld_addr_t addr
,
860 const KXLDArray
*sectarray
)
862 kern_return_t rval
= KERN_FAILURE
;
863 const KXLDSect
*sect
= NULL
;
864 kxld_addr_t start
= 0;
872 for (i
= 0; i
< sectarray
->nitems
; ++i
) {
873 sect
= kxld_array_get_item(sectarray
, i
);
874 start
= sect
->base_addr
;
875 end
= start
+ sect
->size
;
877 if (start
<= addr
&& addr
< end
) break;
881 require_action(sect
, finish
, rval
=KERN_FAILURE
);
883 *target
= sect
->link_addr
- sect
->base_addr
;
890 /*******************************************************************************
891 *******************************************************************************/
893 check_for_direct_pure_virtual_call(const KXLDRelocator
*relocator
, u_long offset
)
895 kern_return_t rval
= KERN_FAILURE
;
896 const KXLDVTableEntry
*entry
= NULL
;
898 if (relocator
->current_vtable
) {
899 entry
= kxld_vtable_get_entry_for_offset(relocator
->current_vtable
,
900 offset
, relocator
->is_32_bit
);
901 require_action(!entry
|| !entry
->patched
.name
||
902 !kxld_sym_name_is_pure_virtual(entry
->patched
.name
),
903 finish
, rval
=KERN_FAILURE
;
904 kxld_log(kKxldLogLinking
, kKxldLogErr
,
905 kKxldLogDirectPureVirtualCall
));
913 #if KXLD_USER_OR_I386
914 /*******************************************************************************
915 *******************************************************************************/
917 generic_reloc_has_pair(u_int _type
)
919 enum reloc_type_generic type
= _type
;
921 return (type
== GENERIC_RELOC_SECTDIFF
||
922 type
== GENERIC_RELOC_LOCAL_SECTDIFF
);
925 /*******************************************************************************
926 *******************************************************************************/
928 generic_reloc_is_pair(u_int _type
, u_int _prev_type __unused
)
930 enum reloc_type_generic type
= _type
;
932 return (type
== GENERIC_RELOC_PAIR
);
935 /*******************************************************************************
936 *******************************************************************************/
937 static boolean_t
generic_reloc_has_got(u_int _type __unused
)
942 /*******************************************************************************
943 *******************************************************************************/
945 generic_process_reloc(const KXLDRelocator
*relocator
, u_char
*instruction
,
946 u_int length
, u_int pcrel
, kxld_addr_t _base_pc
, kxld_addr_t _link_pc
,
947 kxld_addr_t _link_disp __unused
, u_int _type
, kxld_addr_t _target
,
948 kxld_addr_t _pair_target
, boolean_t swap __unused
)
950 kern_return_t rval
= KERN_FAILURE
;
951 uint32_t base_pc
= (uint32_t) _base_pc
;
952 uint32_t link_pc
= (uint32_t) _link_pc
;
953 uint32_t *instr_addr
= NULL
;
954 uint32_t instr_data
= 0;
955 uint32_t target
= (uint32_t) _target
;
956 uint32_t pair_target
= (uint32_t) _pair_target
;
957 enum reloc_type_generic type
= _type
;
960 require_action(length
== 2, finish
, rval
=KERN_FAILURE
);
962 if (pcrel
) target
= target
+ base_pc
- link_pc
;
964 instr_addr
= (uint32_t *)instruction
;
965 instr_data
= *instr_addr
;
968 if (swap
) instr_data
= OSSwapInt32(instr_data
);
971 rval
= check_for_direct_pure_virtual_call(relocator
, instr_data
);
972 require_noerr(rval
, finish
);
975 case GENERIC_RELOC_VANILLA
:
976 instr_data
+= target
;
978 case GENERIC_RELOC_SECTDIFF
:
979 case GENERIC_RELOC_LOCAL_SECTDIFF
:
980 instr_data
= instr_data
+ target
- pair_target
;
982 case GENERIC_RELOC_PB_LA_PTR
:
985 case GENERIC_RELOC_PAIR
:
992 if (swap
) instr_data
= OSSwapInt32(instr_data
);
995 *instr_addr
= instr_data
;
1002 #endif /* KXLD_USER_OR_I386 */
1004 #if KXLD_USER_OR_PPC
1005 /*******************************************************************************
1006 *******************************************************************************/
1008 ppc_reloc_has_pair(u_int _type
)
1010 enum reloc_type_ppc type
= _type
;
1013 case PPC_RELOC_HI16
:
1014 case PPC_RELOC_LO16
:
1015 case PPC_RELOC_HA16
:
1016 case PPC_RELOC_LO14
:
1017 case PPC_RELOC_JBSR
:
1018 case PPC_RELOC_SECTDIFF
:
1025 /*******************************************************************************
1026 *******************************************************************************/
1028 ppc_reloc_is_pair(u_int _type
, u_int _prev_type __unused
)
1030 enum reloc_type_ppc type
= _type
;
1032 return (type
== PPC_RELOC_PAIR
);
1035 /*******************************************************************************
1036 *******************************************************************************/
1037 static boolean_t
ppc_reloc_has_got(u_int _type __unused
)
1042 /*******************************************************************************
1043 *******************************************************************************/
1044 static kern_return_t
1045 ppc_process_reloc(const KXLDRelocator
*relocator __unused
, u_char
*instruction
,
1046 u_int length
, u_int pcrel
, kxld_addr_t _base_pc
, kxld_addr_t _link_pc
,
1047 kxld_addr_t _link_disp __unused
, u_int _type
, kxld_addr_t _target
,
1048 kxld_addr_t _pair_target __unused
, boolean_t swap __unused
)
1050 kern_return_t rval
= KERN_FAILURE
;
1051 uint32_t *instr_addr
= NULL
;
1052 uint32_t instr_data
= 0;
1053 uint32_t base_pc
= (uint32_t) _base_pc
;
1054 uint32_t link_pc
= (uint32_t) _link_pc
;
1055 uint32_t target
= (uint32_t) _target
;
1056 uint32_t pair_target
= (uint32_t) _pair_target
;
1058 int32_t displacement
= 0;
1059 uint32_t difference
= 0;
1060 uint32_t br14_disp_sign
= 0;
1061 enum reloc_type_ppc type
= _type
;
1064 require_action(length
== 2 || length
== 3, finish
,
1067 if (pcrel
) displacement
= target
+ base_pc
- link_pc
;
1069 instr_addr
= (uint32_t *)instruction
;
1070 instr_data
= *instr_addr
;
1073 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1076 rval
= check_for_direct_pure_virtual_call(relocator
, instr_data
);
1077 require_noerr(rval
, finish
);
1080 case PPC_RELOC_VANILLA
:
1081 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1083 instr_data
+= target
;
1085 case PPC_RELOC_BR14
:
1086 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1088 addend
= BR14D(instr_data
);
1089 displacement
+= SIGN_EXTEND(addend
, BR14_NBITS_DISPLACEMENT
);
1090 difference
= ABSOLUTE_VALUE(displacement
);
1091 require_action(difference
< BR14_LIMIT
, finish
,
1093 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocationOverflow
));
1096 br14_disp_sign
= BIT15(instr_data
);
1097 instr_data
= BR14I(instr_data
) | BR14D(displacement
);
1099 /* If this is a predicted conditional branch (signified by an
1100 * instruction length of 3) that is not branch-always, and the sign of
1101 * the displacement is different after relocation, then flip the y-bit
1102 * to preserve the branch prediction
1104 if ((length
== 3) &&
1105 IS_COND_BR_INSTR(instr_data
) &&
1106 IS_NOT_ALWAYS_TAKEN(instr_data
) &&
1107 (BIT15(instr_data
) != br14_disp_sign
))
1109 FLIP_PREDICT_BIT(instr_data
);
1112 case PPC_RELOC_BR24
:
1113 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1115 addend
= BR24D(instr_data
);
1116 displacement
+= SIGN_EXTEND(addend
, BR24_NBITS_DISPLACEMENT
);
1117 difference
= ABSOLUTE_VALUE(displacement
);
1118 require_action(difference
< BR24_LIMIT
, finish
,
1120 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocationOverflow
));
1122 instr_data
= BR24I(instr_data
) | BR24D(displacement
);
1124 case PPC_RELOC_HI16
:
1125 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1127 target
+= LO16S(instr_data
) | LO16(pair_target
);
1128 instr_data
= HI16(instr_data
) | HI16S(target
);
1130 case PPC_RELOC_LO16
:
1131 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1133 target
+= LO16S(pair_target
) | LO16(instr_data
);
1134 instr_data
= HI16(instr_data
) | LO16(target
);
1136 case PPC_RELOC_HA16
:
1137 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1139 instr_data
-= BIT15(pair_target
) ? 1 : 0;
1140 target
+= LO16S(instr_data
) | LO16(pair_target
);
1141 instr_data
= HI16(instr_data
) | HI16S(target
);
1142 instr_data
+= BIT15(target
) ? 1 : 0;
1144 case PPC_RELOC_JBSR
:
1145 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1147 /* The generated code as written branches to an island that loads the
1148 * absolute address of the target. If we can branch to the target
1149 * directly with less than 24 bits of displacement, we modify the branch
1150 * instruction to do so which avoids the cost of the island.
1153 displacement
= target
+ pair_target
- link_pc
;
1154 difference
= ABSOLUTE_VALUE(displacement
);
1155 if (difference
< BR24_LIMIT
) {
1156 instr_data
= BR24I(instr_data
) | BR24D(displacement
);
1159 case PPC_RELOC_SECTDIFF
:
1160 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1162 instr_data
= instr_data
+ target
- pair_target
;
1164 case PPC_RELOC_LO14
:
1165 case PPC_RELOC_PB_LA_PTR
:
1166 case PPC_RELOC_HI16_SECTDIFF
:
1167 case PPC_RELOC_LO16_SECTDIFF
:
1168 case PPC_RELOC_HA16_SECTDIFF
:
1169 case PPC_RELOC_LO14_SECTDIFF
:
1170 case PPC_RELOC_LOCAL_SECTDIFF
:
1171 rval
= KERN_FAILURE
;
1173 case PPC_RELOC_PAIR
:
1175 rval
= KERN_FAILURE
;
1180 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1183 *instr_addr
= instr_data
;
1185 rval
= KERN_SUCCESS
;
1190 #endif /* KXLD_USER_OR_PPC */
1192 #if KXLD_USER_OR_X86_64
1193 /*******************************************************************************
1194 *******************************************************************************/
1196 x86_64_reloc_has_pair(u_int _type
)
1198 enum reloc_type_x86_64 type
= _type
;
1200 return (type
== X86_64_RELOC_SUBTRACTOR
);
1203 /*******************************************************************************
1204 *******************************************************************************/
1206 x86_64_reloc_is_pair(u_int _type
, u_int _prev_type
)
1208 enum reloc_type_x86_64 type
= _type
;
1209 enum reloc_type_x86_64 prev_type
= _prev_type
;
1211 return (x86_64_reloc_has_pair(prev_type
) && type
== X86_64_RELOC_UNSIGNED
);
1214 /*******************************************************************************
1215 *******************************************************************************/
1217 x86_64_reloc_has_got(u_int _type
)
1219 enum reloc_type_x86_64 type
= _type
;
1221 return (type
== X86_64_RELOC_GOT_LOAD
|| type
== X86_64_RELOC_GOT
);
1224 /*******************************************************************************
1225 *******************************************************************************/
1226 static kern_return_t
1227 x86_64_process_reloc(const KXLDRelocator
*relocator __unused
, u_char
*instruction
,
1228 u_int length
, u_int pcrel
, kxld_addr_t _base_pc __unused
,
1229 kxld_addr_t _link_pc
, kxld_addr_t _link_disp
, u_int _type
,
1230 kxld_addr_t _target
, kxld_addr_t _pair_target
, boolean_t swap __unused
)
1232 kern_return_t rval
= KERN_FAILURE
;
1233 enum reloc_type_x86_64 type
= _type
;
1234 int32_t *instr32p
= NULL
;
1235 int32_t instr32
= 0;
1236 uint64_t *instr64p
= NULL
;
1237 uint64_t instr64
= 0;
1238 uint64_t target
= _target
;
1239 uint64_t pair_target
= _pair_target
;
1240 uint64_t link_pc
= (uint64_t) _link_pc
;
1241 uint64_t link_disp
= (uint64_t) _link_disp
;
1242 uint64_t adjustment
= 0;
1245 require_action(length
== 2 || length
== 3,
1246 finish
, rval
=KERN_FAILURE
);
1249 instr32p
= (int32_t *) instruction
;
1250 instr32
= *instr32p
;
1253 if (swap
) instr32
= OSSwapInt32(instr32
);
1256 rval
= check_for_direct_pure_virtual_call(relocator
, instr32
);
1257 require_noerr(rval
, finish
);
1259 /* There are a number of different small adjustments for pc-relative
1260 * relocation entries. The general case is to subtract the size of the
1261 * relocation (represented by the length parameter), and it applies to
1262 * the GOT types and external SIGNED types. The non-external signed types
1263 * have a different adjustment corresponding to the specific type.
1266 case X86_64_RELOC_SIGNED
:
1272 case X86_64_RELOC_SIGNED_1
:
1278 case X86_64_RELOC_SIGNED_2
:
1284 case X86_64_RELOC_SIGNED_4
:
1290 case X86_64_RELOC_BRANCH
:
1291 case X86_64_RELOC_GOT
:
1292 case X86_64_RELOC_GOT_LOAD
:
1293 adjustment
= (1 << length
);
1299 /* Perform the actual relocation. All of the 32-bit relocations are
1300 * pc-relative except for SUBTRACTOR, so a good chunk of the logic is
1301 * stuck in calculate_displacement_x86_64. The signed relocations are
1302 * a special case, because when they are non-external, the instruction
1303 * already contains the pre-relocation displacement, so we only need to
1304 * find the difference between how far the PC was relocated, and how
1305 * far the target is relocated. Since the target variable already
1306 * contains the difference between the target's base and link
1307 * addresses, we add the difference between the PC's base and link
1308 * addresses to the adjustment variable. This will yield the
1309 * appropriate displacement in calculate_displacement.
1312 case X86_64_RELOC_BRANCH
:
1313 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1314 adjustment
+= link_pc
;
1316 case X86_64_RELOC_SIGNED
:
1317 case X86_64_RELOC_SIGNED_1
:
1318 case X86_64_RELOC_SIGNED_2
:
1319 case X86_64_RELOC_SIGNED_4
:
1320 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1321 adjustment
+= (pair_target
) ? (link_disp
) : (link_pc
);
1323 case X86_64_RELOC_GOT
:
1324 case X86_64_RELOC_GOT_LOAD
:
1325 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1326 adjustment
+= link_pc
;
1327 target
= pair_target
;
1329 case X86_64_RELOC_SUBTRACTOR
:
1330 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1331 instr32
= (int32_t) (target
- pair_target
);
1333 case X86_64_RELOC_UNSIGNED
:
1335 rval
= KERN_FAILURE
;
1339 /* Call calculate_displacement for the pc-relative relocations */
1341 rval
= calculate_displacement_x86_64(target
, adjustment
, &instr32
);
1342 require_noerr(rval
, finish
);
1346 if (swap
) instr32
= OSSwapInt32(instr32
);
1349 *instr32p
= instr32
;
1351 instr64p
= (uint64_t *) instruction
;
1352 instr64
= *instr64p
;
1355 if (swap
) instr64
= OSSwapInt64(instr64
);
1358 rval
= check_for_direct_pure_virtual_call(relocator
, (u_long
) instr64
);
1359 require_noerr(rval
, finish
);
1362 case X86_64_RELOC_UNSIGNED
:
1363 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1367 case X86_64_RELOC_SUBTRACTOR
:
1368 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1370 instr64
= target
- pair_target
;
1372 case X86_64_RELOC_SIGNED_1
:
1373 case X86_64_RELOC_SIGNED_2
:
1374 case X86_64_RELOC_SIGNED_4
:
1375 case X86_64_RELOC_GOT_LOAD
:
1376 case X86_64_RELOC_BRANCH
:
1377 case X86_64_RELOC_SIGNED
:
1378 case X86_64_RELOC_GOT
:
1380 rval
= KERN_FAILURE
;
1385 if (swap
) instr64
= OSSwapInt64(instr64
);
1388 *instr64p
= instr64
;
1391 rval
= KERN_SUCCESS
;
1397 /*******************************************************************************
1398 *******************************************************************************/
1399 static kern_return_t
1400 calculate_displacement_x86_64(uint64_t target
, uint64_t adjustment
,
1403 kern_return_t rval
= KERN_FAILURE
;
1404 int64_t displacement
;
1405 uint64_t difference
;
1407 displacement
= *instr32
+ target
- adjustment
;
1408 difference
= ABSOLUTE_VALUE(displacement
);
1409 require_action(difference
< X86_64_RIP_RELATIVE_LIMIT
, finish
,
1411 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocationOverflow
));
1413 *instr32
= (int32_t) displacement
;
1414 rval
= KERN_SUCCESS
;
1419 #endif /* KXLD_USER_OR_X86_64 */
1421 #if KXLD_USER_OR_ARM
1422 /*******************************************************************************
1423 *******************************************************************************/
1425 arm_reloc_has_pair(u_int _type
)
1427 enum reloc_type_arm type
= _type
;
1430 case ARM_RELOC_SECTDIFF
:
1438 /*******************************************************************************
1439 *******************************************************************************/
1441 arm_reloc_is_pair(u_int _type
, u_int _prev_type __unused
)
1443 enum reloc_type_arm type
= _type
;
1445 return (type
== ARM_RELOC_PAIR
);
1448 /*******************************************************************************
1449 *******************************************************************************/
1451 arm_reloc_has_got(u_int _type __unused
)
1456 /*******************************************************************************
1457 *******************************************************************************/
1458 static kern_return_t
1459 arm_process_reloc(const KXLDRelocator
*relocator __unused
, u_char
*instruction
,
1460 u_int length
, u_int pcrel
, kxld_addr_t _base_pc __unused
,
1461 kxld_addr_t _link_pc __unused
, kxld_addr_t _link_disp __unused
,
1462 u_int _type __unused
, kxld_addr_t _target __unused
,
1463 kxld_addr_t _pair_target __unused
, boolean_t swap __unused
)
1465 kern_return_t rval
= KERN_FAILURE
;
1466 uint32_t *instr_addr
= NULL
;
1467 uint32_t instr_data
= 0;
1468 uint32_t base_pc
= (uint32_t) _base_pc
;
1469 uint32_t link_pc
= (uint32_t) _link_pc
;
1470 uint32_t target
= (uint32_t) _target
;
1471 int32_t displacement
= 0;
1472 enum reloc_type_arm type
= _type
;
1475 require_action(length
== 2, finish
, rval
=KERN_FAILURE
);
1477 if (pcrel
) displacement
= target
+ base_pc
- link_pc
;
1479 instr_addr
= (uint32_t *)instruction
;
1480 instr_data
= *instr_addr
;
1483 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1486 rval
= check_for_direct_pure_virtual_call(relocator
, instr_data
);
1487 require_noerr(rval
, finish
);
1490 case ARM_RELOC_VANILLA
:
1491 instr_data
+= target
;
1495 * If the displacement is 0 (the offset between the pc and the target has
1496 * not changed), then we don't need to do anything for BR24 and BR22
1497 * relocs. As it turns out, because kexts build with -mlong-calls all
1498 * relocations currently end up being either vanilla (handled above) or
1499 * BR22/BR24 with a displacement of 0.
1500 * We could handle other displacements here but to keep things simple, we
1501 * won't until it is needed (at which point the kernelcache will fail to
1504 case ARM_RELOC_BR24
:
1505 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1506 require_action(displacement
== 0, finish
, rval
=KERN_FAILURE
);
1508 case ARM_THUMB_RELOC_BR22
:
1509 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1510 require_action(displacement
== 0, finish
, rval
=KERN_FAILURE
);
1513 case ARM_RELOC_SECTDIFF
:
1514 case ARM_RELOC_LOCAL_SECTDIFF
:
1515 case ARM_RELOC_PB_LA_PTR
:
1516 rval
= KERN_FAILURE
;
1519 case ARM_RELOC_PAIR
:
1521 rval
= KERN_FAILURE
;
1526 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1529 *instr_addr
= instr_data
;
1531 rval
= KERN_SUCCESS
;
1537 #endif /* KXLD_USER_OR_ARM */