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