]> git.saurik.com Git - apple/xnu.git/blob - libkern/kxld/kxld_reloc.c
xnu-6153.11.26.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_reloc.c
1 /*
2 * Copyright (c) 2007-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. 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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 #include <string.h>
29 #include <mach/boolean.h>
30 #include <sys/types.h>
31
32 #if KERNEL
33 #include <libkern/libkern.h>
34 #include <mach/machine.h>
35 #else
36 #include <stdlib.h>
37 #include <libkern/OSByteOrder.h>
38
39 /* Get machine.h from the kernel source so we can support all platforms
40 * that the kernel supports. Otherwise we're at the mercy of the host.
41 */
42 #include "../../osfmk/mach/machine.h"
43 #endif
44
45 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
46 #include <AssertMacros.h>
47
48 #include "kxld_array.h"
49 #include "kxld_demangle.h"
50 #include "kxld_dict.h"
51 #include "kxld_reloc.h"
52 #include "kxld_sect.h"
53 #include "kxld_seg.h"
54 #include "kxld_sym.h"
55 #include "kxld_symtab.h"
56 #include "kxld_util.h"
57 #include "kxld_vtable.h"
58
59 #if KXLD_PIC_KEXTS
60 /* This will try to pull in mach/machine.h, so it has to come after the
61 * explicit include above.
62 */
63 #include <mach-o/loader.h>
64 #endif
65
66 /* include target-specific relocation prototypes */
67 #include <mach-o/reloc.h>
68 #if KXLD_USER_OR_X86_64
69 #include <mach-o/x86_64/reloc.h>
70 #endif
71 #if KXLD_USER_OR_ARM
72 #include <mach-o/arm/reloc.h>
73 #endif
74 #if KXLD_USER_OR_ARM64
75 #include <mach-o/arm64/reloc.h>
76 #endif
77
78 extern uint32_t kaslr_offsets_index;
79 extern uint32_t kaslr_offsets_count;
80 extern uint32_t *kaslr_offsets;
81
82 #define KXLD_TARGET_NONE (u_int) 0x0
83 #define KXLD_TARGET_VALUE (u_int) 0x1
84 #define KXLD_TARGET_SECTNUM (u_int) 0x2
85 #define KXLD_TARGET_SYMBOLNUM (u_int) 0x3
86 #define KXLD_TARGET_LOOKUP (u_int) 0x4
87 #define KXLD_TARGET_GOT (u_int) 0x5
88
89 #define ABSOLUTE_VALUE(x) (((x) < 0) ? -(x) : (x))
90
91 #define LO16(x) (0x0000FFFF & x)
92 #define LO16S(x) ((0x0000FFFF & x) << 16)
93 #define HI16(x) (0xFFFF0000 & x)
94 #define HI16S(x) ((0xFFFF0000 & x) >> 16)
95 #define BIT15(x) (0x00008000 & x)
96 #define BR14I(x) (0xFFFF0003 & x)
97 #define BR14D(x) (0x0000FFFC & x)
98 #define BR24I(x) (0xFC000003 & x)
99 #define BR24D(x) (0x03FFFFFC & x)
100 #define HADISP 0x00010000
101 #define BR14_LIMIT 0x00008000
102 #define BR24_LIMIT 0x02000000
103 #define IS_COND_BR_INSTR(x) ((x & 0xFC000000) == 0x40000000)
104 #define IS_NOT_ALWAYS_TAKEN(x) ((x & 0x03E00000) != 0x02800000)
105 #define FLIP_PREDICT_BIT(x) x ^= 0x00200000
106
107 #define SIGN_EXTEND_MASK(n) (1 << ((n) - 1))
108 #define SIGN_EXTEND(x, n) (((x) ^ SIGN_EXTEND_MASK(n)) - SIGN_EXTEND_MASK(n))
109 #define BR14_NBITS_DISPLACEMENT 16
110 #define BR24_NBITS_DISPLACEMENT 26
111
112 #define X86_64_RIP_RELATIVE_LIMIT 0x80000000UL
113
114 /*******************************************************************************
115 * Prototypes
116 *******************************************************************************/
117 #if KXLD_USER_OR_I386
118 static boolean_t generic_reloc_has_pair(u_int _type)
119 __attribute__((const));
120 static u_int generic_reloc_get_pair_type(u_int _prev_type)
121 __attribute__((const));
122 static boolean_t generic_reloc_has_got(u_int _type)
123 __attribute__((const));
124 static kern_return_t generic_process_reloc(const KXLDRelocator *relocator,
125 u_char *instruction, u_int length, u_int pcrel, kxld_addr_t base_pc,
126 kxld_addr_t link_pc, kxld_addr_t link_disp, u_int type, kxld_addr_t target,
127 kxld_addr_t pair_target, boolean_t swap);
128 #endif /* KXLD_USER_OR_I386 */
129
130 #if KXLD_USER_OR_X86_64
131 static boolean_t x86_64_reloc_has_pair(u_int _type)
132 __attribute__((const));
133 static u_int x86_64_reloc_get_pair_type(u_int _prev_type)
134 __attribute__((const));
135 static boolean_t x86_64_reloc_has_got(u_int _type)
136 __attribute__((const));
137 static kern_return_t x86_64_process_reloc(const KXLDRelocator *relocator,
138 u_char *instruction, u_int length, u_int pcrel, kxld_addr_t base_pc,
139 kxld_addr_t link_pc, kxld_addr_t link_disp, u_int type, kxld_addr_t target,
140 kxld_addr_t pair_target, boolean_t swap);
141 static kern_return_t calculate_displacement_x86_64(uint64_t target,
142 uint64_t adjustment, int32_t *instr32);
143 #endif /* KXLD_USER_OR_X86_64 */
144
145 #if KXLD_USER_OR_ARM
146 static boolean_t arm_reloc_has_pair(u_int _type)
147 __attribute__((const));
148 static u_int arm_reloc_get_pair_type(u_int _prev_type)
149 __attribute__((const));
150 static boolean_t arm_reloc_has_got(u_int _type)
151 __attribute__((const));
152 static kern_return_t arm_process_reloc(const KXLDRelocator *relocator,
153 u_char *instruction, u_int length, u_int pcrel, kxld_addr_t base_pc,
154 kxld_addr_t link_pc, kxld_addr_t link_disp, u_int type, kxld_addr_t target,
155 kxld_addr_t pair_target, boolean_t swap);
156 #endif /* KXLD_USER_OR_ARM */
157
158 #if KXLD_USER_OR_ARM64
159 static boolean_t arm64_reloc_has_pair(u_int _type)
160 __attribute__((const));
161 static u_int arm64_reloc_get_pair_type(u_int _prev_type)
162 __attribute__((const));
163 static boolean_t arm64_reloc_has_got(u_int _type)
164 __attribute__((const));
165 static kern_return_t arm64_process_reloc(const KXLDRelocator *relocator,
166 u_char *instruction, u_int length, u_int pcrel, kxld_addr_t base_pc,
167 kxld_addr_t link_pc, kxld_addr_t link_disp, u_int type, kxld_addr_t target,
168 kxld_addr_t pair_target, boolean_t swap);
169 #endif /* KXLD_USER_OR_ARM64 */
170
171 #if KXLD_USER_OR_ILP32
172 static kxld_addr_t get_pointer_at_addr_32(const KXLDRelocator *relocator,
173 const u_char *data, u_long offset)
174 __attribute__((pure, nonnull));
175 #endif /* KXLD_USER_OR_ILP32 */
176 #if KXLD_USER_OR_LP64
177 static kxld_addr_t get_pointer_at_addr_64(const KXLDRelocator *relocator,
178 const u_char *data, u_long offset)
179 __attribute__((pure, nonnull));
180 #endif /* KXLD_USER_OR_LP64 */
181
182 static u_int count_relocatable_relocs(const KXLDRelocator *relocator,
183 const struct relocation_info *relocs, u_int nrelocs)
184 __attribute__((pure));
185
186 static kern_return_t calculate_targets(KXLDRelocator *relocator,
187 kxld_addr_t *_target, kxld_addr_t *_pair_target, const KXLDReloc *reloc);
188
189 static kxld_addr_t align_raw_function_address(const KXLDRelocator *relocator,
190 kxld_addr_t value);
191
192 static kern_return_t get_target_by_address_lookup(kxld_addr_t *target,
193 kxld_addr_t addr, const KXLDArray *sectarray);
194
195 static kern_return_t check_for_direct_pure_virtual_call(
196 const KXLDRelocator *relocator, u_long offset);
197
198 #if KXLD_PIC_KEXTS
199 static u_long get_macho_data_size_for_array(const KXLDArray *relocs);
200
201 static kern_return_t export_macho_for_array(const KXLDRelocator *relocator,
202 const KXLDArray *relocs, struct relocation_info **dstp);
203 #endif /* KXLD_PIC_KEXTS */
204
205 /*******************************************************************************
206 *******************************************************************************/
207 kern_return_t
208 kxld_relocator_init(KXLDRelocator *relocator, u_char *file,
209 const KXLDSymtab *symtab, const KXLDArray *sectarray, cpu_type_t cputype,
210 cpu_subtype_t cpusubtype __unused, boolean_t swap)
211 {
212 kern_return_t rval = KERN_FAILURE;
213
214 check(relocator);
215
216 switch (cputype) {
217 #if KXLD_USER_OR_I386
218 case CPU_TYPE_I386:
219 relocator->reloc_has_pair = generic_reloc_has_pair;
220 relocator->reloc_get_pair_type = generic_reloc_get_pair_type;
221 relocator->reloc_has_got = generic_reloc_has_got;
222 relocator->process_reloc = generic_process_reloc;
223 relocator->function_align = 0;
224 relocator->is_32_bit = TRUE;
225 relocator->may_scatter = TRUE;
226 break;
227 #endif /* KXLD_USER_OR_I386 */
228 #if KXLD_USER_OR_X86_64
229 case CPU_TYPE_X86_64:
230 relocator->reloc_has_pair = x86_64_reloc_has_pair;
231 relocator->reloc_get_pair_type = x86_64_reloc_get_pair_type;
232 relocator->reloc_has_got = x86_64_reloc_has_got;
233 relocator->process_reloc = x86_64_process_reloc;
234 relocator->function_align = 0;
235 relocator->is_32_bit = FALSE;
236 relocator->may_scatter = FALSE;
237 break;
238 #endif /* KXLD_USER_OR_X86_64 */
239 #if KXLD_USER_OR_ARM
240 case CPU_TYPE_ARM:
241 relocator->reloc_has_pair = arm_reloc_has_pair;
242 relocator->reloc_get_pair_type = arm_reloc_get_pair_type;
243 relocator->reloc_has_got = arm_reloc_has_got;
244 relocator->process_reloc = arm_process_reloc;
245 relocator->function_align = 1;
246 relocator->is_32_bit = TRUE;
247 relocator->may_scatter = FALSE;
248 break;
249 #endif /* KXLD_USER_OR_ARM */
250 #if KXLD_USER_OR_ARM64
251 case CPU_TYPE_ARM64:
252 relocator->reloc_has_pair = arm64_reloc_has_pair;
253 relocator->reloc_get_pair_type = arm64_reloc_get_pair_type;
254 relocator->reloc_has_got = arm64_reloc_has_got;
255 relocator->process_reloc = arm64_process_reloc;
256 relocator->function_align = 0;
257 relocator->is_32_bit = FALSE;
258 relocator->may_scatter = FALSE;
259 break;
260 #endif /* KXLD_USER_OR_ARM64 */
261
262 default:
263 rval = KERN_FAILURE;
264 kxld_log(kKxldLogLinking, kKxldLogErr,
265 kKxldLogArchNotSupported, cputype);
266 goto finish;
267 }
268
269 relocator->file = file;
270 relocator->symtab = symtab;
271 relocator->sectarray = sectarray;
272 relocator->is_32_bit = kxld_is_32_bit(cputype);
273 relocator->swap = swap;
274
275 rval = KERN_SUCCESS;
276
277 finish:
278 return rval;
279 }
280
281 /*******************************************************************************
282 *******************************************************************************/
283 kern_return_t
284 kxld_reloc_create_macho(KXLDArray *relocarray, const KXLDRelocator *relocator,
285 const struct relocation_info *srcs, u_int nsrcs)
286 {
287 kern_return_t rval = KERN_FAILURE;
288 KXLDReloc *reloc = NULL;
289 u_int nrelocs = 0;
290 const struct relocation_info *src = NULL;
291 const struct scattered_relocation_info *scatsrc = NULL;
292 u_int i = 0;
293 u_int reloc_index = 0;
294
295 check(relocarray);
296 check(srcs);
297
298 /* If there are no relocation entries, just return */
299 if (!nsrcs) {
300 rval = KERN_SUCCESS;
301 goto finish;
302 }
303
304 /* Count the number of non-pair relocs */
305 nrelocs = count_relocatable_relocs(relocator, srcs, nsrcs);
306
307 if (nrelocs) {
308 /* Allocate the array of relocation entries */
309
310 rval = kxld_array_init(relocarray, sizeof(KXLDReloc), nrelocs);
311 require_noerr(rval, finish);
312
313 /* Initialize the relocation entries */
314
315 for (i = 0; i < nsrcs; ++i) {
316 src = srcs + i;
317 scatsrc = (const struct scattered_relocation_info *) src;
318
319 /* A section-based relocation entry can be skipped for absolute
320 * symbols.
321 */
322
323 if (!(relocator->may_scatter && (src->r_address & R_SCATTERED)) &&
324 !(src->r_extern) && (R_ABS == src->r_symbolnum)) {
325 continue;
326 }
327
328 /* Pull out the data from the relocation entries. The target_type
329 * depends on the r_extern bit:
330 * Scattered -> Section Lookup by Address
331 * Local (not extern) -> Section by Index
332 * Extern -> Symbolnum by Index
333 */
334 reloc = kxld_array_get_item(relocarray, reloc_index++);
335 if (relocator->may_scatter && (src->r_address & R_SCATTERED)) {
336 reloc->address = scatsrc->r_address;
337 reloc->pcrel = scatsrc->r_pcrel;
338 reloc->length = scatsrc->r_length;
339 reloc->reloc_type = scatsrc->r_type;
340 reloc->target = scatsrc->r_value;
341 reloc->target_type = KXLD_TARGET_LOOKUP;
342 } else {
343 reloc->address = src->r_address;
344 reloc->pcrel = src->r_pcrel;
345 reloc->length = src->r_length;
346 reloc->reloc_type = src->r_type;
347 reloc->target = src->r_symbolnum;
348
349 if (0 == src->r_extern) {
350 reloc->target_type = KXLD_TARGET_SECTNUM;
351 reloc->target -= 1;
352 } else {
353 reloc->target_type = KXLD_TARGET_SYMBOLNUM;
354 }
355 }
356
357 /* Find the pair entry if it exists */
358
359 if (relocator->reloc_has_pair(reloc->reloc_type)) {
360 ++i;
361 require_action(i < nsrcs, finish, rval = KERN_FAILURE);
362
363 src = srcs + i;
364 scatsrc = (const struct scattered_relocation_info *) src;
365
366 if (relocator->may_scatter && (src->r_address & R_SCATTERED)) {
367 require_action(relocator->reloc_get_pair_type(
368 reloc->reloc_type) == scatsrc->r_type,
369 finish, rval = KERN_FAILURE);
370 reloc->pair_address = scatsrc->r_address;
371 reloc->pair_target = scatsrc->r_value;
372 reloc->pair_target_type = KXLD_TARGET_LOOKUP;
373 } else {
374 require_action(relocator->reloc_get_pair_type(
375 reloc->reloc_type) == scatsrc->r_type,
376 finish, rval = KERN_FAILURE);
377 reloc->pair_address = scatsrc->r_address;
378 if (src->r_extern) {
379 reloc->pair_target = src->r_symbolnum;
380 reloc->pair_target_type = KXLD_TARGET_SYMBOLNUM;
381 } else {
382 reloc->pair_target = src->r_address;
383 reloc->pair_target_type = KXLD_TARGET_VALUE;
384 }
385 }
386 } else {
387 reloc->pair_target = 0;
388 if (relocator->reloc_has_got(reloc->reloc_type)) {
389 reloc->pair_target_type = KXLD_TARGET_GOT;
390 } else {
391 reloc->pair_target_type = KXLD_TARGET_NONE;
392 }
393 }
394 } // for...
395 }
396 rval = KERN_SUCCESS;
397
398 finish:
399 return rval;
400 }
401
402
403 /*******************************************************************************
404 * Relocatable relocs :
405 * 1) Are not _PAIR_ relocs
406 * 2) Don't reference N_ABS symbols
407 *******************************************************************************/
408 static u_int
409 count_relocatable_relocs(const KXLDRelocator *relocator,
410 const struct relocation_info *relocs, u_int nrelocs)
411 {
412 u_int num_nonpair_relocs = 0;
413 u_int i = 0;
414 const struct relocation_info *reloc = NULL;
415 const struct scattered_relocation_info *sreloc = NULL;
416
417 check(relocator);
418 check(relocs);
419
420 /* Loop over all of the relocation entries */
421
422 num_nonpair_relocs = 1;
423 for (i = 1; i < nrelocs; ++i) {
424 reloc = relocs + i;
425
426 if (reloc->r_address & R_SCATTERED) {
427 /* A scattered relocation entry is relocatable as long as it's not a
428 * pair.
429 */
430 sreloc = (const struct scattered_relocation_info *) reloc;
431
432 num_nonpair_relocs +=
433 !relocator->reloc_has_pair(sreloc->r_type);
434 } else {
435 /* A normal relocation entry is relocatable if it is not a pair and
436 * if it is not a section-based relocation for an absolute symbol.
437 */
438 num_nonpair_relocs +=
439 !(relocator->reloc_has_pair(reloc->r_type)
440 || (0 == reloc->r_extern && R_ABS == reloc->r_symbolnum));
441 }
442 }
443
444 return num_nonpair_relocs;
445 }
446
447 /*******************************************************************************
448 *******************************************************************************/
449 void
450 kxld_relocator_clear(KXLDRelocator *relocator)
451 {
452 bzero(relocator, sizeof(*relocator));
453 }
454
455 /*******************************************************************************
456 *******************************************************************************/
457 boolean_t
458 kxld_relocator_has_pair(const KXLDRelocator *relocator, u_int r_type)
459 {
460 check(relocator);
461
462 return relocator->reloc_has_pair(r_type);
463 }
464
465 /*******************************************************************************
466 *******************************************************************************/
467 u_int
468 kxld_relocator_get_pair_type(const KXLDRelocator *relocator,
469 u_int prev_r_type)
470 {
471 check(relocator);
472
473 return relocator->reloc_get_pair_type(prev_r_type);
474 }
475
476 /*******************************************************************************
477 *******************************************************************************/
478 boolean_t
479 kxld_relocator_has_got(const KXLDRelocator *relocator, u_int r_type)
480 {
481 check(relocator);
482
483 return relocator->reloc_has_got(r_type);
484 }
485
486 /*******************************************************************************
487 *******************************************************************************/
488 KXLDSym *
489 kxld_reloc_get_symbol(const KXLDRelocator *relocator, const KXLDReloc *reloc,
490 const u_char *data)
491 {
492 KXLDSym *sym = NULL;
493 kxld_addr_t value = 0;
494
495 check(reloc);
496
497 switch (reloc->target_type) {
498 case KXLD_TARGET_SYMBOLNUM:
499 sym = kxld_symtab_get_symbol_by_index(relocator->symtab, reloc->target);
500 break;
501 case KXLD_TARGET_SECTNUM:
502 if (data) {
503 value = kxld_relocator_get_pointer_at_addr(relocator, data,
504 reloc->address);
505 sym = kxld_symtab_get_cxx_symbol_by_value(relocator->symtab, value);
506 }
507 break;
508 default:
509 sym = NULL;
510 break;
511 }
512
513 return sym;
514 }
515
516 /*******************************************************************************
517 *******************************************************************************/
518 kern_return_t
519 kxld_reloc_get_reloc_index_by_offset(const KXLDArray *relocs,
520 kxld_size_t offset, u_int *idx)
521 {
522 kern_return_t rval = KERN_FAILURE;
523 KXLDReloc *reloc = NULL;
524 u_int i = 0;
525
526 for (i = 0; i < relocs->nitems; ++i) {
527 reloc = kxld_array_get_item(relocs, i);
528 if (reloc->address == offset) {
529 break;
530 }
531 }
532
533 if (i >= relocs->nitems) {
534 rval = KERN_FAILURE;
535 goto finish;
536 }
537
538 *idx = i;
539 rval = KERN_SUCCESS;
540
541 finish:
542 return rval;
543 }
544
545 /*******************************************************************************
546 *******************************************************************************/
547 KXLDReloc *
548 kxld_reloc_get_reloc_by_offset(const KXLDArray *relocs, kxld_addr_t offset)
549 {
550 kern_return_t rval = KERN_FAILURE;
551 KXLDReloc *reloc = NULL;
552 u_int i = 0;
553
554 rval = kxld_reloc_get_reloc_index_by_offset(relocs, offset, &i);
555 if (rval) {
556 goto finish;
557 }
558
559 reloc = kxld_array_get_item(relocs, i);
560
561 finish:
562 return reloc;
563 }
564
565 #if KXLD_PIC_KEXTS
566 /*******************************************************************************
567 *******************************************************************************/
568 u_long
569 kxld_reloc_get_macho_header_size()
570 {
571 return sizeof(struct dysymtab_command);
572 }
573
574 /*******************************************************************************
575 *******************************************************************************/
576 u_long
577 kxld_reloc_get_macho_data_size(
578 const KXLDArray *locrelocs,
579 const KXLDArray *extrelocs)
580 {
581 u_long rval = 0;
582
583 rval += get_macho_data_size_for_array(locrelocs);
584 rval += get_macho_data_size_for_array(extrelocs);
585
586 return rval;
587 }
588
589 /*******************************************************************************
590 *******************************************************************************/
591 kern_return_t
592 kxld_reloc_export_macho(const KXLDRelocator *relocator,
593 const KXLDArray *locrelocs, const KXLDArray *extrelocs,
594 u_char *buf, u_long *header_offset, u_long header_size,
595 u_long *data_offset, u_long size)
596 {
597 kern_return_t rval = KERN_FAILURE;
598 struct dysymtab_command *dysymtabhdr = NULL;
599 struct relocation_info *start = NULL;
600 struct relocation_info *dst = NULL;
601 u_long count = 0;
602 u_long data_size = 0;
603
604 check(locrelocs);
605 check(extrelocs);
606 check(buf);
607 check(header_offset);
608 check(data_offset);
609
610 require_action(sizeof(*dysymtabhdr) <= header_size - *header_offset, finish, rval = KERN_FAILURE);
611 dysymtabhdr = (struct dysymtab_command *) ((void *) (buf + *header_offset));
612 *header_offset += sizeof(*dysymtabhdr);
613
614 data_size = kxld_reloc_get_macho_data_size(locrelocs, extrelocs);
615 require_action((*data_offset + data_size) <= size, finish, rval = KERN_FAILURE);
616
617 start = dst = (struct relocation_info *) ((void *) (buf + *data_offset));
618
619 if (kaslr_offsets == NULL) {
620 kaslr_offsets_index = 0;
621 kaslr_offsets_count = locrelocs->nitems + extrelocs->nitems;
622 kaslr_offsets = (uint32_t *)calloc(kaslr_offsets_count, sizeof(*kaslr_offsets));
623 }
624
625 // copies the reloc data into the __LINKEDIT segment
626 // data_offset is the new value for locreloff
627 rval = export_macho_for_array(relocator, locrelocs, &dst);
628 require_noerr(rval, finish);
629
630 rval = export_macho_for_array(relocator, extrelocs, &dst);
631 require_noerr(rval, finish);
632
633 count = dst - start;
634
635 memset(dysymtabhdr, 0, sizeof(*dysymtabhdr));
636 dysymtabhdr->cmd = LC_DYSYMTAB;
637 dysymtabhdr->cmdsize = (uint32_t) sizeof(*dysymtabhdr);
638 dysymtabhdr->locreloff = (uint32_t) *data_offset;
639 dysymtabhdr->nlocrel = (uint32_t) count;
640
641 *data_offset += count * sizeof(struct relocation_info);
642
643 #if SPLIT_KEXTS_DEBUG
644 kxld_log(kKxldLogLinking, kKxldLogErr,
645 "%p >>> Start of dysymtabhdr (size %lu) <%s> ",
646 (void *) dysymtabhdr,
647 sizeof(*dysymtabhdr),
648 __func__);
649 kxld_log(kKxldLogLinking, kKxldLogErr,
650 "%p <<< End of dysymtabhdr <%s> ",
651 (void *) ((u_char *)dysymtabhdr + sizeof(*dysymtabhdr)),
652 __func__);
653
654 kxld_log(kKxldLogLinking, kKxldLogErr,
655 "dysymtabhdr at %p: cmdsize %u indirectsymoff %u nindirectsyms %u extreloff %u nextrel %u locreloff %u nlocrel %u <%s>",
656 (void *) dysymtabhdr,
657 dysymtabhdr->cmdsize,
658 dysymtabhdr->indirectsymoff,
659 dysymtabhdr->nindirectsyms,
660 dysymtabhdr->extreloff,
661 dysymtabhdr->nextrel,
662 dysymtabhdr->locreloff,
663 dysymtabhdr->nlocrel,
664 __func__);
665 #endif
666
667 rval = KERN_SUCCESS;
668 finish:
669 return rval;
670 }
671 #endif /* KXLD_PIC_KEXTS */
672
673 /*******************************************************************************
674 *******************************************************************************/
675 kxld_addr_t
676 kxld_relocator_get_pointer_at_addr(const KXLDRelocator *relocator,
677 const u_char *data, u_long offset)
678 {
679 kxld_addr_t value;
680
681 KXLD_3264_FUNC(relocator->is_32_bit, value,
682 get_pointer_at_addr_32, get_pointer_at_addr_64,
683 relocator, data, offset);
684
685 return value;
686 }
687
688 #if KXLD_USER_OR_ILP32
689 /*******************************************************************************
690 *******************************************************************************/
691 static kxld_addr_t
692 get_pointer_at_addr_32(const KXLDRelocator *relocator,
693 const u_char *data, u_long offset)
694 {
695 uint32_t addr = 0;
696
697 check(relocator);
698
699 addr = *(const uint32_t *) ((const void *) (data + offset));
700 #if !KERNEL
701 if (relocator->swap) {
702 addr = OSSwapInt32(addr);
703 }
704 #endif
705
706 return align_raw_function_address(relocator, addr);
707 }
708 #endif /* KXLD_USER_OR_ILP32 */
709
710 #if KXLD_USER_OR_LP64
711 /*******************************************************************************
712 *******************************************************************************/
713 static kxld_addr_t
714 get_pointer_at_addr_64(const KXLDRelocator *relocator,
715 const u_char *data, u_long offset)
716 {
717 uint64_t addr = 0;
718
719 check(relocator);
720
721 addr = *(const uint64_t *) ((const void *) (data + offset));
722
723 #if !KERNEL
724 if (relocator->swap) {
725 addr = OSSwapInt64(addr);
726 }
727 #endif
728
729 return align_raw_function_address(relocator, addr);
730 }
731 #endif /* KXLD_USER_OR_LP64 */
732
733 /*******************************************************************************
734 *******************************************************************************/
735 void
736 kxld_relocator_set_vtables(KXLDRelocator *relocator, const KXLDDict *vtables)
737 {
738 relocator->vtables = vtables;
739 }
740
741 /*******************************************************************************
742 * When we're inspecting the raw binary and not the symbol table, value may
743 * hold a THUMB address (with bit 0 set to 1) but the index will have the real
744 * address (bit 0 set to 0). So if bit 0 is set here, we clear it. This only
745 * impacts ARM for now, but it's implemented as a generic function alignment
746 * mask.
747 *******************************************************************************/
748 static kxld_addr_t
749 align_raw_function_address(const KXLDRelocator *relocator, kxld_addr_t value)
750 {
751 if (relocator->function_align) {
752 value &= ~((1ULL << relocator->function_align) - 1);
753 }
754
755 return value;
756 }
757
758 /*******************************************************************************
759 *******************************************************************************/
760 kern_return_t
761 kxld_relocator_process_sect_reloc(KXLDRelocator *relocator,
762 const KXLDReloc *reloc, const KXLDSect *sect)
763 {
764 kern_return_t rval = KERN_FAILURE;
765 u_char *instruction = NULL;
766 kxld_addr_t target = 0;
767 kxld_addr_t pair_target = 0;
768 kxld_addr_t base_pc = 0;
769 kxld_addr_t link_pc = 0;
770 kxld_addr_t link_disp = 0;
771
772 check(relocator);
773 check(reloc);
774 check(sect);
775
776 /* Find the instruction */
777
778 instruction = sect->data + reloc->address;
779
780 /* Calculate the target */
781
782 rval = calculate_targets(relocator, &target, &pair_target, reloc);
783 require_noerr(rval, finish);
784
785 base_pc = reloc->address;
786 link_pc = base_pc + sect->link_addr;
787 link_disp = sect->link_addr - sect->base_addr;
788
789 /* Relocate */
790
791 rval = relocator->process_reloc(relocator, instruction, reloc->length,
792 reloc->pcrel, base_pc, link_pc, link_disp, reloc->reloc_type, target,
793 pair_target, relocator->swap);
794 require_noerr(rval, finish);
795
796 /* Return */
797
798 relocator->current_vtable = NULL;
799 rval = KERN_SUCCESS;
800
801 finish:
802 return rval;
803 }
804
805 /*******************************************************************************
806 *******************************************************************************/
807 kern_return_t
808 kxld_reloc_update_symindex(KXLDReloc *reloc, u_int symindex)
809 {
810 kern_return_t rval = KERN_FAILURE;
811
812 require_action(reloc->target_type == KXLD_TARGET_SYMBOLNUM,
813 finish, rval = KERN_FAILURE);
814
815 reloc->target = symindex;
816
817 rval = KERN_SUCCESS;
818
819 finish:
820 return rval;
821 }
822
823 /*******************************************************************************
824 *******************************************************************************/
825 kern_return_t
826 kxld_relocator_process_table_reloc(KXLDRelocator *relocator,
827 const KXLDReloc *reloc,
828 const KXLDSeg *seg,
829 kxld_addr_t link_addr)
830 {
831 kern_return_t rval = KERN_FAILURE;
832 u_char *instruction = NULL;
833 kxld_addr_t target = 0;
834 kxld_addr_t pair_target = 0;
835 kxld_addr_t base_pc = 0;
836 kxld_addr_t link_pc = 0;
837 u_long offset = 0;
838
839 check(relocator);
840 check(reloc);
841
842 /* Find the instruction in original kext file we are trying to link */
843
844 offset = (u_long)(seg->fileoff + (reloc->address - seg->base_addr));
845 instruction = relocator->file + offset;
846
847 /* Calculate the target */
848
849 rval = calculate_targets(relocator, &target, &pair_target, reloc);
850 require_noerr(rval, finish);
851
852 base_pc = reloc->address;
853 link_pc = base_pc + link_addr;
854 if (kxld_seg_is_split_seg(seg)) {
855 // link_pc for split segment special case, do not add in the base_pc
856 link_pc = link_addr;
857 }
858
859 /* Relocate */
860
861 rval = relocator->process_reloc(relocator, instruction, reloc->length,
862 reloc->pcrel, base_pc, link_pc, link_addr, reloc->reloc_type, target,
863 pair_target, relocator->swap);
864 require_noerr(rval, finish);
865
866 /* Return */
867
868 relocator->current_vtable = NULL;
869 rval = KERN_SUCCESS;
870
871 finish:
872 return rval;
873 }
874
875 /*******************************************************************************
876 *******************************************************************************/
877 static kern_return_t
878 calculate_targets(KXLDRelocator *relocator, kxld_addr_t *_target,
879 kxld_addr_t *_pair_target, const KXLDReloc *reloc)
880 {
881 kern_return_t rval = KERN_FAILURE;
882 const KXLDSect *sect = NULL;
883 const KXLDSym *sym = NULL;
884 kxld_addr_t target = 0;
885 kxld_addr_t pair_target = 0;
886 char *demangled_name = NULL;
887 size_t demangled_length = 0;
888
889 check(_target);
890 check(_pair_target);
891 *_target = 0;
892 *_pair_target = 0;
893
894 /* Find the target based on the lookup type */
895
896 switch (reloc->target_type) {
897 case KXLD_TARGET_LOOKUP:
898 require_action(reloc->pair_target_type == KXLD_TARGET_NONE ||
899 reloc->pair_target_type == KXLD_TARGET_LOOKUP ||
900 reloc->pair_target_type == KXLD_TARGET_VALUE,
901 finish, rval = KERN_FAILURE);
902
903 rval = get_target_by_address_lookup(&target, reloc->target,
904 relocator->sectarray);
905 require_noerr(rval, finish);
906
907 if (reloc->pair_target_type == KXLD_TARGET_LOOKUP) {
908 rval = get_target_by_address_lookup(&pair_target,
909 reloc->pair_target, relocator->sectarray);
910 require_noerr(rval, finish);
911 } else if (reloc->pair_target_type == KXLD_TARGET_VALUE) {
912 pair_target = reloc->pair_target;
913 }
914 break;
915 case KXLD_TARGET_SECTNUM:
916 require_action(reloc->pair_target_type == KXLD_TARGET_NONE ||
917 reloc->pair_target_type == KXLD_TARGET_VALUE,
918 finish, rval = KERN_FAILURE);
919
920 /* Get the target's section by section number */
921 sect = kxld_array_get_item(relocator->sectarray, reloc->target);
922 require_action(sect, finish, rval = KERN_FAILURE);
923
924 /* target is the change in the section's address */
925 target = sect->link_addr - sect->base_addr;
926
927 if (reloc->pair_target_type) {
928 pair_target = reloc->pair_target;
929 } else {
930 /* x86_64 needs to know when we have a non-external relocation,
931 * so we hack that information in here.
932 */
933 pair_target = TRUE;
934 }
935 break;
936 case KXLD_TARGET_SYMBOLNUM:
937 require_action(reloc->pair_target_type == KXLD_TARGET_NONE ||
938 reloc->pair_target_type == KXLD_TARGET_GOT ||
939 reloc->pair_target_type == KXLD_TARGET_SYMBOLNUM ||
940 reloc->pair_target_type == KXLD_TARGET_VALUE, finish,
941 rval = KERN_FAILURE);
942
943 /* Get the target's symbol by symbol number */
944 sym = kxld_symtab_get_symbol_by_index(relocator->symtab, reloc->target);
945 require_action(sym, finish, rval = KERN_FAILURE);
946
947 /* If this symbol is a padslot that has already been replaced, then the
948 * only way a relocation entry can still reference it is if there is a
949 * vtable that has not been patched. The vtable patcher uses the
950 * MetaClass structure to find classes for patching, so an unpatched
951 * vtable means that there is an OSObject-dervied class that is missing
952 * its OSDeclare/OSDefine macros.
953 */
954 if (kxld_sym_is_padslot(sym) && kxld_sym_is_replaced(sym)) {
955 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogRelocatingPatchedSym,
956 kxld_demangle(sym->name, &demangled_name, &demangled_length));
957 }
958
959 target = sym->link_addr;
960
961 if (kxld_sym_is_vtable(sym)) {
962 relocator->current_vtable = kxld_dict_find(relocator->vtables, sym->name);
963 }
964
965 /* Some relocation types need the GOT entry address instead of the
966 * symbol's actual address. These types don't have pair relocation
967 * entries, so we store the GOT entry address as the pair target.
968 */
969 if (reloc->pair_target_type == KXLD_TARGET_VALUE) {
970 pair_target = reloc->pair_target;
971 } else if (reloc->pair_target_type == KXLD_TARGET_SYMBOLNUM) {
972 sym = kxld_symtab_get_symbol_by_index(relocator->symtab,
973 reloc->pair_target);
974 require_action(sym, finish, rval = KERN_FAILURE);
975 pair_target = sym->link_addr;
976 } else if (reloc->pair_target_type == KXLD_TARGET_GOT) {
977 pair_target = sym->got_addr;
978 }
979 break;
980 default:
981 rval = KERN_FAILURE;
982 goto finish;
983 }
984
985 *_target = target;
986 *_pair_target = pair_target;
987 rval = KERN_SUCCESS;
988
989 finish:
990 if (demangled_name) {
991 kxld_free(demangled_name, demangled_length);
992 }
993 return rval;
994 }
995
996 /*******************************************************************************
997 *******************************************************************************/
998 static kern_return_t
999 get_target_by_address_lookup(kxld_addr_t *target, kxld_addr_t addr,
1000 const KXLDArray *sectarray)
1001 {
1002 kern_return_t rval = KERN_FAILURE;
1003 const KXLDSect *sect = NULL;
1004 kxld_addr_t start = 0;
1005 kxld_addr_t end = 0;
1006 u_int i = 0;
1007
1008 check(target);
1009 check(sectarray);
1010 *target = 0;
1011
1012 for (i = 0; i < sectarray->nitems; ++i) {
1013 sect = kxld_array_get_item(sectarray, i);
1014 start = sect->base_addr;
1015 end = start + sect->size;
1016
1017 if (start <= addr && addr < end) {
1018 break;
1019 }
1020
1021 sect = NULL;
1022 }
1023 require_action(sect, finish, rval = KERN_FAILURE);
1024
1025 *target = sect->link_addr - sect->base_addr;
1026 rval = KERN_SUCCESS;
1027
1028 finish:
1029 return rval;
1030 }
1031
1032 /*******************************************************************************
1033 *******************************************************************************/
1034 static kern_return_t
1035 check_for_direct_pure_virtual_call(const KXLDRelocator *relocator, u_long offset)
1036 {
1037 kern_return_t rval = KERN_FAILURE;
1038 const KXLDVTableEntry *entry = NULL;
1039
1040 if (relocator->current_vtable) {
1041 entry = kxld_vtable_get_entry_for_offset(relocator->current_vtable,
1042 offset, relocator->is_32_bit);
1043 require_action(!entry || !entry->patched.name ||
1044 !kxld_sym_name_is_pure_virtual(entry->patched.name),
1045 finish, rval = KERN_FAILURE;
1046 kxld_log(kKxldLogLinking, kKxldLogErr,
1047 kKxldLogDirectPureVirtualCall));
1048 }
1049
1050 rval = KERN_SUCCESS;
1051 finish:
1052 return rval;
1053 }
1054
1055 #if KXLD_PIC_KEXTS
1056 /*******************************************************************************
1057 *******************************************************************************/
1058 static u_long
1059 get_macho_data_size_for_array(const KXLDArray *relocs)
1060 {
1061 const KXLDReloc *reloc = NULL;
1062 u_int i = 0;
1063 u_long size = 0;
1064
1065 check(relocs);
1066
1067 for (i = 0; i < relocs->nitems; ++i) {
1068 reloc = kxld_array_get_item(relocs, i);
1069 if (!reloc->pcrel) {
1070 size += sizeof(struct relocation_info);
1071 if (reloc->pair_target_type != KXLD_TARGET_NONE) {
1072 size += sizeof(struct relocation_info);
1073 }
1074 }
1075 }
1076
1077 return size;
1078 }
1079
1080 /*******************************************************************************
1081 *******************************************************************************/
1082 static kern_return_t
1083 export_macho_for_array(const KXLDRelocator *relocator,
1084 const KXLDArray *relocs, struct relocation_info **dstp)
1085 {
1086 kern_return_t rval = KERN_FAILURE;
1087 const KXLDReloc *reloc = NULL;
1088 struct relocation_info *dst = NULL;
1089 struct scattered_relocation_info *scatdst = NULL;
1090 u_int i = 0;
1091
1092 dst = *dstp;
1093
1094 for (i = 0; i < relocs->nitems; ++i) {
1095 reloc = kxld_array_get_item(relocs, i);
1096 scatdst = (struct scattered_relocation_info *) dst;
1097
1098 if (reloc->pcrel) {
1099 continue;
1100 }
1101
1102 switch (reloc->target_type) {
1103 case KXLD_TARGET_LOOKUP:
1104 if (kaslr_offsets) {
1105 if (kaslr_offsets_index >= kaslr_offsets_count) {
1106 kxld_log(kKxldLogLinking, kKxldLogErr,
1107 "kaslr_offsets overflow %d > %d <%s> ",
1108 kaslr_offsets_index, kaslr_offsets_count,
1109 __func__);
1110 abort();
1111 }
1112 // reloc->address is really an offset from the start of the kext
1113 *(kaslr_offsets + kaslr_offsets_index++) = reloc->address;
1114 }
1115 scatdst->r_address = reloc->address;
1116 scatdst->r_pcrel = reloc->pcrel;
1117 scatdst->r_length = reloc->length;
1118 scatdst->r_type = reloc->reloc_type;
1119 scatdst->r_value = reloc->target;
1120 scatdst->r_scattered = 1;
1121 break;
1122 case KXLD_TARGET_SECTNUM:
1123 if (kaslr_offsets) {
1124 if (kaslr_offsets_index >= kaslr_offsets_count) {
1125 kxld_log(kKxldLogLinking, kKxldLogErr,
1126 "kaslr_offsets overflow <%s> ", __func__);
1127 abort();
1128 }
1129 // reloc->address is really an offset from the start of the kext
1130 *(kaslr_offsets + kaslr_offsets_index++) = reloc->address;
1131 }
1132 dst->r_address = reloc->address;
1133 dst->r_pcrel = reloc->pcrel;
1134 dst->r_length = reloc->length;
1135 dst->r_type = reloc->reloc_type;
1136 dst->r_symbolnum = reloc->target + 1;
1137 dst->r_extern = 0;
1138 break;
1139 case KXLD_TARGET_SYMBOLNUM:
1140 /* Assume that everything will be slid together; otherwise,
1141 * there is no sensible value for the section number.
1142 */
1143 if (kaslr_offsets) {
1144 if (kaslr_offsets_index >= kaslr_offsets_count) {
1145 kxld_log(kKxldLogLinking, kKxldLogErr,
1146 "kaslr_offsets overflow <%s> ", __func__);
1147 abort();
1148 }
1149 // reloc->address is really an offset from the start of the kext
1150 *(kaslr_offsets + kaslr_offsets_index++) = reloc->address;
1151 }
1152 dst->r_address = reloc->address;
1153 dst->r_pcrel = reloc->pcrel;
1154 dst->r_length = reloc->length;
1155 dst->r_type = reloc->reloc_type;
1156 dst->r_symbolnum = 1;
1157 dst->r_extern = 0;
1158 break;
1159 default:
1160 rval = KERN_FAILURE;
1161 goto finish;
1162 }
1163
1164 ++dst;
1165
1166 if (reloc->pair_target_type != KXLD_TARGET_NONE) {
1167 ++i;
1168 require_action(i < relocs->nitems, finish, rval = KERN_FAILURE);
1169 scatdst = (struct scattered_relocation_info *) dst;
1170 switch (reloc->pair_target_type) {
1171 case KXLD_TARGET_LOOKUP:
1172 scatdst->r_address = reloc->pair_address;
1173 scatdst->r_pcrel = reloc->pcrel;
1174 scatdst->r_length = reloc->length;
1175 scatdst->r_type = relocator->reloc_get_pair_type(reloc->reloc_type);
1176 scatdst->r_value = reloc->pair_target;
1177 scatdst->r_scattered = 1;
1178 break;
1179 case KXLD_TARGET_SECTNUM:
1180 dst->r_address = reloc->pair_address;
1181 dst->r_pcrel = reloc->pcrel;
1182 dst->r_length = reloc->length;
1183 dst->r_type = relocator->reloc_get_pair_type(reloc->reloc_type);
1184 dst->r_symbolnum = reloc->pair_target + 1;
1185 dst->r_extern = 0;
1186 break;
1187 case KXLD_TARGET_SYMBOLNUM:
1188 dst->r_address = reloc->pair_address;
1189 dst->r_pcrel = reloc->pcrel;
1190 dst->r_length = reloc->length;
1191 dst->r_type = relocator->reloc_get_pair_type(reloc->reloc_type);
1192 dst->r_symbolnum = 1;
1193 dst->r_extern = 0;
1194 break;
1195 default:
1196 rval = KERN_FAILURE;
1197 goto finish;
1198 }
1199 ++dst;
1200 }
1201 }
1202
1203 rval = KERN_SUCCESS;
1204 finish:
1205 *dstp = dst;
1206 return rval;
1207 }
1208 #endif /* KXLD_PIC_KEXTS */
1209
1210 #if KXLD_USER_OR_I386
1211 /*******************************************************************************
1212 *******************************************************************************/
1213 static boolean_t
1214 generic_reloc_has_pair(u_int _type)
1215 {
1216 enum reloc_type_generic type = _type;
1217
1218 return type == GENERIC_RELOC_SECTDIFF ||
1219 type == GENERIC_RELOC_LOCAL_SECTDIFF;
1220 }
1221
1222 /*******************************************************************************
1223 *******************************************************************************/
1224 static u_int
1225 generic_reloc_get_pair_type(u_int _prev_type __unused)
1226 {
1227 return GENERIC_RELOC_PAIR;
1228 }
1229
1230 /*******************************************************************************
1231 *******************************************************************************/
1232 static boolean_t
1233 generic_reloc_has_got(u_int _type __unused)
1234 {
1235 return FALSE;
1236 }
1237
1238 /*******************************************************************************
1239 *******************************************************************************/
1240 static kern_return_t
1241 generic_process_reloc(const KXLDRelocator *relocator, u_char *instruction,
1242 u_int length, u_int pcrel, kxld_addr_t _base_pc, kxld_addr_t _link_pc,
1243 kxld_addr_t _link_disp __unused, u_int _type, kxld_addr_t _target,
1244 kxld_addr_t _pair_target, boolean_t swap __unused)
1245 {
1246 kern_return_t rval = KERN_FAILURE;
1247 uint32_t base_pc = (uint32_t) _base_pc;
1248 uint32_t link_pc = (uint32_t) _link_pc;
1249 uint32_t *instr_addr = NULL;
1250 uint32_t instr_data = 0;
1251 uint32_t target = (uint32_t) _target;
1252 uint32_t pair_target = (uint32_t) _pair_target;
1253 enum reloc_type_generic type = _type;
1254
1255 check(instruction);
1256 require_action(length == 2, finish, rval = KERN_FAILURE);
1257
1258 if (pcrel) {
1259 target = target + base_pc - link_pc;
1260 }
1261
1262 instr_addr = (uint32_t *) ((void *) instruction);
1263 instr_data = *instr_addr;
1264
1265 #if !KERNEL
1266 if (swap) {
1267 instr_data = OSSwapInt32(instr_data);
1268 }
1269 #endif
1270
1271 rval = check_for_direct_pure_virtual_call(relocator, instr_data);
1272 require_noerr(rval, finish);
1273
1274 switch (type) {
1275 case GENERIC_RELOC_VANILLA:
1276 instr_data += target;
1277 break;
1278 case GENERIC_RELOC_SECTDIFF:
1279 case GENERIC_RELOC_LOCAL_SECTDIFF:
1280 instr_data = instr_data + target - pair_target;
1281 break;
1282 case GENERIC_RELOC_PB_LA_PTR:
1283 rval = KERN_FAILURE;
1284 goto finish;
1285 case GENERIC_RELOC_PAIR:
1286 default:
1287 rval = KERN_FAILURE;
1288 goto finish;
1289 }
1290
1291 #if !KERNEL
1292 if (swap) {
1293 instr_data = OSSwapInt32(instr_data);
1294 }
1295 #endif
1296
1297 *instr_addr = instr_data;
1298
1299 rval = KERN_SUCCESS;
1300
1301 finish:
1302 return rval;
1303 }
1304 #endif /* KXLD_USER_OR_I386 */
1305
1306 #if KXLD_USER_OR_X86_64
1307 /*******************************************************************************
1308 *******************************************************************************/
1309 static boolean_t
1310 x86_64_reloc_has_pair(u_int _type)
1311 {
1312 enum reloc_type_x86_64 type = _type;
1313
1314 return type == X86_64_RELOC_SUBTRACTOR;
1315 }
1316
1317 /*******************************************************************************
1318 *******************************************************************************/
1319 static u_int
1320 x86_64_reloc_get_pair_type(u_int _prev_type __unused)
1321 {
1322 return X86_64_RELOC_UNSIGNED;
1323 }
1324
1325 /*******************************************************************************
1326 *******************************************************************************/
1327 static boolean_t
1328 x86_64_reloc_has_got(u_int _type)
1329 {
1330 enum reloc_type_x86_64 type = _type;
1331
1332 return type == X86_64_RELOC_GOT_LOAD || type == X86_64_RELOC_GOT;
1333 }
1334
1335 /*******************************************************************************
1336 *******************************************************************************/
1337 static kern_return_t
1338 x86_64_process_reloc(const KXLDRelocator *relocator __unused, u_char *instruction,
1339 u_int length, u_int pcrel, kxld_addr_t _base_pc __unused,
1340 kxld_addr_t _link_pc, kxld_addr_t _link_disp, u_int _type,
1341 kxld_addr_t _target, kxld_addr_t _pair_target, boolean_t swap __unused)
1342 {
1343 kern_return_t rval = KERN_FAILURE;
1344 enum reloc_type_x86_64 type = _type;
1345 int32_t *instr32p = NULL;
1346 int32_t instr32 = 0;
1347 uint64_t *instr64p = NULL;
1348 uint64_t instr64 = 0;
1349 uint64_t target = _target;
1350 uint64_t pair_target = _pair_target;
1351 uint64_t link_pc = (uint64_t) _link_pc;
1352 uint64_t link_disp = (uint64_t) _link_disp;
1353 uint64_t adjustment = 0;
1354
1355 check(instruction);
1356 require_action(length == 2 || length == 3,
1357 finish, rval = KERN_FAILURE);
1358
1359 if (length == 2) {
1360 instr32p = (int32_t *) ((void *) instruction);
1361 instr32 = *instr32p;
1362
1363 #if !KERNEL
1364 if (swap) {
1365 instr32 = OSSwapInt32(instr32);
1366 }
1367 #endif
1368
1369 rval = check_for_direct_pure_virtual_call(relocator, instr32);
1370 require_noerr(rval, finish);
1371
1372 /* There are a number of different small adjustments for pc-relative
1373 * relocation entries. The general case is to subtract the size of the
1374 * relocation (represented by the length parameter), and it applies to
1375 * the GOT types and external SIGNED types. The non-external signed types
1376 * have a different adjustment corresponding to the specific type.
1377 */
1378 switch (type) {
1379 case X86_64_RELOC_SIGNED:
1380 if (pair_target) {
1381 adjustment = 0;
1382 break;
1383 }
1384 /* Fall through */
1385 case X86_64_RELOC_SIGNED_1:
1386 if (pair_target) {
1387 adjustment = 1;
1388 break;
1389 }
1390 /* Fall through */
1391 case X86_64_RELOC_SIGNED_2:
1392 if (pair_target) {
1393 adjustment = 2;
1394 break;
1395 }
1396 /* Fall through */
1397 case X86_64_RELOC_SIGNED_4:
1398 if (pair_target) {
1399 adjustment = 4;
1400 break;
1401 }
1402 /* Fall through */
1403 case X86_64_RELOC_BRANCH:
1404 case X86_64_RELOC_GOT:
1405 case X86_64_RELOC_GOT_LOAD:
1406 adjustment = (1 << length);
1407 break;
1408 default:
1409 break;
1410 }
1411
1412 /* Perform the actual relocation. All of the 32-bit relocations are
1413 * pc-relative except for SUBTRACTOR, so a good chunk of the logic is
1414 * stuck in calculate_displacement_x86_64. The signed relocations are
1415 * a special case, because when they are non-external, the instruction
1416 * already contains the pre-relocation displacement, so we only need to
1417 * find the difference between how far the PC was relocated, and how
1418 * far the target is relocated. Since the target variable already
1419 * contains the difference between the target's base and link
1420 * addresses, we add the difference between the PC's base and link
1421 * addresses to the adjustment variable. This will yield the
1422 * appropriate displacement in calculate_displacement.
1423 */
1424 switch (type) {
1425 case X86_64_RELOC_BRANCH:
1426 require_action(pcrel, finish, rval = KERN_FAILURE);
1427 adjustment += link_pc;
1428 break;
1429 case X86_64_RELOC_SIGNED:
1430 case X86_64_RELOC_SIGNED_1:
1431 case X86_64_RELOC_SIGNED_2:
1432 case X86_64_RELOC_SIGNED_4:
1433 require_action(pcrel, finish, rval = KERN_FAILURE);
1434 adjustment += (pair_target) ? (link_disp) : (link_pc);
1435 break;
1436 case X86_64_RELOC_GOT:
1437 case X86_64_RELOC_GOT_LOAD:
1438 require_action(pcrel, finish, rval = KERN_FAILURE);
1439 adjustment += link_pc;
1440 target = pair_target;
1441 break;
1442 case X86_64_RELOC_SUBTRACTOR:
1443 require_action(!pcrel, finish, rval = KERN_FAILURE);
1444 instr32 = (int32_t) (target - pair_target);
1445 break;
1446 case X86_64_RELOC_UNSIGNED:
1447 default:
1448 rval = KERN_FAILURE;
1449 goto finish;
1450 }
1451
1452 /* Call calculate_displacement for the pc-relative relocations */
1453 if (pcrel) {
1454 rval = calculate_displacement_x86_64(target, adjustment, &instr32);
1455 require_noerr(rval, finish);
1456 }
1457
1458 #if !KERNEL
1459 if (swap) {
1460 instr32 = OSSwapInt32(instr32);
1461 }
1462 #endif
1463
1464 *instr32p = instr32;
1465 } else {
1466 instr64p = (uint64_t *) ((void *) instruction);
1467 instr64 = *instr64p;
1468
1469 #if !KERNEL
1470 if (swap) {
1471 instr64 = OSSwapInt64(instr64);
1472 }
1473 #endif
1474
1475 rval = check_for_direct_pure_virtual_call(relocator, (u_long) instr64);
1476 require_noerr(rval, finish);
1477
1478 switch (type) {
1479 case X86_64_RELOC_UNSIGNED:
1480 require_action(!pcrel, finish, rval = KERN_FAILURE);
1481
1482 instr64 += target;
1483 break;
1484 case X86_64_RELOC_SUBTRACTOR:
1485 require_action(!pcrel, finish, rval = KERN_FAILURE);
1486
1487 instr64 = target - pair_target;
1488 break;
1489 case X86_64_RELOC_SIGNED_1:
1490 case X86_64_RELOC_SIGNED_2:
1491 case X86_64_RELOC_SIGNED_4:
1492 case X86_64_RELOC_GOT_LOAD:
1493 case X86_64_RELOC_BRANCH:
1494 case X86_64_RELOC_SIGNED:
1495 case X86_64_RELOC_GOT:
1496 default:
1497 rval = KERN_FAILURE;
1498 goto finish;
1499 }
1500
1501 #if !KERNEL
1502 if (swap) {
1503 instr64 = OSSwapInt64(instr64);
1504 }
1505 #endif
1506 *instr64p = instr64;
1507 }
1508
1509 rval = KERN_SUCCESS;
1510
1511 finish:
1512 return rval;
1513 }
1514
1515 /*******************************************************************************
1516 *******************************************************************************/
1517 static kern_return_t
1518 calculate_displacement_x86_64(uint64_t target, uint64_t adjustment,
1519 int32_t *instr32)
1520 {
1521 kern_return_t rval = KERN_FAILURE;
1522 int64_t displacement;
1523 uint64_t difference;
1524
1525 displacement = *instr32 + target - adjustment;
1526 difference = ABSOLUTE_VALUE(displacement);
1527 require_action(difference < X86_64_RIP_RELATIVE_LIMIT, finish,
1528 rval = KERN_FAILURE;
1529 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogRelocationOverflow));
1530
1531 *instr32 = (int32_t) displacement;
1532 rval = KERN_SUCCESS;
1533
1534 finish:
1535 return rval;
1536 }
1537 #endif /* KXLD_USER_OR_X86_64 */
1538
1539 #if KXLD_USER_OR_ARM
1540 /*******************************************************************************
1541 *******************************************************************************/
1542 static boolean_t
1543 arm_reloc_has_pair(u_int _type)
1544 {
1545 enum reloc_type_arm type = _type;
1546
1547 switch (type) {
1548 case ARM_RELOC_SECTDIFF:
1549 return TRUE;
1550 default:
1551 return FALSE;
1552 }
1553 return FALSE;
1554 }
1555
1556 /*******************************************************************************
1557 *******************************************************************************/
1558 static u_int
1559 arm_reloc_get_pair_type(u_int _prev_type __unused)
1560 {
1561 return ARM_RELOC_PAIR;
1562 }
1563
1564 /*******************************************************************************
1565 *******************************************************************************/
1566 static boolean_t
1567 arm_reloc_has_got(u_int _type __unused)
1568 {
1569 return FALSE;
1570 }
1571
1572 /*******************************************************************************
1573 *******************************************************************************/
1574 static kern_return_t
1575 arm_process_reloc(const KXLDRelocator *relocator __unused, u_char *instruction,
1576 u_int length, u_int pcrel, kxld_addr_t _base_pc __unused,
1577 kxld_addr_t _link_pc __unused, kxld_addr_t _link_disp __unused,
1578 u_int _type __unused, kxld_addr_t _target __unused,
1579 kxld_addr_t _pair_target __unused, boolean_t swap __unused)
1580 {
1581 kern_return_t rval = KERN_FAILURE;
1582 uint32_t *instr_addr = NULL;
1583 uint32_t instr_data = 0;
1584 uint32_t base_pc = (uint32_t) _base_pc;
1585 uint32_t link_pc = (uint32_t) _link_pc;
1586 uint32_t target = (uint32_t) _target;
1587 int32_t displacement = 0;
1588 enum reloc_type_arm type = _type;
1589
1590 check(instruction);
1591 require_action(length == 2, finish, rval = KERN_FAILURE);
1592
1593 if (pcrel) {
1594 displacement = target + base_pc - link_pc;
1595 }
1596
1597 instr_addr = (uint32_t *) ((void *) instruction);
1598 instr_data = *instr_addr;
1599
1600 #if !KERNEL
1601 if (swap) {
1602 instr_data = OSSwapInt32(instr_data);
1603 }
1604 #endif
1605
1606 rval = check_for_direct_pure_virtual_call(relocator, instr_data);
1607 require_noerr(rval, finish);
1608
1609 switch (type) {
1610 case ARM_RELOC_VANILLA:
1611 instr_data += target;
1612 break;
1613
1614 /*
1615 * If the displacement is 0 (the offset between the pc and the target has
1616 * not changed), then we don't need to do anything for BR24 and BR22
1617 * relocs. As it turns out, because kexts build with -mlong-calls all
1618 * relocations currently end up being either vanilla (handled above) or
1619 * BR22/BR24 with a displacement of 0.
1620 * We could handle other displacements here but to keep things simple, we
1621 * won't until it is needed (at which point the kernelcache will fail to
1622 * link)
1623 */
1624 case ARM_RELOC_BR24:
1625 require_action(pcrel, finish, rval = KERN_FAILURE);
1626 require_action(displacement == 0, finish, rval = KERN_FAILURE);
1627 break;
1628 case ARM_THUMB_RELOC_BR22:
1629 require_action(pcrel, finish, rval = KERN_FAILURE);
1630 require_action(displacement == 0, finish, rval = KERN_FAILURE);
1631 break;
1632
1633 case ARM_RELOC_SECTDIFF:
1634 case ARM_RELOC_LOCAL_SECTDIFF:
1635 case ARM_RELOC_PB_LA_PTR:
1636 rval = KERN_FAILURE;
1637 goto finish;
1638
1639 case ARM_RELOC_PAIR:
1640 default:
1641 rval = KERN_FAILURE;
1642 goto finish;
1643 }
1644
1645 #if !KERNEL
1646 if (swap) {
1647 instr_data = OSSwapInt32(instr_data);
1648 }
1649 #endif
1650
1651 *instr_addr = instr_data;
1652
1653 rval = KERN_SUCCESS;
1654
1655 finish:
1656 return rval;
1657 }
1658
1659 #endif /* KXLD_USER_OR_ARM */
1660
1661 #if KXLD_USER_OR_ARM64
1662 /*******************************************************************************
1663 *******************************************************************************/
1664 boolean_t
1665 arm64_reloc_has_pair(u_int _type)
1666 {
1667 return _type == ARM64_RELOC_SUBTRACTOR;
1668 }
1669
1670 /*******************************************************************************
1671 *******************************************************************************/
1672 u_int
1673 arm64_reloc_get_pair_type(u_int _prev_type __unused)
1674 {
1675 if (_prev_type == ARM64_RELOC_SUBTRACTOR) {
1676 return ARM64_RELOC_UNSIGNED;
1677 } else {
1678 return -1u;
1679 }
1680 }
1681
1682 /*******************************************************************************
1683 *******************************************************************************/
1684 boolean_t
1685 arm64_reloc_has_got(u_int _type)
1686 {
1687 return _type == ARM64_RELOC_GOT_LOAD_PAGE21 ||
1688 _type == ARM64_RELOC_GOT_LOAD_PAGEOFF12;
1689 }
1690
1691 /*******************************************************************************
1692 *******************************************************************************/
1693 kern_return_t
1694 arm64_process_reloc(const KXLDRelocator *relocator __unused, u_char *instruction,
1695 u_int length, u_int pcrel, kxld_addr_t _base_pc __unused, kxld_addr_t _link_pc,
1696 kxld_addr_t _link_disp __unused, u_int _type, kxld_addr_t _target,
1697 kxld_addr_t _pair_target __unused, boolean_t swap)
1698 {
1699 kern_return_t rval = KERN_FAILURE;
1700 enum reloc_type_arm64 type = _type;
1701 uint64_t target = _target;
1702 uint64_t link_pc = (uint64_t) _link_pc;
1703 uint64_t difference = 0;
1704 int64_t displacement = 0;
1705 uint32_t addend = 0;
1706
1707 check(instruction);
1708 require_action((length == 2 || length == 3), finish, rval = KERN_FAILURE);
1709
1710 if (length == 2) {
1711 uint32_t *instr32p = (uint32_t *) (void *) instruction;
1712 uint32_t instr32 = *instr32p;
1713
1714 #if !KERNEL
1715 if (swap) {
1716 instr32 = OSSwapInt32(instr32);
1717 }
1718 #endif
1719
1720 switch (type) {
1721 case ARM64_RELOC_BRANCH26:
1722 require_action(pcrel, finish, rval = KERN_FAILURE);
1723 addend = (instr32 & 0x03FFFFFF) << 2;
1724 addend = SIGN_EXTEND(addend, 27);
1725 displacement = (target - link_pc + addend);
1726 difference = ABSOLUTE_VALUE(displacement);
1727 displacement = (displacement >> 2);
1728 require_action(difference < (128 * 1024 * 1024), finish,
1729 rval = KERN_FAILURE;
1730 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogRelocationOverflow));
1731 instr32 = (instr32 & 0xFC000000) | (displacement & 0x03FFFFFF);
1732 break;
1733
1734 default:
1735 rval = KERN_FAILURE;
1736 goto finish;
1737 }
1738
1739 #if !KERNEL
1740 if (swap) {
1741 instr32 = OSSwapInt32(instr32);
1742 }
1743 #endif
1744
1745 *instr32p = instr32;
1746 } else { /* length == 3 */
1747 uint64_t *instr64p = (uint64_t *) (void *) instruction;
1748 uint64_t instr64 = *instr64p;
1749
1750 #if !KERNEL
1751 if (swap) {
1752 instr64 = OSSwapInt64(instr64);
1753 }
1754 #endif
1755
1756 switch (type) {
1757 case ARM64_RELOC_UNSIGNED:
1758 require_action(!pcrel, finish, rval = KERN_FAILURE);
1759 instr64 += target;
1760 break;
1761 default:
1762 rval = KERN_FAILURE;
1763 goto finish;
1764 }
1765
1766 #if !KERNEL
1767 if (swap) {
1768 instr64 = OSSwapInt64(instr64);
1769 }
1770 #endif
1771
1772 *instr64p = instr64;
1773 }
1774
1775 rval = KERN_SUCCESS;
1776 finish:
1777 return rval;
1778 }
1779
1780
1781 #endif /* KXLD_USER_OR_ARM64 */