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