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_reloc.h"
45 #include "kxld_sect.h"
48 #include "kxld_symtab.h"
49 #include "kxld_util.h"
51 /* include target-specific relocation prototypes */
52 #include <mach-o/reloc.h>
54 #include <mach-o/ppc/reloc.h>
56 #if KXLD_USER_OR_X86_64
57 #include <mach-o/x86_64/reloc.h>
60 #include <mach-o/arm/reloc.h>
63 #define KXLD_TARGET_NONE (u_int) 0x0
64 #define KXLD_TARGET_VALUE (u_int) 0x1
65 #define KXLD_TARGET_SECTNUM (u_int) 0x2
66 #define KXLD_TARGET_SYMBOLNUM (u_int) 0x3
67 #define KXLD_TARGET_LOOKUP (u_int) 0x4
68 #define KXLD_TARGET_GOT (u_int) 0x5
70 #define ABSOLUTE_VALUE(x) (((x) < 0) ? -(x) : (x))
72 #define LO16(x) (0x0000FFFF & x)
73 #define LO16S(x) ((0x0000FFFF & x) << 16)
74 #define HI16(x) (0xFFFF0000 & x)
75 #define HI16S(x) ((0xFFFF0000 & x) >> 16)
76 #define BIT15(x) (0x00008000 & x)
77 #define BR14I(x) (0xFFFF0003 & x)
78 #define BR14D(x) (0x0000FFFC & x)
79 #define BR24I(x) (0xFC000003 & x)
80 #define BR24D(x) (0x03FFFFFC & x)
81 #define HADISP 0x00010000
82 #define BR14_LIMIT 0x00008000
83 #define BR24_LIMIT 0x02000000
84 #define IS_COND_BR_INSTR(x) ((x & 0xFC000000) == 0x40000000)
85 #define IS_NOT_ALWAYS_TAKEN(x) ((x & 0x03E00000) != 0x02800000)
86 #define FLIP_PREDICT_BIT(x) x ^= 0x00200000
88 #define SIGN_EXTEND_MASK(n) (1 << ((n) - 1))
89 #define SIGN_EXTEND(x,n) (((x) ^ SIGN_EXTEND_MASK(n)) - SIGN_EXTEND_MASK(n))
90 #define BR14_NBITS_DISPLACEMENT 16
91 #define BR24_NBITS_DISPLACEMENT 26
93 #define X86_64_RIP_RELATIVE_LIMIT 0x80000000UL
95 /*******************************************************************************
97 *******************************************************************************/
99 static boolean_t
generic_reloc_has_pair(u_int _type
)
100 __attribute__((const));
101 static boolean_t
generic_reloc_is_pair(u_int _type
, u_int _prev_type
)
102 __attribute__((const));
103 static boolean_t
generic_reloc_has_got(u_int _type
)
104 __attribute__((const));
105 static kern_return_t
generic_process_reloc(u_char
*instruction
, u_int length
,
106 u_int pcrel
, kxld_addr_t base_pc
, kxld_addr_t link_pc
, kxld_addr_t link_disp
,
107 u_int type
, kxld_addr_t target
, kxld_addr_t pair_target
, boolean_t swap
);
108 #endif /* KXLD_USER_OR_I386 */
111 static boolean_t
ppc_reloc_has_pair(u_int _type
)
112 __attribute__((const));
113 static boolean_t
ppc_reloc_is_pair(u_int _type
, u_int _prev_type
)
114 __attribute__((const));
115 static boolean_t
ppc_reloc_has_got(u_int _type
)
116 __attribute__((const));
117 static kern_return_t
ppc_process_reloc(u_char
*instruction
, u_int length
,
118 u_int pcrel
, kxld_addr_t base_pc
, kxld_addr_t link_pc
, kxld_addr_t link_disp
,
119 u_int type
, kxld_addr_t target
, kxld_addr_t pair_target
, boolean_t swap
);
120 #endif /* KXLD_USER_OR_PPC */
122 #if KXLD_USER_OR_X86_64
123 static boolean_t
x86_64_reloc_has_pair(u_int _type
)
124 __attribute__((const));
125 static boolean_t
x86_64_reloc_is_pair(u_int _type
, u_int _prev_type
)
126 __attribute__((const));
127 static boolean_t
x86_64_reloc_has_got(u_int _type
)
128 __attribute__((const));
129 static kern_return_t
x86_64_process_reloc(u_char
*instruction
, u_int length
,
130 u_int pcrel
, kxld_addr_t base_pc
, kxld_addr_t link_pc
, kxld_addr_t link_disp
,
131 u_int type
, kxld_addr_t target
, kxld_addr_t pair_target
, boolean_t swap
);
132 static kern_return_t
calculate_displacement_x86_64(uint64_t target
,
133 uint64_t adjustment
, int32_t *instr32
);
134 #endif /* KXLD_USER_OR_X86_64 */
137 static boolean_t
arm_reloc_has_pair(u_int _type
)
138 __attribute__((const));
139 static boolean_t
arm_reloc_is_pair(u_int _type
, u_int _prev_type
)
140 __attribute__((const));
141 static boolean_t
arm_reloc_has_got(u_int _type
)
142 __attribute__((const));
143 static kern_return_t
arm_process_reloc(u_char
*instruction
, u_int length
,
144 u_int pcrel
, kxld_addr_t base_pc
, kxld_addr_t link_pc
, kxld_addr_t link_disp
,
145 u_int type
, kxld_addr_t target
, kxld_addr_t pair_target
, boolean_t swap
);
146 #endif /* KXLD_USER_OR_ARM */
148 #if KXLD_USER_OR_ILP32
149 static kxld_addr_t
get_pointer_at_addr_32(u_char
*data
, u_long offset
,
150 const KXLDRelocator
*relocator __unused
)
151 __attribute__((pure
, nonnull
));
152 #endif /* KXLD_USER_OR_ILP32 */
153 #if KXLD_USER_OR_LP64
154 static kxld_addr_t
get_pointer_at_addr_64(u_char
*data
, u_long offset
,
155 const KXLDRelocator
*relocator __unused
)
156 __attribute__((pure
, nonnull
));
157 #endif /* KXLD_USER_OR_LP64 */
159 static u_int
count_relocatable_relocs(const KXLDRelocator
*relocator
,
160 const struct relocation_info
*relocs
, u_int nrelocs
)
161 __attribute__((pure
));
163 static kern_return_t
calculate_targets(kxld_addr_t
*_target
,
164 kxld_addr_t
*_pair_target
, const KXLDReloc
*reloc
,
165 const KXLDArray
*sectarray
, const KXLDSymtab
*symtab
);
166 static kern_return_t
get_target_by_address_lookup(kxld_addr_t
*target
,
167 kxld_addr_t addr
, const KXLDArray
*sectarray
);
169 /*******************************************************************************
170 *******************************************************************************/
172 kxld_relocator_init(KXLDRelocator
*relocator
, cpu_type_t cputype
,
173 cpu_subtype_t cpusubtype __unused
, boolean_t swap
)
175 kern_return_t rval
= KERN_FAILURE
;
180 #if KXLD_USER_OR_I386
182 relocator
->reloc_has_pair
= generic_reloc_has_pair
;
183 relocator
->reloc_is_pair
= generic_reloc_is_pair
;
184 relocator
->reloc_has_got
= generic_reloc_has_got
;
185 relocator
->process_reloc
= generic_process_reloc
;
186 relocator
->is_32_bit
= TRUE
;
188 #endif /* KXLD_USER_OR_I386 */
190 case CPU_TYPE_POWERPC
:
191 relocator
->reloc_has_pair
= ppc_reloc_has_pair
;
192 relocator
->reloc_is_pair
= ppc_reloc_is_pair
;
193 relocator
->reloc_has_got
= ppc_reloc_has_got
;
194 relocator
->process_reloc
= ppc_process_reloc
;
195 relocator
->is_32_bit
= TRUE
;
197 #endif /* KXLD_USER_OR_PPC */
198 #if KXLD_USER_OR_X86_64
199 case CPU_TYPE_X86_64
:
200 relocator
->reloc_has_pair
= x86_64_reloc_has_pair
;
201 relocator
->reloc_is_pair
= x86_64_reloc_is_pair
;
202 relocator
->reloc_has_got
= x86_64_reloc_has_got
;
203 relocator
->process_reloc
= x86_64_process_reloc
;
204 relocator
->is_32_bit
= FALSE
;
206 #endif /* KXLD_USER_OR_X86_64 */
209 relocator
->reloc_has_pair
= arm_reloc_has_pair
;
210 relocator
->reloc_is_pair
= arm_reloc_is_pair
;
211 relocator
->reloc_has_got
= arm_reloc_has_got
;
212 relocator
->process_reloc
= arm_process_reloc
;
213 relocator
->is_32_bit
= TRUE
;
215 #endif /* KXLD_USER_OR_ARM */
218 kxld_log(kKxldLogLinking
, kKxldLogErr
,
219 kKxldLogArchNotSupported
, cputype
);
223 relocator
->is_32_bit
= kxld_is_32_bit(cputype
);
224 relocator
->swap
= swap
;
232 /*******************************************************************************
233 *******************************************************************************/
235 kxld_reloc_create_macho(KXLDArray
*relocarray
, const KXLDRelocator
*relocator
,
236 const struct relocation_info
*srcs
, u_int nsrcs
)
238 kern_return_t rval
= KERN_FAILURE
;
239 KXLDReloc
*reloc
= NULL
;
241 const struct relocation_info
*src
= NULL
, *prev_src
= NULL
;
242 const struct scattered_relocation_info
*scatsrc
= NULL
, *prev_scatsrc
= NULL
;
244 u_int reloc_index
= 0;
249 /* If there are no relocation entries, just return */
255 /* Count the number of non-pair relocs */
256 nrelocs
= count_relocatable_relocs(relocator
, srcs
, nsrcs
);
260 /* Allocate the array of relocation entries */
262 rval
= kxld_array_init(relocarray
, sizeof(KXLDReloc
), nrelocs
);
263 require_noerr(rval
, finish
);
265 /* Initialize the relocation entries */
267 for (i
= 0; i
< nsrcs
; ++i
) {
269 scatsrc
= (const struct scattered_relocation_info
*) src
;
271 /* A section-based relocation entry can be skipped for absolute
275 if (!(src
->r_address
& R_SCATTERED
) && !(src
->r_extern
) &&
276 (R_ABS
== src
->r_symbolnum
))
281 /* Pull out the data from the relocation entries. The target_type
282 * depends on the r_extern bit:
283 * Scattered -> Section Lookup by Address
284 * Local (not extern) -> Section by Index
285 * Extern -> Symbolnum by Index
287 reloc
= kxld_array_get_item(relocarray
, reloc_index
++);
288 if (src
->r_address
& R_SCATTERED
) {
289 reloc
->address
= scatsrc
->r_address
;
290 reloc
->pcrel
= scatsrc
->r_pcrel
;
291 reloc
->length
= scatsrc
->r_length
;
292 reloc
->reloc_type
= scatsrc
->r_type
;
293 reloc
->target
= scatsrc
->r_value
;
294 reloc
->target_type
= KXLD_TARGET_LOOKUP
;
296 reloc
->address
= src
->r_address
;
297 reloc
->pcrel
= src
->r_pcrel
;
298 reloc
->length
= src
->r_length
;
299 reloc
->reloc_type
= src
->r_type
;
300 reloc
->target
= src
->r_symbolnum
;
302 if (0 == src
->r_extern
) {
303 reloc
->target_type
= KXLD_TARGET_SECTNUM
;
306 reloc
->target_type
= KXLD_TARGET_SYMBOLNUM
;
310 /* Find the pair entry if it exists */
312 if (relocator
->reloc_has_pair(reloc
->reloc_type
)) {
314 require_action(i
< nsrcs
, finish
, rval
=KERN_FAILURE
);
318 prev_scatsrc
= (const struct scattered_relocation_info
*) prev_src
;
319 scatsrc
= (const struct scattered_relocation_info
*) src
;
321 if (src
->r_address
& R_SCATTERED
) {
322 require_action(relocator
->reloc_is_pair(
323 scatsrc
->r_type
, reloc
->reloc_type
),
324 finish
, rval
=KERN_FAILURE
);
325 reloc
->pair_target
= scatsrc
->r_value
;
326 reloc
->pair_target_type
= KXLD_TARGET_LOOKUP
;
328 require_action(relocator
->reloc_is_pair(src
->r_type
,
329 reloc
->reloc_type
), finish
, rval
=KERN_FAILURE
);
332 reloc
->pair_target
= src
->r_symbolnum
;
333 reloc
->pair_target_type
= KXLD_TARGET_SYMBOLNUM
;
335 reloc
->pair_target
= src
->r_address
;
336 reloc
->pair_target_type
= KXLD_TARGET_VALUE
;
340 reloc
->pair_target
= 0;
341 if (relocator
->reloc_has_got(reloc
->reloc_type
)) {
342 reloc
->pair_target_type
= KXLD_TARGET_GOT
;
344 reloc
->pair_target_type
= KXLD_TARGET_NONE
;
357 /*******************************************************************************
358 * Relocatable relocs :
359 * 1) Are not _PAIR_ relocs
360 * 2) Don't reference N_ABS symbols
361 *******************************************************************************/
363 count_relocatable_relocs(const KXLDRelocator
*relocator
,
364 const struct relocation_info
*relocs
, u_int nrelocs
)
366 u_int num_nonpair_relocs
= 0;
369 const struct relocation_info
*reloc
= NULL
;
370 const struct scattered_relocation_info
*sreloc
= NULL
;
375 /* Loop over all of the relocation entries */
377 num_nonpair_relocs
= 1;
378 prev_type
= relocs
->r_type
;
379 for (i
= 1; i
< nrelocs
; ++i
) {
382 if (reloc
->r_address
& R_SCATTERED
) {
383 /* A scattered relocation entry is relocatable as long as it's not a
386 sreloc
= (const struct scattered_relocation_info
*) reloc
;
388 num_nonpair_relocs
+=
389 (!relocator
->reloc_is_pair(sreloc
->r_type
, prev_type
));
391 prev_type
= sreloc
->r_type
;
393 /* A normal relocation entry is relocatable if it is not a pair and
394 * if it is not a section-based relocation for an absolute symbol.
396 num_nonpair_relocs
+=
397 !(relocator
->reloc_is_pair(reloc
->r_type
, prev_type
)
398 || (0 == reloc
->r_extern
&& R_ABS
== reloc
->r_symbolnum
));
400 prev_type
= reloc
->r_type
;
405 return num_nonpair_relocs
;
408 /*******************************************************************************
409 *******************************************************************************/
411 kxld_relocator_clear(KXLDRelocator
*relocator
)
413 bzero(relocator
, sizeof(*relocator
));
416 /*******************************************************************************
417 *******************************************************************************/
419 kxld_relocator_has_pair(const KXLDRelocator
*relocator
, u_int r_type
)
423 return relocator
->reloc_has_pair(r_type
);
426 /*******************************************************************************
427 *******************************************************************************/
429 kxld_relocator_is_pair(const KXLDRelocator
*relocator
, u_int r_type
,
434 return relocator
->reloc_is_pair(r_type
, prev_r_type
);
437 /*******************************************************************************
438 *******************************************************************************/
440 kxld_relocator_has_got(const KXLDRelocator
*relocator
, u_int r_type
)
444 return relocator
->reloc_has_got(r_type
);
447 /*******************************************************************************
448 *******************************************************************************/
450 kxld_reloc_get_symbol(const KXLDRelocator
*relocator
, const KXLDReloc
*reloc
,
451 u_char
*data
, const KXLDSymtab
*symtab
)
454 kxld_addr_t value
= 0;
459 switch (reloc
->target_type
) {
460 case KXLD_TARGET_SYMBOLNUM
:
461 sym
= kxld_symtab_get_symbol_by_index(symtab
, reloc
->target
);
463 case KXLD_TARGET_SECTNUM
:
465 KXLD_3264_FUNC(relocator
->is_32_bit
, value
,
466 get_pointer_at_addr_32
, get_pointer_at_addr_64
,
467 data
, reloc
->address
, relocator
);
468 sym
= kxld_symtab_get_cxx_symbol_by_value(symtab
, value
);
479 /*******************************************************************************
480 *******************************************************************************/
482 kxld_reloc_get_reloc_index_by_offset(const KXLDArray
*relocs
,
483 kxld_size_t offset
, u_int
*idx
)
485 kern_return_t rval
= KERN_FAILURE
;
486 KXLDReloc
*reloc
= NULL
;
489 for (i
= 0; i
< relocs
->nitems
; ++i
) {
490 reloc
= kxld_array_get_item(relocs
, i
);
491 if (reloc
->address
== offset
) break;
494 if (i
>= relocs
->nitems
) {
506 /*******************************************************************************
507 *******************************************************************************/
509 kxld_reloc_get_reloc_by_offset(const KXLDArray
*relocs
, kxld_addr_t offset
)
511 kern_return_t rval
= KERN_FAILURE
;
512 KXLDReloc
*reloc
= NULL
;
515 rval
= kxld_reloc_get_reloc_index_by_offset(relocs
, offset
, &i
);
516 if (rval
) goto finish
;
518 reloc
= kxld_array_get_item(relocs
, i
);
524 #if KXLD_USER_OR_ILP32
525 /*******************************************************************************
526 *******************************************************************************/
528 get_pointer_at_addr_32(u_char
*data
, u_long offset
,
529 const KXLDRelocator
*relocator __unused
)
536 addr
= *(uint32_t *) (data
+ offset
);
538 if (relocator
->swap
) {
539 addr
= OSSwapInt32(addr
);
543 return (kxld_addr_t
) addr
;
545 #endif /* KXLD_USER_OR_ILP32 */
547 #if KXLD_USER_OR_LP64
548 /*******************************************************************************
549 *******************************************************************************/
551 get_pointer_at_addr_64(u_char
*data
, u_long offset
,
552 const KXLDRelocator
*relocator __unused
)
559 addr
= *(uint64_t *) (data
+ offset
);
561 if (relocator
->swap
) {
562 addr
= OSSwapInt64(addr
);
566 return (kxld_addr_t
) addr
;
568 #endif /* KXLD_USER_OR_LP64 */
570 /*******************************************************************************
571 *******************************************************************************/
573 kxld_relocator_process_sect_reloc(const KXLDRelocator
*relocator
,
574 const KXLDReloc
*reloc
, const struct kxld_sect
*sect
,
575 const KXLDArray
*sectarray
, const struct kxld_symtab
*symtab
)
577 kern_return_t rval
= KERN_FAILURE
;
578 u_char
*instruction
= NULL
;
579 kxld_addr_t target
= 0;
580 kxld_addr_t pair_target
= 0;
581 kxld_addr_t base_pc
= 0;
582 kxld_addr_t link_pc
= 0;
583 kxld_addr_t link_disp
= 0;
591 /* Find the instruction */
593 instruction
= sect
->data
+ reloc
->address
;
595 /* Calculate the target */
597 rval
= calculate_targets(&target
, &pair_target
, reloc
, sectarray
, symtab
);
598 require_noerr(rval
, finish
);
600 base_pc
= reloc
->address
;
601 link_pc
= base_pc
+ sect
->link_addr
;
602 link_disp
= sect
->link_addr
- sect
->base_addr
;
606 rval
= relocator
->process_reloc(instruction
, reloc
->length
, reloc
->pcrel
,
607 base_pc
, link_pc
, link_disp
, reloc
->reloc_type
, target
, pair_target
,
609 require_noerr(rval
, finish
);
619 /*******************************************************************************
620 *******************************************************************************/
622 kxld_reloc_update_symindex(KXLDReloc
*reloc
, u_int symindex
)
624 kern_return_t rval
= KERN_FAILURE
;
626 require_action(reloc
->target_type
== KXLD_TARGET_SYMBOLNUM
,
627 finish
, rval
= KERN_FAILURE
);
629 reloc
->target
= symindex
;
637 /*******************************************************************************
638 *******************************************************************************/
640 kxld_relocator_process_table_reloc(const KXLDRelocator
*relocator
,
641 const KXLDReloc
*reloc
, const KXLDSeg
*seg
, u_char
*file
,
642 const struct kxld_array
*sectarray
, const struct kxld_symtab
*symtab
)
644 kern_return_t rval
= KERN_FAILURE
;
645 u_char
*instruction
= NULL
;
646 kxld_addr_t target
= 0;
647 kxld_addr_t pair_target
= 0;
648 kxld_addr_t base_pc
= 0;
649 kxld_addr_t link_pc
= 0;
650 kxld_addr_t link_disp
= 0;
658 /* Find the instruction */
660 instruction
= file
+ seg
->fileoff
+ reloc
->address
;
662 /* Calculate the target */
664 rval
= calculate_targets(&target
, &pair_target
, reloc
, sectarray
, symtab
);
665 require_noerr(rval
, finish
);
667 base_pc
= reloc
->address
;
668 link_pc
= base_pc
+ seg
->link_addr
;
669 link_disp
= seg
->link_addr
- seg
->base_addr
;
673 rval
= relocator
->process_reloc(instruction
, reloc
->length
, reloc
->pcrel
,
674 base_pc
, link_pc
, link_disp
, reloc
->reloc_type
, target
, pair_target
,
676 require_noerr(rval
, finish
);
686 /*******************************************************************************
687 *******************************************************************************/
689 calculate_targets(kxld_addr_t
*_target
, kxld_addr_t
*_pair_target
,
690 const KXLDReloc
*reloc
, const KXLDArray
*sectarray
, const KXLDSymtab
*symtab
)
692 kern_return_t rval
= KERN_FAILURE
;
693 const KXLDSect
*sect
= NULL
;
694 const KXLDSym
*sym
= NULL
;
695 kxld_addr_t target
= 0;
696 kxld_addr_t pair_target
= 0;
705 /* Find the target based on the lookup type */
707 switch(reloc
->target_type
) {
708 case KXLD_TARGET_LOOKUP
:
709 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
710 reloc
->pair_target_type
== KXLD_TARGET_LOOKUP
||
711 reloc
->pair_target_type
== KXLD_TARGET_VALUE
,
712 finish
, rval
=KERN_FAILURE
);
714 rval
= get_target_by_address_lookup(&target
, reloc
->target
, sectarray
);
715 require_noerr(rval
, finish
);
717 if (reloc
->pair_target_type
== KXLD_TARGET_LOOKUP
) {
718 rval
= get_target_by_address_lookup(&pair_target
,
719 reloc
->pair_target
, sectarray
);
720 require_noerr(rval
, finish
);
721 } else if (reloc
->pair_target_type
== KXLD_TARGET_VALUE
) {
722 pair_target
= reloc
->pair_target
;
725 case KXLD_TARGET_SECTNUM
:
726 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
727 reloc
->pair_target_type
== KXLD_TARGET_VALUE
,
728 finish
, rval
=KERN_FAILURE
);
730 /* Get the target's section by section number */
731 sect
= kxld_array_get_item(sectarray
, reloc
->target
);
732 require_action(sect
, finish
, rval
=KERN_FAILURE
);
734 /* target is the change in the section's address */
735 target
= sect
->link_addr
- sect
->base_addr
;
737 if (reloc
->pair_target_type
) {
738 pair_target
= reloc
->pair_target
;
740 /* x86_64 needs to know when we have a non-external relocation,
741 * so we hack that information in here.
746 case KXLD_TARGET_SYMBOLNUM
:
747 require_action(reloc
->pair_target_type
== KXLD_TARGET_NONE
||
748 reloc
->pair_target_type
== KXLD_TARGET_GOT
||
749 reloc
->pair_target_type
== KXLD_TARGET_SYMBOLNUM
||
750 reloc
->pair_target_type
== KXLD_TARGET_VALUE
, finish
,
753 /* Get the target's symbol by symbol number */
754 sym
= kxld_symtab_get_symbol_by_index(symtab
, reloc
->target
);
755 require_action(sym
, finish
, rval
=KERN_FAILURE
);
756 target
= sym
->link_addr
;
758 /* Some relocation types need the GOT entry address instead of the
759 * symbol's actual address. These types don't have pair relocation
760 * entries, so we store the GOT entry address as the pair target.
762 if (reloc
->pair_target_type
== KXLD_TARGET_VALUE
) {
763 pair_target
= reloc
->pair_target
;
764 } else if (reloc
->pair_target_type
== KXLD_TARGET_SYMBOLNUM
) {
765 sym
= kxld_symtab_get_symbol_by_index(symtab
, reloc
->pair_target
);
766 require_action(sym
, finish
, rval
=KERN_FAILURE
);
767 pair_target
= sym
->link_addr
;
768 } else if (reloc
->pair_target_type
== KXLD_TARGET_GOT
) {
769 pair_target
= sym
->got_addr
;
778 *_pair_target
= pair_target
;
785 /*******************************************************************************
786 *******************************************************************************/
788 get_target_by_address_lookup(kxld_addr_t
*target
, kxld_addr_t addr
,
789 const KXLDArray
*sectarray
)
791 kern_return_t rval
= KERN_FAILURE
;
792 const KXLDSect
*sect
= NULL
;
793 kxld_addr_t start
= 0;
801 for (i
= 0; i
< sectarray
->nitems
; ++i
) {
802 sect
= kxld_array_get_item(sectarray
, i
);
803 start
= sect
->base_addr
;
804 end
= start
+ sect
->size
;
806 if (start
<= addr
&& addr
< end
) break;
808 require_action(i
< sectarray
->nitems
, finish
,
811 *target
= sect
->link_addr
- sect
->base_addr
;
818 #if KXLD_USER_OR_I386
819 /*******************************************************************************
820 *******************************************************************************/
822 generic_reloc_has_pair(u_int _type
)
824 enum reloc_type_generic type
= _type
;
826 return (type
== GENERIC_RELOC_SECTDIFF
||
827 type
== GENERIC_RELOC_LOCAL_SECTDIFF
);
830 /*******************************************************************************
831 *******************************************************************************/
833 generic_reloc_is_pair(u_int _type
, u_int _prev_type __unused
)
835 enum reloc_type_generic type
= _type
;
837 return (type
== GENERIC_RELOC_PAIR
);
840 /*******************************************************************************
841 *******************************************************************************/
842 static boolean_t
generic_reloc_has_got(u_int _type __unused
)
847 /*******************************************************************************
848 *******************************************************************************/
850 generic_process_reloc(u_char
*instruction
, u_int length
, u_int pcrel
,
851 kxld_addr_t _base_pc
, kxld_addr_t _link_pc
, kxld_addr_t _link_disp __unused
,
852 u_int _type
, kxld_addr_t _target
, kxld_addr_t _pair_target
,
853 boolean_t swap __unused
)
855 kern_return_t rval
= KERN_FAILURE
;
856 uint32_t base_pc
= (uint32_t) _base_pc
;
857 uint32_t link_pc
= (uint32_t) _link_pc
;
858 uint32_t *instr_addr
= NULL
;
859 uint32_t instr_data
= 0;
860 uint32_t target
= (uint32_t) _target
;
861 uint32_t pair_target
= (uint32_t) _pair_target
;
862 enum reloc_type_generic type
= _type
;
865 require_action(length
== 2, finish
, rval
=KERN_FAILURE
);
867 if (pcrel
) target
= target
+ base_pc
- link_pc
;
869 instr_addr
= (uint32_t *)instruction
;
870 instr_data
= *instr_addr
;
873 if (swap
) instr_data
= OSSwapInt32(instr_data
);
877 case GENERIC_RELOC_VANILLA
:
878 instr_data
+= target
;
880 case GENERIC_RELOC_SECTDIFF
:
881 case GENERIC_RELOC_LOCAL_SECTDIFF
:
882 instr_data
= instr_data
+ target
- pair_target
;
884 case GENERIC_RELOC_PB_LA_PTR
:
887 case GENERIC_RELOC_PAIR
:
894 if (swap
) instr_data
= OSSwapInt32(instr_data
);
897 *instr_addr
= instr_data
;
904 #endif /* KXLD_USER_OR_I386 */
907 /*******************************************************************************
908 *******************************************************************************/
910 ppc_reloc_has_pair(u_int _type
)
912 enum reloc_type_ppc type
= _type
;
920 case PPC_RELOC_SECTDIFF
:
927 /*******************************************************************************
928 *******************************************************************************/
930 ppc_reloc_is_pair(u_int _type
, u_int _prev_type __unused
)
932 enum reloc_type_ppc type
= _type
;
934 return (type
== PPC_RELOC_PAIR
);
937 /*******************************************************************************
938 *******************************************************************************/
939 static boolean_t
ppc_reloc_has_got(u_int _type __unused
)
944 /*******************************************************************************
945 *******************************************************************************/
947 ppc_process_reloc(u_char
*instruction
, u_int length
, u_int pcrel
,
948 kxld_addr_t _base_pc
, kxld_addr_t _link_pc
, kxld_addr_t _link_disp __unused
,
949 u_int _type
, kxld_addr_t _target
, kxld_addr_t _pair_target __unused
,
950 boolean_t swap __unused
)
952 kern_return_t rval
= KERN_FAILURE
;
953 uint32_t *instr_addr
= NULL
;
954 uint32_t instr_data
= 0;
955 uint32_t base_pc
= (uint32_t) _base_pc
;
956 uint32_t link_pc
= (uint32_t) _link_pc
;
957 uint32_t target
= (uint32_t) _target
;
958 uint32_t pair_target
= (uint32_t) _pair_target
;
960 int32_t displacement
= 0;
961 uint32_t difference
= 0;
962 uint32_t br14_disp_sign
= 0;
963 enum reloc_type_ppc type
= _type
;
966 require_action(length
== 2 || length
== 3, finish
,
969 if (pcrel
) displacement
= target
+ base_pc
- link_pc
;
971 instr_addr
= (uint32_t *)instruction
;
972 instr_data
= *instr_addr
;
975 if (swap
) instr_data
= OSSwapInt32(instr_data
);
979 case PPC_RELOC_VANILLA
:
980 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
982 instr_data
+= target
;
985 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
987 addend
= BR14D(instr_data
);
988 displacement
+= SIGN_EXTEND(addend
, BR14_NBITS_DISPLACEMENT
);
989 difference
= ABSOLUTE_VALUE(displacement
);
990 require_action(difference
< BR14_LIMIT
, finish
,
992 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocationOverflow
));
995 br14_disp_sign
= BIT15(instr_data
);
996 instr_data
= BR14I(instr_data
) | BR14D(displacement
);
998 /* If this is a predicted conditional branch (signified by an
999 * instruction length of 3) that is not branch-always, and the sign of
1000 * the displacement is different after relocation, then flip the y-bit
1001 * to preserve the branch prediction
1003 if ((length
== 3) &&
1004 IS_COND_BR_INSTR(instr_data
) &&
1005 IS_NOT_ALWAYS_TAKEN(instr_data
) &&
1006 (BIT15(instr_data
) != br14_disp_sign
))
1008 FLIP_PREDICT_BIT(instr_data
);
1011 case PPC_RELOC_BR24
:
1012 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1014 addend
= BR24D(instr_data
);
1015 displacement
+= SIGN_EXTEND(addend
, BR24_NBITS_DISPLACEMENT
);
1016 difference
= ABSOLUTE_VALUE(displacement
);
1017 require_action(difference
< BR24_LIMIT
, finish
,
1019 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocationOverflow
));
1021 instr_data
= BR24I(instr_data
) | BR24D(displacement
);
1023 case PPC_RELOC_HI16
:
1024 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1026 target
+= LO16S(instr_data
) | LO16(pair_target
);
1027 instr_data
= HI16(instr_data
) | HI16S(target
);
1029 case PPC_RELOC_LO16
:
1030 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1032 target
+= LO16S(pair_target
) | LO16(instr_data
);
1033 instr_data
= HI16(instr_data
) | LO16(target
);
1035 case PPC_RELOC_HA16
:
1036 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1038 instr_data
-= BIT15(pair_target
) ? 1 : 0;
1039 target
+= LO16S(instr_data
) | LO16(pair_target
);
1040 instr_data
= HI16(instr_data
) | HI16S(target
);
1041 instr_data
+= BIT15(target
) ? 1 : 0;
1043 case PPC_RELOC_JBSR
:
1044 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1046 /* The generated code as written branches to an island that loads the
1047 * absolute address of the target. If we can branch to the target
1048 * directly with less than 24 bits of displacement, we modify the branch
1049 * instruction to do so which avoids the cost of the island.
1052 displacement
= target
+ pair_target
- link_pc
;
1053 difference
= ABSOLUTE_VALUE(displacement
);
1054 if (difference
< BR24_LIMIT
) {
1055 instr_data
= BR24I(instr_data
) | BR24D(displacement
);
1058 case PPC_RELOC_SECTDIFF
:
1059 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1061 instr_data
= instr_data
+ target
- pair_target
;
1063 case PPC_RELOC_LO14
:
1064 case PPC_RELOC_PB_LA_PTR
:
1065 case PPC_RELOC_HI16_SECTDIFF
:
1066 case PPC_RELOC_LO16_SECTDIFF
:
1067 case PPC_RELOC_HA16_SECTDIFF
:
1068 case PPC_RELOC_LO14_SECTDIFF
:
1069 case PPC_RELOC_LOCAL_SECTDIFF
:
1070 rval
= KERN_FAILURE
;
1072 case PPC_RELOC_PAIR
:
1074 rval
= KERN_FAILURE
;
1079 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1082 *instr_addr
= instr_data
;
1084 rval
= KERN_SUCCESS
;
1089 #endif /* KXLD_USER_OR_PPC */
1091 #if KXLD_USER_OR_X86_64
1092 /*******************************************************************************
1093 *******************************************************************************/
1095 x86_64_reloc_has_pair(u_int _type
)
1097 enum reloc_type_x86_64 type
= _type
;
1099 return (type
== X86_64_RELOC_SUBTRACTOR
);
1102 /*******************************************************************************
1103 *******************************************************************************/
1105 x86_64_reloc_is_pair(u_int _type
, u_int _prev_type
)
1107 enum reloc_type_x86_64 type
= _type
;
1108 enum reloc_type_x86_64 prev_type
= _prev_type
;
1110 return (x86_64_reloc_has_pair(prev_type
) && type
== X86_64_RELOC_UNSIGNED
);
1113 /*******************************************************************************
1114 *******************************************************************************/
1116 x86_64_reloc_has_got(u_int _type
)
1118 enum reloc_type_x86_64 type
= _type
;
1120 return (type
== X86_64_RELOC_GOT_LOAD
|| type
== X86_64_RELOC_GOT
);
1123 /*******************************************************************************
1124 *******************************************************************************/
1125 static kern_return_t
1126 x86_64_process_reloc(u_char
*instruction
, u_int length
, u_int pcrel
,
1127 kxld_addr_t _base_pc __unused
, kxld_addr_t _link_pc
, kxld_addr_t _link_disp
,
1128 u_int _type
, kxld_addr_t _target
, kxld_addr_t _pair_target
,
1129 boolean_t swap __unused
)
1131 kern_return_t rval
= KERN_FAILURE
;
1132 enum reloc_type_x86_64 type
= _type
;
1133 int32_t *instr32p
= NULL
;
1134 int32_t instr32
= 0;
1135 uint64_t *instr64p
= NULL
;
1136 uint64_t instr64
= 0;
1137 uint64_t target
= _target
;
1138 uint64_t pair_target
= _pair_target
;
1139 uint64_t link_pc
= (uint64_t) _link_pc
;
1140 uint64_t link_disp
= (uint64_t) _link_disp
;
1141 uint64_t adjustment
= 0;
1144 require_action(length
== 2 || length
== 3,
1145 finish
, rval
=KERN_FAILURE
);
1148 instr32p
= (int32_t *) instruction
;
1149 instr32
= *instr32p
;
1152 if (swap
) instr32
= OSSwapInt32(instr32
);
1155 /* There are a number of different small adjustments for pc-relative
1156 * relocation entries. The general case is to subtract the size of the
1157 * relocation (represented by the length parameter), and it applies to
1158 * the GOT types and external SIGNED types. The non-external signed types
1159 * have a different adjustment corresponding to the specific type.
1162 case X86_64_RELOC_SIGNED
:
1168 case X86_64_RELOC_SIGNED_1
:
1174 case X86_64_RELOC_SIGNED_2
:
1180 case X86_64_RELOC_SIGNED_4
:
1186 case X86_64_RELOC_BRANCH
:
1187 case X86_64_RELOC_GOT
:
1188 case X86_64_RELOC_GOT_LOAD
:
1189 adjustment
= (1 << length
);
1195 /* Perform the actual relocation. All of the 32-bit relocations are
1196 * pc-relative except for SUBTRACTOR, so a good chunk of the logic is
1197 * stuck in calculate_displacement_x86_64. The signed relocations are
1198 * a special case, because when they are non-external, the instruction
1199 * already contains the pre-relocation displacement, so we only need to
1200 * find the difference between how far the PC was relocated, and how
1201 * far the target is relocated. Since the target variable already
1202 * contains the difference between the target's base and link
1203 * addresses, we add the difference between the PC's base and link
1204 * addresses to the adjustment variable. This will yield the
1205 * appropriate displacement in calculate_displacement.
1208 case X86_64_RELOC_BRANCH
:
1209 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1210 adjustment
+= link_pc
;
1212 case X86_64_RELOC_SIGNED
:
1213 case X86_64_RELOC_SIGNED_1
:
1214 case X86_64_RELOC_SIGNED_2
:
1215 case X86_64_RELOC_SIGNED_4
:
1216 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1217 adjustment
+= (pair_target
) ? (link_disp
) : (link_pc
);
1219 case X86_64_RELOC_GOT
:
1220 case X86_64_RELOC_GOT_LOAD
:
1221 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1222 adjustment
+= link_pc
;
1223 target
= pair_target
;
1225 case X86_64_RELOC_SUBTRACTOR
:
1226 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1227 instr32
= (int32_t) (target
- pair_target
);
1229 case X86_64_RELOC_UNSIGNED
:
1231 rval
= KERN_FAILURE
;
1235 /* Call calculate_displacement for the pc-relative relocations */
1237 rval
= calculate_displacement_x86_64(target
, adjustment
, &instr32
);
1238 require_noerr(rval
, finish
);
1242 if (swap
) instr32
= OSSwapInt32(instr32
);
1245 *instr32p
= instr32
;
1247 instr64p
= (uint64_t *) instruction
;
1248 instr64
= *instr64p
;
1251 if (swap
) instr64
= OSSwapInt64(instr64
);
1255 case X86_64_RELOC_UNSIGNED
:
1256 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1260 case X86_64_RELOC_SUBTRACTOR
:
1261 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1263 instr64
= target
- pair_target
;
1265 case X86_64_RELOC_SIGNED_1
:
1266 case X86_64_RELOC_SIGNED_2
:
1267 case X86_64_RELOC_SIGNED_4
:
1268 case X86_64_RELOC_GOT_LOAD
:
1269 case X86_64_RELOC_BRANCH
:
1270 case X86_64_RELOC_SIGNED
:
1271 case X86_64_RELOC_GOT
:
1273 rval
= KERN_FAILURE
;
1278 if (swap
) instr64
= OSSwapInt64(instr64
);
1281 *instr64p
= instr64
;
1284 rval
= KERN_SUCCESS
;
1290 /*******************************************************************************
1291 *******************************************************************************/
1292 static kern_return_t
1293 calculate_displacement_x86_64(uint64_t target
, uint64_t adjustment
,
1296 kern_return_t rval
= KERN_FAILURE
;
1297 int64_t displacement
;
1298 uint64_t difference
;
1300 displacement
= *instr32
+ target
- adjustment
;
1301 difference
= ABSOLUTE_VALUE(displacement
);
1302 require_action(difference
< X86_64_RIP_RELATIVE_LIMIT
, finish
,
1304 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogRelocationOverflow
));
1306 *instr32
= (int32_t) displacement
;
1307 rval
= KERN_SUCCESS
;
1312 #endif /* KXLD_USER_OR_X86_64 */
1314 #if KXLD_USER_OR_ARM
1315 /*******************************************************************************
1316 *******************************************************************************/
1318 arm_reloc_has_pair(u_int _type
)
1320 enum reloc_type_arm type
= _type
;
1323 case ARM_RELOC_SECTDIFF
:
1331 /*******************************************************************************
1332 *******************************************************************************/
1334 arm_reloc_is_pair(u_int _type
, u_int _prev_type __unused
)
1336 enum reloc_type_arm type
= _type
;
1338 return (type
== ARM_RELOC_PAIR
);
1341 /*******************************************************************************
1342 *******************************************************************************/
1344 arm_reloc_has_got(u_int _type __unused
)
1349 /*******************************************************************************
1350 *******************************************************************************/
1351 static kern_return_t
1352 arm_process_reloc(u_char
*instruction
, u_int length
, u_int pcrel
,
1353 kxld_addr_t _base_pc __unused
, kxld_addr_t _link_pc __unused
, kxld_addr_t _link_disp __unused
,
1354 u_int _type __unused
, kxld_addr_t _target __unused
, kxld_addr_t _pair_target __unused
,
1355 boolean_t swap __unused
)
1357 kern_return_t rval
= KERN_FAILURE
;
1358 uint32_t *instr_addr
= NULL
;
1359 uint32_t instr_data
= 0;
1360 uint32_t base_pc
= (uint32_t) _base_pc
;
1361 uint32_t link_pc
= (uint32_t) _link_pc
;
1362 uint32_t target
= (uint32_t) _target
;
1363 int32_t displacement
= 0;
1364 enum reloc_type_arm type
= _type
;
1367 require_action(length
== 2, finish
, rval
=KERN_FAILURE
);
1369 if (pcrel
) displacement
= target
+ base_pc
- link_pc
;
1371 instr_addr
= (uint32_t *)instruction
;
1372 instr_data
= *instr_addr
;
1375 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1379 case ARM_RELOC_VANILLA
:
1380 require_action(!pcrel
, finish
, rval
=KERN_FAILURE
);
1381 instr_data
+= target
;
1385 * If the displacement is 0 (the offset between the pc and the target has
1386 * not changed), then we don't need to do anything for BR24 and BR22
1387 * relocs. As it turns out, because kexts build with -mlong-calls all
1388 * relocations currently end up being either vanilla (handled above) or
1389 * BR22/BR24 with a displacement of 0.
1390 * We could handle other displacements here but to keep things simple, we
1391 * won't until it is needed (at which point the kernelcache will fail to
1394 case ARM_RELOC_BR24
:
1395 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1396 require_action(displacement
== 0, finish
, rval
=KERN_FAILURE
);
1398 case ARM_THUMB_RELOC_BR22
:
1399 require_action(pcrel
, finish
, rval
=KERN_FAILURE
);
1400 require_action(displacement
== 0, finish
, rval
=KERN_FAILURE
);
1403 case ARM_RELOC_SECTDIFF
:
1404 case ARM_RELOC_LOCAL_SECTDIFF
:
1405 case ARM_RELOC_PB_LA_PTR
:
1406 rval
= KERN_FAILURE
;
1409 case ARM_RELOC_PAIR
:
1411 rval
= KERN_FAILURE
;
1416 if (swap
) instr_data
= OSSwapInt32(instr_data
);
1419 *instr_addr
= instr_data
;
1421 rval
= KERN_SUCCESS
;
1427 #endif /* KXLD_USER_OR_ARM */