]> git.saurik.com Git - apple/xnu.git/blob - libkern/kxld/kxld_reloc.c
xnu-4903.221.2.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
309 /* Allocate the array of relocation entries */
310
311 rval = kxld_array_init(relocarray, sizeof(KXLDReloc), nrelocs);
312 require_noerr(rval, finish);
313
314 /* Initialize the relocation entries */
315
316 for (i = 0; i < nsrcs; ++i) {
317 src = srcs + i;
318 scatsrc = (const struct scattered_relocation_info *) src;
319
320 /* A section-based relocation entry can be skipped for absolute
321 * symbols.
322 */
323
324 if (!(relocator->may_scatter && (src->r_address & R_SCATTERED)) &&
325 !(src->r_extern) && (R_ABS == src->r_symbolnum))
326 {
327 continue;
328 }
329
330 /* Pull out the data from the relocation entries. The target_type
331 * depends on the r_extern bit:
332 * Scattered -> Section Lookup by Address
333 * Local (not extern) -> Section by Index
334 * Extern -> Symbolnum by Index
335 */
336 reloc = kxld_array_get_item(relocarray, reloc_index++);
337 if (relocator->may_scatter && (src->r_address & R_SCATTERED)) {
338 reloc->address = scatsrc->r_address;
339 reloc->pcrel = scatsrc->r_pcrel;
340 reloc->length = scatsrc->r_length;
341 reloc->reloc_type = scatsrc->r_type;
342 reloc->target = scatsrc->r_value;
343 reloc->target_type = KXLD_TARGET_LOOKUP;
344 } else {
345 reloc->address = src->r_address;
346 reloc->pcrel = src->r_pcrel;
347 reloc->length = src->r_length;
348 reloc->reloc_type = src->r_type;
349 reloc->target = src->r_symbolnum;
350
351 if (0 == src->r_extern) {
352 reloc->target_type = KXLD_TARGET_SECTNUM;
353 reloc->target -= 1;
354 } else {
355 reloc->target_type = KXLD_TARGET_SYMBOLNUM;
356 }
357 }
358
359 /* Find the pair entry if it exists */
360
361 if (relocator->reloc_has_pair(reloc->reloc_type)) {
362 ++i;
363 require_action(i < nsrcs, finish, rval=KERN_FAILURE);
364
365 src = srcs + i;
366 scatsrc = (const struct scattered_relocation_info *) src;
367
368 if (relocator->may_scatter && (src->r_address & R_SCATTERED)) {
369 require_action(relocator->reloc_get_pair_type(
370 reloc->reloc_type) == scatsrc->r_type,
371 finish, rval=KERN_FAILURE);
372 reloc->pair_address= scatsrc->r_address;
373 reloc->pair_target = scatsrc->r_value;
374 reloc->pair_target_type = KXLD_TARGET_LOOKUP;
375 } else {
376 require_action(relocator->reloc_get_pair_type(
377 reloc->reloc_type) == scatsrc->r_type,
378 finish, rval=KERN_FAILURE);
379 reloc->pair_address = scatsrc->r_address;
380 if (src->r_extern) {
381 reloc->pair_target = src->r_symbolnum;
382 reloc->pair_target_type = KXLD_TARGET_SYMBOLNUM;
383 } else {
384 reloc->pair_target = src->r_address;
385 reloc->pair_target_type = KXLD_TARGET_VALUE;
386 }
387 }
388 } else {
389 reloc->pair_target = 0;
390 if (relocator->reloc_has_got(reloc->reloc_type)) {
391 reloc->pair_target_type = KXLD_TARGET_GOT;
392 } else {
393 reloc->pair_target_type = KXLD_TARGET_NONE;
394 }
395 }
396 } // for...
397 }
398 rval = KERN_SUCCESS;
399
400 finish:
401 return rval;
402 }
403
404
405 /*******************************************************************************
406 * Relocatable relocs :
407 * 1) Are not _PAIR_ relocs
408 * 2) Don't reference N_ABS symbols
409 *******************************************************************************/
410 static u_int
411 count_relocatable_relocs(const KXLDRelocator *relocator,
412 const struct relocation_info *relocs, u_int nrelocs)
413 {
414 u_int num_nonpair_relocs = 0;
415 u_int i = 0;
416 const struct relocation_info *reloc = NULL;
417 const struct scattered_relocation_info *sreloc = NULL;
418
419 check(relocator);
420 check(relocs);
421
422 /* Loop over all of the relocation entries */
423
424 num_nonpair_relocs = 1;
425 for (i = 1; i < nrelocs; ++i) {
426 reloc = relocs + i;
427
428 if (reloc->r_address & R_SCATTERED) {
429 /* A scattered relocation entry is relocatable as long as it's not a
430 * pair.
431 */
432 sreloc = (const struct scattered_relocation_info *) reloc;
433
434 num_nonpair_relocs +=
435 !relocator->reloc_has_pair(sreloc->r_type);
436 } else {
437 /* A normal relocation entry is relocatable if it is not a pair and
438 * if it is not a section-based relocation for an absolute symbol.
439 */
440 num_nonpair_relocs +=
441 !(relocator->reloc_has_pair(reloc->r_type)
442 || (0 == reloc->r_extern && R_ABS == reloc->r_symbolnum));
443 }
444
445 }
446
447 return num_nonpair_relocs;
448 }
449
450 /*******************************************************************************
451 *******************************************************************************/
452 void
453 kxld_relocator_clear(KXLDRelocator *relocator)
454 {
455 bzero(relocator, sizeof(*relocator));
456 }
457
458 /*******************************************************************************
459 *******************************************************************************/
460 boolean_t
461 kxld_relocator_has_pair(const KXLDRelocator *relocator, u_int r_type)
462 {
463 check(relocator);
464
465 return relocator->reloc_has_pair(r_type);
466 }
467
468 /*******************************************************************************
469 *******************************************************************************/
470 u_int
471 kxld_relocator_get_pair_type(const KXLDRelocator *relocator,
472 u_int prev_r_type)
473 {
474 check(relocator);
475
476 return relocator->reloc_get_pair_type(prev_r_type);
477 }
478
479 /*******************************************************************************
480 *******************************************************************************/
481 boolean_t
482 kxld_relocator_has_got(const KXLDRelocator *relocator, u_int r_type)
483 {
484 check(relocator);
485
486 return relocator->reloc_has_got(r_type);
487 }
488
489 /*******************************************************************************
490 *******************************************************************************/
491 KXLDSym *
492 kxld_reloc_get_symbol(const KXLDRelocator *relocator, const KXLDReloc *reloc,
493 const u_char *data)
494 {
495 KXLDSym *sym = NULL;
496 kxld_addr_t value = 0;
497
498 check(reloc);
499
500 switch (reloc->target_type) {
501 case KXLD_TARGET_SYMBOLNUM:
502 sym = kxld_symtab_get_symbol_by_index(relocator->symtab, reloc->target);
503 break;
504 case KXLD_TARGET_SECTNUM:
505 if (data) {
506 value = kxld_relocator_get_pointer_at_addr(relocator, data,
507 reloc->address);
508 sym = kxld_symtab_get_cxx_symbol_by_value(relocator->symtab, value);
509 }
510 break;
511 default:
512 sym = NULL;
513 break;
514 }
515
516 return sym;
517 }
518
519 /*******************************************************************************
520 *******************************************************************************/
521 kern_return_t
522 kxld_reloc_get_reloc_index_by_offset(const KXLDArray *relocs,
523 kxld_size_t offset, u_int *idx)
524 {
525 kern_return_t rval = KERN_FAILURE;
526 KXLDReloc *reloc = NULL;
527 u_int i = 0;
528
529 for (i = 0; i < relocs->nitems; ++i) {
530 reloc = kxld_array_get_item(relocs, i);
531 if (reloc->address == offset) break;
532 }
533
534 if (i >= relocs->nitems) {
535 rval = KERN_FAILURE;
536 goto finish;
537 }
538
539 *idx = i;
540 rval = KERN_SUCCESS;
541
542 finish:
543 return rval;
544 }
545
546 /*******************************************************************************
547 *******************************************************************************/
548 KXLDReloc *
549 kxld_reloc_get_reloc_by_offset(const KXLDArray *relocs, kxld_addr_t offset)
550 {
551 kern_return_t rval = KERN_FAILURE;
552 KXLDReloc *reloc = NULL;
553 u_int i = 0;
554
555 rval = kxld_reloc_get_reloc_index_by_offset(relocs, offset, &i);
556 if (rval) goto finish;
557
558 reloc = kxld_array_get_item(relocs, i);
559
560 finish:
561 return reloc;
562 }
563
564 #if KXLD_PIC_KEXTS
565 /*******************************************************************************
566 *******************************************************************************/
567 u_long
568 kxld_reloc_get_macho_header_size()
569 {
570 return sizeof(struct dysymtab_command);
571 }
572
573 /*******************************************************************************
574 *******************************************************************************/
575 u_long
576 kxld_reloc_get_macho_data_size(
577 const KXLDArray *locrelocs,
578 const KXLDArray *extrelocs)
579 {
580 u_long rval = 0;
581
582 rval += get_macho_data_size_for_array(locrelocs);
583 rval += get_macho_data_size_for_array(extrelocs);
584
585 return (rval);
586 }
587
588 /*******************************************************************************
589 *******************************************************************************/
590 kern_return_t
591 kxld_reloc_export_macho(const KXLDRelocator *relocator,
592 const KXLDArray *locrelocs, const KXLDArray *extrelocs,
593 u_char *buf, u_long *header_offset, u_long header_size,
594 u_long *data_offset, u_long size)
595 {
596 kern_return_t rval = KERN_FAILURE;
597 struct dysymtab_command *dysymtabhdr = NULL;
598 struct relocation_info *start = NULL;
599 struct relocation_info *dst = NULL;
600 u_long count = 0;
601 u_long data_size = 0;
602
603 check(locrelocs);
604 check(extrelocs);
605 check(buf);
606 check(header_offset);
607 check(data_offset);
608
609 require_action(sizeof(*dysymtabhdr) <= header_size - *header_offset, finish, rval=KERN_FAILURE);
610 dysymtabhdr = (struct dysymtab_command *) ((void *) (buf + *header_offset));
611 *header_offset += sizeof(*dysymtabhdr);
612
613 data_size = kxld_reloc_get_macho_data_size(locrelocs, extrelocs);
614 require_action((*data_offset + data_size) <= size, finish, rval=KERN_FAILURE);
615
616 start = dst = (struct relocation_info *) ((void *) (buf + *data_offset));
617
618 if (kaslr_offsets == NULL) {
619 kaslr_offsets_index = 0;
620 kaslr_offsets_count = locrelocs->nitems + extrelocs->nitems;
621 kaslr_offsets = (uint32_t *)malloc(kaslr_offsets_count * sizeof(*kaslr_offsets));
622 bzero(kaslr_offsets, kaslr_offsets_count * sizeof(*kaslr_offsets));
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 require_action(!kxld_sym_is_padslot(sym) || !kxld_sym_is_replaced(sym),
955 finish, rval=KERN_FAILURE;
956 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogRelocatingPatchedSym,
957 kxld_demangle(sym->name, &demangled_name, &demangled_length)));
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) kxld_free(demangled_name, demangled_length);
991 return rval;
992 }
993
994 /*******************************************************************************
995 *******************************************************************************/
996 static kern_return_t
997 get_target_by_address_lookup(kxld_addr_t *target, kxld_addr_t addr,
998 const KXLDArray *sectarray)
999 {
1000 kern_return_t rval = KERN_FAILURE;
1001 const KXLDSect *sect = NULL;
1002 kxld_addr_t start = 0;
1003 kxld_addr_t end = 0;
1004 u_int i = 0;
1005
1006 check(target);
1007 check(sectarray);
1008 *target = 0;
1009
1010 for (i = 0; i < sectarray->nitems; ++i) {
1011 sect = kxld_array_get_item(sectarray, i);
1012 start = sect->base_addr;
1013 end = start + sect->size;
1014
1015 if (start <= addr && addr < end) break;
1016
1017 sect = NULL;
1018 }
1019 require_action(sect, finish, rval=KERN_FAILURE);
1020
1021 *target = sect->link_addr - sect->base_addr;
1022 rval = KERN_SUCCESS;
1023
1024 finish:
1025 return rval;
1026 }
1027
1028 /*******************************************************************************
1029 *******************************************************************************/
1030 static kern_return_t
1031 check_for_direct_pure_virtual_call(const KXLDRelocator *relocator, u_long offset)
1032 {
1033 kern_return_t rval = KERN_FAILURE;
1034 const KXLDVTableEntry *entry = NULL;
1035
1036 if (relocator->current_vtable) {
1037 entry = kxld_vtable_get_entry_for_offset(relocator->current_vtable,
1038 offset, relocator->is_32_bit);
1039 require_action(!entry || !entry->patched.name ||
1040 !kxld_sym_name_is_pure_virtual(entry->patched.name),
1041 finish, rval=KERN_FAILURE;
1042 kxld_log(kKxldLogLinking, kKxldLogErr,
1043 kKxldLogDirectPureVirtualCall));
1044 }
1045
1046 rval = KERN_SUCCESS;
1047 finish:
1048 return rval;
1049 }
1050
1051 #if KXLD_PIC_KEXTS
1052 /*******************************************************************************
1053 *******************************************************************************/
1054 static u_long
1055 get_macho_data_size_for_array(const KXLDArray *relocs)
1056 {
1057 const KXLDReloc *reloc = NULL;
1058 u_int i = 0;
1059 u_long size = 0;
1060
1061 check(relocs);
1062
1063 for (i = 0; i < relocs->nitems; ++i) {
1064 reloc = kxld_array_get_item(relocs, i);
1065 if (!reloc->pcrel) {
1066 size += sizeof(struct relocation_info);
1067 if(reloc->pair_target_type != KXLD_TARGET_NONE) {
1068 size += sizeof(struct relocation_info);
1069 }
1070 }
1071 }
1072
1073 return size;
1074 }
1075
1076 /*******************************************************************************
1077 *******************************************************************************/
1078 static kern_return_t
1079 export_macho_for_array(const KXLDRelocator *relocator,
1080 const KXLDArray *relocs, struct relocation_info **dstp)
1081 {
1082 kern_return_t rval = KERN_FAILURE;
1083 const KXLDReloc *reloc = NULL;
1084 struct relocation_info *dst = NULL;
1085 struct scattered_relocation_info *scatdst = NULL;
1086 u_int i = 0;
1087
1088 dst = *dstp;
1089
1090 for (i = 0; i < relocs->nitems; ++i) {
1091 reloc = kxld_array_get_item(relocs, i);
1092 scatdst = (struct scattered_relocation_info *) dst;
1093
1094 if (reloc->pcrel) {
1095 continue;
1096 }
1097
1098 switch (reloc->target_type) {
1099 case KXLD_TARGET_LOOKUP:
1100 if (kaslr_offsets) {
1101 if (kaslr_offsets_index >= kaslr_offsets_count) {
1102 kxld_log(kKxldLogLinking, kKxldLogErr,
1103 "kaslr_offsets overflow %d > %d <%s> ",
1104 kaslr_offsets_index, kaslr_offsets_count,
1105 __func__);
1106 abort();
1107 }
1108 // reloc->address is really an offset from the start of the kext
1109 *(kaslr_offsets + kaslr_offsets_index++) = reloc->address;
1110 }
1111 scatdst->r_address = reloc->address;
1112 scatdst->r_pcrel = reloc->pcrel;
1113 scatdst->r_length = reloc->length;
1114 scatdst->r_type = reloc->reloc_type;
1115 scatdst->r_value = reloc->target;
1116 scatdst->r_scattered = 1;
1117 break;
1118 case KXLD_TARGET_SECTNUM:
1119 if (kaslr_offsets) {
1120 if (kaslr_offsets_index >= kaslr_offsets_count) {
1121 kxld_log(kKxldLogLinking, kKxldLogErr,
1122 "kaslr_offsets overflow <%s> ", __func__);
1123 abort();
1124 }
1125 // reloc->address is really an offset from the start of the kext
1126 *(kaslr_offsets + kaslr_offsets_index++) = reloc->address;
1127 }
1128 dst->r_address = reloc->address;
1129 dst->r_pcrel = reloc->pcrel;
1130 dst->r_length = reloc->length;
1131 dst->r_type = reloc->reloc_type;
1132 dst->r_symbolnum = reloc->target + 1;
1133 dst->r_extern = 0;
1134 break;
1135 case KXLD_TARGET_SYMBOLNUM:
1136 /* Assume that everything will be slid together; otherwise,
1137 * there is no sensible value for the section number.
1138 */
1139 if (kaslr_offsets) {
1140 if (kaslr_offsets_index >= kaslr_offsets_count) {
1141 kxld_log(kKxldLogLinking, kKxldLogErr,
1142 "kaslr_offsets overflow <%s> ", __func__);
1143 abort();
1144 }
1145 // reloc->address is really an offset from the start of the kext
1146 *(kaslr_offsets + kaslr_offsets_index++) = reloc->address;
1147 }
1148 dst->r_address = reloc->address;
1149 dst->r_pcrel = reloc->pcrel;
1150 dst->r_length = reloc->length;
1151 dst->r_type = reloc->reloc_type;
1152 dst->r_symbolnum = 1;
1153 dst->r_extern = 0;
1154 break;
1155 default:
1156 rval = KERN_FAILURE;
1157 goto finish;
1158 }
1159
1160 ++dst;
1161
1162 if(reloc->pair_target_type != KXLD_TARGET_NONE) {
1163 ++i;
1164 require_action(i < relocs->nitems, finish, rval=KERN_FAILURE);
1165 scatdst = (struct scattered_relocation_info *) dst;
1166 switch (reloc->pair_target_type) {
1167 case KXLD_TARGET_LOOKUP:
1168 scatdst->r_address = reloc->pair_address;
1169 scatdst->r_pcrel = reloc->pcrel;
1170 scatdst->r_length = reloc->length;
1171 scatdst->r_type = relocator->reloc_get_pair_type(reloc->reloc_type);
1172 scatdst->r_value = reloc->pair_target;
1173 scatdst->r_scattered = 1;
1174 break;
1175 case KXLD_TARGET_SECTNUM:
1176 dst->r_address = reloc->pair_address;
1177 dst->r_pcrel = reloc->pcrel;
1178 dst->r_length = reloc->length;
1179 dst->r_type = relocator->reloc_get_pair_type(reloc->reloc_type);
1180 dst->r_symbolnum = reloc->pair_target + 1;
1181 dst->r_extern = 0;
1182 break;
1183 case KXLD_TARGET_SYMBOLNUM:
1184 dst->r_address = reloc->pair_address;
1185 dst->r_pcrel = reloc->pcrel;
1186 dst->r_length = reloc->length;
1187 dst->r_type = relocator->reloc_get_pair_type(reloc->reloc_type);
1188 dst->r_symbolnum = 1;
1189 dst->r_extern = 0;
1190 break;
1191 default:
1192 rval = KERN_FAILURE;
1193 goto finish;
1194 }
1195 ++dst;
1196 }
1197 }
1198
1199 rval = KERN_SUCCESS;
1200 finish:
1201 *dstp = dst;
1202 return rval;
1203 }
1204 #endif /* KXLD_PIC_KEXTS */
1205
1206 #if KXLD_USER_OR_I386
1207 /*******************************************************************************
1208 *******************************************************************************/
1209 static boolean_t
1210 generic_reloc_has_pair(u_int _type)
1211 {
1212 enum reloc_type_generic type = _type;
1213
1214 return (type == GENERIC_RELOC_SECTDIFF ||
1215 type == GENERIC_RELOC_LOCAL_SECTDIFF);
1216 }
1217
1218 /*******************************************************************************
1219 *******************************************************************************/
1220 static u_int
1221 generic_reloc_get_pair_type(u_int _prev_type __unused)
1222 {
1223 return GENERIC_RELOC_PAIR;
1224 }
1225
1226 /*******************************************************************************
1227 *******************************************************************************/
1228 static boolean_t generic_reloc_has_got(u_int _type __unused)
1229 {
1230 return FALSE;
1231 }
1232
1233 /*******************************************************************************
1234 *******************************************************************************/
1235 static kern_return_t
1236 generic_process_reloc(const KXLDRelocator *relocator, u_char *instruction,
1237 u_int length, u_int pcrel, kxld_addr_t _base_pc, kxld_addr_t _link_pc,
1238 kxld_addr_t _link_disp __unused, u_int _type, kxld_addr_t _target,
1239 kxld_addr_t _pair_target, boolean_t swap __unused)
1240 {
1241 kern_return_t rval = KERN_FAILURE;
1242 uint32_t base_pc = (uint32_t) _base_pc;
1243 uint32_t link_pc = (uint32_t) _link_pc;
1244 uint32_t *instr_addr = NULL;
1245 uint32_t instr_data = 0;
1246 uint32_t target = (uint32_t) _target;
1247 uint32_t pair_target = (uint32_t) _pair_target;
1248 enum reloc_type_generic type = _type;
1249
1250 check(instruction);
1251 require_action(length == 2, finish, rval=KERN_FAILURE);
1252
1253 if (pcrel) target = target + base_pc - link_pc;
1254
1255 instr_addr = (uint32_t *) ((void *) instruction);
1256 instr_data = *instr_addr;
1257
1258 #if !KERNEL
1259 if (swap) instr_data = OSSwapInt32(instr_data);
1260 #endif
1261
1262 rval = check_for_direct_pure_virtual_call(relocator, instr_data);
1263 require_noerr(rval, finish);
1264
1265 switch (type) {
1266 case GENERIC_RELOC_VANILLA:
1267 instr_data += target;
1268 break;
1269 case GENERIC_RELOC_SECTDIFF:
1270 case GENERIC_RELOC_LOCAL_SECTDIFF:
1271 instr_data = instr_data + target - pair_target;
1272 break;
1273 case GENERIC_RELOC_PB_LA_PTR:
1274 rval = KERN_FAILURE;
1275 goto finish;
1276 case GENERIC_RELOC_PAIR:
1277 default:
1278 rval = KERN_FAILURE;
1279 goto finish;
1280 }
1281
1282 #if !KERNEL
1283 if (swap) instr_data = OSSwapInt32(instr_data);
1284 #endif
1285
1286 *instr_addr = instr_data;
1287
1288 rval = KERN_SUCCESS;
1289
1290 finish:
1291 return rval;
1292 }
1293 #endif /* KXLD_USER_OR_I386 */
1294
1295 #if KXLD_USER_OR_X86_64
1296 /*******************************************************************************
1297 *******************************************************************************/
1298 static boolean_t
1299 x86_64_reloc_has_pair(u_int _type)
1300 {
1301 enum reloc_type_x86_64 type = _type;
1302
1303 return (type == X86_64_RELOC_SUBTRACTOR);
1304 }
1305
1306 /*******************************************************************************
1307 *******************************************************************************/
1308 static u_int
1309 x86_64_reloc_get_pair_type(u_int _prev_type __unused)
1310 {
1311 return X86_64_RELOC_UNSIGNED;
1312 }
1313
1314 /*******************************************************************************
1315 *******************************************************************************/
1316 static boolean_t
1317 x86_64_reloc_has_got(u_int _type)
1318 {
1319 enum reloc_type_x86_64 type = _type;
1320
1321 return (type == X86_64_RELOC_GOT_LOAD || type == X86_64_RELOC_GOT);
1322 }
1323
1324 /*******************************************************************************
1325 *******************************************************************************/
1326 static kern_return_t
1327 x86_64_process_reloc(const KXLDRelocator *relocator __unused, u_char *instruction,
1328 u_int length, u_int pcrel, kxld_addr_t _base_pc __unused,
1329 kxld_addr_t _link_pc, kxld_addr_t _link_disp, u_int _type,
1330 kxld_addr_t _target, kxld_addr_t _pair_target, boolean_t swap __unused)
1331 {
1332 kern_return_t rval = KERN_FAILURE;
1333 enum reloc_type_x86_64 type = _type;
1334 int32_t *instr32p = NULL;
1335 int32_t instr32 = 0;
1336 uint64_t *instr64p = NULL;
1337 uint64_t instr64 = 0;
1338 uint64_t target = _target;
1339 uint64_t pair_target = _pair_target;
1340 uint64_t link_pc = (uint64_t) _link_pc;
1341 uint64_t link_disp = (uint64_t) _link_disp;
1342 uint64_t adjustment = 0;
1343
1344 check(instruction);
1345 require_action(length == 2 || length == 3,
1346 finish, rval=KERN_FAILURE);
1347
1348 if (length == 2) {
1349 instr32p = (int32_t *) ((void *) instruction);
1350 instr32 = *instr32p;
1351
1352 #if !KERNEL
1353 if (swap) instr32 = OSSwapInt32(instr32);
1354 #endif
1355
1356 rval = check_for_direct_pure_virtual_call(relocator, instr32);
1357 require_noerr(rval, finish);
1358
1359 /* There are a number of different small adjustments for pc-relative
1360 * relocation entries. The general case is to subtract the size of the
1361 * relocation (represented by the length parameter), and it applies to
1362 * the GOT types and external SIGNED types. The non-external signed types
1363 * have a different adjustment corresponding to the specific type.
1364 */
1365 switch (type) {
1366 case X86_64_RELOC_SIGNED:
1367 if (pair_target) {
1368 adjustment = 0;
1369 break;
1370 }
1371 /* Fall through */
1372 case X86_64_RELOC_SIGNED_1:
1373 if (pair_target) {
1374 adjustment = 1;
1375 break;
1376 }
1377 /* Fall through */
1378 case X86_64_RELOC_SIGNED_2:
1379 if (pair_target) {
1380 adjustment = 2;
1381 break;
1382 }
1383 /* Fall through */
1384 case X86_64_RELOC_SIGNED_4:
1385 if (pair_target) {
1386 adjustment = 4;
1387 break;
1388 }
1389 /* Fall through */
1390 case X86_64_RELOC_BRANCH:
1391 case X86_64_RELOC_GOT:
1392 case X86_64_RELOC_GOT_LOAD:
1393 adjustment = (1 << length);
1394 break;
1395 default:
1396 break;
1397 }
1398
1399 /* Perform the actual relocation. All of the 32-bit relocations are
1400 * pc-relative except for SUBTRACTOR, so a good chunk of the logic is
1401 * stuck in calculate_displacement_x86_64. The signed relocations are
1402 * a special case, because when they are non-external, the instruction
1403 * already contains the pre-relocation displacement, so we only need to
1404 * find the difference between how far the PC was relocated, and how
1405 * far the target is relocated. Since the target variable already
1406 * contains the difference between the target's base and link
1407 * addresses, we add the difference between the PC's base and link
1408 * addresses to the adjustment variable. This will yield the
1409 * appropriate displacement in calculate_displacement.
1410 */
1411 switch (type) {
1412 case X86_64_RELOC_BRANCH:
1413 require_action(pcrel, finish, rval=KERN_FAILURE);
1414 adjustment += link_pc;
1415 break;
1416 case X86_64_RELOC_SIGNED:
1417 case X86_64_RELOC_SIGNED_1:
1418 case X86_64_RELOC_SIGNED_2:
1419 case X86_64_RELOC_SIGNED_4:
1420 require_action(pcrel, finish, rval=KERN_FAILURE);
1421 adjustment += (pair_target) ? (link_disp) : (link_pc);
1422 break;
1423 case X86_64_RELOC_GOT:
1424 case X86_64_RELOC_GOT_LOAD:
1425 require_action(pcrel, finish, rval=KERN_FAILURE);
1426 adjustment += link_pc;
1427 target = pair_target;
1428 break;
1429 case X86_64_RELOC_SUBTRACTOR:
1430 require_action(!pcrel, finish, rval=KERN_FAILURE);
1431 instr32 = (int32_t) (target - pair_target);
1432 break;
1433 case X86_64_RELOC_UNSIGNED:
1434 default:
1435 rval = KERN_FAILURE;
1436 goto finish;
1437 }
1438
1439 /* Call calculate_displacement for the pc-relative relocations */
1440 if (pcrel) {
1441 rval = calculate_displacement_x86_64(target, adjustment, &instr32);
1442 require_noerr(rval, finish);
1443 }
1444
1445 #if !KERNEL
1446 if (swap) instr32 = OSSwapInt32(instr32);
1447 #endif
1448
1449 *instr32p = instr32;
1450 } else {
1451 instr64p = (uint64_t *) ((void *) instruction);
1452 instr64 = *instr64p;
1453
1454 #if !KERNEL
1455 if (swap) instr64 = OSSwapInt64(instr64);
1456 #endif
1457
1458 rval = check_for_direct_pure_virtual_call(relocator, (u_long) instr64);
1459 require_noerr(rval, finish);
1460
1461 switch (type) {
1462 case X86_64_RELOC_UNSIGNED:
1463 require_action(!pcrel, finish, rval=KERN_FAILURE);
1464
1465 instr64 += target;
1466 break;
1467 case X86_64_RELOC_SUBTRACTOR:
1468 require_action(!pcrel, finish, rval=KERN_FAILURE);
1469
1470 instr64 = target - pair_target;
1471 break;
1472 case X86_64_RELOC_SIGNED_1:
1473 case X86_64_RELOC_SIGNED_2:
1474 case X86_64_RELOC_SIGNED_4:
1475 case X86_64_RELOC_GOT_LOAD:
1476 case X86_64_RELOC_BRANCH:
1477 case X86_64_RELOC_SIGNED:
1478 case X86_64_RELOC_GOT:
1479 default:
1480 rval = KERN_FAILURE;
1481 goto finish;
1482 }
1483
1484 #if !KERNEL
1485 if (swap) instr64 = OSSwapInt64(instr64);
1486 #endif
1487 *instr64p = instr64;
1488 }
1489
1490 rval = KERN_SUCCESS;
1491
1492 finish:
1493 return rval;
1494 }
1495
1496 /*******************************************************************************
1497 *******************************************************************************/
1498 static kern_return_t
1499 calculate_displacement_x86_64(uint64_t target, uint64_t adjustment,
1500 int32_t *instr32)
1501 {
1502 kern_return_t rval = KERN_FAILURE;
1503 int64_t displacement;
1504 uint64_t difference;
1505
1506 displacement = *instr32 + target - adjustment;
1507 difference = ABSOLUTE_VALUE(displacement);
1508 require_action(difference < X86_64_RIP_RELATIVE_LIMIT, finish,
1509 rval=KERN_FAILURE;
1510 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogRelocationOverflow));
1511
1512 *instr32 = (int32_t) displacement;
1513 rval = KERN_SUCCESS;
1514
1515 finish:
1516 return rval;
1517 }
1518 #endif /* KXLD_USER_OR_X86_64 */
1519
1520 #if KXLD_USER_OR_ARM
1521 /*******************************************************************************
1522 *******************************************************************************/
1523 static boolean_t
1524 arm_reloc_has_pair(u_int _type)
1525 {
1526 enum reloc_type_arm type = _type;
1527
1528 switch(type) {
1529 case ARM_RELOC_SECTDIFF:
1530 return TRUE;
1531 default:
1532 return FALSE;
1533 }
1534 return FALSE;
1535 }
1536
1537 /*******************************************************************************
1538 *******************************************************************************/
1539 static u_int
1540 arm_reloc_get_pair_type(u_int _prev_type __unused)
1541 {
1542 return ARM_RELOC_PAIR;
1543 }
1544
1545 /*******************************************************************************
1546 *******************************************************************************/
1547 static boolean_t
1548 arm_reloc_has_got(u_int _type __unused)
1549 {
1550 return FALSE;
1551 }
1552
1553 /*******************************************************************************
1554 *******************************************************************************/
1555 static kern_return_t
1556 arm_process_reloc(const KXLDRelocator *relocator __unused, u_char *instruction,
1557 u_int length, u_int pcrel, kxld_addr_t _base_pc __unused,
1558 kxld_addr_t _link_pc __unused, kxld_addr_t _link_disp __unused,
1559 u_int _type __unused, kxld_addr_t _target __unused,
1560 kxld_addr_t _pair_target __unused, boolean_t swap __unused)
1561 {
1562 kern_return_t rval = KERN_FAILURE;
1563 uint32_t *instr_addr = NULL;
1564 uint32_t instr_data = 0;
1565 uint32_t base_pc = (uint32_t) _base_pc;
1566 uint32_t link_pc = (uint32_t) _link_pc;
1567 uint32_t target = (uint32_t) _target;
1568 int32_t displacement = 0;
1569 enum reloc_type_arm type = _type;
1570
1571 check(instruction);
1572 require_action(length == 2, finish, rval=KERN_FAILURE);
1573
1574 if (pcrel) displacement = target + base_pc - link_pc;
1575
1576 instr_addr = (uint32_t *) ((void *) instruction);
1577 instr_data = *instr_addr;
1578
1579 #if !KERNEL
1580 if (swap) instr_data = OSSwapInt32(instr_data);
1581 #endif
1582
1583 rval = check_for_direct_pure_virtual_call(relocator, instr_data);
1584 require_noerr(rval, finish);
1585
1586 switch (type) {
1587 case ARM_RELOC_VANILLA:
1588 instr_data += target;
1589 break;
1590
1591 /*
1592 * If the displacement is 0 (the offset between the pc and the target has
1593 * not changed), then we don't need to do anything for BR24 and BR22
1594 * relocs. As it turns out, because kexts build with -mlong-calls all
1595 * relocations currently end up being either vanilla (handled above) or
1596 * BR22/BR24 with a displacement of 0.
1597 * We could handle other displacements here but to keep things simple, we
1598 * won't until it is needed (at which point the kernelcache will fail to
1599 * link)
1600 */
1601 case ARM_RELOC_BR24:
1602 require_action(pcrel, finish, rval=KERN_FAILURE);
1603 require_action(displacement == 0, finish, rval=KERN_FAILURE);
1604 break;
1605 case ARM_THUMB_RELOC_BR22:
1606 require_action(pcrel, finish, rval=KERN_FAILURE);
1607 require_action(displacement == 0, finish, rval=KERN_FAILURE);
1608 break;
1609
1610 case ARM_RELOC_SECTDIFF:
1611 case ARM_RELOC_LOCAL_SECTDIFF:
1612 case ARM_RELOC_PB_LA_PTR:
1613 rval = KERN_FAILURE;
1614 goto finish;
1615
1616 case ARM_RELOC_PAIR:
1617 default:
1618 rval = KERN_FAILURE;
1619 goto finish;
1620 }
1621
1622 #if !KERNEL
1623 if (swap) instr_data = OSSwapInt32(instr_data);
1624 #endif
1625
1626 *instr_addr = instr_data;
1627
1628 rval = KERN_SUCCESS;
1629
1630 finish:
1631 return rval;
1632 }
1633
1634 #endif /* KXLD_USER_OR_ARM */
1635
1636 #if KXLD_USER_OR_ARM64
1637 /*******************************************************************************
1638 *******************************************************************************/
1639 boolean_t
1640 arm64_reloc_has_pair(u_int _type)
1641 {
1642 return (_type == ARM64_RELOC_SUBTRACTOR);
1643 }
1644
1645 /*******************************************************************************
1646 *******************************************************************************/
1647 u_int
1648 arm64_reloc_get_pair_type(u_int _prev_type __unused)
1649 {
1650 if (_prev_type == ARM64_RELOC_SUBTRACTOR) {
1651 return ARM64_RELOC_UNSIGNED;
1652 } else {
1653 return -1u;
1654 }
1655 }
1656
1657 /*******************************************************************************
1658 *******************************************************************************/
1659 boolean_t
1660 arm64_reloc_has_got(u_int _type)
1661 {
1662 return (_type == ARM64_RELOC_GOT_LOAD_PAGE21 ||
1663 _type == ARM64_RELOC_GOT_LOAD_PAGEOFF12);
1664 }
1665
1666 /*******************************************************************************
1667 *******************************************************************************/
1668 kern_return_t
1669 arm64_process_reloc(const KXLDRelocator *relocator __unused, u_char *instruction,
1670 u_int length, u_int pcrel, kxld_addr_t _base_pc __unused, kxld_addr_t _link_pc,
1671 kxld_addr_t _link_disp __unused, u_int _type, kxld_addr_t _target,
1672 kxld_addr_t _pair_target __unused, boolean_t swap)
1673 {
1674 kern_return_t rval = KERN_FAILURE;
1675 enum reloc_type_arm64 type = _type;
1676 uint64_t target = _target;
1677 uint64_t link_pc = (uint64_t) _link_pc;
1678 uint64_t difference = 0;
1679 int64_t displacement = 0;
1680 uint32_t addend = 0;
1681
1682 check(instruction);
1683 require_action((length == 2 || length == 3), finish, rval=KERN_FAILURE);
1684
1685 if (length == 2) {
1686 uint32_t *instr32p = (uint32_t *) (void *) instruction;
1687 uint32_t instr32 = *instr32p;
1688
1689 #if !KERNEL
1690 if (swap) instr32 = OSSwapInt32(instr32);
1691 #endif
1692
1693 switch (type) {
1694 case ARM64_RELOC_BRANCH26:
1695 require_action(pcrel, finish, rval=KERN_FAILURE);
1696 addend = (instr32 & 0x03FFFFFF) << 2;
1697 addend = SIGN_EXTEND(addend, 27);
1698 displacement = (target - link_pc + addend);
1699 difference = ABSOLUTE_VALUE(displacement);
1700 displacement = (displacement >> 2);
1701 require_action(difference < (128 * 1024 * 1024), finish,
1702 rval = KERN_FAILURE;
1703 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogRelocationOverflow));
1704 instr32 = (instr32 & 0xFC000000) | (displacement & 0x03FFFFFF);
1705 break;
1706
1707 default:
1708 rval = KERN_FAILURE;
1709 goto finish;
1710 }
1711
1712 #if !KERNEL
1713 if (swap) instr32 = OSSwapInt32(instr32);
1714 #endif
1715
1716 *instr32p = instr32;
1717 } else { /* length == 3 */
1718 uint64_t *instr64p = (uint64_t *) (void *) instruction;
1719 uint64_t instr64 = *instr64p;
1720
1721 #if !KERNEL
1722 if (swap) instr64 = OSSwapInt64(instr64);
1723 #endif
1724
1725 switch (type) {
1726 case ARM64_RELOC_UNSIGNED:
1727 require_action(!pcrel, finish, rval=KERN_FAILURE);
1728 instr64 += target;
1729 break;
1730 default:
1731 rval = KERN_FAILURE;
1732 goto finish;
1733 }
1734
1735 #if !KERNEL
1736 if (swap) instr64 = OSSwapInt64(instr64);
1737 #endif
1738
1739 *instr64p = instr64;
1740 }
1741
1742 rval = KERN_SUCCESS;
1743 finish:
1744 return rval;
1745 }
1746
1747
1748 #endif /* KXLD_USER_OR_ARM64 */