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_alloc(sizeof(*context
));
141 require_action(context
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
142 bzero(context
, sizeof(*context
));
144 context
->flags
= flags
;
145 context
->allocate_callback
= allocate_callback
;
146 context
->cputype
= cputype
;
147 context
->cpusubtype
= cpusubtype
;
151 kxld_set_cross_link_page_size(pagesize
);
155 kxld_set_logging_callback(logging_callback
);
157 context
->kext
= kxld_alloc(kxld_kext_sizeof());
158 require_action(context
->kext
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
159 bzero(context
->kext
, kxld_kext_sizeof());
161 /* Check if we already have an order array for this arch */
163 #if KXLD_USER_OR_OBJECT
165 context
->section_order
= s_section_order
;
167 /* In userspace, create the dictionary if it doesn't already exist */
169 s_order_dict
= kxld_alloc(sizeof(*s_order_dict
));
170 require_action(s_order_dict
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
171 bzero(s_order_dict
, sizeof(*s_order_dict
));
173 rval
= kxld_dict_init(s_order_dict
, kxld_dict_uint32_hash
,
174 kxld_dict_uint32_cmp
, 0);
175 require_noerr(rval
, finish
);
178 context
->section_order
= kxld_dict_find(s_order_dict
, &cputype
);
181 /* Create an order array for this arch if needed */
183 if (!context
->section_order
) {
185 section_order
= kxld_alloc(sizeof(*section_order
));
186 require_action(section_order
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
187 bzero(section_order
, sizeof(*section_order
));
190 s_section_order
= section_order
;
192 /* In userspace, add the new array to the order dictionary */
193 cputype_p
= kxld_alloc(sizeof(*cputype_p
));
194 require_action(cputype_p
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
195 *cputype_p
= cputype
;
197 rval
= kxld_dict_insert(s_order_dict
, cputype_p
, section_order
);
198 require_noerr(rval
, finish
);
203 context
->section_order
= section_order
;
205 section_order
= NULL
;
207 #endif /* KXLD_USER_OR_OBJECT */
214 if (context
) kxld_destroy_context(context
);
215 if (section_order
) kxld_free(section_order
, sizeof(*section_order
));
217 if (cputype_p
) kxld_free(cputype_p
, sizeof(*cputype_p
));
223 /*******************************************************************************
224 *******************************************************************************/
226 kxld_destroy_context(KXLDContext
*context
)
228 KXLDObject
*object
= NULL
;
229 KXLDKext
*dep
= NULL
;
234 kxld_kext_deinit(context
->kext
);
236 for (i
= 0; i
< context
->objects
.maxitems
; ++i
) {
237 object
= kxld_array_get_slot(&context
->objects
, i
);
238 kxld_object_deinit(object
);
240 kxld_array_deinit(&context
->objects
);
242 for (i
= 0; i
< context
->dependencies
.maxitems
; ++i
) {
243 dep
= kxld_array_get_slot(&context
->dependencies
, i
);
244 kxld_kext_deinit(dep
);
246 kxld_array_deinit(&context
->dependencies
);
248 kxld_dict_deinit(&context
->defined_symbols_by_name
);
249 kxld_dict_deinit(&context
->defined_cxx_symbols_by_value
);
250 kxld_dict_deinit(&context
->obsolete_symbols_by_name
);
251 kxld_dict_deinit(&context
->vtables_by_name
);
253 kxld_free(context
->kext
, kxld_kext_sizeof());
254 kxld_free(context
, sizeof(*context
));
256 kxld_print_memory_report();
259 /*******************************************************************************
260 *******************************************************************************/
262 kxld_link_split_file(
263 KXLDContext
* context
,
264 splitKextLinkInfo
*link_info
,
266 void * callback_data
,
267 KXLDDependency
* dependencies
,
269 kxld_addr_t
* kmod_info_kern
)
271 kern_return_t rval
= KERN_FAILURE
;
272 KXLDObject
* kext_object
= NULL
;
273 splitKextLinkInfo
* my_link_info
= NULL
;
275 isSplitKext
= (link_info
->vmaddr_TEXT_EXEC
!= 0);
276 isOldInterface
= FALSE
;
278 kxld_set_logging_callback_data(name
, callback_data
);
280 kxld_log(kKxldLogLinking
, kKxldLogBasic
, "Linking kext %s", name
);
282 kaslr_offsets_count
= 0;
283 kaslr_offsets_index
= 0;
284 kaslr_offsets
= NULL
;
286 require_action(context
, finish
, rval
=KERN_INVALID_ARGUMENT
);
287 require_action(link_info
, finish
, rval
=KERN_INVALID_ARGUMENT
);
288 require_action(dependencies
, finish
, rval
=KERN_INVALID_ARGUMENT
);
289 require_action(ndependencies
, finish
, rval
=KERN_INVALID_ARGUMENT
);
290 require_action(kmod_info_kern
, finish
, rval
=KERN_INVALID_ARGUMENT
);
292 rval
= init_context(context
, ndependencies
);
293 require_noerr(rval
, finish
);
295 rval
= init_kext_objects(context
,
296 link_info
->kextExecutable
,
299 dependencies
, ndependencies
);
300 require_noerr(rval
, finish
);
302 kext_object
= get_object_for_file(context
,
303 link_info
->kextExecutable
,
306 require_action(kext_object
, finish
, rval
=KERN_FAILURE
);
308 // copy vmaddrs and fileoffsets for split segments into kext_object
309 kxld_object_set_link_info(kext_object
, link_info
);
311 my_link_info
= kxld_object_get_link_info(kext_object
);
313 rval
= allocate_split_kext(context
, my_link_info
);
314 require_noerr(rval
, finish
);
316 #if SPLIT_KEXTS_DEBUG
317 kxld_log(kKxldLogLinking
, kKxldLogErr
, "Linking kext %s", name
);
318 kxld_show_split_info(link_info
);
319 #endif // SPLIT_KEXTS_DEBUG
321 rval
= kxld_kext_relocate(context
->kext
,
322 (kxld_addr_t
)my_link_info
,
323 &context
->vtables_by_name
,
324 &context
->defined_symbols_by_name
,
325 &context
->obsolete_symbols_by_name
,
326 &context
->defined_cxx_symbols_by_value
);
327 require_noerr(rval
, finish
);
329 rval
= kxld_kext_export_linked_object(context
->kext
,
330 (void *) my_link_info
,
332 require_noerr(rval
, finish
);
334 // pass back info about linked kext
335 link_info
->kaslr_offsets_count
= kaslr_offsets_count
;
336 link_info
->kaslr_offsets
= kaslr_offsets
;
337 link_info
->linkedKext
= my_link_info
->linkedKext
;
338 link_info
->linkedKextSize
= my_link_info
->linkedKextSize
;
340 if (kaslr_offsets_count
!= kaslr_offsets_index
) {
341 kxld_log(kKxldLogLinking
, kKxldLogErr
, "[ERROR] %s: KASLR pointers: count=%d, but only populated %d!", name
, kaslr_offsets_count
, kaslr_offsets_index
);
346 // the values are now the responsibility of the caller
347 kaslr_offsets_count
= 0;
348 kaslr_offsets_index
= 0;
349 kaslr_offsets
= NULL
;
353 clear_context(context
);
354 kxld_set_logging_callback_data(NULL
, NULL
);
359 /*******************************************************************************
360 *******************************************************************************/
363 KXLDContext
* context
,
367 void * callback_data
,
368 KXLDDependency
* dependencies
,
370 u_char
** linked_object_out
,
371 kxld_addr_t
* kmod_info_kern
)
373 kern_return_t rval
= KERN_FAILURE
;
374 kxld_addr_t vmaddr
= 0;
376 u_char
* linked_object
= NULL
;
377 u_char
* linked_object_alloc
= NULL
;
379 kaslr_offsets_count
= 0;
380 kaslr_offsets_index
= 0;
381 kaslr_offsets
= NULL
;
383 kxld_set_logging_callback_data(name
, callback_data
);
385 kxld_log(kKxldLogLinking
, kKxldLogBasic
, "Linking kext %s", name
);
387 require_action(context
, finish
, rval
=KERN_INVALID_ARGUMENT
);
388 require_action(dependencies
, finish
, rval
=KERN_INVALID_ARGUMENT
);
389 require_action(ndependencies
, finish
, rval
=KERN_INVALID_ARGUMENT
);
390 require_action(file
, finish
, rval
=KERN_INVALID_ARGUMENT
);
391 require_action(size
, finish
, rval
=KERN_INVALID_ARGUMENT
);
392 require_action(linked_object_out
, finish
, rval
=KERN_INVALID_ARGUMENT
);
393 require_action(kmod_info_kern
, finish
, rval
=KERN_INVALID_ARGUMENT
);
396 isOldInterface
= TRUE
;
398 rval
= init_context(context
, ndependencies
);
399 require_noerr(rval
, finish
);
401 rval
= init_kext_objects(context
, file
, size
, name
,
402 dependencies
, ndependencies
);
403 require_noerr(rval
, finish
);
405 linked_object
= allocate_kext(context
, callback_data
,
406 &vmaddr
, &vmsize
, &linked_object_alloc
);
407 require_action(linked_object
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
410 rval
= kxld_kext_relocate(context
->kext
,
412 &context
->vtables_by_name
,
413 &context
->defined_symbols_by_name
,
414 &context
->obsolete_symbols_by_name
,
415 &context
->defined_cxx_symbols_by_value
);
416 require_noerr(rval
, finish
);
418 rval
= kxld_kext_export_linked_object(context
->kext
,
419 (void *) linked_object
,
421 require_noerr(rval
, finish
);
422 *linked_object_out
= linked_object
;
424 linked_object_alloc
= NULL
;
428 if (linked_object_alloc
) {
429 kxld_page_free_untracked(linked_object_alloc
, vmsize
);
432 clear_context(context
);
433 kxld_set_logging_callback_data(NULL
, NULL
);
439 /*******************************************************************************
440 *******************************************************************************/
442 init_context(KXLDContext
*context
, u_int ndependencies
)
444 kern_return_t rval
= KERN_FAILURE
;
446 /* Create an array of objects large enough to hold an object
447 * for every dependency, an interface for each dependency, and a kext. */
448 rval
= kxld_array_init(&context
->objects
,
449 kxld_object_sizeof(), 2 * ndependencies
+ 1);
450 require_noerr(rval
, finish
);
452 rval
= kxld_array_init(&context
->dependencies
,
453 kxld_kext_sizeof(), ndependencies
);
454 require_noerr(rval
, finish
);
456 rval
= kxld_dict_init(&context
->defined_symbols_by_name
,
457 kxld_dict_string_hash
, kxld_dict_string_cmp
, 0);
458 require_noerr(rval
, finish
);
460 rval
= kxld_dict_init(&context
->defined_cxx_symbols_by_value
,
461 kxld_dict_kxldaddr_hash
, kxld_dict_kxldaddr_cmp
, 0);
462 require_noerr(rval
, finish
);
464 rval
= kxld_dict_init(&context
->obsolete_symbols_by_name
,
465 kxld_dict_string_hash
, kxld_dict_string_cmp
, 0);
466 require_noerr(rval
, finish
);
468 rval
= kxld_dict_init(&context
->vtables_by_name
, kxld_dict_string_hash
,
469 kxld_dict_string_cmp
, 0);
470 require_noerr(rval
, finish
);
477 /*******************************************************************************
478 *******************************************************************************/
480 init_kext_objects(KXLDContext
*context
,
484 KXLDDependency
*dependencies
,
487 kern_return_t rval
= KERN_FAILURE
;
488 KXLDKext
*kext
= NULL
;
489 KXLDObject
*kext_object
= NULL
;
490 KXLDObject
*interface_object
= NULL
;
493 /* Create a kext object for each dependency. If it's a direct dependency,
494 * export its symbols by name by value. If it's indirect, just export the
495 * C++ symbols by value.
497 for (i
= 0; i
< ndependencies
; ++i
) {
498 kext
= kxld_array_get_item(&context
->dependencies
, i
);
500 interface_object
= NULL
;
502 kext_object
= get_object_for_file(context
, dependencies
[i
].kext
,
503 dependencies
[i
].kext_size
, dependencies
[i
].kext_name
);
504 require_action(kext_object
, finish
, rval
=KERN_FAILURE
);
506 if (dependencies
[i
].interface
) {
507 interface_object
= get_object_for_file(context
,
508 dependencies
[i
].interface
, dependencies
[i
].interface_size
,
509 dependencies
[i
].interface_name
);
510 require_action(interface_object
, finish
, rval
=KERN_FAILURE
);
513 rval
= kxld_kext_init(kext
, kext_object
, interface_object
);
514 require_noerr(rval
, finish
);
516 if (dependencies
[i
].is_direct_dependency
) {
517 rval
= kxld_kext_export_symbols(kext
,
518 &context
->defined_symbols_by_name
,
519 &context
->obsolete_symbols_by_name
,
520 &context
->defined_cxx_symbols_by_value
);
521 require_noerr(rval
, finish
);
523 rval
= kxld_kext_export_symbols(kext
,
524 /* defined_symbols */ NULL
, /* obsolete_symbols */ NULL
,
525 &context
->defined_cxx_symbols_by_value
);
526 require_noerr(rval
, finish
);
530 /* Export the vtables for all of the dependencies. */
531 for (i
= 0; i
< context
->dependencies
.nitems
; ++i
) {
532 kext
= kxld_array_get_item(&context
->dependencies
, i
);
534 rval
= kxld_kext_export_vtables(kext
,
535 &context
->defined_cxx_symbols_by_value
,
536 &context
->defined_symbols_by_name
,
537 &context
->vtables_by_name
);
538 require_noerr(rval
, finish
);
541 /* Create a kext object for the kext we're linking and export its locally
542 * defined C++ symbols.
544 kext_object
= get_object_for_file(context
, file
, size
, name
);
545 require_action(kext_object
, finish
, rval
=KERN_FAILURE
);
547 rval
= kxld_kext_init(context
->kext
, kext_object
, /* interface */ NULL
);
548 require_noerr(rval
, finish
);
550 rval
= kxld_kext_export_symbols(context
->kext
,
551 /* defined_symbols */ NULL
, /* obsolete_symbols */ NULL
,
552 &context
->defined_cxx_symbols_by_value
);
553 require_noerr(rval
, finish
);
560 /*******************************************************************************
561 *******************************************************************************/
563 get_object_for_file(KXLDContext
*context
, u_char
*file
, u_long size
,
566 KXLDObject
*rval
= NULL
;
567 KXLDObject
*object
= NULL
;
568 kern_return_t result
= 0;
571 for (i
= 0; i
< context
->objects
.nitems
; ++i
) {
572 object
= kxld_array_get_item(&context
->objects
, i
);
574 if (!kxld_object_get_file(object
)) {
575 result
= kxld_object_init_from_macho(object
, file
, size
, name
,
576 context
->section_order
, context
->cputype
, context
->cpusubtype
, context
->flags
);
577 require_noerr(result
, finish
);
583 if (kxld_object_get_file(object
) == file
) {
593 #include <mach-o/loader.h>
595 /*******************************************************************************
596 *******************************************************************************/
598 allocate_split_kext(KXLDContext
*context
, splitKextLinkInfo
* link_info
)
600 kern_return_t rval
= KERN_FAILURE
;
602 u_long header_size
= 0;
603 u_char
* linked_object
= NULL
;
605 kxld_kext_get_vmsize(context
->kext
, &header_size
, &vmsize
);
608 /* get __LINKEDIT vmsize */
609 kxld_kext_get_vmsize_for_seg_by_name(context
->kext
, SEG_LINKEDIT
, &vmsize
);
611 vmsize
+= (link_info
->vmaddr_LINKEDIT
- link_info
->vmaddr_TEXT
);
613 link_info
->linkedKextSize
= vmsize
;
615 linked_object
= kxld_page_alloc_untracked(link_info
->linkedKextSize
);
616 require(linked_object
, finish
);
617 link_info
->linkedKext
= linked_object
;
619 bzero(linked_object
, vmsize
);
626 /*******************************************************************************
627 *******************************************************************************/
629 allocate_kext(KXLDContext
*context
,
631 kxld_addr_t
*vmaddr_out
,
633 u_char
**linked_object_alloc_out
)
635 KXLDAllocateFlags flags
= 0;
636 kxld_addr_t vmaddr
= 0;
638 u_long header_size
= 0;
639 u_char
* linked_object
= NULL
;
641 *linked_object_alloc_out
= NULL
;
643 kxld_kext_get_vmsize(context
->kext
, &header_size
, &vmsize
);
645 vmaddr
= context
->allocate_callback(vmsize
, &flags
, callback_data
);
646 require_action(!(vmaddr
& (kxld_get_effective_page_size()-1)), finish
,
647 kxld_log(kKxldLogLinking
, kKxldLogErr
,
648 "Load address %p is not page-aligned.",
649 (void *) (uintptr_t) vmaddr
));
651 if (flags
& kKxldAllocateWritable
) {
652 linked_object
= (u_char
*) (u_long
) vmaddr
;
654 linked_object
= kxld_page_alloc_untracked(vmsize
);
655 require(linked_object
, finish
);
657 *linked_object_alloc_out
= linked_object
;
660 kxld_kext_set_linked_object_size(context
->kext
, vmsize
);
662 /* Zero out the memory before we fill it. We fill this buffer in a
663 * sparse fashion, and it's simpler to clear it now rather than
664 * track and zero any pieces we didn't touch after we've written
665 * all of the sections to memory.
667 bzero(linked_object
, vmsize
);
668 *vmaddr_out
= vmaddr
;
669 *vmsize_out
= vmsize
;
672 return linked_object
;
675 /*******************************************************************************
676 *******************************************************************************/
678 clear_context(KXLDContext
*context
)
680 KXLDObject
* object
= NULL
;
681 KXLDKext
* dep
= NULL
;
686 kxld_kext_clear(context
->kext
);
688 for (i
= 0; i
< context
->objects
.nitems
; ++i
) {
689 object
= kxld_array_get_item(&context
->objects
, i
);
690 kxld_object_clear(object
);
692 kxld_array_reset(&context
->objects
);
694 for (i
= 0; i
< context
->dependencies
.nitems
; ++i
) {
695 dep
= kxld_array_get_item(&context
->dependencies
, i
);
696 kxld_kext_clear(dep
);
698 kxld_array_reset(&context
->dependencies
);
700 kxld_dict_clear(&context
->defined_symbols_by_name
);
701 kxld_dict_clear(&context
->defined_cxx_symbols_by_value
);
702 kxld_dict_clear(&context
->obsolete_symbols_by_name
);
703 kxld_dict_clear(&context
->vtables_by_name
);