]> git.saurik.com Git - apple/xnu.git/blame - libkern/kxld/kxld_object.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_object.c
CommitLineData
6d2010ae 1/*
fe8ab488 2 * Copyright (c) 2009-2014 Apple Inc. All rights reserved.
6d2010ae
A
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
6d2010ae
A
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.
0a7de745 14 *
6d2010ae
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
6d2010ae
A
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.
0a7de745 25 *
6d2010ae
A
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#include <string.h>
6d2010ae
A
29#include <sys/types.h>
30
31#if KERNEL
32 #include <libkern/kernel_mach_header.h>
316670eb 33 #include <mach/machine.h>
6d2010ae
A
34 #include <mach/vm_param.h>
35 #include <mach-o/fat.h>
36#else /* !KERNEL */
0a7de745
A
37/* Get machine.h from the kernel source so we can support all platforms
38 * that the kernel supports. Otherwise we're at the mercy of the host.
39 */
316670eb
A
40 #include "../../osfmk/mach/machine.h"
41
6d2010ae
A
42 #include <architecture/byte_order.h>
43 #include <mach/mach_init.h>
44 #include <mach-o/arch.h>
45 #include <mach-o/swap.h>
46#endif /* KERNEL */
47
316670eb
A
48#include <mach-o/loader.h>
49#include <mach-o/nlist.h>
50#include <mach-o/reloc.h>
5ba3f43e 51#include <os/overflow.h>
316670eb 52
6d2010ae
A
53#define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
54#include <AssertMacros.h>
55
56#include "kxld_demangle.h"
57#include "kxld_dict.h"
58#include "kxld_reloc.h"
59#include "kxld_sect.h"
60#include "kxld_seg.h"
316670eb 61#include "kxld_srcversion.h"
6d2010ae
A
62#include "kxld_symtab.h"
63#include "kxld_util.h"
64#include "kxld_uuid.h"
316670eb 65#include "kxld_versionmin.h"
6d2010ae 66#include "kxld_vtable.h"
39037602 67#include "kxld_splitinfolc.h"
6d2010ae
A
68
69#include "kxld_object.h"
70
39037602
A
71extern boolean_t isSplitKext;
72extern boolean_t isOldInterface;
73
6d2010ae
A
74/*******************************************************************************
75* Data structures
76*******************************************************************************/
77
78struct kxld_object {
0a7de745
A
79 u_char *file; // used by old interface
80 u_long size; // used by old interface
81 const char *name;
82 uint32_t filetype;
83 cpu_type_t cputype;
84 cpu_subtype_t cpusubtype;
85 KXLDArray segs;
86 KXLDArray sects;
87 KXLDArray extrelocs;
88 KXLDArray locrelocs;
89 KXLDRelocator relocator;
90 KXLDuuid uuid;
91 KXLDversionmin versionmin;
92 KXLDsrcversion srcversion;
93 KXLDSymtab *symtab;
94 struct dysymtab_command *dysymtab_hdr;
95 KXLDsplitinfolc splitinfolc;
96 splitKextLinkInfo split_info;
97 kxld_addr_t link_addr;
98 u_long output_buffer_size;
99 boolean_t is_kernel;
100 boolean_t is_final_image;
101 boolean_t is_linked;
102 boolean_t got_is_created;
6d2010ae 103#if KXLD_USER_OR_OBJECT
0a7de745 104 KXLDArray *section_order;
6d2010ae 105#endif
316670eb 106#if KXLD_PIC_KEXTS
0a7de745 107 boolean_t include_kaslr_relocs;
316670eb 108#endif
6d2010ae 109#if !KERNEL
0a7de745
A
110 enum NXByteOrder host_order;
111 enum NXByteOrder target_order;
6d2010ae
A
112#endif
113};
114
115/*******************************************************************************
116* Prototypes
117*******************************************************************************/
118
0a7de745 119static kern_return_t get_target_machine_info(KXLDObject *object,
6d2010ae 120 cpu_type_t cputype, cpu_subtype_t cpusubtype);
0a7de745 121static kern_return_t get_macho_slice_for_arch(KXLDObject *object,
6d2010ae
A
122 u_char *file, u_long size);
123
124static u_long get_macho_header_size(const KXLDObject *object);
125static u_long get_macho_data_size(const KXLDObject *object) __unused;
126
127static kern_return_t init_from_execute(KXLDObject *object);
0a7de745 128static kern_return_t init_from_final_linked_image(KXLDObject *object,
6d2010ae
A
129 u_int *filetype_out, struct symtab_command **symtab_hdr_out);
130
131static boolean_t target_supports_protected_segments(const KXLDObject *object)
0a7de745 132__attribute__((pure));
6d2010ae
A
133static void set_is_object_linked(KXLDObject *object);
134
135#if KXLD_USER_OR_BUNDLE
0a7de745
A
136static boolean_t target_supports_bundle(const KXLDObject *object)
137__attribute((pure));
6d2010ae
A
138static kern_return_t init_from_bundle(KXLDObject *object);
139static kern_return_t process_relocs_from_tables(KXLDObject *object);
140static KXLDSeg *get_seg_by_base_addr(KXLDObject *object,
141 kxld_addr_t base_addr);
142static kern_return_t process_symbol_pointers(KXLDObject *object);
143static void add_to_ptr(u_char *symptr, kxld_addr_t val, boolean_t is_32_bit);
144#endif /* KXLD_USER_OR_BUNDLE */
145
146#if KXLD_USER_OR_OBJECT
0a7de745
A
147static boolean_t target_supports_object(const KXLDObject *object)
148__attribute((pure));
6d2010ae
A
149static kern_return_t init_from_object(KXLDObject *object);
150static kern_return_t process_relocs_from_sections(KXLDObject *object);
151#endif /* KXLD_USER_OR_OBJECT */
152
316670eb
A
153#if KXLD_PIC_KEXTS
154static boolean_t target_supports_slideable_kexts(const KXLDObject *object);
155#endif /* KXLD_PIC_KEXTS */
156
157
0a7de745 158static kern_return_t export_macho_header(const KXLDObject *object, u_char *buf,
6d2010ae
A
159 u_int ncmds, u_long *header_offset, u_long header_size);
160#if KXLD_USER_OR_ILP32
0a7de745 161static u_long get_macho_cmd_data_32(u_char *file, u_long offset,
6d2010ae 162 u_int *filetype, u_int *ncmds);
0a7de745 163static kern_return_t export_macho_header_32(const KXLDObject *object,
6d2010ae
A
164 u_char *buf, u_int ncmds, u_long *header_offset, u_long header_size);
165#endif /* KXLD_USER_OR_ILP32 */
166#if KXLD_USER_OR_LP64
167static u_long get_macho_cmd_data_64(u_char *file, u_long offset,
168 u_int *filetype, u_int *ncmds);
0a7de745 169static kern_return_t export_macho_header_64(const KXLDObject *object,
6d2010ae
A
170 u_char *buf, u_int ncmds, u_long *header_offset, u_long header_size);
171#endif /* KXLD_USER_OR_LP64 */
172
173#if KXLD_USER_OR_GOT || KXLD_USER_OR_COMMON
174static kern_return_t add_section(KXLDObject *object, KXLDSect **sect);
175#endif /* KXLD_USER_OR_GOT || KXLD_USER_OR_COMMON */
176
177#if KXLD_USER_OR_COMMON
178static kern_return_t resolve_common_symbols(KXLDObject *object);
179#endif /* KXLD_USER_OR_COMMON */
180
181#if KXLD_USER_OR_GOT
182static boolean_t target_has_got(const KXLDObject *object) __attribute__((pure));
183static kern_return_t create_got(KXLDObject *object);
184static kern_return_t populate_got(KXLDObject *object);
185#endif /* KXLD_USER_OR_GOT */
186
187static KXLDSym *get_mutable_sym(const KXLDObject *object, const KXLDSym *sym);
188
189static kern_return_t populate_kmod_info(KXLDObject *object);
190
191/*******************************************************************************
192* Prototypes that may need to be exported
193*******************************************************************************/
194static boolean_t kxld_object_target_needs_swap(const KXLDObject *object __unused);
195static KXLDSeg * kxld_object_get_seg_by_name(const KXLDObject *object, const char *segname);
39037602 196static KXLDSect * kxld_object_get_sect_by_name(const KXLDObject *object, const char *segname,
6d2010ae
A
197 const char *sectname);
198
199/*******************************************************************************
200*******************************************************************************/
0a7de745 201size_t
6d2010ae
A
202kxld_object_sizeof(void)
203{
0a7de745 204 return sizeof(KXLDObject);
6d2010ae
A
205}
206
207/*******************************************************************************
208*******************************************************************************/
0a7de745 209kern_return_t
6d2010ae 210kxld_object_init_from_macho(KXLDObject *object, u_char *file, u_long size,
0a7de745 211 const char *name, KXLDArray *section_order __unused,
316670eb 212 cpu_type_t cputype, cpu_subtype_t cpusubtype, KXLDFlags flags __unused)
6d2010ae 213{
0a7de745
A
214 kern_return_t rval = KERN_FAILURE;
215 KXLDSeg * seg = NULL;
216 u_int i = 0;
217 u_char * my_file;
6d2010ae 218
0a7de745
A
219 check(object);
220 check(file);
221 check(name);
6d2010ae 222
0a7de745 223 object->name = name;
6d2010ae
A
224
225#if KXLD_USER_OR_OBJECT
0a7de745 226 object->section_order = section_order;
6d2010ae 227#endif
316670eb 228#if KXLD_PIC_KEXTS
0a7de745 229 object->include_kaslr_relocs = ((flags & kKXLDFlagIncludeRelocs) == kKXLDFlagIncludeRelocs);
316670eb 230#endif
0a7de745
A
231
232 /* Find the local architecture */
233
234 rval = get_target_machine_info(object, cputype, cpusubtype);
235 require_noerr(rval, finish);
236
237 /* Find the Mach-O slice for the target architecture */
238
239 rval = get_macho_slice_for_arch(object, file, size);
240 require_noerr(rval, finish);
241
242 if (isOldInterface) {
243 my_file = object->file;
244 } else {
245 my_file = object->split_info.kextExecutable;
246 }
247
248 /* Allocate the symbol table */
249
250 if (!object->symtab) {
cb323159 251 object->symtab = kxld_calloc(kxld_symtab_sizeof());
0a7de745 252 require_action(object->symtab, finish, rval = KERN_RESOURCE_SHORTAGE);
0a7de745
A
253 }
254
255 /* Build the relocator */
256
257 rval = kxld_relocator_init(&object->relocator,
258 my_file,
259 object->symtab, &object->sects,
260 object->cputype,
261 object->cpusubtype,
262 kxld_object_target_needs_swap(object));
263 require_noerr(rval, finish);
264
265 /* There are four types of Mach-O files that we can support:
266 * 1) 32-bit MH_OBJECT - Snow Leopard and earlier
267 * 2) 32-bit MH_KEXT_BUNDLE - Lion and Later
268 * 3) 64-bit MH_OBJECT - Unsupported
269 * 4) 64-bit MH_KEXT_BUNDLE - Snow Leopard and Later
270 */
271
272 if (kxld_object_is_32_bit(object)) {
273 struct mach_header *mach_hdr = (struct mach_header *) ((void *) my_file);
274 object->filetype = mach_hdr->filetype;
275 } else {
276 struct mach_header_64 *mach_hdr = (struct mach_header_64 *) ((void *) my_file);
277 object->filetype = mach_hdr->filetype;
278 }
279
280 switch (object->filetype) {
6d2010ae 281#if KXLD_USER_OR_BUNDLE
0a7de745
A
282 case MH_KEXT_BUNDLE:
283 rval = init_from_bundle(object);
284 require_noerr(rval, finish);
285 break;
6d2010ae
A
286#endif /* KXLD_USER_OR_BUNDLE */
287#if KXLD_USER_OR_OBJECT
0a7de745
A
288 case MH_OBJECT:
289 rval = init_from_object(object);
290 require_noerr(rval, finish);
291 break;
6d2010ae 292#endif /* KXLD_USER_OR_OBJECT */
0a7de745
A
293 case MH_EXECUTE:
294 object->is_kernel = TRUE;
295 rval = init_from_execute(object);
296 require_noerr(rval, finish);
297 break;
298 default:
299 rval = KERN_FAILURE;
300 kxld_log(kKxldLogLinking, kKxldLogErr,
301 kKxldLogFiletypeNotSupported, object->filetype);
302 goto finish;
303 }
304
305 if (!kxld_object_is_kernel(object)) {
306 for (i = 0; i < object->segs.nitems; ++i) {
307 seg = kxld_array_get_item(&object->segs, i);
308 kxld_seg_set_vm_protections(seg,
309 target_supports_protected_segments(object));
310 }
311
312 seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
313 if (seg) {
314 (void) kxld_seg_populate_linkedit(seg, object->symtab,
315 kxld_object_is_32_bit(object)
316670eb 316#if KXLD_PIC_KEXTS
0a7de745
A
317 , &object->locrelocs, &object->extrelocs,
318 target_supports_slideable_kexts(object)
316670eb 319#endif
0a7de745
A
320 , isOldInterface ? 0 : object->splitinfolc.datasize
321 );
322 }
323 }
324
325 (void) set_is_object_linked(object);
326
327 rval = KERN_SUCCESS;
6d2010ae 328finish:
0a7de745 329 return rval;
6d2010ae
A
330}
331
39037602 332/*******************************************************************************
0a7de745 333*******************************************************************************/
39037602
A
334splitKextLinkInfo *
335kxld_object_get_link_info(KXLDObject *object)
336{
0a7de745
A
337 check(object);
338
339 return &object->split_info;
39037602
A
340}
341
342
343/*******************************************************************************
0a7de745 344*******************************************************************************/
39037602
A
345void
346kxld_object_set_link_info(KXLDObject *object, splitKextLinkInfo *link_info)
347{
0a7de745
A
348 check(object);
349 check(link_info);
39037602 350
0a7de745
A
351 object->split_info.vmaddr_TEXT = link_info->vmaddr_TEXT;
352 object->split_info.vmaddr_TEXT_EXEC = link_info->vmaddr_TEXT_EXEC;
353 object->split_info.vmaddr_DATA = link_info->vmaddr_DATA;
354 object->split_info.vmaddr_DATA_CONST = link_info->vmaddr_DATA_CONST;
355 object->split_info.vmaddr_LLVM_COV = link_info->vmaddr_LLVM_COV;
356 object->split_info.vmaddr_LINKEDIT = link_info->vmaddr_LINKEDIT;
813fb2f6 357
0a7de745 358 return;
39037602
A
359}
360
6d2010ae
A
361/*******************************************************************************
362*******************************************************************************/
363kern_return_t
0a7de745 364get_target_machine_info(KXLDObject *object, cpu_type_t cputype __unused,
6d2010ae
A
365 cpu_subtype_t cpusubtype __unused)
366{
367#if KERNEL
368
0a7de745
A
369 /* Because the kernel can only link for its own architecture, we know what
370 * the host and target architectures are at compile time, so we can use
371 * a vastly simplified version of this function.
372 */
6d2010ae 373
0a7de745 374 check(object);
6d2010ae 375
39236c6e 376#if defined(__x86_64__)
0a7de745 377 object->cputype = CPU_TYPE_X86_64;
fe8ab488
A
378/* FIXME: we need clang to provide a __x86_64h__ macro for the sub-type. Using
379 * __AVX2__ is a temporary solution until this is available. */
380#if defined(__AVX2__)
0a7de745 381 object->cpusubtype = CPU_SUBTYPE_X86_64_H;
fe8ab488 382#else
0a7de745 383 object->cpusubtype = CPU_SUBTYPE_X86_64_ALL;
fe8ab488 384#endif
0a7de745 385 return KERN_SUCCESS;
5ba3f43e 386#elif defined(__arm__)
0a7de745
A
387 object->cputype = CPU_TYPE_ARM;
388 object->cpusubtype = CPU_SUBTYPE_ARM_ALL;
389 return KERN_SUCCESS;
5ba3f43e 390#elif defined(__arm64__)
0a7de745
A
391 object->cputype = CPU_TYPE_ARM64;
392 object->cpusubtype = CPU_SUBTYPE_ARM64_ALL;
393 return KERN_SUCCESS;
394#else
395 kxld_log(kKxldLogLinking, kKxldLogErr,
396 kKxldLogArchNotSupported, _mh_execute_header->cputype);
397 return KERN_NOT_SUPPORTED;
6d2010ae
A
398#endif /* Supported architecture defines */
399
400
401#else /* !KERNEL */
402
0a7de745
A
403 /* User-space must look up the architecture it's running on and the target
404 * architecture at run-time.
405 */
406
407 kern_return_t rval = KERN_FAILURE;
408 const NXArchInfo *host_arch = NULL;
409
410 check(object);
411
412 host_arch = NXGetLocalArchInfo();
413 require_action(host_arch, finish, rval = KERN_FAILURE);
414
415 object->host_order = host_arch->byteorder;
416
417 /* If the user did not specify a cputype, use the local architecture.
418 */
419
420 if (cputype) {
421 object->cputype = cputype;
422 object->cpusubtype = cpusubtype;
423 } else {
424 object->cputype = host_arch->cputype;
425 object->target_order = object->host_order;
426
427 switch (object->cputype) {
428 case CPU_TYPE_I386:
429 object->cpusubtype = CPU_SUBTYPE_I386_ALL;
430 break;
431 case CPU_TYPE_X86_64:
432 object->cpusubtype = CPU_SUBTYPE_X86_64_ALL;
433 break;
434 case CPU_TYPE_ARM:
435 object->cpusubtype = CPU_SUBTYPE_ARM_ALL;
436 break;
437 case CPU_TYPE_ARM64:
438 object->cpusubtype = CPU_SUBTYPE_ARM64_ALL;
439 break;
440 default:
441 object->cpusubtype = 0;
442 break;
443 }
444 }
445
446 /* Validate that we support the target architecture and record its
447 * endianness.
448 */
449
450 switch (object->cputype) {
451 case CPU_TYPE_ARM:
452 case CPU_TYPE_ARM64:
453 case CPU_TYPE_I386:
454 case CPU_TYPE_X86_64:
455 object->target_order = NX_LittleEndian;
456 break;
457 default:
458 rval = KERN_NOT_SUPPORTED;
459 kxld_log(kKxldLogLinking, kKxldLogErr,
460 kKxldLogArchNotSupported, object->cputype);
461 goto finish;
462 }
463
464 rval = KERN_SUCCESS;
6d2010ae
A
465
466finish:
0a7de745 467 return rval;
6d2010ae
A
468#endif /* KERNEL */
469}
470
471/*******************************************************************************
472*******************************************************************************/
473static kern_return_t
474get_macho_slice_for_arch(KXLDObject *object, u_char *file, u_long size)
475{
0a7de745
A
476 kern_return_t rval = KERN_FAILURE;
477 struct mach_header *mach_hdr = NULL;
6d2010ae 478#if !KERNEL
0a7de745
A
479 struct fat_header *fat = (struct fat_header *) ((void *) file);
480 struct fat_arch *archs = (struct fat_arch *) &fat[1];
481 boolean_t swap = FALSE;
6d2010ae 482#endif /* KERNEL */
0a7de745
A
483 u_char *my_file = file;
484 u_long my_file_size = size;
485
486 check(object);
487 check(file);
488 check(size);
6d2010ae 489
0a7de745 490 /* We are assuming that we will never receive a fat file in the kernel */
6d2010ae
A
491
492#if !KERNEL
0a7de745
A
493 require_action(size >= sizeof(*fat), finish,
494 rval = KERN_FAILURE;
495 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
496
497 /* The fat header is always big endian, so swap if necessary */
498 if (fat->magic == FAT_CIGAM) {
499 (void) swap_fat_header(fat, object->host_order);
500 swap = TRUE;
501 }
502
503 if (fat->magic == FAT_MAGIC) {
504 struct fat_arch *arch = NULL;
505 u_long arch_size;
506 boolean_t ovr = os_mul_and_add_overflow(fat->nfat_arch, sizeof(*archs), sizeof(*fat), &arch_size);
507
508 require_action(!ovr && size >= arch_size,
509 finish,
510 rval = KERN_FAILURE;
511 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
512
513 /* Swap the fat_arch structures if necessary */
514 if (swap) {
515 (void) swap_fat_arch(archs, fat->nfat_arch, object->host_order);
516 }
517
518 /* Locate the Mach-O for the requested architecture */
519
520 arch = NXFindBestFatArch(object->cputype, object->cpusubtype, archs, fat->nfat_arch);
521 require_action(arch, finish, rval = KERN_FAILURE;
522 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogArchNotFound));
523 require_action(size >= arch->offset + arch->size, finish,
524 rval = KERN_FAILURE;
525 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
526
527 my_file = my_file + arch->offset;
528 my_file_size = arch->size;
529 }
6d2010ae
A
530#endif /* !KERNEL */
531
0a7de745
A
532 /* Swap the Mach-O's headers to this architecture if necessary */
533 if (kxld_object_is_32_bit(object)) {
534 rval = validate_and_swap_macho_32(my_file, my_file_size
6d2010ae 535#if !KERNEL
0a7de745 536 , object->host_order
6d2010ae 537#endif /* !KERNEL */
0a7de745
A
538 );
539 } else {
540 rval = validate_and_swap_macho_64(my_file, my_file_size
6d2010ae 541#if !KERNEL
0a7de745 542 , object->host_order
6d2010ae 543#endif /* !KERNEL */
0a7de745
A
544 );
545 }
546 require_noerr(rval, finish);
547
548 mach_hdr = (struct mach_header *) ((void *) my_file);
549 require_action(object->cputype == mach_hdr->cputype, finish,
550 rval = KERN_FAILURE;
551 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
552 object->cpusubtype = mach_hdr->cpusubtype; /* <rdar://problem/16008438> */
553
554 if (isOldInterface) {
555 object->file = my_file;
556 object->size = my_file_size;
557 } else {
558 object->split_info.kextExecutable = my_file;
559 object->split_info.kextSize = my_file_size;
560 }
561
562 rval = KERN_SUCCESS;
6d2010ae 563finish:
0a7de745 564 return rval;
6d2010ae
A
565}
566
567/*******************************************************************************
568*******************************************************************************/
569static kern_return_t
570init_from_final_linked_image(KXLDObject *object, u_int *filetype_out,
571 struct symtab_command **symtab_hdr_out)
572{
0a7de745
A
573 kern_return_t rval = KERN_FAILURE;
574 KXLDSeg *seg = NULL;
575 KXLDSect *sect = NULL;
576 struct load_command *cmd_hdr = NULL;
577 struct symtab_command *symtab_hdr = NULL;
578 struct uuid_command *uuid_hdr = NULL;
579 struct version_min_command *versionmin_hdr = NULL;
580 struct build_version_command *build_version_hdr = NULL;
581 struct source_version_command *source_version_hdr = NULL;
582 u_long base_offset = 0;
583 u_long offset = 0;
584 u_long sect_offset = 0;
585 u_int filetype = 0;
586 u_int i = 0;
587 u_int j = 0;
588 u_int segi = 0;
589 u_int secti = 0;
590 u_int nsegs = 0;
591 u_int nsects = 0;
592 u_int ncmds = 0;
593 u_char *my_file;
594
595 if (isOldInterface) {
596 my_file = object->file;
597 } else {
598 my_file = object->split_info.kextExecutable;
599 }
600
601 KXLD_3264_FUNC(kxld_object_is_32_bit(object), base_offset,
602 get_macho_cmd_data_32, get_macho_cmd_data_64,
603 my_file, offset, &filetype, &ncmds);
604
605 /* First pass to count segments and sections */
606
607 offset = base_offset;
608 for (i = 0; i < ncmds; ++i, offset += cmd_hdr->cmdsize) {
609 cmd_hdr = (struct load_command *) ((void *) (my_file + offset));
610
611 switch (cmd_hdr->cmd) {
6d2010ae 612#if KXLD_USER_OR_ILP32
0a7de745
A
613 case LC_SEGMENT:
614 {
615 struct segment_command *seg_hdr =
616 (struct segment_command *) cmd_hdr;
617
618 /* Ignore segments with no vm size */
619 if (!seg_hdr->vmsize) {
620 continue;
621 }
622
623 ++nsegs;
624 nsects += seg_hdr->nsects;
625 }
626 break;
6d2010ae
A
627#endif /* KXLD_USER_OR_ILP32 */
628#if KXLD_USER_OR_LP64
0a7de745
A
629 case LC_SEGMENT_64:
630 {
631 struct segment_command_64 *seg_hdr =
632 (struct segment_command_64 *) ((void *) cmd_hdr);
633
634 /* Ignore segments with no vm size */
635 if (!seg_hdr->vmsize) {
636 continue;
637 }
638
639 ++nsegs;
640 nsects += seg_hdr->nsects;
641 }
642 break;
6d2010ae 643#endif /* KXLD_USER_OR_LP64 */
0a7de745
A
644 default:
645 continue;
646 }
647 }
6d2010ae 648
0a7de745 649 /* Allocate the segments and sections */
6d2010ae 650
0a7de745
A
651 if (nsegs) {
652 rval = kxld_array_init(&object->segs, sizeof(KXLDSeg), nsegs);
653 require_noerr(rval, finish);
6d2010ae 654
0a7de745
A
655 rval = kxld_array_init(&object->sects, sizeof(KXLDSect), nsects);
656 require_noerr(rval, finish);
657 }
6d2010ae 658
0a7de745 659 /* Initialize the segments and sections */
6d2010ae 660
0a7de745
A
661 offset = base_offset;
662 for (i = 0; i < ncmds; ++i, offset += cmd_hdr->cmdsize) {
663 cmd_hdr = (struct load_command *) ((void *) (my_file + offset));
664 seg = NULL;
6d2010ae 665
0a7de745 666 switch (cmd_hdr->cmd) {
6d2010ae 667#if KXLD_USER_OR_ILP32
0a7de745
A
668 case LC_SEGMENT:
669 {
670 struct segment_command *seg_hdr =
671 (struct segment_command *) cmd_hdr;
6d2010ae 672
0a7de745
A
673 /* Ignore segments with no vm size */
674 if (!seg_hdr->vmsize) {
675 continue;
676 }
6d2010ae 677
0a7de745 678 seg = kxld_array_get_item(&object->segs, segi++);
6d2010ae 679
0a7de745
A
680 rval = kxld_seg_init_from_macho_32(seg, seg_hdr);
681 require_noerr(rval, finish);
6d2010ae 682
0a7de745
A
683 sect_offset = offset + sizeof(*seg_hdr);
684 }
685 break;
6d2010ae
A
686#endif /* KXLD_USER_OR_ILP32 */
687#if KXLD_USER_OR_LP64
0a7de745
A
688 case LC_SEGMENT_64:
689 {
690 struct segment_command_64 *seg_hdr =
691 (struct segment_command_64 *) ((void *) cmd_hdr);
6d2010ae 692
0a7de745
A
693 /* Ignore segments with no vm size */
694 if (!seg_hdr->vmsize) {
695 continue;
696 }
6d2010ae 697
0a7de745 698 seg = kxld_array_get_item(&object->segs, segi++);
6d2010ae 699
0a7de745
A
700 rval = kxld_seg_init_from_macho_64(seg, seg_hdr);
701 require_noerr(rval, finish);
6d2010ae 702
0a7de745
A
703 sect_offset = offset + sizeof(*seg_hdr);
704 }
705 break;
6d2010ae 706#endif /* KXLD_USER_OR_LP64 */
0a7de745
A
707 case LC_SYMTAB:
708 symtab_hdr = (struct symtab_command *) cmd_hdr;
709 break;
710 case LC_UUID:
711 uuid_hdr = (struct uuid_command *) cmd_hdr;
712 kxld_uuid_init_from_macho(&object->uuid, uuid_hdr);
713 break;
714 case LC_VERSION_MIN_MACOSX:
715 case LC_VERSION_MIN_IPHONEOS:
716 case LC_VERSION_MIN_TVOS:
717 case LC_VERSION_MIN_WATCHOS:
718 versionmin_hdr = (struct version_min_command *) cmd_hdr;
719 kxld_versionmin_init_from_macho(&object->versionmin, versionmin_hdr);
720 break;
721 case LC_BUILD_VERSION:
722 build_version_hdr = (struct build_version_command *)cmd_hdr;
723 kxld_versionmin_init_from_build_cmd(&object->versionmin, build_version_hdr);
724 break;
725 case LC_SOURCE_VERSION:
726 source_version_hdr = (struct source_version_command *) (void *) cmd_hdr;
727 kxld_srcversion_init_from_macho(&object->srcversion, source_version_hdr);
728 break;
729 case LC_DYSYMTAB:
730 object->dysymtab_hdr = (struct dysymtab_command *) cmd_hdr;
731 rval = kxld_reloc_create_macho(&object->extrelocs, &object->relocator,
732 (struct relocation_info *) ((void *) (my_file + object->dysymtab_hdr->extreloff)),
733 object->dysymtab_hdr->nextrel);
734 require_noerr(rval, finish);
735
736 rval = kxld_reloc_create_macho(&object->locrelocs, &object->relocator,
737 (struct relocation_info *) ((void *) (my_file + object->dysymtab_hdr->locreloff)),
738 object->dysymtab_hdr->nlocrel);
739 require_noerr(rval, finish);
740
741 break;
742 case LC_UNIXTHREAD:
743 case LC_MAIN:
744 /* Don't need to do anything with UNIXTHREAD or MAIN for the kernel */
745 require_action(kxld_object_is_kernel(object),
746 finish, rval = KERN_FAILURE;
747 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
748 "LC_UNIXTHREAD/LC_MAIN segment is not valid in a kext."));
749 break;
750 case LC_SEGMENT_SPLIT_INFO:
751 if (isSplitKext) {
752 struct linkedit_data_command *split_info_hdr = NULL;
753 split_info_hdr = (struct linkedit_data_command *) (void *) cmd_hdr;
754 kxld_splitinfolc_init_from_macho(&object->splitinfolc, split_info_hdr);
755 }
756 break;
757 case LC_NOTE:
758 /* binary blob of data */
759 break;
760 case LC_CODE_SIGNATURE:
761 case LC_DYLD_INFO:
762 case LC_DYLD_INFO_ONLY:
763 case LC_FUNCTION_STARTS:
764 case LC_DATA_IN_CODE:
765 case LC_DYLIB_CODE_SIGN_DRS:
766 /* Various metadata that might be stored in the linkedit segment */
767 break;
768 default:
769 rval = KERN_FAILURE;
770 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
771 "Invalid load command type in MH_KEXT_BUNDLE kext: %u.", cmd_hdr->cmd);
772 goto finish;
773 }
774
775 if (seg) {
776 /* Initialize the sections */
777 for (j = 0; j < seg->sects.nitems; ++j, ++secti) {
778 sect = kxld_array_get_item(&object->sects, secti);
779
780 KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
781 kxld_sect_init_from_macho_32, kxld_sect_init_from_macho_64,
782 sect, my_file, &sect_offset, secti, &object->relocator);
783 require_noerr(rval, finish);
784
785 /* Add the section to the segment. This will also make sure
786 * that the sections and segments have the same segname.
787 */
788 rval = kxld_seg_add_section(seg, sect);
789 require_noerr(rval, finish);
790 }
791 rval = kxld_seg_finish_init(seg);
792 require_noerr(rval, finish);
793 }
794 }
795
796 if (filetype_out) {
797 *filetype_out = filetype;
798 }
799 if (symtab_hdr_out) {
800 *symtab_hdr_out = symtab_hdr;
801 }
802 object->is_final_image = TRUE;
803 rval = KERN_SUCCESS;
6d2010ae 804finish:
0a7de745 805 return rval;
6d2010ae
A
806}
807
808/*******************************************************************************
809*******************************************************************************/
810static kern_return_t
811init_from_execute(KXLDObject *object)
812{
0a7de745
A
813 kern_return_t rval = KERN_FAILURE;
814 struct symtab_command *symtab_hdr = NULL;
815 u_int filetype = 0;
816 KXLDSeg * kernel_linkedit_seg = NULL; // used if running kernel
6d2010ae 817#if KXLD_USER_OR_OBJECT
0a7de745
A
818 KXLDSeg *seg = NULL;
819 KXLDSect *sect = NULL;
820 KXLDSectionName *sname = NULL;
821 u_int i = 0, j = 0, k = 0;
6d2010ae 822#endif /* KXLD_USER_OR_OBJECT */
0a7de745
A
823 u_char *my_file;
824
825 check(object);
826
827 if (isOldInterface) {
828 my_file = object->file;
829 } else {
830 my_file = object->split_info.kextExecutable;
831 }
832
833 require_action(kxld_object_is_kernel(object), finish, rval = KERN_FAILURE);
834
835 rval = init_from_final_linked_image(object, &filetype, &symtab_hdr);
836 require_noerr(rval, finish);
837
838 require_action(filetype == MH_EXECUTE, finish, rval = KERN_FAILURE;
839 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
840 "The kernel file is not of type MH_EXECUTE."));
841
842 /* Initialize the symbol table. If this is the running kernel
843 * we will work from the in-memory linkedit segment;
844 * otherwise we work from the whole mach-o image.
845 */
6d2010ae 846#if KERNEL
0a7de745
A
847 kernel_linkedit_seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
848 require_action(kernel_linkedit_seg, finish, rval = KERN_FAILURE;
849 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO));
6d2010ae
A
850#endif
851
0a7de745
A
852 KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
853 kxld_symtab_init_from_macho_32, kxld_symtab_init_from_macho_64,
854 object->symtab, symtab_hdr, my_file, kernel_linkedit_seg);
855 require_noerr(rval, finish);
6d2010ae
A
856
857#if KXLD_USER_OR_OBJECT
0a7de745
A
858 /* Save off the order of section names so that we can lay out kext
859 * sections for MH_OBJECT-based systems.
860 */
861 if (target_supports_object(object)) {
862 rval = kxld_array_init(object->section_order, sizeof(KXLDSectionName),
863 object->sects.nitems);
864 require_noerr(rval, finish);
865
866 /* Copy the section names into the section_order array for future kext
867 * section ordering.
868 */
869 for (i = 0, k = 0; i < object->segs.nitems; ++i) {
870 seg = kxld_array_get_item(&object->segs, i);
871
872 for (j = 0; j < seg->sects.nitems; ++j, ++k) {
873 sect = *(KXLDSect **) kxld_array_get_item(&seg->sects, j);
874 sname = kxld_array_get_item(object->section_order, k);
875
876 strlcpy(sname->segname, sect->segname, sizeof(sname->segname));
877 strlcpy(sname->sectname, sect->sectname, sizeof(sname->sectname));
878 }
879 }
880 }
6d2010ae
A
881#endif /* KXLD_USER_OR_OBJECT */
882
0a7de745 883 rval = KERN_SUCCESS;
6d2010ae 884finish:
0a7de745 885 return rval;
6d2010ae
A
886}
887
888#if KXLD_USER_OR_BUNDLE
889/*******************************************************************************
890*******************************************************************************/
891static boolean_t
316670eb 892target_supports_bundle(const KXLDObject *object __unused)
6d2010ae 893{
0a7de745 894 return TRUE;
6d2010ae
A
895}
896
897/*******************************************************************************
898*******************************************************************************/
0a7de745 899static kern_return_t
6d2010ae
A
900init_from_bundle(KXLDObject *object)
901{
0a7de745
A
902 kern_return_t rval = KERN_FAILURE;
903 struct symtab_command *symtab_hdr = NULL;
904 u_int filetype = 0;
905 u_char *my_file;
906
907 check(object);
908
909 if (isOldInterface) {
910 my_file = object->file;
911 } else {
912 my_file = object->split_info.kextExecutable;
913 }
914
915 require_action(target_supports_bundle(object), finish,
916 rval = KERN_FAILURE;
917 kxld_log(kKxldLogLinking, kKxldLogErr,
918 kKxldLogFiletypeNotSupported, MH_KEXT_BUNDLE));
919
920 rval = init_from_final_linked_image(object, &filetype, &symtab_hdr);
921 require_noerr(rval, finish);
922
923 require_action(filetype == MH_KEXT_BUNDLE, finish,
924 rval = KERN_FAILURE);
925
926 KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
927 kxld_symtab_init_from_macho_32, kxld_symtab_init_from_macho_64,
928 object->symtab, symtab_hdr, my_file,
929 /* kernel_linkedit_seg */ NULL);
930 require_noerr(rval, finish);
931
932 rval = KERN_SUCCESS;
6d2010ae 933finish:
0a7de745 934 return rval;
6d2010ae
A
935}
936#endif /* KXLD_USER_OR_BUNDLE */
937
938#if KXLD_USER_OR_OBJECT
939/*******************************************************************************
940*******************************************************************************/
0a7de745
A
941static boolean_t
942target_supports_object(const KXLDObject *object)
6d2010ae 943{
0a7de745 944 return object->cputype == CPU_TYPE_I386;
6d2010ae
A
945}
946
947/*******************************************************************************
948*******************************************************************************/
0a7de745 949static kern_return_t
6d2010ae
A
950init_from_object(KXLDObject *object)
951{
0a7de745
A
952 kern_return_t rval = KERN_FAILURE;
953 struct load_command *cmd_hdr = NULL;
954 struct symtab_command *symtab_hdr = NULL;
955 struct uuid_command *uuid_hdr = NULL;
956 KXLDSect *sect = NULL;
957 u_long offset = 0;
958 u_long sect_offset = 0;
959 u_int filetype = 0;
960 u_int ncmds = 0;
961 u_int nsects = 0;
962 u_int i = 0;
963 boolean_t has_segment = FALSE;
964 u_char *my_file;
965
966 check(object);
967
968 if (isOldInterface) {
969 my_file = object->file;
970 } else {
971 my_file = object->split_info.kextExecutable;
972 }
973
974 require_action(target_supports_object(object),
975 finish, rval = KERN_FAILURE;
976 kxld_log(kKxldLogLinking, kKxldLogErr,
977 kKxldLogFiletypeNotSupported, MH_OBJECT));
978
979 KXLD_3264_FUNC(kxld_object_is_32_bit(object), offset,
980 get_macho_cmd_data_32, get_macho_cmd_data_64,
981 my_file, offset, &filetype, &ncmds);
982
983 require_action(filetype == MH_OBJECT, finish, rval = KERN_FAILURE);
984
985 /* MH_OBJECTs use one unnamed segment to contain all of the sections. We
986 * loop over all of the load commands to initialize the structures we
987 * expect. Then, we'll use the unnamed segment to get to all of the
988 * sections, and then use those sections to create the actual segments.
989 */
990
991 for (; i < ncmds; ++i, offset += cmd_hdr->cmdsize) {
992 cmd_hdr = (struct load_command *) ((void *) (my_file + offset));
993
994 switch (cmd_hdr->cmd) {
6d2010ae 995#if KXLD_USER_OR_ILP32
0a7de745
A
996 case LC_SEGMENT:
997 {
998 struct segment_command *seg_hdr =
999 (struct segment_command *) cmd_hdr;
1000
1001 /* Ignore segments with no vm size */
1002 if (!seg_hdr->vmsize) {
1003 continue;
1004 }
1005
1006 /* Ignore LINKEDIT segments */
1007 if (streq_safe(seg_hdr->segname, SEG_LINKEDIT,
1008 const_strlen(SEG_LINKEDIT))) {
1009 continue;
1010 }
1011
1012 require_action(kxld_object_is_32_bit(object), finish, rval = KERN_FAILURE;
1013 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
1014 "LC_SEGMENT in 64-bit kext."));
1015 require_action(!has_segment, finish, rval = KERN_FAILURE;
1016 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
1017 "Multiple segments in an MH_OBJECT kext."));
1018
1019 nsects = seg_hdr->nsects;
1020 sect_offset = offset + sizeof(*seg_hdr);
1021 has_segment = TRUE;
1022 }
1023 break;
6d2010ae
A
1024#endif /* KXLD_USER_OR_ILP32 */
1025#if KXLD_USER_OR_LP64
0a7de745
A
1026 case LC_SEGMENT_64:
1027 {
1028 struct segment_command_64 *seg_hdr =
1029 (struct segment_command_64 *) ((void *) cmd_hdr);
1030
1031 /* Ignore segments with no vm size */
1032 if (!seg_hdr->vmsize) {
1033 continue;
1034 }
1035
1036 /* Ignore LINKEDIT segments */
1037 if (streq_safe(seg_hdr->segname, SEG_LINKEDIT,
1038 const_strlen(SEG_LINKEDIT))) {
1039 continue;
1040 }
1041
1042 require_action(!kxld_object_is_32_bit(object), finish, rval = KERN_FAILURE;
1043 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
1044 "LC_SEGMENT_64 in a 32-bit kext."));
1045 require_action(!has_segment, finish, rval = KERN_FAILURE;
1046 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
1047 "Multiple segments in an MH_OBJECT kext."));
1048
1049 nsects = seg_hdr->nsects;
1050 sect_offset = offset + sizeof(*seg_hdr);
1051 has_segment = TRUE;
1052 }
1053 break;
6d2010ae 1054#endif /* KXLD_USER_OR_LP64 */
0a7de745
A
1055 case LC_SYMTAB:
1056 symtab_hdr = (struct symtab_command *) cmd_hdr;
1057
1058 KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
1059 kxld_symtab_init_from_macho_32, kxld_symtab_init_from_macho_64,
1060 object->symtab, symtab_hdr, my_file,
1061 /* kernel_linkedit_seg */ NULL);
1062 require_noerr(rval, finish);
1063 break;
1064 case LC_UUID:
1065 uuid_hdr = (struct uuid_command *) cmd_hdr;
1066 kxld_uuid_init_from_macho(&object->uuid, uuid_hdr);
1067 break;
1068 case LC_UNIXTHREAD:
1069 case LC_MAIN:
1070 /* Don't need to do anything with UNIXTHREAD or MAIN */
1071 break;
1072 case LC_CODE_SIGNATURE:
1073 case LC_DYLD_INFO:
1074 case LC_DYLD_INFO_ONLY:
1075 case LC_FUNCTION_STARTS:
1076 case LC_DATA_IN_CODE:
1077 case LC_DYLIB_CODE_SIGN_DRS:
1078 /* Various metadata that might be stored in the linkedit segment */
1079 break;
1080 case LC_NOTE:
1081 /* bag-of-bits carried with the binary: ignore */
1082 break;
1083 case LC_BUILD_VERSION:
1084 /* should be able to ignore build version commands */
1085 kxld_log(kKxldLogLinking, kKxldLogWarn,
1086 "Ignoring LC_BUILD_VERSION (%u) in MH_OBJECT kext: (platform:%d)",
1087 cmd_hdr->cmd, ((struct build_version_command *)cmd_hdr)->platform);
1088 break;
1089 case LC_VERSION_MIN_MACOSX:
1090 case LC_VERSION_MIN_IPHONEOS:
1091 case LC_VERSION_MIN_TVOS:
1092 case LC_VERSION_MIN_WATCHOS:
1093 case LC_SOURCE_VERSION:
1094 /* Not supported for object files, fall through */
1095 default:
1096 rval = KERN_FAILURE;
1097 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
1098 "Invalid load command type in MH_OBJECT kext: %u.", cmd_hdr->cmd);
1099 goto finish;
1100 }
1101 }
1102
1103 if (has_segment) {
1104 /* Get the number of sections from the segment and build the section index */
1105
1106 rval = kxld_array_init(&object->sects, sizeof(KXLDSect), nsects);
1107 require_noerr(rval, finish);
1108
1109 /* Loop over all of the sections to initialize the section index */
1110
1111 for (i = 0; i < nsects; ++i) {
1112 sect = kxld_array_get_item(&object->sects, i);
1113
1114 KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
1115 kxld_sect_init_from_macho_32, kxld_sect_init_from_macho_64,
1116 sect, my_file, &sect_offset, i, &object->relocator);
1117 require_noerr(rval, finish);
1118 }
1119
1120 /* Create special sections */
6d2010ae
A
1121
1122#if KXLD_USER_OR_GOT
0a7de745
A
1123 rval = create_got(object);
1124 require_noerr(rval, finish);
6d2010ae
A
1125#endif /* KXLD_USER_OR_GOT */
1126
1127#if KXLD_USER_OR_COMMON
0a7de745
A
1128 rval = resolve_common_symbols(object);
1129 require_noerr(rval, finish);
6d2010ae
A
1130#endif /* KXLD_USER_OR_COMMON */
1131
0a7de745 1132 /* Create the segments from the section index */
6d2010ae 1133
0a7de745
A
1134 rval = kxld_seg_create_seg_from_sections(&object->segs, &object->sects);
1135 require_noerr(rval, finish);
6d2010ae 1136
0a7de745
A
1137 rval = kxld_seg_finalize_object_segment(&object->segs,
1138 object->section_order, get_macho_header_size(object));
1139 require_noerr(rval, finish);
6d2010ae 1140
0a7de745
A
1141 rval = kxld_seg_init_linkedit(&object->segs);
1142 require_noerr(rval, finish);
1143 }
6d2010ae 1144
0a7de745 1145 rval = KERN_SUCCESS;
6d2010ae 1146finish:
0a7de745 1147 return rval;
6d2010ae
A
1148}
1149#endif /* KXLD_USER_OR_OBJECT */
1150
1151#if KXLD_USER_OR_ILP32
1152/*******************************************************************************
1153*******************************************************************************/
1154static u_long
1155get_macho_cmd_data_32(u_char *file, u_long offset, u_int *filetype, u_int *ncmds)
1156{
0a7de745 1157 struct mach_header *mach_hdr = (struct mach_header *) ((void *) (file + offset));
6d2010ae 1158
0a7de745
A
1159 if (filetype) {
1160 *filetype = mach_hdr->filetype;
1161 }
1162 if (ncmds) {
1163 *ncmds = mach_hdr->ncmds;
1164 }
6d2010ae 1165
0a7de745 1166 return sizeof(*mach_hdr);
6d2010ae
A
1167}
1168
1169#endif /* KXLD_USER_OR_ILP32 */
1170
1171#if KXLD_USER_OR_LP64
1172/*******************************************************************************
1173*******************************************************************************/
1174static u_long
0a7de745 1175get_macho_cmd_data_64(u_char *file, u_long offset, u_int *filetype, u_int *ncmds)
6d2010ae 1176{
0a7de745 1177 struct mach_header_64 *mach_hdr = (struct mach_header_64 *) ((void *) (file + offset));
6d2010ae 1178
0a7de745
A
1179 if (filetype) {
1180 *filetype = mach_hdr->filetype;
1181 }
1182 if (ncmds) {
1183 *ncmds = mach_hdr->ncmds;
1184 }
6d2010ae 1185
0a7de745 1186 return sizeof(*mach_hdr);
6d2010ae
A
1187}
1188#endif /* KXLD_USER_OR_LP64 */
1189
1190/*******************************************************************************
1191*******************************************************************************/
1192static u_long
1193get_macho_header_size(const KXLDObject *object)
1194{
0a7de745
A
1195 KXLDSeg *seg = NULL;
1196 u_long header_size = 0;
1197 u_int i = 0;
1198 boolean_t object_is_32_bit = kxld_object_is_32_bit(object);
6d2010ae 1199
0a7de745 1200 check(object);
6d2010ae 1201
0a7de745 1202 /* Mach, segment, symtab, and UUID headers */
6d2010ae 1203
0a7de745 1204 header_size += object_is_32_bit ? sizeof(struct mach_header) : sizeof(struct mach_header_64);
6d2010ae 1205
0a7de745
A
1206 for (i = 0; i < object->segs.nitems; ++i) {
1207 seg = kxld_array_get_item(&object->segs, i);
1208 header_size += kxld_seg_get_macho_header_size(seg, object_is_32_bit);
1209 }
6d2010ae 1210
0a7de745 1211 header_size += kxld_symtab_get_macho_header_size();
6d2010ae 1212
316670eb 1213#if KXLD_PIC_KEXTS
0a7de745
A
1214 if (target_supports_slideable_kexts(object)) {
1215 header_size += kxld_reloc_get_macho_header_size();
1216 }
1217#endif /* KXLD_PIC_KEXTS */
1218
1219 if (object->uuid.has_uuid) {
1220 header_size += kxld_uuid_get_macho_header_size();
1221 }
316670eb 1222
0a7de745
A
1223 if (object->versionmin.has_versionmin) {
1224 header_size += kxld_versionmin_get_macho_header_size(&object->versionmin);
1225 }
6d2010ae 1226
0a7de745
A
1227 if (object->srcversion.has_srcversion) {
1228 header_size += kxld_srcversion_get_macho_header_size();
1229 }
316670eb 1230
0a7de745
A
1231 if (isSplitKext && object->splitinfolc.has_splitinfolc) {
1232 header_size += kxld_splitinfolc_get_macho_header_size();
1233 }
1234
1235 return header_size;
6d2010ae
A
1236}
1237
1238/*******************************************************************************
1239*******************************************************************************/
1240static u_long
1241get_macho_data_size(const KXLDObject *object)
1242{
0a7de745
A
1243 KXLDSeg *seg = NULL;
1244 u_long data_size = 0;
1245 u_int i = 0;
6d2010ae 1246
0a7de745 1247 check(object);
6d2010ae 1248
0a7de745
A
1249 /* total all segment vmsize values */
1250 for (i = 0; i < object->segs.nitems; ++i) {
1251 seg = kxld_array_get_item(&object->segs, i);
1252 data_size += (u_long) kxld_seg_get_vmsize(seg);
1253 }
6d2010ae 1254
316670eb 1255#if KXLD_PIC_KEXTS
0a7de745
A
1256 {
1257 /* ensure that when we eventually emit the final linked object,
1258 * appending the __DYSYMTAB data after the __LINKEDIT data will
1259 * not overflow the space allocated for the __LINKEDIT segment
1260 */
1261
1262 u_long seg_vmsize = 0;
1263 u_long symtab_size = 0;
1264 u_long reloc_size = 0;
1265
1266 /* get current __LINKEDIT sizes */
1267 seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
1268
1269 seg_vmsize = (u_long) kxld_seg_get_vmsize(seg);
1270
1271 /* get size of symbol table data that will eventually be dumped
1272 * into the __LINKEDIT segment
1273 */
1274 symtab_size = kxld_symtab_get_macho_data_size(object->symtab, kxld_object_is_32_bit(object));
1275
1276 if (target_supports_slideable_kexts(object)) {
1277 /* get size of __DYSYMTAB relocation entries */
1278 reloc_size = kxld_reloc_get_macho_data_size(&object->locrelocs, &object->extrelocs);
1279 }
1280
1281 /* combine, and ensure they'll both fit within the page(s)
1282 * allocated for the __LINKEDIT segment. If they'd overflow,
1283 * increase the vmsize appropriately so no overflow will occur
1284 */
1285 if ((symtab_size + reloc_size) > seg_vmsize) {
1286 u_long overflow = (symtab_size + reloc_size) - seg_vmsize;
1287 data_size += kxld_round_page_cross_safe(overflow);
1288 }
1289 }
316670eb
A
1290#endif // KXLD_PIC_KEXTS
1291
0a7de745 1292 return data_size;
6d2010ae
A
1293}
1294
1295/*******************************************************************************
1296*******************************************************************************/
0a7de745 1297boolean_t
6d2010ae
A
1298kxld_object_target_needs_swap(const KXLDObject *object __unused)
1299{
1300#if KERNEL
0a7de745 1301 return FALSE;
6d2010ae 1302#else
0a7de745 1303 return object->target_order != object->host_order;
6d2010ae
A
1304#endif /* KERNEL */
1305}
1306
1307/*******************************************************************************
1308*******************************************************************************/
1309KXLDSeg *
1310kxld_object_get_seg_by_name(const KXLDObject *object, const char *segname)
1311{
0a7de745
A
1312 KXLDSeg *seg = NULL;
1313 u_int i = 0;
6d2010ae 1314
0a7de745
A
1315 for (i = 0; i < object->segs.nitems; ++i) {
1316 seg = kxld_array_get_item(&object->segs, i);
6d2010ae 1317
0a7de745
A
1318 if (streq_safe(segname, seg->segname, sizeof(seg->segname))) {
1319 break;
1320 }
6d2010ae 1321
0a7de745
A
1322 seg = NULL;
1323 }
6d2010ae 1324
0a7de745 1325 return seg;
6d2010ae
A
1326}
1327
1328/*******************************************************************************
1329*******************************************************************************/
0a7de745 1330const KXLDRelocator *
6d2010ae
A
1331kxld_object_get_relocator(const KXLDObject * object)
1332{
0a7de745 1333 check(object);
6d2010ae 1334
0a7de745 1335 return &object->relocator;
6d2010ae
A
1336}
1337
1338/*******************************************************************************
1339*******************************************************************************/
1340KXLDSect *
0a7de745 1341kxld_object_get_sect_by_name(const KXLDObject *object, const char *segname,
6d2010ae
A
1342 const char *sectname)
1343{
0a7de745
A
1344 KXLDSect *sect = NULL;
1345 u_int i = 0;
6d2010ae 1346
0a7de745
A
1347 for (i = 0; i < object->sects.nitems; ++i) {
1348 sect = kxld_array_get_item(&object->sects, i);
6d2010ae 1349
0a7de745
A
1350 if (streq_safe(segname, sect->segname, sizeof(sect->segname)) &&
1351 streq_safe(sectname, sect->sectname, sizeof(sect->sectname))) {
1352 break;
1353 }
6d2010ae 1354
0a7de745
A
1355 sect = NULL;
1356 }
6d2010ae 1357
0a7de745 1358 return sect;
6d2010ae
A
1359}
1360
1361/*******************************************************************************
1362*******************************************************************************/
0a7de745 1363const KXLDReloc *
6d2010ae
A
1364kxld_object_get_reloc_at_symbol(const KXLDObject *object, const KXLDSym *sym)
1365{
0a7de745
A
1366 const KXLDReloc *reloc = NULL;
1367 const KXLDSect *sect = NULL;
1368 uint32_t offset = 0;
6d2010ae 1369
0a7de745
A
1370 check(object);
1371 check(sym);
6d2010ae 1372
0a7de745
A
1373 sect = kxld_object_get_section_by_index(object, sym->sectnum);
1374 require(sect, finish);
6d2010ae 1375
0a7de745
A
1376 if (kxld_object_is_final_image(object)) {
1377 reloc = kxld_reloc_get_reloc_by_offset(&object->extrelocs,
1378 sym->base_addr);
1379 if (!reloc) {
1380 reloc = kxld_reloc_get_reloc_by_offset(&object->locrelocs,
1381 sym->base_addr);
1382 }
1383 } else {
1384 offset = kxld_sym_get_section_offset(sym, sect);
1385 reloc = kxld_reloc_get_reloc_by_offset(&sect->relocs, offset);
1386 }
6d2010ae
A
1387
1388finish:
0a7de745 1389 return reloc;
6d2010ae
A
1390}
1391
1392/*******************************************************************************
1393*******************************************************************************/
0a7de745
A
1394const KXLDSym *
1395kxld_object_get_symbol_of_reloc(const KXLDObject *object,
6d2010ae
A
1396 const KXLDReloc *reloc, const KXLDSect *sect)
1397{
0a7de745
A
1398 const KXLDSym *sym = NULL;
1399 u_char *my_file;
1400
1401 if (isOldInterface) {
1402 my_file = object->file;
1403 } else {
1404 my_file = object->split_info.kextExecutable;
1405 }
1406
1407 if (kxld_object_is_final_image(object)) {
1408 sym = kxld_reloc_get_symbol(&object->relocator, reloc, my_file);
1409 } else {
1410 sym = kxld_reloc_get_symbol(&object->relocator, reloc, sect->data);
1411 }
1412 return sym;
6d2010ae
A
1413}
1414
1415/*******************************************************************************
1416*******************************************************************************/
0a7de745 1417const KXLDSect *
6d2010ae
A
1418kxld_object_get_section_by_index(const KXLDObject *object, u_int sectnum)
1419{
0a7de745 1420 KXLDSect *sect = NULL;
6d2010ae 1421
0a7de745 1422 check(object);
6d2010ae 1423
0a7de745
A
1424 if (sectnum < object->sects.nitems) {
1425 sect = kxld_array_get_item(&object->sects, sectnum);
1426 }
1427
1428 return sect;
6d2010ae
A
1429}
1430
1431/*******************************************************************************
1432*******************************************************************************/
0a7de745 1433const KXLDArray *
6d2010ae
A
1434kxld_object_get_extrelocs(const KXLDObject *object)
1435{
0a7de745
A
1436 const KXLDArray *rval = NULL;
1437
1438 check(object);
6d2010ae 1439
0a7de745
A
1440 if (kxld_object_is_final_image(object)) {
1441 rval = &object->extrelocs;
1442 }
6d2010ae 1443
0a7de745 1444 return rval;
6d2010ae
A
1445}
1446
1447/*******************************************************************************
1448*******************************************************************************/
1449const KXLDSymtab *
1450kxld_object_get_symtab(const KXLDObject *object)
1451{
0a7de745 1452 check(object);
6d2010ae 1453
0a7de745 1454 return object->symtab;
6d2010ae
A
1455}
1456
1457#if KXLD_USER_OR_GOT || KXLD_USER_OR_COMMON
1458/*******************************************************************************
1459*******************************************************************************/
1460static kern_return_t
1461add_section(KXLDObject *object, KXLDSect **sect)
1462{
0a7de745
A
1463 kern_return_t rval = KERN_FAILURE;
1464 u_int nsects = object->sects.nitems;
6d2010ae 1465
0a7de745
A
1466 rval = kxld_array_resize(&object->sects, nsects + 1);
1467 require_noerr(rval, finish);
6d2010ae 1468
0a7de745 1469 *sect = kxld_array_get_item(&object->sects, nsects);
6d2010ae 1470
0a7de745 1471 rval = KERN_SUCCESS;
6d2010ae
A
1472
1473finish:
0a7de745 1474 return rval;
6d2010ae
A
1475}
1476#endif /* KXLD_USER_OR_GOT || KXLD_USER_OR_COMMON */
1477
1478#if KXLD_USER_OR_COMMON
1479/*******************************************************************************
1480* If there are common symbols, calculate how much space they'll need
1481* and create/grow the __DATA __common section to accommodate them.
1482* Then, resolve them against that section.
1483*******************************************************************************/
1484static kern_return_t
1485resolve_common_symbols(KXLDObject *object)
1486{
0a7de745
A
1487 kern_return_t rval = KERN_FAILURE;
1488 KXLDSymtabIterator iter;
1489 KXLDSym *sym = NULL;
1490 KXLDSect *sect = NULL;
1491 kxld_addr_t base_addr = 0;
1492 kxld_size_t size = 0;
1493 kxld_size_t total_size = 0;
1494 u_int align = 0;
1495 u_int max_align = 0;
1496 u_int sectnum = 0;
1497
1498 if (!kxld_object_target_supports_common_symbols(object)) {
1499 rval = KERN_SUCCESS;
1500 goto finish;
1501 }
1502
1503 /* Iterate over the common symbols to calculate their total aligned size */
1504 kxld_symtab_iterator_init(&iter, object->symtab, kxld_sym_is_common, FALSE);
1505 while ((sym = kxld_symtab_iterator_get_next(&iter))) {
1506 align = kxld_sym_get_common_align(sym);
1507 size = kxld_sym_get_common_size(sym);
1508
1509 if (align > max_align) {
1510 max_align = align;
1511 }
1512
1513 total_size = kxld_align_address(total_size, align) + size;
1514 }
1515
1516 /* If there are common symbols, grow or create the __DATA __common section
1517 * to hold them.
1518 */
1519 if (total_size) {
1520 sect = kxld_object_get_sect_by_name(object, SEG_DATA, SECT_COMMON);
1521 if (sect) {
1522 base_addr = sect->base_addr + sect->size;
1523
1524 kxld_sect_grow(sect, total_size, max_align);
1525 } else {
1526 base_addr = 0;
1527
1528 rval = add_section(object, &sect);
1529 require_noerr(rval, finish);
1530
1531 kxld_sect_init_zerofill(sect, SEG_DATA, SECT_COMMON,
1532 total_size, max_align);
1533 }
1534
1535 /* Resolve the common symbols against the new section */
1536 rval = kxld_array_get_index(&object->sects, sect, &sectnum);
1537 require_noerr(rval, finish);
1538
1539 kxld_symtab_iterator_reset(&iter);
1540 while ((sym = kxld_symtab_iterator_get_next(&iter))) {
1541 align = kxld_sym_get_common_align(sym);
1542 size = kxld_sym_get_common_size(sym);
1543
1544 base_addr = kxld_align_address(base_addr, align);
1545 kxld_sym_resolve_common(sym, sectnum, base_addr);
1546
1547 base_addr += size;
1548 }
1549 }
1550
1551 rval = KERN_SUCCESS;
6d2010ae
A
1552
1553finish:
0a7de745 1554 return rval;
6d2010ae
A
1555}
1556#endif /* KXLD_USER_OR_COMMON */
1557
1558#if KXLD_USER_OR_GOT
1559/*******************************************************************************
1560*******************************************************************************/
1561static boolean_t
1562target_has_got(const KXLDObject *object)
1563{
0a7de745 1564 return FALSE:
6d2010ae
A
1565}
1566
1567/*******************************************************************************
1568* Create and initialize the Global Offset Table
1569*******************************************************************************/
1570static kern_return_t
1571create_got(KXLDObject *object)
1572{
0a7de745
A
1573 kern_return_t rval = KERN_FAILURE;
1574 KXLDSect *sect = NULL;
1575 u_int ngots = 0;
1576 u_int i = 0;
6d2010ae 1577
0a7de745
A
1578 if (!target_has_got(object)) {
1579 rval = KERN_SUCCESS;
1580 goto finish;
1581 }
6d2010ae 1582
0a7de745
A
1583 for (i = 0; i < object->sects.nitems; ++i) {
1584 sect = kxld_array_get_item(&object->sects, i);
1585 ngots += kxld_sect_get_ngots(sect, &object->relocator,
1586 object->symtab);
1587 }
6d2010ae 1588
0a7de745
A
1589 rval = add_section(object, &sect);
1590 require_noerr(rval, finish);
6d2010ae 1591
0a7de745
A
1592 rval = kxld_sect_init_got(sect, ngots);
1593 require_noerr(rval, finish);
6d2010ae 1594
0a7de745
A
1595 object->got_is_created = TRUE;
1596 rval = KERN_SUCCESS;
6d2010ae
A
1597
1598finish:
0a7de745 1599 return rval;
6d2010ae
A
1600}
1601
1602/*******************************************************************************
1603*******************************************************************************/
1604static kern_return_t
1605populate_got(KXLDObject *object)
1606{
0a7de745
A
1607 kern_return_t rval = KERN_FAILURE;
1608 KXLDSect *sect = NULL;
1609 u_int i = 0;
6d2010ae 1610
0a7de745
A
1611 if (!target_has_got(object) || !object->got_is_created) {
1612 rval = KERN_SUCCESS;
1613 goto finish;
1614 }
6d2010ae 1615
0a7de745
A
1616 for (i = 0; i < object->sects.nitems; ++i) {
1617 sect = kxld_array_get_item(&object->sects, i);
1618 if (streq_safe(sect->segname, KXLD_SEG_GOT, sizeof(KXLD_SEG_GOT)) &&
1619 streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT))) {
1620 kxld_sect_populate_got(sect, object->symtab,
1621 kxld_object_target_needs_swap(object));
1622 break;
1623 }
1624 }
6d2010ae 1625
0a7de745 1626 require_action(i < object->sects.nitems, finish, rval = KXLD_MISSING_GOT);
6d2010ae 1627
0a7de745 1628 rval = KERN_SUCCESS;
6d2010ae
A
1629
1630finish:
0a7de745 1631 return rval;
6d2010ae
A
1632}
1633#endif /* KXLD_USER_OR_GOT */
1634
1635/*******************************************************************************
1636*******************************************************************************/
1637static boolean_t
1638target_supports_protected_segments(const KXLDObject *object)
1639{
0a7de745
A
1640 return object->is_final_image &&
1641 (object->cputype == CPU_TYPE_X86_64 ||
1642 object->cputype == CPU_TYPE_ARM ||
1643 object->cputype == CPU_TYPE_ARM64);
6d2010ae
A
1644}
1645
1646/*******************************************************************************
1647*******************************************************************************/
1648static void
1649set_is_object_linked(KXLDObject *object)
1650{
0a7de745 1651 u_int i = 0;
6d2010ae 1652
0a7de745
A
1653 if (kxld_object_is_kernel(object)) {
1654 object->is_linked = TRUE;
1655 return;
1656 }
6d2010ae 1657
0a7de745
A
1658 if (object->is_final_image) {
1659 object->is_linked = !object->extrelocs.nitems;
1660 return;
1661 }
6d2010ae 1662
0a7de745
A
1663 object->is_linked = TRUE;
1664 for (i = 0; i < object->sects.nitems; ++i) {
1665 KXLDSect *sect = kxld_array_get_item(&object->sects, i);
1666 if (sect->relocs.nitems) {
1667 object->is_linked = FALSE;
1668 break;
1669 }
1670 }
6d2010ae
A
1671}
1672
1673
1674/*******************************************************************************
1675*******************************************************************************/
0a7de745
A
1676void
1677kxld_object_clear(KXLDObject *object)
6d2010ae 1678{
0a7de745
A
1679 KXLDSeg *seg = NULL;
1680 KXLDSect *sect = NULL;
1681 u_int i;
1682 u_char *my_file;
1683
1684 check(object);
6d2010ae 1685
0a7de745
A
1686 if (isOldInterface) {
1687 my_file = object->file;
1688 } else {
1689 my_file = object->split_info.kextExecutable;
1690 }
39037602 1691
6d2010ae 1692#if !KERNEL
0a7de745
A
1693 if (kxld_object_is_kernel(object)) {
1694 unswap_macho(my_file, object->host_order, object->target_order);
1695 }
6d2010ae
A
1696#endif /* !KERNEL */
1697
0a7de745
A
1698 for (i = 0; i < object->segs.nitems; ++i) {
1699 seg = kxld_array_get_item(&object->segs, i);
1700 kxld_seg_clear(seg);
1701 }
1702 kxld_array_reset(&object->segs);
1703
1704 for (i = 0; i < object->sects.nitems; ++i) {
1705 sect = kxld_array_get_item(&object->sects, i);
1706 kxld_sect_clear(sect);
1707 }
1708 kxld_array_reset(&object->sects);
1709
1710 kxld_array_reset(&object->extrelocs);
1711 kxld_array_reset(&object->locrelocs);
1712 kxld_relocator_clear(&object->relocator);
1713 kxld_uuid_clear(&object->uuid);
1714 kxld_versionmin_clear(&object->versionmin);
1715 kxld_srcversion_clear(&object->srcversion);
1716
1717 if (object->symtab) {
1718 kxld_symtab_clear(object->symtab);
1719 }
1720
1721 if (isOldInterface) {
1722 object->file = NULL;
1723 object->size = 0;
1724 } else {
1725 kxld_splitinfolc_clear(&object->splitinfolc);
1726 object->split_info.kextExecutable = NULL;
1727 object->split_info.kextSize = 0;
1728 }
1729 object->filetype = 0;
1730 object->cputype = 0;
1731 object->cpusubtype = 0;
1732 object->is_kernel = FALSE;
1733 object->is_final_image = FALSE;
1734 object->is_linked = FALSE;
1735 object->got_is_created = FALSE;
6d2010ae
A
1736
1737#if KXLD_USER_OR_OBJECT
0a7de745 1738 object->section_order = NULL;
6d2010ae
A
1739#endif
1740#if !KERNEL
0a7de745
A
1741 object->host_order = 0;
1742 object->target_order = 0;
6d2010ae
A
1743#endif
1744}
1745
1746/*******************************************************************************
1747*******************************************************************************/
0a7de745
A
1748void
1749kxld_object_deinit(KXLDObject *object __unused)
6d2010ae 1750{
0a7de745
A
1751 KXLDSeg *seg = NULL;
1752 KXLDSect *sect = NULL;
1753 u_int i;
1754 u_char *my_file;
1755
1756 check(object);
1757
1758 if (isOldInterface) {
1759 my_file = object->file;
1760 } else {
1761 my_file = object->split_info.kextExecutable;
1762 }
6d2010ae
A
1763
1764#if !KERNEL
0a7de745
A
1765 if (my_file && kxld_object_is_kernel(object)) {
1766 unswap_macho(my_file, object->host_order, object->target_order);
1767 }
6d2010ae
A
1768#endif /* !KERNEL */
1769
0a7de745
A
1770 for (i = 0; i < object->segs.maxitems; ++i) {
1771 seg = kxld_array_get_slot(&object->segs, i);
1772 kxld_seg_deinit(seg);
1773 }
1774 kxld_array_deinit(&object->segs);
6d2010ae 1775
0a7de745
A
1776 for (i = 0; i < object->sects.maxitems; ++i) {
1777 sect = kxld_array_get_slot(&object->sects, i);
1778 kxld_sect_deinit(sect);
1779 }
1780 kxld_array_deinit(&object->sects);
6d2010ae 1781
0a7de745
A
1782 kxld_array_deinit(&object->extrelocs);
1783 kxld_array_deinit(&object->locrelocs);
6d2010ae 1784
0a7de745
A
1785 if (object->symtab) {
1786 kxld_symtab_deinit(object->symtab);
1787 kxld_free(object->symtab, kxld_symtab_sizeof());
1788 }
6d2010ae 1789
0a7de745 1790 bzero(object, sizeof(*object));
6d2010ae
A
1791}
1792
1793/*******************************************************************************
1794*******************************************************************************/
1795const u_char *
1796kxld_object_get_file(const KXLDObject *object)
1797{
0a7de745
A
1798 const u_char *my_file;
1799
1800 check(object);
6d2010ae 1801
0a7de745
A
1802 if (isOldInterface) {
1803 my_file = object->file;
1804 } else {
1805 my_file = object->split_info.kextExecutable;
1806 }
1807
1808 return my_file;
6d2010ae
A
1809}
1810
1811/*******************************************************************************
1812*******************************************************************************/
1813const char *
1814kxld_object_get_name(const KXLDObject *object)
1815{
0a7de745 1816 check(object);
6d2010ae 1817
0a7de745 1818 return object->name;
6d2010ae
A
1819}
1820
1821/*******************************************************************************
1822*******************************************************************************/
0a7de745 1823boolean_t
6d2010ae
A
1824kxld_object_is_32_bit(const KXLDObject *object)
1825{
0a7de745 1826 check(object);
6d2010ae 1827
0a7de745 1828 return kxld_is_32_bit(object->cputype);
6d2010ae
A
1829}
1830
1831/*******************************************************************************
1832*******************************************************************************/
0a7de745 1833boolean_t
6d2010ae
A
1834kxld_object_is_final_image(const KXLDObject *object)
1835{
0a7de745 1836 check(object);
6d2010ae 1837
0a7de745 1838 return object->is_final_image;
6d2010ae
A
1839}
1840
1841/*******************************************************************************
1842*******************************************************************************/
0a7de745 1843boolean_t
6d2010ae
A
1844kxld_object_is_kernel(const KXLDObject *object)
1845{
0a7de745 1846 check(object);
6d2010ae 1847
0a7de745 1848 return object->is_kernel;
6d2010ae
A
1849}
1850
1851/*******************************************************************************
1852*******************************************************************************/
0a7de745 1853boolean_t
6d2010ae
A
1854kxld_object_is_linked(const KXLDObject *object)
1855{
0a7de745 1856 check(object);
6d2010ae 1857
0a7de745 1858 return object->is_linked;
6d2010ae
A
1859}
1860
1861/*******************************************************************************
1862*******************************************************************************/
1863boolean_t
1864kxld_object_target_supports_strict_patching(const KXLDObject *object)
1865{
0a7de745 1866 check(object);
6d2010ae 1867
0a7de745 1868 return object->cputype != CPU_TYPE_I386;
6d2010ae
A
1869}
1870
1871/*******************************************************************************
1872*******************************************************************************/
1873boolean_t
1874kxld_object_target_supports_common_symbols(const KXLDObject *object)
1875{
0a7de745 1876 check(object);
6d2010ae 1877
0a7de745 1878 return object->cputype == CPU_TYPE_I386;
6d2010ae
A
1879}
1880
39037602
A
1881
1882/*******************************************************************************
0a7de745 1883*******************************************************************************/
39037602
A
1884void
1885kxld_object_get_vmsize_for_seg_by_name(const KXLDObject *object,
0a7de745
A
1886 const char *segname,
1887 u_long *vmsize)
39037602 1888{
0a7de745
A
1889 check(object);
1890 check(segname);
1891 check(vmsize);
1892
1893 KXLDSeg *seg = NULL;
1894 u_long my_size = 0;
1895
1896 /* segment vmsize */
1897 seg = kxld_object_get_seg_by_name(object, segname);
39037602 1898
0a7de745 1899 my_size = (u_long) kxld_seg_get_vmsize(seg);
39037602 1900
39037602 1901#if KXLD_PIC_KEXTS
0a7de745
A
1902 if (kxld_seg_is_linkedit_seg(seg)) {
1903 u_long reloc_size = 0;
1904
1905 if (target_supports_slideable_kexts(object)) {
1906 /* get size of __DYSYMTAB relocation entries */
1907 reloc_size = kxld_reloc_get_macho_data_size(&object->locrelocs, &object->extrelocs);
1908 my_size += reloc_size;
1909 }
1910 }
39037602 1911#endif
0a7de745
A
1912
1913 *vmsize = my_size;
39037602
A
1914}
1915
6d2010ae
A
1916/*******************************************************************************
1917*******************************************************************************/
1918void
0a7de745 1919kxld_object_get_vmsize(const KXLDObject *object, u_long *header_size,
6d2010ae
A
1920 u_long *vmsize)
1921{
0a7de745
A
1922 check(object);
1923 check(header_size);
1924 check(vmsize);
1925 *header_size = 0;
1926 *vmsize = 0;
6d2010ae 1927
0a7de745 1928 /* vmsize is the padded header page(s) + segment vmsizes */
6d2010ae 1929
0a7de745
A
1930 *header_size = (object->is_final_image) ?
1931 0 : (u_long)kxld_round_page_cross_safe(get_macho_header_size(object));
6d2010ae 1932
0a7de745 1933 *vmsize = *header_size + get_macho_data_size(object);
6d2010ae
A
1934}
1935
316670eb 1936/*******************************************************************************
0a7de745 1937*******************************************************************************/
316670eb
A
1938void
1939kxld_object_set_linked_object_size(KXLDObject *object, u_long vmsize)
1940{
0a7de745
A
1941 check(object);
1942
1943 if (isOldInterface) {
1944 object->output_buffer_size = vmsize; /* cache this for use later */
1945 } else {
1946 object->split_info.linkedKextSize = vmsize;
1947 }
1948 return;
1949}
1950
1951/*******************************************************************************
1952*******************************************************************************/
1953kern_return_t
1954kxld_object_export_linked_object(const KXLDObject *object,
1955 void *linked_object
1956 )
1957{
1958 kern_return_t rval = KERN_FAILURE;
1959 KXLDSeg *seg = NULL;
1960 u_long size = 0;
1961 u_long header_size = 0;
1962 u_long header_offset = 0;
1963 u_long data_offset = 0;
1964 u_int ncmds = 0;
1965 u_int i = 0;
1966 boolean_t is_32bit_object = kxld_object_is_32_bit(object);
1967 kxld_addr_t link_addr;
1968 u_char *my_linked_object;
1969
1970 check(object);
1971 check(linked_object);
1972
1973 if (isOldInterface) {
1974 size = object->output_buffer_size;
1975 link_addr = object->link_addr;
1976 my_linked_object = (u_char *) linked_object;
1977 } else {
1978 size = ((splitKextLinkInfo *)linked_object)->linkedKextSize;
1979 link_addr = ((splitKextLinkInfo *)linked_object)->vmaddr_TEXT;
1980 my_linked_object = ((splitKextLinkInfo *)linked_object)->linkedKext;
1981 }
1982
1983 /* Calculate the size of the headers and data */
1984
1985 header_size = get_macho_header_size(object);
1986
1987 /* Copy data to the file */
1988
1989 ncmds = object->segs.nitems + 1 /* LC_SYMTAB */;
6d2010ae 1990
316670eb 1991#if KXLD_PIC_KEXTS
0a7de745
A
1992 /* don't write out a DYSYMTAB segment for targets that can't digest it
1993 */
1994 if (target_supports_slideable_kexts(object)) {
1995 ncmds++; /* dysymtab */
1996 }
1997#endif /* KXLD_PIC_KEXTS */
1998
1999 if (object->uuid.has_uuid == TRUE) {
2000 ncmds++;
2001 }
2002
2003 if (object->versionmin.has_versionmin == TRUE) {
2004 ncmds++;
2005 }
2006
2007 if (object->srcversion.has_srcversion == TRUE) {
2008 ncmds++;
2009 }
2010
2011 if (isSplitKext && object->splitinfolc.has_splitinfolc) {
2012 ncmds++;
2013 }
2014
2015 rval = export_macho_header(object, my_linked_object, ncmds, &header_offset, header_size);
2016 require_noerr(rval, finish);
2017
2018 for (i = 0; i < object->segs.nitems; ++i) {
2019 seg = kxld_array_get_item(&object->segs, i);
2020
2021 rval = kxld_seg_export_macho_to_vm(seg, my_linked_object, &header_offset,
2022 header_size, size, link_addr, is_32bit_object);
2023 require_noerr(rval, finish);
2024 }
2025
2026 seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
2027 data_offset = (u_long) (seg->link_addr - link_addr);
2028
2029 // data_offset is used to set the fileoff in the macho header load commands
2030 rval = kxld_symtab_export_macho(object->symtab,
2031 my_linked_object,
2032 &header_offset,
2033 header_size,
2034 &data_offset, size, is_32bit_object);
2035 require_noerr(rval, finish);
2036
2037 // data_offset now points past the symbol tab and strings data in the linkedit
2038 // segment - (it was used to set new values for symoff and stroff)
39037602 2039
316670eb 2040#if KXLD_PIC_KEXTS
0a7de745
A
2041 if (target_supports_slideable_kexts(object)) {
2042 rval = kxld_reloc_export_macho(&object->relocator,
2043 &object->locrelocs,
2044 &object->extrelocs,
2045 my_linked_object,
2046 &header_offset,
2047 header_size,
2048 &data_offset, size);
2049 require_noerr(rval, finish);
2050 }
2051#endif /* KXLD_PIC_KEXTS */
2052
2053 if (object->uuid.has_uuid) {
2054 rval = kxld_uuid_export_macho(&object->uuid, my_linked_object, &header_offset, header_size);
2055 require_noerr(rval, finish);
2056 }
2057
2058 if (object->versionmin.has_versionmin) {
2059 rval = kxld_versionmin_export_macho(&object->versionmin, my_linked_object, &header_offset, header_size);
2060 require_noerr(rval, finish);
2061 }
2062
2063 if (object->srcversion.has_srcversion) {
2064 rval = kxld_srcversion_export_macho(&object->srcversion, my_linked_object, &header_offset, header_size);
2065 require_noerr(rval, finish);
2066 }
2067
2068 if (isSplitKext && object->splitinfolc.has_splitinfolc) {
2069 rval = kxld_splitinfolc_export_macho(&object->splitinfolc,
2070 linked_object,
2071 &header_offset,
2072 header_size,
2073 &data_offset,
2074 size);
2075 require_noerr(rval, finish);
2076 }
39037602 2077
6d2010ae 2078#if !KERNEL
0a7de745 2079 unswap_macho(my_linked_object, object->host_order, object->target_order);
6d2010ae
A
2080#endif /* KERNEL */
2081
0a7de745 2082 rval = KERN_SUCCESS;
6d2010ae
A
2083
2084finish:
0a7de745 2085 return rval;
6d2010ae
A
2086}
2087
2088/*******************************************************************************
2089*******************************************************************************/
2090static kern_return_t
2091export_macho_header(const KXLDObject *object, u_char *buf, u_int ncmds,
2092 u_long *header_offset, u_long header_size)
2093{
0a7de745 2094 kern_return_t rval = KERN_FAILURE;
6d2010ae 2095
0a7de745
A
2096 check(object);
2097 check(buf);
2098 check(header_offset);
6d2010ae 2099
0a7de745
A
2100 KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
2101 export_macho_header_32, export_macho_header_64,
2102 object, buf, ncmds, header_offset, header_size);
2103 require_noerr(rval, finish);
6d2010ae 2104
0a7de745 2105 rval = KERN_SUCCESS;
6d2010ae
A
2106
2107finish:
0a7de745 2108 return rval;
6d2010ae
A
2109}
2110
2111#if KXLD_USER_OR_ILP32
2112/*******************************************************************************
2113*******************************************************************************/
2114static kern_return_t
2115export_macho_header_32(const KXLDObject *object, u_char *buf, u_int ncmds,
2116 u_long *header_offset, u_long header_size)
2117{
0a7de745
A
2118 kern_return_t rval = KERN_FAILURE;
2119 struct mach_header *mach = NULL;
2120
2121 check(object);
2122 check(buf);
2123 check(header_offset);
2124
2125 require_action(sizeof(*mach) <= header_size - *header_offset, finish,
2126 rval = KERN_FAILURE);
2127 mach = (struct mach_header *) ((void *) (buf + *header_offset));
2128
2129 mach->magic = MH_MAGIC;
2130 mach->cputype = object->cputype;
2131 mach->cpusubtype = object->cpusubtype;
2132 mach->filetype = object->filetype;
2133 mach->ncmds = ncmds;
2134 mach->sizeofcmds = (uint32_t) (header_size - sizeof(*mach));
2135 mach->flags = MH_NOUNDEFS;
2136
2137 *header_offset += sizeof(*mach);
2138
2139 rval = KERN_SUCCESS;
6d2010ae
A
2140
2141finish:
0a7de745 2142 return rval;
6d2010ae
A
2143}
2144#endif /* KXLD_USER_OR_ILP32 */
2145
2146#if KXLD_USER_OR_LP64
2147/*******************************************************************************
2148*******************************************************************************/
2149static kern_return_t
2150export_macho_header_64(const KXLDObject *object, u_char *buf, u_int ncmds,
2151 u_long *header_offset, u_long header_size)
2152{
0a7de745
A
2153 kern_return_t rval = KERN_FAILURE;
2154 struct mach_header_64 *mach = NULL;
2155
2156 check(object);
2157 check(buf);
2158 check(header_offset);
2159
2160 require_action(sizeof(*mach) <= header_size - *header_offset, finish,
2161 rval = KERN_FAILURE);
2162 mach = (struct mach_header_64 *) ((void *) (buf + *header_offset));
2163
2164 mach->magic = MH_MAGIC_64;
2165 mach->cputype = object->cputype;
2166 mach->cpusubtype = object->cpusubtype;
2167 mach->filetype = object->filetype;
2168 mach->ncmds = ncmds;
2169 mach->sizeofcmds = (uint32_t) (header_size - sizeof(*mach));
2170 mach->flags = MH_NOUNDEFS;
2171
2172 *header_offset += sizeof(*mach);
2173
39037602 2174#if SPLIT_KEXTS_DEBUG
0a7de745
A
2175 {
2176 kxld_log(kKxldLogLinking, kKxldLogErr,
2177 " %p >>> Start of macho header (size %lu) <%s>",
2178 (void *) mach,
2179 sizeof(*mach),
2180 __func__);
2181 kxld_log(kKxldLogLinking, kKxldLogErr,
2182 " %p <<< End of macho header <%s>",
2183 (void *) ((u_char *)mach + sizeof(*mach)),
2184 __func__);
2185 }
39037602 2186#endif
0a7de745
A
2187
2188 rval = KERN_SUCCESS;
6d2010ae
A
2189
2190finish:
0a7de745 2191 return rval;
6d2010ae
A
2192}
2193#endif /* KXLD_USER_OR_LP64 */
2194
2195/*******************************************************************************
2196*******************************************************************************/
0a7de745 2197kern_return_t
6d2010ae
A
2198kxld_object_index_symbols_by_name(KXLDObject *object)
2199{
0a7de745 2200 return kxld_symtab_index_symbols_by_name(object->symtab);
6d2010ae
A
2201}
2202
2203/*******************************************************************************
2204*******************************************************************************/
0a7de745 2205kern_return_t
6d2010ae
A
2206kxld_object_index_cxx_symbols_by_value(KXLDObject *object)
2207{
0a7de745 2208 return kxld_symtab_index_cxx_symbols_by_value(object->symtab);
6d2010ae
A
2209}
2210
2211/*******************************************************************************
2212*******************************************************************************/
0a7de745 2213kern_return_t
6d2010ae
A
2214kxld_object_relocate(KXLDObject *object, kxld_addr_t link_address)
2215{
0a7de745
A
2216 kern_return_t rval = KERN_FAILURE;
2217 KXLDSeg *seg = NULL;
2218 u_int i = 0;
6d2010ae 2219
0a7de745 2220 check(object);
6d2010ae 2221
0a7de745 2222 object->link_addr = link_address;
6d2010ae 2223
0a7de745
A
2224 /* Relocate segments (which relocates the sections) */
2225 for (i = 0; i < object->segs.nitems; ++i) {
2226 seg = kxld_array_get_item(&object->segs, i);
2227 kxld_seg_relocate(seg, link_address);
2228 } // for...
6d2010ae 2229
0a7de745
A
2230 /* Relocate symbols */
2231 rval = kxld_symtab_relocate(object->symtab, &object->sects);
2232 require_noerr(rval, finish);
6d2010ae 2233
0a7de745 2234 rval = KERN_SUCCESS;
6d2010ae 2235finish:
0a7de745 2236 return rval;
6d2010ae
A
2237}
2238
2239/*******************************************************************************
2240*******************************************************************************/
2241static KXLDSym *
2242get_mutable_sym(const KXLDObject *object, const KXLDSym *sym)
2243{
0a7de745
A
2244 KXLDSym *rval = NULL;
2245 kern_return_t result = KERN_FAILURE;
2246 u_int i = 0;
6d2010ae 2247
0a7de745
A
2248 result = kxld_symtab_get_sym_index(object->symtab, sym, &i);
2249 require_noerr(result, finish);
6d2010ae 2250
0a7de745
A
2251 rval = kxld_symtab_get_symbol_by_index(object->symtab, i);
2252 require_action(rval == sym, finish, rval = NULL);
6d2010ae
A
2253
2254finish:
0a7de745 2255 return rval;
6d2010ae
A
2256}
2257
2258/*******************************************************************************
2259*******************************************************************************/
0a7de745
A
2260kern_return_t
2261kxld_object_resolve_symbol(KXLDObject *object,
6d2010ae
A
2262 const KXLDSym *sym, kxld_addr_t addr)
2263{
0a7de745
A
2264 kern_return_t rval = KERN_FAILURE;
2265 KXLDSym *resolved_sym = NULL;
6d2010ae 2266
0a7de745
A
2267 resolved_sym = get_mutable_sym(object, sym);
2268 require_action(resolved_sym, finish, rval = KERN_FAILURE);
6d2010ae 2269
0a7de745
A
2270 rval = kxld_sym_resolve(resolved_sym, addr);
2271 require_noerr(rval, finish);
6d2010ae 2272
0a7de745 2273 rval = KERN_SUCCESS;
6d2010ae 2274finish:
0a7de745 2275 return rval;
6d2010ae
A
2276}
2277
2278/*******************************************************************************
2279*******************************************************************************/
0a7de745 2280kern_return_t
6d2010ae
A
2281kxld_object_patch_symbol(KXLDObject *object, const struct kxld_sym *sym)
2282{
0a7de745
A
2283 kern_return_t rval = KERN_FAILURE;
2284 KXLDSym *patched_sym = NULL;
6d2010ae 2285
0a7de745
A
2286 patched_sym = get_mutable_sym(object, sym);
2287 require_action(patched_sym, finish, rval = KERN_FAILURE);
6d2010ae 2288
0a7de745
A
2289 (void) kxld_sym_patch(patched_sym);
2290 rval = KERN_SUCCESS;
6d2010ae 2291finish:
0a7de745 2292 return rval;
6d2010ae
A
2293}
2294
2295/*******************************************************************************
2296*******************************************************************************/
0a7de745
A
2297kern_return_t
2298kxld_object_add_symbol(KXLDObject *object, char *name, kxld_addr_t link_addr,
6d2010ae
A
2299 const KXLDSym **sym_out)
2300{
0a7de745
A
2301 kern_return_t rval = KERN_FAILURE;
2302 KXLDSym *sym = NULL;
6d2010ae 2303
0a7de745
A
2304 rval = kxld_symtab_add_symbol(object->symtab, name, link_addr, &sym);
2305 require_noerr(rval, finish);
6d2010ae 2306
0a7de745
A
2307 *sym_out = sym;
2308 rval = KERN_SUCCESS;
6d2010ae 2309finish:
0a7de745 2310 return rval;
6d2010ae
A
2311}
2312
2313/*******************************************************************************
2314*******************************************************************************/
0a7de745
A
2315kern_return_t
2316kxld_object_process_relocations(KXLDObject *object,
6d2010ae
A
2317 const KXLDDict *patched_vtables)
2318{
0a7de745
A
2319 kern_return_t rval = KERN_FAILURE;
2320
2321 (void) kxld_relocator_set_vtables(&object->relocator, patched_vtables);
2322
2323 /* Process relocation entries and populate the global offset table.
2324 *
2325 * For final linked images: the relocation entries are contained in a couple
2326 * of tables hanging off the end of the symbol table. The GOT has its own
2327 * section created by the linker; we simply need to fill it.
2328 *
2329 * For object files: the relocation entries are bound to each section.
2330 * The GOT, if it exists for the target architecture, is created by kxld,
2331 * and we must populate it according to our internal structures.
2332 */
2333 if (object->is_final_image) {
6d2010ae 2334#if KXLD_USER_OR_BUNDLE
0a7de745
A
2335 rval = process_symbol_pointers(object);
2336 require_noerr(rval, finish);
6d2010ae 2337
0a7de745
A
2338 rval = process_relocs_from_tables(object);
2339 require_noerr(rval, finish);
6d2010ae 2340#else
0a7de745 2341 require_action(FALSE, finish, rval = KERN_FAILURE);
6d2010ae 2342#endif /* KXLD_USER_OR_BUNDLE */
0a7de745 2343 } else {
6d2010ae 2344#if KXLD_USER_OR_GOT
0a7de745
A
2345 /* Populate GOT */
2346 rval = populate_got(object);
2347 require_noerr(rval, finish);
6d2010ae
A
2348#endif /* KXLD_USER_OR_GOT */
2349#if KXLD_USER_OR_OBJECT
0a7de745
A
2350 rval = process_relocs_from_sections(object);
2351 require_noerr(rval, finish);
6d2010ae 2352#else
0a7de745 2353 require_action(FALSE, finish, rval = KERN_FAILURE);
6d2010ae 2354#endif /* KXLD_USER_OR_OBJECT */
0a7de745 2355 }
6d2010ae 2356
0a7de745
A
2357 /* Populate kmod info structure */
2358 rval = populate_kmod_info(object);
2359 require_noerr(rval, finish);
2360
2361 rval = KERN_SUCCESS;
6d2010ae 2362finish:
0a7de745 2363 return rval;
6d2010ae
A
2364}
2365
2366#if KXLD_USER_OR_BUNDLE
2367
39037602
A
2368#if SPLIT_KEXTS_DEBUG
2369static boolean_t kxld_show_ptr_value;
2370#endif
2371
6d2010ae
A
2372#define SECT_SYM_PTRS "__nl_symbol_ptr"
2373
2374/*******************************************************************************
2375* Final linked images create an __nl_symbol_ptr section for the global offset
2376* table and for symbol pointer lookups in general. Rather than use relocation
2377* entries, the linker creates an "indirect symbol table" which stores indexes
2378* into the symbol table corresponding to the entries of this section. This
2379* function populates the section with the relocated addresses of those symbols.
2380*******************************************************************************/
2381static kern_return_t
2382process_symbol_pointers(KXLDObject *object)
2383{
0a7de745
A
2384 kern_return_t rval = KERN_FAILURE;
2385 KXLDSect *sect = NULL;
2386 KXLDSym *sym = NULL;
2387 int32_t *symidx = NULL;
2388 u_char *symptr = NULL;
2389 u_long symptrsize = 0;
2390 u_int nsyms = 0;
2391 u_int firstsym = 0;
2392 u_int i = 0;
2393
2394 check(object);
2395
2396 require_action(object->is_final_image && object->dysymtab_hdr,
2397 finish, rval = KERN_FAILURE);
2398
2399 /* Get the __DATA,__nl_symbol_ptr section. If it doesn't exist, we have
2400 * nothing to do.
2401 */
2402
2403 sect = kxld_object_get_sect_by_name(object, SEG_DATA, SECT_SYM_PTRS);
2404 if (!sect || !(sect->flags & S_NON_LAZY_SYMBOL_POINTERS)) {
2405 rval = KERN_SUCCESS;
2406 goto finish;
2407 }
2408
2409 /* Calculate the table offset and number of entries in the section */
2410
2411 if (kxld_object_is_32_bit(object)) {
2412 symptrsize = sizeof(uint32_t);
2413 } else {
2414 symptrsize = sizeof(uint64_t);
2415 }
2416
2417 nsyms = (u_int) (sect->size / symptrsize);
2418 firstsym = sect->reserved1;
2419
2420 require_action(firstsym + nsyms <= object->dysymtab_hdr->nindirectsyms,
2421 finish, rval = KERN_FAILURE;
2422 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
2423 "firstsym + nsyms > object->dysymtab_hdr->nindirectsyms"));
2424
2425 /* Iterate through the indirect symbol table and fill in the section of
2426 * symbol pointers. There are three cases:
2427 * 1) A normal symbol - put its value directly in the table
2428 * 2) An INDIRECT_SYMBOL_LOCAL - symbols that are local and already have
2429 * their offset from the start of the file in the section. Simply
2430 * add the file's link address to fill this entry.
2431 * 3) An INDIRECT_SYMBOL_ABS - prepopulated absolute symbols. No
2432 * action is required.
2433 */
2434
2435 if (isOldInterface) {
2436 symidx = (int32_t *) ((void *) (object->file + object->dysymtab_hdr->indirectsymoff));
2437 } else {
2438 symidx = (int32_t *) ((void *) (object->split_info.kextExecutable + object->dysymtab_hdr->indirectsymoff));
2439 }
2440
2441 symidx += firstsym;
2442 symptr = sect->data;
2443 for (i = 0; i < nsyms; ++i, ++symidx, symptr += symptrsize) {
2444 if (*symidx & INDIRECT_SYMBOL_LOCAL) {
2445 if (*symidx & INDIRECT_SYMBOL_ABS) {
2446 continue;
2447 }
2448
2449 if (isOldInterface) {
2450 add_to_ptr(symptr, object->link_addr, kxld_object_is_32_bit(object));
2451 } else {
2452 add_to_ptr(symptr, object->split_info.vmaddr_TEXT, kxld_object_is_32_bit(object));
2453 }
2454 } else {
2455 sym = kxld_symtab_get_symbol_by_index(object->symtab, *symidx);
2456 require_action(sym, finish, rval = KERN_FAILURE);
2457
2458 if (isOldInterface) {
2459 add_to_ptr(symptr, sym->link_addr, kxld_object_is_32_bit(object));
2460 } else {
2461 add_to_ptr(symptr, object->split_info.vmaddr_TEXT, kxld_object_is_32_bit(object));
2462 }
2463 }
2464 }
2465
2466 rval = KERN_SUCCESS;
6d2010ae 2467finish:
0a7de745 2468 return rval;
6d2010ae
A
2469}
2470
2471/*******************************************************************************
2472*******************************************************************************/
2473static KXLDSeg *
2474get_seg_by_base_addr(KXLDObject *object, kxld_addr_t base_addr)
2475{
0a7de745
A
2476 KXLDSeg *seg = NULL;
2477 kxld_addr_t start = 0;
2478 kxld_addr_t end = 0;
2479 u_int i = 0;
6d2010ae 2480
0a7de745
A
2481 for (i = 0; i < object->segs.nitems; ++i) {
2482 seg = kxld_array_get_item(&object->segs, i);
2483 start = seg->base_addr;
2484 end = seg->base_addr + seg->vmsize;
6d2010ae 2485
0a7de745
A
2486 if (start <= base_addr && base_addr < end) {
2487 return seg;
2488 }
2489 }
6d2010ae 2490
0a7de745 2491 return NULL;
6d2010ae
A
2492}
2493
2494/*******************************************************************************
2495*******************************************************************************/
2496static kern_return_t
2497process_relocs_from_tables(KXLDObject *object)
2498{
0a7de745
A
2499 kern_return_t rval = KERN_FAILURE;
2500 KXLDReloc *reloc = NULL;
2501 KXLDSeg *seg = NULL;
2502 u_int i = 0;
2503
2504 /* Process external relocations */
2505 for (i = 0; i < object->extrelocs.nitems; ++i) {
2506 reloc = kxld_array_get_item(&object->extrelocs, i);
2507
2508 seg = get_seg_by_base_addr(object, reloc->address);
2509 require_action(seg, finish, rval = KERN_FAILURE);
2510
2511 if (isOldInterface) {
2512 rval = kxld_relocator_process_table_reloc(&object->relocator, reloc,
2513 seg, object->link_addr);
2514 } else {
2515 kxld_addr_t my_link_addr = object->split_info.vmaddr_TEXT;
2516 if (isSplitKext) {
2517 if (kxld_seg_is_text_exec_seg(seg)) {
2518 my_link_addr = object->split_info.vmaddr_TEXT_EXEC;
2519 } else if (kxld_seg_is_data_seg(seg)) {
2520 my_link_addr = object->split_info.vmaddr_DATA;
2521 } else if (kxld_seg_is_data_const_seg(seg)) {
2522 my_link_addr = object->split_info.vmaddr_DATA_CONST;
2523 } else if (kxld_seg_is_llvm_cov_seg(seg)) {
2524 my_link_addr = object->split_info.vmaddr_LLVM_COV;
2525 } else if (kxld_seg_is_linkedit_seg(seg)) {
2526 my_link_addr = object->split_info.vmaddr_LINKEDIT;
2527 }
2528 }
2529 rval = kxld_relocator_process_table_reloc(&object->relocator,
2530 reloc,
2531 seg,
2532 my_link_addr);
2533 }
2534 require_noerr(rval, finish);
2535 }
2536
2537 /* Process local relocations */
2538 for (i = 0; i < object->locrelocs.nitems; ++i) {
2539 reloc = kxld_array_get_item(&object->locrelocs, i);
2540
2541 seg = get_seg_by_base_addr(object, reloc->address);
2542 require_action(seg, finish, rval = KERN_FAILURE);
2543
2544 if (isOldInterface) {
2545 rval = kxld_relocator_process_table_reloc(&object->relocator, reloc,
2546 seg, object->link_addr);
2547 } else {
2548 kxld_addr_t my_link_addr = object->split_info.vmaddr_TEXT;
2549 if (isSplitKext) {
2550 if (kxld_seg_is_text_exec_seg(seg)) {
2551 my_link_addr = object->split_info.vmaddr_TEXT_EXEC;
2552 } else if (kxld_seg_is_data_seg(seg)) {
2553 my_link_addr = object->split_info.vmaddr_DATA;
2554 } else if (kxld_seg_is_data_const_seg(seg)) {
2555 my_link_addr = object->split_info.vmaddr_DATA_CONST;
2556 } else if (kxld_seg_is_llvm_cov_seg(seg)) {
2557 my_link_addr = object->split_info.vmaddr_LLVM_COV;
2558 } else if (kxld_seg_is_linkedit_seg(seg)) {
2559 my_link_addr = object->split_info.vmaddr_LINKEDIT;
2560 }
2561 }
2562 rval = kxld_relocator_process_table_reloc(&object->relocator,
2563 reloc,
2564 seg,
2565 my_link_addr);
2566 }
2567 require_noerr(rval, finish);
2568 }
2569
2570 rval = KERN_SUCCESS;
6d2010ae 2571finish:
0a7de745 2572 return rval;
6d2010ae
A
2573}
2574
2575/*******************************************************************************
2576*******************************************************************************/
2577static void
2578add_to_ptr(u_char *symptr, kxld_addr_t val, boolean_t is_32_bit)
2579{
0a7de745
A
2580 if (is_32_bit) {
2581 uint32_t *ptr = (uint32_t *) ((void *) symptr);
2582
2583 *ptr += (uint32_t) val;
2584 } else {
2585 uint64_t *ptr = (uint64_t *) ((void *) symptr);
2586
2587 *ptr += (uint64_t) val;
2588 }
2589
39037602 2590#if SPLIT_KEXTS_DEBUG
0a7de745 2591 kxld_show_ptr_value = FALSE;
39037602 2592#endif
6d2010ae
A
2593}
2594#endif /* KXLD_USER_OR_BUNDLE */
2595
2596#if KXLD_USER_OR_OBJECT
2597/*******************************************************************************
2598*******************************************************************************/
2599static kern_return_t
2600process_relocs_from_sections(KXLDObject *object)
2601{
0a7de745
A
2602 kern_return_t rval = KERN_FAILURE;
2603 KXLDSect *sect = NULL;
2604 u_int i = 0;
6d2010ae 2605
0a7de745
A
2606 for (i = 0; i < object->sects.nitems; ++i) {
2607 sect = kxld_array_get_item(&object->sects, i);
2608 rval = kxld_sect_process_relocs(sect, &object->relocator);
2609 require_noerr(rval, finish);
2610 }
6d2010ae 2611
0a7de745 2612 rval = KERN_SUCCESS;
6d2010ae 2613finish:
0a7de745 2614 return rval;
6d2010ae
A
2615}
2616#endif /* KXLD_USER_OR_OBJECT */
2617
2618/*******************************************************************************
2619*******************************************************************************/
2620static kern_return_t
2621populate_kmod_info(KXLDObject *object)
2622{
0a7de745
A
2623 kern_return_t rval = KERN_FAILURE;
2624 KXLDSect *kmodsect = NULL;
2625 KXLDSym *kmodsym = NULL;
2626 kmod_info_t *kmod_info = NULL;
2627 u_long kmod_offset = 0;
2628 u_long header_size;
2629 u_long size;
2630
2631 if (kxld_object_is_kernel(object)) {
2632 rval = KERN_SUCCESS;
2633 goto finish;
2634 }
2635
2636 kxld_object_get_vmsize(object, &header_size, &size);
2637
2638 kmodsym = kxld_symtab_get_locally_defined_symbol_by_name(object->symtab,
2639 KXLD_KMOD_INFO_SYMBOL);
2640 require_action(kmodsym, finish, rval = KERN_FAILURE;
2641 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogNoKmodInfo));
2642
2643 kmodsect = kxld_array_get_item(&object->sects, kmodsym->sectnum);
2644
2645 kmod_offset = (u_long) (kmodsym->base_addr - kmodsect->base_addr);
2646 kmod_info = (kmod_info_t *) ((void *) (kmodsect->data + kmod_offset));
2647
2648 if (kxld_object_is_32_bit(object)) {
2649 kmod_info_32_v1_t *kmod = (kmod_info_32_v1_t *) (kmod_info);
2650
2651 if (isOldInterface) {
2652 kmod->address = (uint32_t) object->link_addr;
2653 } else {
2654 kmod->address = (uint32_t) object->split_info.vmaddr_TEXT;
2655 }
2656
2657 kmod->size = (uint32_t) size;
2658 kmod->hdr_size = (uint32_t) header_size;
6d2010ae
A
2659
2660#if !KERNEL
0a7de745
A
2661 if (kxld_object_target_needs_swap(object)) {
2662 kmod->address = OSSwapInt32(kmod->address);
2663 kmod->size = OSSwapInt32(kmod->size);
2664 kmod->hdr_size = OSSwapInt32(kmod->hdr_size);
2665 }
6d2010ae 2666#endif /* !KERNEL */
0a7de745
A
2667 } else {
2668 kmod_info_64_v1_t *kmod = (kmod_info_64_v1_t *) (kmod_info);
2669
2670 if (isOldInterface) {
2671 kmod->address = object->link_addr;
2672 } else {
2673 kmod->address = object->split_info.vmaddr_TEXT;
2674 }
2675
2676 kmod->size = size;
2677 kmod->hdr_size = header_size;
6d2010ae
A
2678
2679#if !KERNEL
0a7de745
A
2680 if (kxld_object_target_needs_swap(object)) {
2681 kmod->address = OSSwapInt64(kmod->address);
2682 kmod->size = OSSwapInt64(kmod->size);
2683 kmod->hdr_size = OSSwapInt64(kmod->hdr_size);
2684 }
6d2010ae 2685#endif /* !KERNEL */
0a7de745 2686
39037602 2687#if SPLIT_KEXTS_DEBUG
0a7de745
A
2688 {
2689 kxld_log(kKxldLogLinking, kKxldLogErr,
2690 " kmodsect %p kmod_info %p = kmodsect->data %p + kmod_offset %lu <%s>",
2691 (void *) kmodsect,
2692 (void *) kmod_info,
2693 (void *) kmodsect->data,
2694 kmod_offset,
2695 __func__);
2696
2697 kxld_log(kKxldLogLinking, kKxldLogErr,
2698 " kmod_info data: address %p size %llu hdr_size %llu start_addr %p stop_addr %p <%s>",
2699 (void *) kmod->address,
2700 kmod->size,
2701 kmod->hdr_size,
2702 (void *) kmod->start_addr,
2703 (void *) kmod->stop_addr,
2704 __func__);
2705 }
39037602 2706#endif
0a7de745 2707 }
6d2010ae 2708
0a7de745 2709 rval = KERN_SUCCESS;
6d2010ae
A
2710
2711finish:
0a7de745 2712 return rval;
6d2010ae
A
2713}
2714
316670eb
A
2715#if KXLD_PIC_KEXTS
2716/*******************************************************************************
0a7de745 2717*******************************************************************************/
316670eb
A
2718static boolean_t
2719target_supports_slideable_kexts(const KXLDObject *object)
2720{
0a7de745 2721 check(object);
316670eb 2722
0a7de745 2723 return object->cputype != CPU_TYPE_I386 && object->include_kaslr_relocs;
316670eb
A
2724}
2725#endif /* KXLD_PIC_KEXTS */