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