2 * Copyright (c) 2007-2008, 2012 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/types.h>
30 #include <mach/vm_param.h> /* For PAGE_SIZE */
32 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
33 #include <AssertMacros.h>
36 #define __KXLD_KERNEL_UNUSED __unused
38 #define __KXLD_KERNEL_UNUSED
43 #include "kxld_types.h"
45 #include <libkern/kxld.h>
46 #include <libkern/kxld_types.h>
49 #include "kxld_array.h"
50 #include "kxld_dict.h"
51 #include "kxld_kext.h"
52 #include "kxld_object.h"
54 #include "kxld_symtab.h"
55 #include "kxld_util.h"
56 #include "kxld_vtable.h"
62 KXLDArray
*section_order
;
64 KXLDArray dependencies
;
65 KXLDDict defined_symbols_by_name
;
66 KXLDDict defined_cxx_symbols_by_value
;
67 KXLDDict obsolete_symbols_by_name
;
68 KXLDDict vtables_by_name
;
70 KXLDAllocateCallback allocate_callback
;
72 cpu_subtype_t cpusubtype
;
75 // set to TRUE if the kext has a vmaddr_TEXT_EXEC != 0
76 boolean_t isSplitKext
= FALSE
;
78 // set to TRUE is we come in via kxld_link_file
79 boolean_t isOldInterface
= FALSE
;
80 uint32_t kaslr_offsets_count
= 0;
81 uint32_t *kaslr_offsets
= NULL
;
82 uint32_t kaslr_offsets_index
= 0;
84 /*******************************************************************************
86 *******************************************************************************/
88 /* Certain architectures alter the order of a kext's sections from its input
89 * binary, so we track that order in a dictionary of arrays, with one array for
90 * each architecture. Since the kernel only has one architecture, we can
91 * eliminate the dictionary and use a simple array.
92 * XXX: If we ever use the linker in a multithreaded environment, we will need
93 * locks around these global structures.
95 #if KXLD_USER_OR_OBJECT
97 static KXLDArray
*s_section_order
;
99 static KXLDDict
*s_order_dict
;
103 /*******************************************************************************
105 *******************************************************************************/
107 static kern_return_t
init_context(KXLDContext
*context
, u_int ndependencies
);
108 static KXLDObject
* get_object_for_file(KXLDContext
*context
,
109 u_char
*file
, u_long size
, const char *name
);
110 static kern_return_t
allocate_split_kext(KXLDContext
*context
, splitKextLinkInfo
* link_info
);
111 static u_char
* allocate_kext(KXLDContext
*context
, void *callback_data
,
112 kxld_addr_t
*vmaddr
, u_long
*vmsize
, u_char
**linked_object_alloc_out
);
113 static kern_return_t
init_kext_objects(KXLDContext
*context
, u_char
*file
,
114 u_long size
, const char *name
, KXLDDependency
*dependencies
,
115 u_int ndependencies
);
116 static void clear_context(KXLDContext
*context
);
118 /*******************************************************************************
119 *******************************************************************************/
121 kxld_create_context(KXLDContext
**_context
,
122 KXLDAllocateCallback allocate_callback
, KXLDLoggingCallback logging_callback
,
123 KXLDFlags flags
, cpu_type_t cputype
, cpu_subtype_t cpusubtype
,
124 vm_size_t pagesize __KXLD_KERNEL_UNUSED
)
126 kern_return_t rval
= KERN_FAILURE
;
127 KXLDContext
* context
= NULL
;
128 KXLDArray
* section_order
= NULL
;
130 cpu_type_t
* cputype_p
= NULL
;
134 if (isOldInterface
) {
135 check(allocate_callback
);
137 check(logging_callback
);
140 context
= kxld_calloc(sizeof(*context
));
141 require_action(context
, finish
, rval
= KERN_RESOURCE_SHORTAGE
);
143 context
->flags
= flags
;
144 context
->allocate_callback
= allocate_callback
;
145 context
->cputype
= cputype
;
146 context
->cpusubtype
= cpusubtype
;
150 kxld_set_cross_link_page_size(pagesize
);
154 kxld_set_logging_callback(logging_callback
);
156 context
->kext
= kxld_calloc(kxld_kext_sizeof());
157 require_action(context
->kext
, finish
, rval
= KERN_RESOURCE_SHORTAGE
);
159 /* Check if we already have an order array for this arch */
161 #if KXLD_USER_OR_OBJECT
163 context
->section_order
= s_section_order
;
165 /* In userspace, create the dictionary if it doesn't already exist */
167 s_order_dict
= kxld_calloc(sizeof(*s_order_dict
));
168 require_action(s_order_dict
, finish
, rval
= KERN_RESOURCE_SHORTAGE
);
170 rval
= kxld_dict_init(s_order_dict
, kxld_dict_uint32_hash
,
171 kxld_dict_uint32_cmp
, 0);
172 require_noerr(rval
, finish
);
175 context
->section_order
= kxld_dict_find(s_order_dict
, &cputype
);
178 /* Create an order array for this arch if needed */
180 if (!context
->section_order
) {
181 section_order
= kxld_calloc(sizeof(*section_order
));
182 require_action(section_order
, finish
, rval
= KERN_RESOURCE_SHORTAGE
);
185 s_section_order
= section_order
;
187 /* In userspace, add the new array to the order dictionary */
188 cputype_p
= kxld_alloc(sizeof(*cputype_p
));
189 require_action(cputype_p
, finish
, rval
= KERN_RESOURCE_SHORTAGE
);
190 *cputype_p
= cputype
;
192 rval
= kxld_dict_insert(s_order_dict
, cputype_p
, section_order
);
193 require_noerr(rval
, finish
);
198 context
->section_order
= section_order
;
200 section_order
= NULL
;
202 #endif /* KXLD_USER_OR_OBJECT */
210 kxld_destroy_context(context
);
213 kxld_free(section_order
, sizeof(*section_order
));
217 kxld_free(cputype_p
, sizeof(*cputype_p
));
224 /*******************************************************************************
225 *******************************************************************************/
227 kxld_destroy_context(KXLDContext
*context
)
229 KXLDObject
*object
= NULL
;
230 KXLDKext
*dep
= NULL
;
235 kxld_kext_deinit(context
->kext
);
237 for (i
= 0; i
< context
->objects
.maxitems
; ++i
) {
238 object
= kxld_array_get_slot(&context
->objects
, i
);
239 kxld_object_deinit(object
);
241 kxld_array_deinit(&context
->objects
);
243 for (i
= 0; i
< context
->dependencies
.maxitems
; ++i
) {
244 dep
= kxld_array_get_slot(&context
->dependencies
, i
);
245 kxld_kext_deinit(dep
);
247 kxld_array_deinit(&context
->dependencies
);
249 kxld_dict_deinit(&context
->defined_symbols_by_name
);
250 kxld_dict_deinit(&context
->defined_cxx_symbols_by_value
);
251 kxld_dict_deinit(&context
->obsolete_symbols_by_name
);
252 kxld_dict_deinit(&context
->vtables_by_name
);
254 kxld_free(context
->kext
, kxld_kext_sizeof());
255 kxld_free(context
, sizeof(*context
));
257 kxld_print_memory_report();
260 /*******************************************************************************
261 *******************************************************************************/
263 kxld_link_split_file(
264 KXLDContext
* context
,
265 splitKextLinkInfo
*link_info
,
267 void * callback_data
,
268 KXLDDependency
* dependencies
,
270 kxld_addr_t
* kmod_info_kern
)
272 kern_return_t rval
= KERN_FAILURE
;
273 KXLDObject
* kext_object
= NULL
;
274 splitKextLinkInfo
* my_link_info
= NULL
;
276 isSplitKext
= (link_info
->vmaddr_TEXT_EXEC
!= 0);
277 isOldInterface
= FALSE
;
279 kxld_set_logging_callback_data(name
, callback_data
);
281 kxld_log(kKxldLogLinking
, kKxldLogBasic
, "Linking kext %s", name
);
283 kaslr_offsets_count
= 0;
284 kaslr_offsets_index
= 0;
285 kaslr_offsets
= NULL
;
287 require_action(context
, finish
, rval
= KERN_INVALID_ARGUMENT
);
288 require_action(link_info
, finish
, rval
= KERN_INVALID_ARGUMENT
);
289 require_action(dependencies
, finish
, rval
= KERN_INVALID_ARGUMENT
);
290 require_action(ndependencies
, finish
, rval
= KERN_INVALID_ARGUMENT
);
291 require_action(kmod_info_kern
, finish
, rval
= KERN_INVALID_ARGUMENT
);
293 rval
= init_context(context
, ndependencies
);
294 require_noerr(rval
, finish
);
296 rval
= init_kext_objects(context
,
297 link_info
->kextExecutable
,
300 dependencies
, ndependencies
);
301 require_noerr(rval
, finish
);
303 kext_object
= get_object_for_file(context
,
304 link_info
->kextExecutable
,
307 require_action(kext_object
, finish
, rval
= KERN_FAILURE
);
309 // copy vmaddrs and fileoffsets for split segments into kext_object
310 kxld_object_set_link_info(kext_object
, link_info
);
312 my_link_info
= kxld_object_get_link_info(kext_object
);
314 rval
= allocate_split_kext(context
, my_link_info
);
315 require_noerr(rval
, finish
);
317 #if SPLIT_KEXTS_DEBUG
318 kxld_log(kKxldLogLinking
, kKxldLogErr
, "Linking kext %s", name
);
319 kxld_show_split_info(link_info
);
320 #endif // SPLIT_KEXTS_DEBUG
322 rval
= kxld_kext_relocate(context
->kext
,
323 (kxld_addr_t
)my_link_info
,
324 &context
->vtables_by_name
,
325 &context
->defined_symbols_by_name
,
326 &context
->obsolete_symbols_by_name
,
327 &context
->defined_cxx_symbols_by_value
);
328 require_noerr(rval
, finish
);
330 rval
= kxld_kext_export_linked_object(context
->kext
,
331 (void *) my_link_info
,
333 require_noerr(rval
, finish
);
335 // pass back info about linked kext
336 link_info
->kaslr_offsets_count
= kaslr_offsets_count
;
337 link_info
->kaslr_offsets
= kaslr_offsets
;
338 link_info
->linkedKext
= my_link_info
->linkedKext
;
339 link_info
->linkedKextSize
= my_link_info
->linkedKextSize
;
341 if (kaslr_offsets_count
!= kaslr_offsets_index
) {
342 kxld_log(kKxldLogLinking
, kKxldLogErr
, "[ERROR] %s: KASLR pointers: count=%d, but only populated %d!", name
, kaslr_offsets_count
, kaslr_offsets_index
);
347 // the values are now the responsibility of the caller
348 kaslr_offsets_count
= 0;
349 kaslr_offsets_index
= 0;
350 kaslr_offsets
= NULL
;
354 clear_context(context
);
355 kxld_set_logging_callback_data(NULL
, NULL
);
360 /*******************************************************************************
361 *******************************************************************************/
364 KXLDContext
* context
,
368 void * callback_data
,
369 KXLDDependency
* dependencies
,
371 u_char
** linked_object_out
,
372 kxld_addr_t
* kmod_info_kern
)
374 kern_return_t rval
= KERN_FAILURE
;
375 kxld_addr_t vmaddr
= 0;
377 u_char
* linked_object
= NULL
;
378 u_char
* linked_object_alloc
= NULL
;
380 kaslr_offsets_count
= 0;
381 kaslr_offsets_index
= 0;
382 kaslr_offsets
= NULL
;
384 kxld_set_logging_callback_data(name
, callback_data
);
386 kxld_log(kKxldLogLinking
, kKxldLogBasic
, "Linking kext %s", name
);
388 require_action(context
, finish
, rval
= KERN_INVALID_ARGUMENT
);
389 require_action(dependencies
, finish
, rval
= KERN_INVALID_ARGUMENT
);
390 require_action(ndependencies
, finish
, rval
= KERN_INVALID_ARGUMENT
);
391 require_action(file
, finish
, rval
= KERN_INVALID_ARGUMENT
);
392 require_action(size
, finish
, rval
= KERN_INVALID_ARGUMENT
);
393 require_action(linked_object_out
, finish
, rval
= KERN_INVALID_ARGUMENT
);
394 require_action(kmod_info_kern
, finish
, rval
= KERN_INVALID_ARGUMENT
);
397 isOldInterface
= TRUE
;
399 rval
= init_context(context
, ndependencies
);
400 require_noerr(rval
, finish
);
402 rval
= init_kext_objects(context
, file
, size
, name
,
403 dependencies
, ndependencies
);
404 require_noerr(rval
, finish
);
406 linked_object
= allocate_kext(context
, callback_data
,
407 &vmaddr
, &vmsize
, &linked_object_alloc
);
408 require_action(linked_object
, finish
, rval
= KERN_RESOURCE_SHORTAGE
);
411 rval
= kxld_kext_relocate(context
->kext
,
413 &context
->vtables_by_name
,
414 &context
->defined_symbols_by_name
,
415 &context
->obsolete_symbols_by_name
,
416 &context
->defined_cxx_symbols_by_value
);
417 require_noerr(rval
, finish
);
419 rval
= kxld_kext_export_linked_object(context
->kext
,
420 (void *) linked_object
,
422 require_noerr(rval
, finish
);
423 *linked_object_out
= linked_object
;
425 linked_object_alloc
= NULL
;
429 if (linked_object_alloc
) {
430 kxld_page_free_untracked(linked_object_alloc
, vmsize
);
433 clear_context(context
);
434 kxld_set_logging_callback_data(NULL
, NULL
);
440 /*******************************************************************************
441 *******************************************************************************/
443 init_context(KXLDContext
*context
, u_int ndependencies
)
445 kern_return_t rval
= KERN_FAILURE
;
447 /* Create an array of objects large enough to hold an object
448 * for every dependency, an interface for each dependency, and a kext. */
449 rval
= kxld_array_init(&context
->objects
,
450 kxld_object_sizeof(), 2 * ndependencies
+ 1);
451 require_noerr(rval
, finish
);
453 rval
= kxld_array_init(&context
->dependencies
,
454 kxld_kext_sizeof(), ndependencies
);
455 require_noerr(rval
, finish
);
457 rval
= kxld_dict_init(&context
->defined_symbols_by_name
,
458 kxld_dict_string_hash
, kxld_dict_string_cmp
, 0);
459 require_noerr(rval
, finish
);
461 rval
= kxld_dict_init(&context
->defined_cxx_symbols_by_value
,
462 kxld_dict_kxldaddr_hash
, kxld_dict_kxldaddr_cmp
, 0);
463 require_noerr(rval
, finish
);
465 rval
= kxld_dict_init(&context
->obsolete_symbols_by_name
,
466 kxld_dict_string_hash
, kxld_dict_string_cmp
, 0);
467 require_noerr(rval
, finish
);
469 rval
= kxld_dict_init(&context
->vtables_by_name
, kxld_dict_string_hash
,
470 kxld_dict_string_cmp
, 0);
471 require_noerr(rval
, finish
);
478 /*******************************************************************************
479 *******************************************************************************/
481 init_kext_objects(KXLDContext
*context
,
485 KXLDDependency
*dependencies
,
488 kern_return_t rval
= KERN_FAILURE
;
489 KXLDKext
*kext
= NULL
;
490 KXLDObject
*kext_object
= NULL
;
491 KXLDObject
*interface_object
= NULL
;
494 /* Create a kext object for each dependency. If it's a direct dependency,
495 * export its symbols by name by value. If it's indirect, just export the
496 * C++ symbols by value.
498 for (i
= 0; i
< ndependencies
; ++i
) {
499 kext
= kxld_array_get_item(&context
->dependencies
, i
);
501 interface_object
= NULL
;
503 kext_object
= get_object_for_file(context
, dependencies
[i
].kext
,
504 dependencies
[i
].kext_size
, dependencies
[i
].kext_name
);
505 require_action(kext_object
, finish
, rval
= KERN_FAILURE
);
507 if (dependencies
[i
].interface
) {
508 interface_object
= get_object_for_file(context
,
509 dependencies
[i
].interface
, dependencies
[i
].interface_size
,
510 dependencies
[i
].interface_name
);
511 require_action(interface_object
, finish
, rval
= KERN_FAILURE
);
514 rval
= kxld_kext_init(kext
, kext_object
, interface_object
);
515 require_noerr(rval
, finish
);
517 if (dependencies
[i
].is_direct_dependency
) {
518 rval
= kxld_kext_export_symbols(kext
,
519 &context
->defined_symbols_by_name
,
520 &context
->obsolete_symbols_by_name
,
521 &context
->defined_cxx_symbols_by_value
);
522 require_noerr(rval
, finish
);
524 rval
= kxld_kext_export_symbols(kext
,
525 /* defined_symbols */ NULL
, /* obsolete_symbols */ NULL
,
526 &context
->defined_cxx_symbols_by_value
);
527 require_noerr(rval
, finish
);
531 /* Export the vtables for all of the dependencies. */
532 for (i
= 0; i
< context
->dependencies
.nitems
; ++i
) {
533 kext
= kxld_array_get_item(&context
->dependencies
, i
);
535 rval
= kxld_kext_export_vtables(kext
,
536 &context
->defined_cxx_symbols_by_value
,
537 &context
->defined_symbols_by_name
,
538 &context
->vtables_by_name
);
539 require_noerr(rval
, finish
);
542 /* Create a kext object for the kext we're linking and export its locally
543 * defined C++ symbols.
545 kext_object
= get_object_for_file(context
, file
, size
, name
);
546 require_action(kext_object
, finish
, rval
= KERN_FAILURE
);
548 rval
= kxld_kext_init(context
->kext
, kext_object
, /* interface */ NULL
);
549 require_noerr(rval
, finish
);
551 rval
= kxld_kext_export_symbols(context
->kext
,
552 /* defined_symbols */ NULL
, /* obsolete_symbols */ NULL
,
553 &context
->defined_cxx_symbols_by_value
);
554 require_noerr(rval
, finish
);
561 /*******************************************************************************
562 *******************************************************************************/
564 get_object_for_file(KXLDContext
*context
, u_char
*file
, u_long size
,
567 KXLDObject
*rval
= NULL
;
568 KXLDObject
*object
= NULL
;
569 kern_return_t result
= 0;
572 for (i
= 0; i
< context
->objects
.nitems
; ++i
) {
573 object
= kxld_array_get_item(&context
->objects
, i
);
575 if (!kxld_object_get_file(object
)) {
576 result
= kxld_object_init_from_macho(object
, file
, size
, name
,
577 context
->section_order
, context
->cputype
, context
->cpusubtype
, context
->flags
);
578 require_noerr(result
, finish
);
584 if (kxld_object_get_file(object
) == file
) {
594 #include <mach-o/loader.h>
596 /*******************************************************************************
597 *******************************************************************************/
599 allocate_split_kext(KXLDContext
*context
, splitKextLinkInfo
* link_info
)
601 kern_return_t rval
= KERN_FAILURE
;
603 u_long header_size
= 0;
604 u_char
* linked_object
= NULL
;
606 kxld_kext_get_vmsize(context
->kext
, &header_size
, &vmsize
);
609 /* get __LINKEDIT vmsize */
610 kxld_kext_get_vmsize_for_seg_by_name(context
->kext
, SEG_LINKEDIT
, &vmsize
);
612 vmsize
+= (link_info
->vmaddr_LINKEDIT
- link_info
->vmaddr_TEXT
);
614 link_info
->linkedKextSize
= vmsize
;
616 linked_object
= kxld_page_alloc_untracked(link_info
->linkedKextSize
);
617 require(linked_object
, finish
);
618 link_info
->linkedKext
= linked_object
;
625 /*******************************************************************************
626 *******************************************************************************/
628 allocate_kext(KXLDContext
*context
,
630 kxld_addr_t
*vmaddr_out
,
632 u_char
**linked_object_alloc_out
)
634 KXLDAllocateFlags flags
= 0;
635 kxld_addr_t vmaddr
= 0;
637 u_long header_size
= 0;
638 u_char
* linked_object
= NULL
;
640 *linked_object_alloc_out
= NULL
;
642 kxld_kext_get_vmsize(context
->kext
, &header_size
, &vmsize
);
644 vmaddr
= context
->allocate_callback(vmsize
, &flags
, callback_data
);
645 require_action(!(vmaddr
& (kxld_get_effective_page_size() - 1)), finish
,
646 kxld_log(kKxldLogLinking
, kKxldLogErr
,
647 "Load address %p is not page-aligned.",
648 (void *) (uintptr_t) vmaddr
));
650 /* Zero out the memory before we fill it. We fill this buffer in a
651 * sparse fashion, and it's simpler to clear it now rather than
652 * track and zero any pieces we didn't touch after we've written
653 * all of the sections to memory.
655 if (flags
& kKxldAllocateWritable
) {
656 linked_object
= (u_char
*) (u_long
) vmaddr
;
657 bzero(linked_object
, vmsize
);
659 linked_object
= kxld_page_alloc_untracked(vmsize
);
660 require(linked_object
, finish
);
662 *linked_object_alloc_out
= linked_object
;
665 kxld_kext_set_linked_object_size(context
->kext
, vmsize
);
667 *vmaddr_out
= vmaddr
;
668 *vmsize_out
= vmsize
;
671 return linked_object
;
674 /*******************************************************************************
675 *******************************************************************************/
677 clear_context(KXLDContext
*context
)
679 KXLDObject
* object
= NULL
;
680 KXLDKext
* dep
= NULL
;
685 kxld_kext_clear(context
->kext
);
687 for (i
= 0; i
< context
->objects
.nitems
; ++i
) {
688 object
= kxld_array_get_item(&context
->objects
, i
);
689 kxld_object_clear(object
);
691 kxld_array_reset(&context
->objects
);
693 for (i
= 0; i
< context
->dependencies
.nitems
; ++i
) {
694 dep
= kxld_array_get_item(&context
->dependencies
, i
);
695 kxld_kext_clear(dep
);
697 kxld_array_reset(&context
->dependencies
);
699 kxld_dict_clear(&context
->defined_symbols_by_name
);
700 kxld_dict_clear(&context
->defined_cxx_symbols_by_value
);
701 kxld_dict_clear(&context
->obsolete_symbols_by_name
);
702 kxld_dict_clear(&context
->vtables_by_name
);