2 * Copyright (c) 2007-2008 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>
37 #include "kxld_types.h"
39 #include <libkern/kxld.h>
40 #include <libkern/kxld_types.h>
43 #include "kxld_array.h"
44 #include "kxld_dict.h"
45 #include "kxld_kext.h"
46 #include "kxld_state.h"
48 #include "kxld_symtab.h"
49 #include "kxld_util.h"
50 #include "kxld_vtable.h"
56 KXLDArray
*section_order
;
59 KXLDDict defined_symbols
;
60 KXLDDict obsolete_symbols
;
63 KXLDAllocateCallback allocate_callback
;
65 cpu_subtype_t cpusubtype
;
68 /*******************************************************************************
70 *******************************************************************************/
72 /* Certain architectures alter the order of a kext's sections from its input
73 * binary, so we track that order in a dictionary of arrays, with one array for
74 * each architecture. Since the kernel only has one architecture, we can
75 * eliminate the dictionary and use a simple array.
76 * XXX: If we ever use the linker in a multithreaded environment, we will need
77 * locks around these global structures.
79 #if KXLD_USER_OR_OBJECT
81 static KXLDArray
*s_section_order
;
83 static KXLDDict
*s_order_dict
;
87 /*******************************************************************************
89 *******************************************************************************/
91 static void clear_context(KXLDContext
*context
);
93 /*******************************************************************************
94 *******************************************************************************/
96 kxld_create_context(KXLDContext
**_context
,
97 KXLDAllocateCallback allocate_callback
, KXLDLoggingCallback logging_callback
,
98 KXLDFlags flags
, cpu_type_t cputype
, cpu_subtype_t cpusubtype
)
100 kern_return_t rval
= KERN_FAILURE
;
101 KXLDContext
*context
= NULL
;
102 KXLDArray
*section_order
= NULL
;
104 cpu_type_t
*cputype_p
= NULL
;
108 check(allocate_callback
);
109 check(logging_callback
);
112 context
= kxld_alloc(sizeof(*context
));
113 require_action(context
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
114 bzero(context
, sizeof(*context
));
116 context
->flags
= flags
;
117 context
->allocate_callback
= allocate_callback
;
118 context
->cputype
= cputype
;
119 context
->cpusubtype
= cpusubtype
;
121 kxld_set_logging_callback(logging_callback
);
123 context
->kext
= kxld_alloc(kxld_kext_sizeof());
124 require_action(context
->kext
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
125 bzero(context
->kext
, kxld_kext_sizeof());
127 /* Check if we already have an order array for this arch */
129 #if KXLD_USER_OR_OBJECT
131 context
->section_order
= s_section_order
;
133 /* In userspace, create the dictionary if it doesn't already exist */
135 s_order_dict
= kxld_alloc(sizeof(*s_order_dict
));
136 require_action(s_order_dict
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
137 bzero(s_order_dict
, sizeof(*s_order_dict
));
139 rval
= kxld_dict_init(s_order_dict
, kxld_dict_uint32_hash
,
140 kxld_dict_uint32_cmp
, 0);
141 require_noerr(rval
, finish
);
144 context
->section_order
= kxld_dict_find(s_order_dict
, &cputype
);
147 /* Create an order array for this arch if needed */
149 if (!context
->section_order
) {
151 section_order
= kxld_alloc(sizeof(*section_order
));
152 require_action(section_order
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
153 bzero(section_order
, sizeof(*section_order
));
156 s_section_order
= section_order
;
158 /* In userspace, add the new array to the order dictionary */
159 cputype_p
= kxld_alloc(sizeof(*cputype_p
));
160 require_action(cputype_p
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
161 *cputype_p
= cputype
;
163 rval
= kxld_dict_insert(s_order_dict
, cputype_p
, section_order
);
164 require_noerr(rval
, finish
);
169 context
->section_order
= section_order
;
171 section_order
= NULL
;
173 #endif /* KXLD_USER_OR_OBJECT */
180 if (context
) kxld_free(context
, sizeof(*context
));
181 if (section_order
) kxld_free(section_order
, sizeof(*section_order
));
183 if (cputype_p
) kxld_free(cputype_p
, sizeof(*cputype_p
));
189 /*******************************************************************************
190 *******************************************************************************/
192 kxld_destroy_context(KXLDContext
*context
)
194 KXLDState
*dep
= NULL
;
199 kxld_kext_deinit(context
->kext
);
201 for (i
= 0; i
< context
->deps
.maxitems
; ++i
) {
202 dep
= kxld_array_get_slot(&context
->deps
, i
);
203 kxld_state_deinit(dep
);
206 kxld_array_deinit(&context
->deps
);
207 kxld_array_deinit(&context
->tmps
);
209 kxld_dict_deinit(&context
->defined_symbols
);
210 kxld_dict_deinit(&context
->obsolete_symbols
);
211 kxld_dict_deinit(&context
->vtables
);
213 kxld_free(context
->kext
, kxld_kext_sizeof());
214 kxld_free(context
, sizeof(*context
));
216 kxld_print_memory_report();
219 /*******************************************************************************
220 *******************************************************************************/
223 KXLDContext
*context
,
230 u_char
**_linked_object
,
231 kxld_addr_t
*kmod_info_kern
,
232 u_char
**_link_state
,
233 u_long
*_link_state_size
,
234 u_char
**_symbol_file __unused
,
235 u_long
*_symbol_file_size __unused
)
237 kern_return_t rval
= KERN_FAILURE
;
238 KXLDState
*state
= NULL
;
239 KXLDAllocateFlags flags
= 0;
240 kxld_addr_t vmaddr
= 0;
241 u_long header_size
= 0;
246 u_char
*linked_object
= NULL
;
247 u_char
*linked_object_alloc
= NULL
;
248 u_char
*link_state
= NULL
;
249 u_char
*symbol_file
= NULL
;
250 u_long link_state_size
= 0;
251 u_long symbol_file_size
= 0;
253 kxld_set_logging_callback_data(name
, callback_data
);
255 require_action(context
, finish
, rval
=KERN_INVALID_ARGUMENT
);
256 require_action(file
, finish
, rval
=KERN_INVALID_ARGUMENT
);
257 require_action(size
, finish
, rval
=KERN_INVALID_ARGUMENT
);
259 rval
= kxld_array_init(&context
->deps
, sizeof(struct kxld_state
), ndeps
);
260 require_noerr(rval
, finish
);
263 /* Initialize the dependencies */
264 for (i
= 0; i
< ndeps
; ++i
) {
265 state
= kxld_array_get_item(&context
->deps
, i
);
267 rval
= kxld_state_init_from_file(state
, deps
[i
],
268 context
->section_order
);
269 require_noerr(rval
, finish
);
273 rval
= kxld_kext_init(context
->kext
, file
, size
, name
,
274 context
->flags
, (deps
== 0) /* is_kernel */, context
->section_order
,
275 context
->cputype
, context
->cpusubtype
);
276 require_noerr(rval
, finish
);
280 /* Calculate the base number of symbols and vtables in the kext */
282 nsyms
+= kxld_kext_get_num_symbols(context
->kext
);
283 nvtables
+= kxld_kext_get_num_vtables(context
->kext
);
285 /* Extract the symbol and vtable counts from the dependencies.
288 for (i
= 0; i
< ndeps
; ++i
) {
290 cpu_subtype_t cpusubtype
;
292 state
= kxld_array_get_item(&context
->deps
, i
);
294 kxld_state_get_cputype(state
, &cputype
, &cpusubtype
);
296 rval
= kxld_kext_validate_cputype(context
->kext
,
297 cputype
, cpusubtype
);
298 require_noerr(rval
, finish
);
300 nsyms
+= kxld_state_get_num_symbols(state
);
301 nvtables
+= kxld_state_get_num_vtables(state
);
304 /* Create the global symbol and vtable tables */
306 rval
= kxld_dict_init(&context
->defined_symbols
, kxld_dict_string_hash
,
307 kxld_dict_string_cmp
, nsyms
);
308 require_noerr(rval
, finish
);
310 rval
= kxld_dict_init(&context
->obsolete_symbols
, kxld_dict_string_hash
,
311 kxld_dict_string_cmp
, 0);
312 require_noerr(rval
, finish
);
314 rval
= kxld_dict_init(&context
->vtables
, kxld_dict_string_hash
,
315 kxld_dict_string_cmp
, nvtables
);
316 require_noerr(rval
, finish
);
318 /* Populate the global tables */
320 for (i
= 0; i
< ndeps
; ++i
) {
321 state
= kxld_array_get_item(&context
->deps
, i
);
323 rval
= kxld_state_get_symbols(state
, &context
->defined_symbols
,
324 &context
->obsolete_symbols
);
325 require_noerr(rval
, finish
);
327 rval
= kxld_state_get_vtables(state
, &context
->vtables
);
328 require_noerr(rval
, finish
);
331 if (kxld_kext_is_true_kext(context
->kext
)) {
333 /* Allocate the kext object */
335 kxld_kext_get_vmsize(context
->kext
, &header_size
, &vmsize
);
336 vmaddr
= context
->allocate_callback(vmsize
, &flags
, callback_data
);
337 require_action(!(vmaddr
& (PAGE_SIZE
-1)), finish
, rval
=KERN_FAILURE
;
338 kxld_log(kKxldLogLinking
, kKxldLogErr
,
339 "Load address %p is not page-aligned.",
340 (void *) (uintptr_t) vmaddr
));
342 if (flags
& kKxldAllocateWritable
) {
343 linked_object
= (u_char
*) (u_long
) vmaddr
;
345 linked_object_alloc
= kxld_page_alloc_untracked(vmsize
);
346 require_action(linked_object_alloc
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
347 linked_object
= linked_object_alloc
;
350 /* Zero out the memory before we fill it. We fill this buffer in a
351 * sparse fashion, and it's simpler to clear it now rather than
352 * track and zero any pieces we didn't touch after we've written
353 * all of the sections to memory.
355 bzero(linked_object
, vmsize
);
357 /* Relocate to the new link address */
359 rval
= kxld_kext_relocate(context
->kext
, vmaddr
, &context
->vtables
,
360 &context
->defined_symbols
, &context
->obsolete_symbols
);
361 require_noerr(rval
, finish
);
363 /* Generate linked object if requested */
365 if (_linked_object
) {
366 check(kmod_info_kern
);
367 *_linked_object
= NULL
;
370 rval
= kxld_kext_export_linked_object(context
->kext
, linked_object
,
372 require_noerr(rval
, finish
);
376 /* Resolve the pseudokext's symbols */
378 rval
= kxld_kext_resolve(context
->kext
, &context
->vtables
,
379 &context
->defined_symbols
);
380 require_noerr(rval
, finish
);
384 /* Generate link state if requested */
387 check(_link_state_size
);
389 *_link_state_size
= 0;
391 kxld_dict_clear(&context
->defined_symbols
);
392 rval
= kxld_state_export_kext_to_file(context
->kext
, &link_state
,
393 &link_state_size
, &context
->defined_symbols
, &context
->tmps
);
394 require_noerr(rval
, finish
);
398 /* Generate symbol file if requested */
401 check(_symbol_file_size
);
402 *_symbol_file
= NULL
;
403 *_symbol_file_size
= 0;
405 rval
= kxld_kext_export_symbol_file(context
->kext
, &symbol_file
,
407 require_noerr(rval
, finish
);
411 /* Commit output to return variables */
413 if (_linked_object
) {
414 *_linked_object
= linked_object
;
415 linked_object
= NULL
;
416 linked_object_alloc
= NULL
;
420 *_link_state
= link_state
;
421 *_link_state_size
= link_state_size
;
427 *_symbol_file
= symbol_file
;
428 *_symbol_file_size
= symbol_file_size
;
437 if (linked_object_alloc
) kxld_page_free_untracked(linked_object_alloc
, vmsize
);
438 if (link_state
) kxld_page_free_untracked(link_state
, link_state_size
);
439 if (symbol_file
) kxld_page_free_untracked(symbol_file
, symbol_file_size
);
441 clear_context(context
);
443 kxld_set_logging_callback_data(NULL
, NULL
);
448 /*******************************************************************************
449 *******************************************************************************/
451 clear_context(KXLDContext
*context
)
453 KXLDState
*state
= NULL
;
458 kxld_kext_clear(context
->kext
);
459 for (i
= 0; i
< context
->deps
.nitems
; ++i
) {
460 state
= kxld_array_get_item(&context
->deps
, i
);
461 kxld_state_clear(state
);
463 kxld_array_reset(&context
->deps
);
465 kxld_array_clear(&context
->tmps
);
466 kxld_dict_clear(&context
->defined_symbols
);
467 kxld_dict_clear(&context
->obsolete_symbols
);
468 kxld_dict_clear(&context
->vtables
);