2 * Copyright (c) 2000-2007 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@
34 #include <CoreFoundation/CoreFoundation.h>
45 #include <sys/param.h>
46 #include <sys/types.h>
49 #include <mach/mach_types.h>
50 #include <mach/mach.h>
51 #include <mach/mach_init.h>
52 #include <mach/mach_error.h>
53 #include <mach/mach_host.h>
54 #include <mach/mach_port.h>
55 #include <mach-o/kld.h>
56 #include <mach-o/arch.h>
57 #include <mach-o/fat.h>
58 #include <mach-o/loader.h>
59 #include <mach-o/nlist.h>
60 #include <kern/kern_types.h>
61 #include <kern/kalloc.h>
62 #include <libkern/OSByteOrder.h>
64 #include "vers_rsrc.h"
68 #include <mach-o/kld.h>
69 #include <mach-o/loader.h>
70 #include <mach-o/nlist.h>
71 #include <libsa/vers_rsrc.h>
73 #endif /* not KERNEL */
77 #include "kld_patch.h"
89 #define PRIV_EXT __private_extern__
92 #define LOG_DELAY(x) IODelay((x) * 1000000)
93 #define VTYELLOW "\033[33m"
94 #define VTRESET "\033[0m"
101 #endif /* not KERNEL */
109 kmod_create_internal(
114 kmod_destroy_internal(kmod_t id
);
121 mach_msg_type_number_t
*dataCount
);
123 extern kern_return_t
kmod_retain(kmod_t id
);
124 extern kern_return_t
kmod_release(kmod_t id
);
126 extern struct mach_header _mh_execute_header
;
130 // Used to pass info between kld library and callbacks
131 static dgraph_entry_t
* G_current_load_entry
= NULL
;
134 static mach_port_t G_kernel_port
= PORT_NULL
;
135 static mach_port_t G_kernel_priv_port
= PORT_NULL
;
136 static int G_syms_only
;
139 register_prelink(dgraph_entry_t
* entry
,
140 kmod_info_t
* local_kmod_info
, vm_offset_t kernel_kmod_info
);
144 kmod_info_t modules
[1];
146 struct PrelinkState
* G_prelink
;
147 CFMutableDataRef G_prelink_data
;
148 CFMutableDataRef G_prelink_dependencies
;
150 #endif /* not KERNEL */
152 // used by dgraph.c so can't be static
153 kload_log_level log_level
= 0;
156 static void __kload_null_log(const char * format
, ...);
157 static void __kload_null_err_log(const char * format
, ...);
158 static int __kload_null_approve(int default_answer
, const char * format
, ...);
159 static int __kload_null_veto(int default_answer
, const char * format
, ...);
160 static const char * __kload_null_input(const char * format
, ...);
162 void (*__kload_log_func
)(const char * format
, ...) =
164 void (*__kload_err_log_func
)(const char * format
, ...) = &__kload_null_err_log
;
165 int (*__kload_approve_func
)(int default_answer
,
166 const char * format
, ...) = &__kload_null_approve
;
167 int (*__kload_veto_func
)(int default_answer
,
168 const char * format
, ...) = &__kload_null_veto
;
169 const char * (*__kload_input_func
)(const char * format
, ...) =
171 #endif /* not KERNEL */
173 static unsigned long __kload_linkedit_address(
175 unsigned long headers_size
);
176 static void __kload_clean_up_entry(dgraph_entry_t
* entry
);
177 static void __kload_clear_kld_globals(void);
178 static kload_error
__kload_patch_dgraph(dgraph_t
* dgraph
181 const char * kernel_file
182 #endif /* not KERNEL */
184 static kload_error
__kload_load_modules(dgraph_t
* dgraph
187 const char * kernel_file
,
188 const char * patch_file
, const char * patch_dir
,
189 const char * symbol_file
, const char * symbol_dir
,
190 int do_load
, int do_start_kmod
, int do_prelink
,
191 int interactive_level
,
192 int ask_overwrite_symbols
, int overwrite_symbols
193 #endif /* not KERNEL */
196 static kload_error
__kload_check_module_loaded(
198 dgraph_entry_t
* entry
,
200 kmod_info_t
* kmod_list
,
201 #endif /* not KERNEL */
204 static kload_error
__kload_load_module(dgraph_t
* dgraph
,
205 dgraph_entry_t
* entry
,
209 const char * symbol_file
,
210 const char * symbol_dir
,
212 int interactive_level
,
213 int ask_overwrite_symbols
,
214 int overwrite_symbols
215 #endif /* not KERNEL */
217 static kload_error
__kload_set_module_dependencies(dgraph_entry_t
* entry
);
218 static kload_error
__kload_start_module(dgraph_entry_t
* entry
);
221 static kload_error
__kload_output_patches(
223 const char * patch_file
,
224 const char * patch_dir
,
225 int ask_overwrite_symbols
,
226 int overwrite_symbols
);
228 Boolean
_IOReadBytesFromFile(CFAllocatorRef alloc
, const char *path
, void **bytes
,
229 CFIndex
*length
, CFIndex maxLength
);
230 Boolean
_IOWriteBytesToFile(const char *path
, const void *bytes
, CFIndex length
);
232 #endif /* not KERNEL */
234 /*******************************************************************************
236 *******************************************************************************/
238 kload_error
kload_load_dgraph(dgraph_t
* dgraph
241 const char * kernel_file
,
242 const char * patch_file
, const char * patch_dir
,
243 const char * symbol_file
, const char * symbol_dir
,
244 int do_load
, int do_start_kmod
, int do_prelink
,
245 int interactive_level
,
246 int ask_overwrite_symbols
, int overwrite_symbols
247 #endif /* not KERNEL */
250 kload_error result
= kload_error_none
;
251 int one_has_address
= 0;
252 int one_lacks_address
= 0;
257 syms_only
= (!do_load
) && (symbol_dir
|| symbol_file
);
259 if (log_level
>= kload_log_level_load_details
) {
260 kload_log_message("loading dependency graph:" KNL
);
264 if (syms_only
&& log_level
>= kload_log_level_load_details
) {
265 kload_log_message("loading for symbol generation only" KNL
);
269 * If we're not loading and have no request to emit a symbol
270 * or patch file, there's nothing to do!
272 if (!do_load
&& !symbol_dir
&& !symbol_file
&&
273 !patch_dir
&& !patch_file
) {
275 if (syms_only
&& log_level
>= kload_log_level_load_details
) {
276 kload_log_message("loader has no work to do" KNL
);
279 result
= kload_error_none
; // fixme: should this be USAGE error?
284 * If we're doing symbols only, then all entries in the dgraph must
285 * have addresses assigned, or none must.
288 if (log_level
>= kload_log_level_load_details
) {
289 kload_log_message("checking whether modules have addresses assigned" KNL
);
291 for (i
= 0; i
< dgraph
->length
; i
++) {
292 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
293 if (entry
->is_kernel_component
) {
296 if (entry
->loaded_address
!= 0) {
299 one_lacks_address
= 1;
303 #endif /* not KERNEL */
305 if (one_has_address
&& one_lacks_address
) {
307 "either all modules must have addresses set to nonzero values or "
309 result
= kload_error_invalid_argument
;
314 /* we need the priv port to check/load modules in the kernel.
316 if (PORT_NULL
== G_kernel_priv_port
) {
317 G_kernel_priv_port
= mach_host_self(); /* if we are privileged */
319 #endif /* not KERNEL */
322 * In the kernel, ALWAYS get load addresses of existing loaded kmods.
326 * If we don't have addresses, then get them from the kernel.
328 if (!one_has_address
&& !do_prelink
&& (do_load
|| symbol_file
|| symbol_dir
)) {
329 #endif /* not KERNEL */
330 if (log_level
>= kload_log_level_load_details
) {
331 kload_log_message("getting module addresses from kernel" KNL
);
334 result
= kload_set_load_addresses_from_kernel(dgraph
, kernel_file
,
337 result
= kload_set_load_addresses_from_kernel(dgraph
);
338 #endif /* not KERNEL */
339 if (result
== kload_error_already_loaded
) {
347 #endif /* not KERNEL */
349 } else if (result
!= kload_error_none
) {
350 kload_log_error("can't check load addresses of modules" KNL
);
355 #endif /* not KERNEL */
359 * At this point, if we're doing symbols only, it's an error to not
360 * have a load address for every module.
362 if (syms_only
&& !do_prelink
) {
363 if (log_level
>= kload_log_level_load_details
) {
364 kload_log_message("checking that all modules have addresses assigned" KNL
);
366 for (i
= 0; i
< dgraph
->length
; i
++) {
367 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
368 if (entry
->is_kernel_component
) {
371 if (!entry
->loaded_address
) {
373 "missing load address during symbol generation: %s" KNL
,
375 result
= kload_error_unspecified
;
385 CFAllocatorRef alloc
;
387 // We need a real allocator to pass to _IOReadBytesFromFile
388 alloc
= CFRetain(CFAllocatorGetDefault());
389 if (_IOReadBytesFromFile(alloc
, "prelinkstate", &bytes
, &length
, 0))
391 G_prelink_data
= CFDataCreateMutable(alloc
, 0);
392 CFDataAppendBytes(G_prelink_data
, (UInt8
*) bytes
, length
);
393 CFAllocatorDeallocate(alloc
, bytes
);
395 G_prelink_dependencies
= CFDataCreateMutable(alloc
, 0);
396 if (_IOReadBytesFromFile(alloc
, "prelinkdependencies", &bytes
, &length
, 0))
398 CFDataAppendBytes(G_prelink_dependencies
, (UInt8
*) bytes
, length
);
399 CFAllocatorDeallocate(alloc
, bytes
);
403 if (!G_prelink_data
) {
405 "can't get load address for prelink %s" KNL
, kernel_file
);
406 result
= kload_error_link_load
;
410 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
414 #endif /* not KERNEL */
418 result
= __kload_load_modules(dgraph
, kernel_file
,
419 patch_file
, patch_dir
, symbol_file
, symbol_dir
,
420 do_load
, do_start_kmod
, do_prelink
, interactive_level
,
421 ask_overwrite_symbols
, overwrite_symbols
);
423 result
= __kload_load_modules(dgraph
);
424 #endif /* not KERNEL */
429 /* Dispose of the host port to prevent security breaches and port
430 * leaks. We don't care about the kern_return_t value of this
431 * call for now as there's nothing we can do if it fails.
433 if (PORT_NULL
!= G_kernel_priv_port
) {
434 mach_port_deallocate(mach_task_self(), G_kernel_priv_port
);
435 G_kernel_priv_port
= PORT_NULL
;
437 #endif /* not KERNEL */
439 for (i
= 0; i
< dgraph
->length
; i
++) {
440 dgraph_entry_t
* current_entry
= dgraph
->graph
[i
];
441 __kload_clean_up_entry(current_entry
);
451 length
= CFDataGetLength(G_prelink_data
);
452 bytes
= (0 == length
) ? (const void *)"" : CFDataGetBytePtr(G_prelink_data
);
453 success
= _IOWriteBytesToFile("prelinkstate", bytes
, length
);
456 kload_log_error("write prelinkstate" KNL
);
457 result
= kload_error_link_load
;
459 length
= CFDataGetLength(G_prelink_dependencies
);
460 bytes
= (0 == length
) ? (const void *)"" : CFDataGetBytePtr(G_prelink_dependencies
);
461 success
= _IOWriteBytesToFile("prelinkdependencies", bytes
, length
);
464 kload_log_error("write prelinkdependencies" KNL
);
465 result
= kload_error_link_load
;
468 #endif /* not KERNEL */
474 /*******************************************************************************
475 * This function claims the option flags d and D for object file dependencies
476 * and in-kernel dependencies, respectively.
477 *******************************************************************************/
478 kload_error
kload_load_with_arglist(
479 int argc
, char **argv
,
480 const char * kernel_file
,
481 const char * patch_file
, const char * patch_dir
,
482 const char * symbol_file
, const char * symbol_dir
,
483 int do_load
, int do_start_kmod
,
484 int interactive_level
,
485 int ask_overwrite_symbols
, int overwrite_symbols
)
487 kload_error result
= kload_error_none
;
488 dgraph_error_t dgraph_result
;
489 int syms_only
= (!do_load
) && (symbol_file
|| symbol_dir
);
491 static dgraph_t dependency_graph
;
493 /* Zero out fields in dependency graph for proper error handling later.
495 bzero(&dependency_graph
, sizeof(dependency_graph
));
497 dgraph_result
= dgraph_init_with_arglist(&dependency_graph
,
498 syms_only
, "-d", "-D", argc
, argv
);
499 if (dgraph_result
== dgraph_error
) {
500 kload_log_error("error processing dependency list" KNL
);
501 result
= kload_error_unspecified
;
503 } else if (dgraph_result
== dgraph_invalid
) {
504 // anything to print here, or did init call print something?
505 result
= kload_error_invalid_argument
;
509 result
= kload_load_dgraph(&dependency_graph
, kernel_file
,
510 patch_file
, patch_dir
, symbol_file
, symbol_dir
,
511 do_load
, do_start_kmod
, false /* do_prelink */, interactive_level
,
512 ask_overwrite_symbols
, overwrite_symbols
);
517 #endif /* not KERNEL */
518 /*******************************************************************************
519 * This function can only operate on 32 bit mach object file symbol table
521 *******************************************************************************/
523 kload_error
__kload_keep_symbols(dgraph_entry_t
* entry
)
525 struct mach_header
* hdr
;
526 struct segment_command
* seg
;
528 struct symtab_command
* symcmd
;
529 unsigned long idx
, ncmds
;
533 struct mach_header hdr
;
534 struct segment_command seg
;
535 struct symtab_command symcmd
;
537 struct load_cmds
* cmd
;
538 unsigned int symtabsize
;
541 return kload_error_none
;
543 hdr
= entry
->linked_image
;
545 seg
= (struct segment_command
*)(hdr
+ 1);
548 idx
++, seg
= (struct segment_command
*)(((vm_offset_t
)seg
) + seg
->cmdsize
))
550 if (LC_SYMTAB
== seg
->cmd
)
555 kload_log_error("no LC_SYMTAB" KNL
);
556 return kload_error_unspecified
;
559 symcmd
= (struct symtab_command
*) seg
;
561 symtabsize
= symcmd
->stroff
+ symcmd
->strsize
- symcmd
->symoff
;
563 size
= sizeof(struct load_cmds
) + symtabsize
;
565 mem
= (vm_offset_t
) malloc(size
);
567 cmd
= (struct load_cmds
*) mem
;
568 sym
= (struct nlist
*) (cmd
+ 1);
571 cmd
->symcmd
= *symcmd
;
572 bcopy((const void *) (((vm_offset_t
) hdr
) + symcmd
->symoff
),
576 hdr
= (struct mach_header
*) mem
;
578 cmd
->hdr
.sizeofcmds
= sizeof(struct load_cmds
) - sizeof(struct mach_header
);
579 cmd
->hdr
.flags
&= ~MH_INCRLINK
;
581 cmd
->symcmd
.stroff
-= (symcmd
->symoff
- sizeof(struct load_cmds
));
582 cmd
->symcmd
.symoff
= sizeof(struct load_cmds
);
584 cmd
->seg
.cmd
= LC_SEGMENT
;
585 cmd
->seg
.cmdsize
= sizeof(struct segment_command
);
586 strlcpy(cmd
->seg
.segname
, SEG_LINKEDIT
, sizeof(cmd
->seg
.segname
));
589 cmd
->seg
.fileoff
= cmd
->symcmd
.symoff
;
590 cmd
->seg
.filesize
= symtabsize
;
591 cmd
->seg
.maxprot
= 7;
592 cmd
->seg
.initprot
= 1;
596 sym
= (struct nlist
*) (cmd
+ 1);
597 for (idx
= 0; idx
< symcmd
->nsyms
; idx
++, sym
++)
599 if ( (sym
->n_type
& N_STAB
) != 0)
603 sym
->n_value
= sym
->n_un
.n_strx
;
604 sym
->n_un
.n_strx
= 0;
605 sym
->n_sect
= NO_SECT
;
607 else if ( (sym
->n_type
& N_TYPE
) == N_SECT
)
609 sym
->n_sect
= NO_SECT
;
610 sym
->n_type
= (sym
->n_type
& ~N_TYPE
) | N_ABS
;
613 if (log_level
>= kload_log_level_load_details
)
615 kload_log_message("__kload_keep_symbols %s, nsyms %ld, 0x%x bytes" KNL
,
616 entry
->name
, (unsigned long)symcmd
->nsyms
, size
);
619 entry
->symbols
= mem
;
620 entry
->symbols_malloc
= mem
;
621 entry
->symbols_length
= size
;
623 return kload_error_none
;
627 /*******************************************************************************
628 * This function can only operate on 32 bit mach object files
629 *******************************************************************************/
631 kload_error
__kload_make_opaque_basefile(dgraph_t
* dgraph
, struct mach_header
* hdr
)
633 struct segment_command
* seg
;
634 struct segment_command
* data_seg
;
635 struct segment_command
* text_seg
;
636 struct section
* sec
;
639 unsigned long idx
, ncmds
;
641 vm_address_t mem
, out
;
642 static vm_address_t keep_base_image
;
643 static vm_size_t keep_base_size
;
645 if (dgraph
->opaque_base_image
)
646 return kload_error_none
;
650 dgraph
->opaque_base_image
= keep_base_image
;
651 dgraph
->opaque_base_length
= keep_base_size
;
652 return kload_error_none
;
655 data_seg
= text_seg
= NULL
;
657 seg
= (struct segment_command
*)(hdr
+ 1);
660 idx
++, seg
= (struct segment_command
*)(((vm_offset_t
)seg
) + seg
->cmdsize
))
662 if (LC_SEGMENT
!= seg
->cmd
)
664 if (!strcmp(SEG_TEXT
, seg
->segname
))
666 else if (!strcmp(SEG_DATA
, seg
->segname
))
669 if (!text_seg
|| !data_seg
)
671 kload_log_error("no SEG_TEXT or SEG_DATA" KNL
);
672 return kload_error_unspecified
;
675 size
= sizeof(struct mach_header
) + text_seg
->cmdsize
+ data_seg
->cmdsize
;
676 mem
= (vm_offset_t
) malloc(size
);
679 bcopy(hdr
, (void *) out
, sizeof(struct mach_header
));
680 hdr
= (struct mach_header
*) out
;
681 out
+= sizeof(struct mach_header
);
683 bcopy(text_seg
, (void *) out
, text_seg
->cmdsize
);
684 text_seg
= (struct segment_command
*) out
;
685 out
+= text_seg
->cmdsize
;
687 bcopy(data_seg
, (void *) out
, data_seg
->cmdsize
);
688 data_seg
= (struct segment_command
*) out
;
689 out
+= data_seg
->cmdsize
;
692 hdr
->sizeofcmds
= text_seg
->cmdsize
+ data_seg
->cmdsize
;
694 offset
= hdr
->sizeofcmds
;
696 text_seg
->fileoff
= offset
;
697 text_seg
->filesize
= 0;
699 sec
= (struct section
*)(text_seg
+ 1);
700 for (j
= 0; j
< text_seg
->nsects
; j
++, sec
++)
702 // sec->addr = (unsigned long) addr;
704 sec
->offset
= offset
;
708 data_seg
->fileoff
= offset
;
709 data_seg
->filesize
= 0;
711 sec
= (struct section
*)(data_seg
+ 1);
712 for (j
= 0; j
< data_seg
->nsects
; j
++, sec
++)
714 // sec->addr = (unsigned long) addr;
716 sec
->offset
= offset
;
720 dgraph
->opaque_base_image
= mem
;
721 dgraph
->opaque_base_length
= size
;
722 keep_base_image
= mem
;
723 keep_base_size
= size
;
725 return kload_error_none
;
728 /*******************************************************************************
730 *******************************************************************************/
732 kload_error
__kload_load_modules(dgraph_t
* dgraph
735 const char * kernel_file
,
736 const char * patch_file
,
737 const char * patch_dir
,
738 const char * symbol_file
,
739 const char * symbol_dir
,
743 int interactive_level
,
744 int ask_overwrite_symbols
,
745 int overwrite_symbols
746 #endif /* not KERNEL */
749 kload_error result
= kload_error_none
;
751 unsigned long int kernel_size
= 0;
752 kern_return_t mach_result
= KERN_SUCCESS
;
754 const char *kernel_file
= "(kernel)";
755 #endif /* not KERNEL */
756 char *kernel_base_addr
= NULL
;
758 Boolean cleanup_kld_loader
= false;
760 char opaque_now
= false;
762 /* We have to map all object files to get their CFBundleIdentifier
766 result
= kload_map_dgraph(dgraph
, kernel_file
);
768 result
= kload_map_dgraph(dgraph
);
769 #endif /* not KERNEL */
770 if (result
!= kload_error_none
) {
771 kload_log_error("error mapping object files" KNL
);
776 result
= __kload_patch_dgraph(dgraph
, kernel_file
);
778 result
= __kload_patch_dgraph(dgraph
);
779 #endif /* not KERNEL */
780 if (result
!= kload_error_none
) {
781 // FIXME: print an error message here?
786 // FIXME: check error return
787 __kload_output_patches(dgraph
, patch_file
, patch_dir
,
788 ask_overwrite_symbols
, overwrite_symbols
);
791 * If we're not loading or writing symbols, we're done.
793 if (!do_load
&& !do_prelink
&& !symbol_file
&& !symbol_dir
) {
797 if (do_load
&& PORT_NULL
== G_kernel_port
) {
798 mach_result
= task_for_pid(mach_task_self(), 0, &G_kernel_port
);
799 if (mach_result
!= KERN_SUCCESS
) {
800 kload_log_error("unable to get kernel task port: %s" KNL
,
801 mach_error_string(mach_result
));
802 kload_log_error("you must be running as root to load "
803 "modules into the kernel" KNL
);
804 result
= kload_error_kernel_permission
;
808 #endif /* not KERNEL */
810 kld_address_func(&__kload_linkedit_address
);
813 G_syms_only
= (!do_load
) && (symbol_file
|| symbol_dir
|| patch_dir
);
815 kernel_base_addr
= kld_file_getaddr(kernel_file
, &kernel_size
);
816 if (!kernel_base_addr
) {
818 "can't get load address for kernel %s" KNL
, kernel_file
);
819 result
= kload_error_link_load
;
824 kernel_base_addr
= (char *) &_mh_execute_header
;
826 #endif /* not KERNEL */
829 if (dgraph
->has_symbol_sets
)
831 result
= __kload_make_opaque_basefile(dgraph
, (struct mach_header
*) kernel_base_addr
);
832 if (result
!= kload_error_none
) {
833 kload_log_error("can't construct opaque base image from %s" KNL
, kernel_file
);
837 kld_result
= kld_load_basefile_from_memory(kernel_file
,
838 (char *) dgraph
->opaque_base_image
,
839 dgraph
->opaque_base_length
);
843 kld_result
= kld_load_basefile_from_memory(kernel_file
,
844 (char *) kernel_base_addr
, kernel_size
);
845 #endif /* not KERNEL */
848 kload_log_error("can't link base image %s" KNL
, kernel_file
);
849 result
= kload_error_link_load
;
853 cleanup_kld_loader
= true;
855 for (i
= 0; i
< dgraph
->length
; i
++) {
856 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
858 opaque_now
|= current_entry
->opaque_link
;
860 if (kOpaqueLink
& opaque_now
)
864 if (log_level
>= kload_log_level_load_details
)
866 kload_log_message("opaque link for %s" KNL
, current_entry
->name
);
869 kld_set_link_options(KLD_STRIP_ALL
); // KLD_STRIP_NONE
871 if (dgraph
->have_loaded_symbols
)
874 if (kRawKernelLink
& current_entry
->opaque_link
) {
876 kld_result
= kld_load_basefile_from_memory(kernel_file
,
877 (char *) kernel_base_addr
, kernel_size
);
880 kld_result
= kld_load_basefile_from_memory(kernel_file
,
881 (char *) dgraph
->opaque_base_image
,
882 dgraph
->opaque_base_length
);
883 dgraph
->have_loaded_symbols
= false;
886 kload_log_error("can't link base image %s" KNL
, kernel_file
);
887 result
= kload_error_link_load
;
892 for (j
= 0; j
< i
; j
++)
895 dgraph_entry_t
* image_dep
= dgraph
->load_order
[j
];
897 if (current_entry
->opaque_link
)
900 (k
< current_entry
->num_dependencies
)
901 && (current_entry
->dependencies
[k
] != image_dep
);
904 if (k
== current_entry
->num_dependencies
)
908 if (!current_entry
->opaque_link
&& image_dep
->opaques
)
910 // kpi not on direct dependency list
913 if (kRawKernelLink
& image_dep
->opaques
)
915 // raw kernel already in base image
919 if (!image_dep
->symbols
)
921 kload_log_error("internal error; no dependent symbols" KNL
);
922 result
= kload_error_link_load
;
927 struct mach_header
* kld_header
;
930 kld_result
= kld_load_from_memory(&kld_header
, image_dep
->name
,
931 (char *) image_dep
->symbols
, image_dep
->symbols_length
, NULL
);
933 kld_result
= kld_load_from_memory(&kld_header
, image_dep
->name
,
934 (char *) image_dep
->symbols
, image_dep
->symbols_length
);
935 #endif /* not KERNEL */
937 kload_log_error("can't link dependent image %s" KNL
, image_dep
->name
);
938 result
= kload_error_link_load
;
941 kld_forget_symbol("_kmod_info");
942 dgraph
->have_loaded_symbols
= true;
947 if (dgraph
->has_opaque_links
949 || symbol_file
|| symbol_dir
952 kld_set_link_options(KLD_STRIP_NONE
);
954 kld_set_link_options(KLD_STRIP_ALL
);
957 result
= __kload_load_module(dgraph
, current_entry
,
958 (current_entry
== dgraph
->root
),
959 symbol_file
, symbol_dir
, do_load
,
960 interactive_level
, ask_overwrite_symbols
, overwrite_symbols
);
962 result
= __kload_load_module(dgraph
, current_entry
,
963 (current_entry
== dgraph
->root
));
964 #endif /* not KERNEL */
965 if (result
!= kload_error_none
) {
969 if (dgraph
->has_opaque_links
&& (current_entry
!= dgraph
->root
))
971 if (!(kRawKernelLink
& current_entry
->opaques
)) {
972 result
= __kload_keep_symbols(current_entry
);
974 if (result
!= kload_error_none
) {
975 kload_log_error("__kload_keep_symbols() failed for module %s" KNL
,
976 current_entry
->name
);
982 if (do_load
&& current_entry
->do_load
) {
984 if (current_entry
->do_load
) {
985 #endif /* not KERNEL */
986 result
= __kload_set_module_dependencies(current_entry
);
987 if ( ! (result
== kload_error_none
||
988 result
== kload_error_already_loaded
) ) {
993 if ( (interactive_level
== 1 && current_entry
== dgraph
->root
) ||
994 (interactive_level
== 2) ) {
996 int approve
= (*__kload_approve_func
)(1,
997 "\nStart module %s (answering no will abort the load)",
998 current_entry
->name
);
1001 do_start_kmod
= true; // override 'cause user said so
1003 kern_return_t mach_result
;
1005 kload_log_message("error reading user response; "
1006 "destroying loaded module" KNL
);
1008 kload_log_message("user canceled module start; "
1009 "destroying loaded module" KNL
);
1011 mach_result
= kmod_destroy(G_kernel_priv_port
, current_entry
->kmod_id
);
1012 if (mach_result
!= KERN_SUCCESS
) {
1013 kload_log_error("kmod_destroy() failed" KNL
);
1016 result
= kload_error_unspecified
;
1019 result
= kload_error_user_abort
;
1024 #endif /* not KERNEL */
1027 if (current_entry
!= dgraph
->root
||
1028 (current_entry
== dgraph
->root
&& do_start_kmod
)) {
1029 #endif /* not KERNEL */
1031 result
= __kload_start_module(current_entry
);
1032 if ( ! (result
== kload_error_none
||
1033 result
== kload_error_already_loaded
) ) {
1036 } else if (interactive_level
||
1037 log_level
>= kload_log_level_load_details
) {
1039 } else if (log_level
>= kload_log_level_load_details
) {
1040 #endif /* not KERNEL */
1042 kload_log_message("started module %s" KNL
,
1043 current_entry
->name
);
1046 } /* current_entry... */
1047 #endif /* not KERNEL */
1054 #endif /* not KERNEL */
1055 } /* for i, dgraph->length */
1060 /* Dispose of the kernel port to prevent security breaches and port
1061 * leaks. We don't care about the kern_return_t value of this
1062 * call for now as there's nothing we can do if it fails.
1064 if (PORT_NULL
!= G_kernel_port
) {
1065 mach_port_deallocate(mach_task_self(), G_kernel_port
);
1066 G_kernel_port
= PORT_NULL
;
1068 #endif /* not KERNEL */
1070 if (cleanup_kld_loader
) {
1078 /*******************************************************************************
1080 *******************************************************************************/
1083 #define __KLOAD_SYMBOL_EXTENSION ".sym"
1084 #endif /* not KERNEL */
1087 kload_error
__kload_load_module(dgraph_t
* dgraph
,
1088 dgraph_entry_t
* entry
,
1090 __unused
int is_root
1091 #else /* not KERNEL */
1093 const char * symbol_file
,
1094 const char * symbol_dir
,
1096 int interactive_level
,
1097 int ask_overwrite_symbols
,
1098 int overwrite_symbols
1099 #endif /* not KERNEL */
1102 kload_error result
= kload_error_none
;
1106 struct mach_header
* kld_header
;
1107 const char * kmod_symbol
= "_kmod_info";
1108 unsigned long kernel_kmod_info
;
1109 kmod_info_t
* local_kmod_info
= NULL
;
1110 char * dest_address
= 0;
1112 char * allocated_filename
= NULL
;
1113 char * symbol_filename
= NULL
;
1115 vm_address_t vm_buffer
= 0;
1116 #endif /* not KERNEL */
1118 /* A kernel component is by nature already linked and loaded and has
1119 * no work to be done upon it.
1121 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1122 result
= kload_error_none
;
1126 G_current_load_entry
= entry
;
1128 if (log_level
>= kload_log_level_load_basic
) {
1131 #endif /* not KERNEL */
1132 kload_log_message("link/loading file %s" KNL
, entry
->name
);
1135 kload_log_message("linking file %s" KNL
, entry
->name
);
1137 #endif /* not KERNEL */
1141 if (entry
->link_output_file
!= entry
->name
) {
1142 symbol_filename
= entry
->link_output_file
;
1145 if (symbol_filename
) {
1146 file_check
= kload_file_exists(symbol_filename
);
1147 if (file_check
< 0) {
1148 kload_log_error("error checking existence of file %s" KNL
,
1150 } else if (file_check
> 0 && !overwrite_symbols
) {
1152 if (!ask_overwrite_symbols
) {
1153 kload_log_message("symbol file %s exists; not overwriting" KNL
,
1155 symbol_filename
= NULL
;
1157 int approve
= (*__kload_approve_func
)(1,
1158 "\nSymbol file %s exists; overwrite", symbol_filename
);
1161 result
= kload_error_unspecified
;
1163 } else if (approve
== 0) {
1164 if (allocated_filename
) free(allocated_filename
);
1165 allocated_filename
= NULL
;
1166 symbol_filename
= NULL
;
1172 if (symbol_filename
&&
1173 (interactive_level
||
1174 log_level
>= kload_log_level_basic
) ) {
1176 kload_log_message("writing symbol file %s" KNL
, symbol_filename
);
1180 if (interactive_level
&& entry
->loaded_address
) {
1182 "module %s is already loaded as %s at address 0x%08x" KNL
,
1183 entry
->name
, entry
->expected_kmod_name
,
1184 entry
->loaded_address
);
1185 } else if ( (interactive_level
== 1 && is_root
) ||
1186 (interactive_level
== 2) ) {
1188 int approve
= (*__kload_approve_func
)(1,
1189 "\nLoad module %s", entry
->name
);
1192 result
= kload_error_unspecified
;
1194 } else if (approve
== 0) {
1195 result
= kload_error_user_abort
;
1200 #endif /* not KERNEL */
1202 entry
->object
= kld_file_getaddr(entry
->name
, &entry
->object_length
);
1203 if (!entry
->object
) {
1204 kload_log_error("kld_file_getaddr() failed for module %s" KNL
,
1206 __kload_clear_kld_globals();
1207 result
= kload_error_link_load
;
1211 if (entry
->is_symbol_set
) {
1212 entry
->symbols
= (vm_address_t
) entry
->object
;
1213 entry
->symbols_length
= entry
->object_length
;
1216 if (symbol_filename
) {
1217 if (!_IOWriteBytesToFile(symbol_filename
, (void *) entry
->symbols
, entry
->symbols_length
)) {
1218 kload_log_error("write symbol file failed for module %s" KNL
,
1220 __kload_clear_kld_globals();
1221 result
= kload_error_link_load
;
1224 symbol_filename
= 0;
1225 if (G_prelink
&& (entry
->name
!= entry
->link_output_file
))
1227 kload_log_error("prelink %s %s %s" KNL
,
1228 entry
->name
, entry
->link_output_file
, entry
->expected_kmod_name
);
1229 register_prelink(entry
, NULL
, NULL
);
1232 #endif /* not KERNEL */
1233 if (entry
->opaques
) {
1234 result
= kload_error_none
;
1240 kld_result
= kld_load_from_memory(&kld_header
, entry
->name
,
1241 entry
->object
, entry
->object_length
, symbol_filename
);
1243 kld_result
= kld_load_from_memory(&kld_header
, entry
->name
,
1244 entry
->object
, entry
->object_length
);
1245 #endif /* not KERNEL */
1250 #endif /* not KERNEL */
1252 dgraph
->have_loaded_symbols
= true;
1254 if (!kld_result
|| !entry
->kernel_load_address
) {
1255 kload_log_error("kld_load_from_memory() failed for module %s" KNL
,
1257 __kload_clear_kld_globals();
1258 entry
->need_cleanup
= 1;
1259 result
= kload_error_link_load
;
1263 if (entry
->is_symbol_set
) {
1264 result
= kload_error_none
;
1268 entry
->linked_image
= kld_header
;
1269 entry
->linked_image_length
= -1; // unknown!
1271 /* If we're in the kernel and not loading (as when handling an
1272 * already-loaded dependency), we don't need to waste any CPU
1273 * cycles looking up the kmod_info struct.
1276 if (entry
->do_load
) {
1279 kld_result
= kld_lookup(kmod_symbol
, &kernel_kmod_info
);
1281 kload_log_error("kld_lookup(\"%s\") failed for module %s" KNL
,
1282 kmod_symbol
, entry
->name
);
1283 entry
->need_cleanup
= 1;
1284 result
= kload_error_link_load
;
1292 kld_result
= kld_forget_symbol(kmod_symbol
);
1296 #endif /* not KERNEL */
1298 kload_log_error("kld_forget_symbol(\"%s\") failed for module %s" KNL
,
1299 kmod_symbol
, entry
->name
);
1300 entry
->need_cleanup
= 1;
1301 result
= kload_error_link_load
;
1305 /* This section is always done in userland, but in kernel space
1306 * only if we're loading the kext, because what we have in kernel
1307 * space for an already-loaded kext is the kext itself, which
1308 * must not be touched again after it's been loaded and started.
1316 /* Get the linked image's kmod_info by translating from the
1317 * destined kernel-space address at kernel_kmod_info to an
1318 * offset from kld_header.
1320 local_kmod_info
= (kmod_info_t
*)((unsigned long)kernel_kmod_info
-
1321 (unsigned long)G_current_load_entry
->kernel_load_address
+
1322 (unsigned long)kld_header
);
1324 /* Stamp the bundle ID and version from the entry over anything
1325 * resident inside the kmod.
1327 bzero(local_kmod_info
->name
, sizeof(local_kmod_info
->name
));
1328 strlcpy(local_kmod_info
->name
, entry
->expected_kmod_name
, sizeof(local_kmod_info
->name
));
1330 bzero(local_kmod_info
->version
, sizeof(local_kmod_info
->version
));
1331 strlcpy(local_kmod_info
->version
, entry
->expected_kmod_vers
, sizeof(local_kmod_info
->version
));
1333 if (log_level
>= kload_log_level_details
) {
1334 kload_log_message("kmod name: %s" KNL
, local_kmod_info
->name
);
1335 kload_log_message("kmod start @ 0x%x (offset 0x%lx)" KNL
,
1336 (vm_address_t
)local_kmod_info
->start
,
1337 (unsigned long)local_kmod_info
->start
- (unsigned long)G_current_load_entry
->kernel_load_address
);
1338 kload_log_message("kmod stop @ 0x%x (offset 0x%lx)" KNL
,
1339 (vm_address_t
)local_kmod_info
->stop
,
1340 (unsigned long)local_kmod_info
->stop
- (unsigned long)G_current_load_entry
->kernel_load_address
);
1343 if (!local_kmod_info
->start
|| !local_kmod_info
->start
) {
1345 "error for module file %s; start or stop address is zero" KNL
,
1347 entry
->need_cleanup
= 1;
1348 result
= kload_error_link_load
;
1352 /* Record link info into kmod_info struct, rounding the hdr_size
1353 * to fit the adjustment that was made in __kload_linkedit_address().
1355 if (entry
->kernel_alloc_address
) {
1356 local_kmod_info
->address
= entry
->kernel_alloc_address
;
1358 local_kmod_info
->address
= entry
->loaded_address
;
1360 local_kmod_info
->size
= entry
->kernel_alloc_size
;
1361 local_kmod_info
->hdr_size
= round_page(entry
->kernel_hdr_size
);
1366 if (G_prelink
&& (entry
->name
!= entry
->link_output_file
))
1368 register_prelink(entry
, local_kmod_info
, kernel_kmod_info
);
1371 if (do_load
&& entry
->do_load
) {
1372 mach_result
= vm_allocate(mach_task_self(), &vm_buffer
,
1373 entry
->kernel_alloc_size
, VM_FLAGS_ANYWHERE
);
1374 if (mach_result
!= KERN_SUCCESS
) {
1375 kload_log_error("unable to vm_allocate() copy buffer" KNL
);
1376 entry
->need_cleanup
= 1;
1377 result
= kload_error_no_memory
; // FIXME: kernel error?
1381 dest_address
= (char *)vm_buffer
;
1383 memcpy(dest_address
, kld_header
, entry
->kernel_hdr_size
);
1384 memcpy(dest_address
+ round_page(entry
->kernel_hdr_size
),
1385 (void *)((unsigned long)kld_header
+ entry
->kernel_hdr_size
),
1386 entry
->kernel_load_size
- entry
->kernel_hdr_size
);
1388 mach_result
= vm_write(G_kernel_port
, entry
->kernel_alloc_address
,
1389 vm_buffer
, entry
->kernel_alloc_size
);
1390 if (mach_result
!= KERN_SUCCESS
) {
1391 kload_log_error("unable to write module to kernel memory" KNL
);
1392 entry
->need_cleanup
= 1;
1393 result
= kload_error_kernel_error
;
1397 mach_result
= kmod_create(G_kernel_priv_port
,
1398 (vm_address_t
)kernel_kmod_info
, &(entry
->kmod_id
));
1401 if (entry
->do_load
) {
1402 dest_address
= (char *)entry
->kernel_alloc_address
;
1403 memcpy(dest_address
, kld_header
, entry
->kernel_hdr_size
);
1404 memcpy(dest_address
+ round_page(entry
->kernel_hdr_size
),
1405 (void *)((unsigned long)kld_header
+ entry
->kernel_hdr_size
),
1406 entry
->kernel_load_size
- entry
->kernel_hdr_size
);
1408 /* We've written data & instructions into kernel memory, so flush
1409 * the data cache and invalidate the instruction cache.
1411 flush_dcache(entry
->kernel_alloc_address
, entry
->kernel_alloc_size
, false);
1412 invalidate_icache(entry
->kernel_alloc_address
, entry
->kernel_alloc_size
, false);
1414 mach_result
= kmod_create_internal(
1415 (kmod_info_t
*)kernel_kmod_info
, &(entry
->kmod_id
));
1417 #endif /* not KERNEL */
1419 if (mach_result
!= KERN_SUCCESS
) {
1420 kload_log_error("unable to register module with kernel" KNL
);
1421 entry
->need_cleanup
= 1;
1422 result
= kload_error_kernel_error
;
1427 if (interactive_level
|| log_level
>= kload_log_level_load_basic
) {
1429 if (log_level
>= kload_log_level_load_basic
) {
1430 #endif /* not KERNEL */
1432 "module %s created as # %d at address 0x%x, size %ld" KNL
,
1433 entry
->expected_kmod_name
, entry
->kmod_id
,
1434 entry
->kernel_alloc_address
,
1435 entry
->kernel_alloc_size
);
1441 #endif /* not KERNEL */
1444 if (interactive_level
) {
1446 "You can now break to the debugger and set breakpoints "
1447 " for this extension." KNL
);
1449 #endif /* not KERNEL */
1455 #endif /* not KERNEL */
1460 if (allocated_filename
) {
1461 free(allocated_filename
);
1464 vm_deallocate(mach_task_self(), vm_buffer
, entry
->kernel_alloc_size
);
1466 #endif /* not KERNEL */
1467 __kload_clear_kld_globals();
1472 /*******************************************************************************
1473 *******************************************************************************/
1477 register_prelink(dgraph_entry_t
* entry
,
1478 kmod_info_t
* local_kmod_info
, vm_offset_t kernel_kmod_info
)
1480 CFIndex i
, j
, depoffset
;
1484 depoffset
= CFDataGetLength(G_prelink_dependencies
) / sizeof(CFIndex
);
1486 for (i
= 0; i
< entry
->num_dependencies
; i
++)
1489 for (j
= 1; (j
< (1 + G_prelink
->modules
[0].id
)); j
++)
1491 exists
= (0 == strcmp(entry
->dependencies
[i
]->expected_kmod_name
,
1492 G_prelink
->modules
[j
].name
));
1498 bzero(&desc
, sizeof(desc
));
1499 strcpy(desc
.name
, entry
->dependencies
[i
]->expected_kmod_name
);
1501 if (log_level
>= kload_log_level_basic
) {
1502 kload_log_message("[%d] (dep)\n %s" KNL
,
1503 G_prelink
->modules
[0].id
+ 1, desc
.name
);
1505 G_prelink
->modules
[0].id
++;
1506 CFDataAppendBytes(G_prelink_data
, (UInt8
*) &desc
, sizeof(desc
));
1507 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
1510 G_prelink
->modules
[0].reference_count
++;
1511 OSWriteBigInt32(&j
, 0, j
);
1512 CFDataAppendBytes(G_prelink_dependencies
, (UInt8
*) &j
, sizeof(j
));
1514 if (log_level
>= kload_log_level_basic
) {
1515 kload_log_message("[%d] 0x%08x info 0x%08x\n %s,\n %s" KNL
,
1516 G_prelink
->modules
[0].id
+ 1, entry
->kernel_load_address
,
1517 kernel_kmod_info
, entry
->link_output_file
, entry
->name
);
1520 if (local_kmod_info
)
1521 desc
= *local_kmod_info
;
1524 bzero(&desc
, sizeof(desc
));
1525 desc
.size
= entry
->symbols_length
;
1528 desc
.id
= kernel_kmod_info
;
1529 desc
.reference_count
= entry
->num_dependencies
;
1530 desc
.reference_list
= (kmod_reference_t
*) depoffset
;
1532 /* Stamp the bundle ID and version from the entry over anything
1533 * resident inside the kmod.
1535 bzero(desc
.name
, sizeof(local_kmod_info
->name
));
1536 strcpy(desc
.name
, entry
->expected_kmod_name
);
1537 bzero(desc
.version
, sizeof(local_kmod_info
->version
));
1538 strcpy(desc
.version
, entry
->expected_kmod_vers
);
1540 G_prelink
->modules
[0].id
++;
1541 CFDataAppendBytes(G_prelink_data
, (UInt8
*) &desc
, sizeof(desc
));
1542 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
1544 return kload_error_none
;
1549 /*******************************************************************************
1551 *******************************************************************************/
1554 kload_error
kload_map_dgraph(
1556 const char * kernel_file
)
1558 kload_error
kload_map_dgraph(
1560 #endif /* not KERNEL */
1562 kload_error result
= kload_error_none
;
1565 if (log_level
>= kload_log_level_load_details
) {
1567 kload_log_message("mapping the kernel file %s" KNL
, kernel_file
);
1569 kload_log_message("mapping the kernel" KNL
);
1570 #endif /* not KERNEL */
1574 if (!kld_file_map(kernel_file
)) {
1575 result
= kload_error_link_load
;
1578 #endif /* not KERNEL */
1580 for (i
= 0; i
< dgraph
->length
; i
++) {
1581 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1583 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1587 result
= kload_map_entry(entry
);
1588 if (result
!= kload_error_none
) {
1598 /*******************************************************************************
1600 *******************************************************************************/
1602 kload_error
kload_map_entry(dgraph_entry_t
* entry
)
1604 kload_error result
= kload_error_none
;
1606 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1607 kload_log_error("attempt to map kernel component %s" KNL
, entry
->name
);
1608 result
= kload_error_invalid_argument
;
1612 if (log_level
>= kload_log_level_load_details
) {
1613 kload_log_message("mapping module file %s" KNL
, entry
->name
);
1616 if (kld_file_getaddr(entry
->name
, NULL
)) {
1617 if (log_level
>= kload_log_level_load_details
) {
1618 kload_log_message("module file %s is already mapped" KNL
, entry
->name
);
1620 result
= kload_error_none
;
1625 if (!kld_file_map(entry
->name
)) {
1627 if (!kld_file_map(entry
->name
, entry
->object
, entry
->object_length
,
1628 entry
->object_is_kmem
)) {
1629 #endif /* not KERNEL */
1630 kload_log_error("error mapping module file %s" KNL
, entry
->name
);
1632 result
= kload_error_link_load
;
1638 #endif /* not KERNEL */
1640 entry
->is_mapped
= true;
1642 /* Clear these bits now, as the kld patch module now owns the info
1643 * and it is subject to change. We reset them in the entry from the
1644 * kld patch module as needed.
1647 entry
->object_length
= 0;
1649 entry
->object_is_kmem
= false;
1652 // FIXME: Stop using this symbol; have the info passed in by
1653 // FIXME: ...the kext management library.
1655 if (!entry
->is_kernel_component
&& !kld_file_lookupsymbol(entry
->name
, "_kmod_info")) {
1656 kload_log_error("%s does not not contain kernel extension code" KNL
,
1658 result
= kload_error_executable_bad
;
1661 #endif /* not KERNEL */
1668 /*******************************************************************************
1670 *******************************************************************************/
1671 kload_error
kload_request_load_addresses(
1673 const char * kernel_file
)
1675 kload_error result
= kload_error_none
;
1677 const char * user_response
= NULL
; // must free
1679 unsigned int address
;
1681 /* We have to map all object files to get their CFBundleIdentifier
1684 result
= kload_map_dgraph(dgraph
, kernel_file
);
1685 if (result
!= kload_error_none
) {
1686 kload_log_error("error mapping object files" KNL
);
1690 // fixme: this shouldn't be printf, should it?
1691 printf("enter the hexadecimal load addresses for these modules:\n");
1693 for (i
= 0; i
< dgraph
->length
; i
++) {
1694 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1697 result
= kload_error_unspecified
;
1701 if (entry
->is_kernel_component
) {
1705 if (!entry
->is_mapped
) {
1706 result
= kload_error_unspecified
;
1710 user_response
= __kload_input_func("%s:",
1711 entry
->expected_kmod_name
);
1712 if (!user_response
) {
1713 result
= kload_error_unspecified
;
1716 scan_result
= sscanf(user_response
, "%x", &address
);
1717 if (scan_result
< 1 || scan_result
== EOF
) {
1718 result
= kload_error_unspecified
;
1721 entry
->loaded_address
= address
;
1729 /*******************************************************************************
1730 * addresses is a NULL-terminated list of string of the form "module_id@address"
1731 *******************************************************************************/
1732 kload_error
kload_set_load_addresses_from_args(
1734 const char * kernel_file
,
1737 kload_error result
= kload_error_none
;
1741 /* We have to map all object files to get their CFBundleIdentifier
1744 result
= kload_map_dgraph(dgraph
, kernel_file
);
1745 if (result
!= kload_error_none
) {
1746 kload_log_error("error mapping object files" KNL
);
1751 * Run through and assign all addresses to their relevant module
1754 for (i
= 0; i
< dgraph
->length
; i
++) {
1755 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1758 result
= kload_error_unspecified
;
1762 if (entry
->is_kernel_component
) {
1766 if (!entry
->is_mapped
) {
1767 result
= kload_error_unspecified
;
1771 for (j
= 0; addresses
[j
]; j
++) {
1772 char * this_addr
= addresses
[j
];
1773 char * address_string
= NULL
;
1774 unsigned int address
;
1775 unsigned int module_namelen
= strlen(entry
->expected_kmod_name
);
1778 result
= kload_error_unspecified
;
1782 if (strncmp(this_addr
, entry
->expected_kmod_name
, module_namelen
)) {
1785 if (this_addr
[module_namelen
] != '@') {
1789 address_string
= index(this_addr
, '@');
1790 if (!address_string
) {
1791 result
= kload_error_unspecified
;
1795 address
= strtoul(address_string
, NULL
, 16);
1796 entry
->loaded_address
= address
;
1801 * Now that we've done that see that all non-kernel modules do have
1802 * addresses set. If even one doesn't, we can't complete the link
1803 * relocation of symbols, so return a usage error.
1805 for (i
= 0; i
< dgraph
->length
; i
++) {
1806 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1808 if (entry
->is_kernel_component
) {
1812 if (!entry
->loaded_address
) {
1813 result
= kload_error_invalid_argument
;
1823 /*******************************************************************************
1824 * This function requires G_kernel_priv_port to be set before it will work.
1825 *******************************************************************************/
1826 kload_error
kload_set_load_addresses_from_kernel(
1828 const char * kernel_file
,
1831 kload_error result
= kload_error_none
;
1833 kmod_info_t
* loaded_modules
= NULL
;
1834 int loaded_bytecount
= 0;
1839 * We have to map the dgraph's modules before checking whether they've
1842 result
= kload_map_dgraph(dgraph
, kernel_file
);
1843 if (result
!= kload_error_none
) {
1844 kload_log_error("can't map module files" KNL
);
1849 /* First clear all the load addresses.
1851 for (i
= 0; i
< dgraph
->length
; i
++) {
1852 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1853 entry
->loaded_address
= 0;
1856 mach_result
= kmod_get_info(G_kernel_priv_port
,
1857 (void *)&loaded_modules
, &loaded_bytecount
);
1858 if (mach_result
!= KERN_SUCCESS
) {
1859 kload_log_error("kmod_get_info() failed" KNL
);
1860 result
= kload_error_kernel_error
;
1865 * Find out which modules have already been loaded & verify
1866 * that loaded versions are same as requested.
1868 for (i
= 0; i
< dgraph
->length
; i
++) {
1869 kload_error cresult
;
1870 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
1872 /* If necessary, check whether the current module is already loaded.
1873 * (We already did the root module above.)
1875 cresult
= __kload_check_module_loaded(dgraph
, current_entry
,
1876 loaded_modules
, do_load
);
1877 if ( ! (cresult
== kload_error_none
||
1878 cresult
== kload_error_already_loaded
) ) {
1881 if (current_entry
== dgraph
->root
&&
1882 cresult
== kload_error_already_loaded
) {
1890 if (loaded_modules
) {
1891 vm_deallocate(mach_task_self(), (vm_address_t
)loaded_modules
,
1900 /*******************************************************************************
1902 *******************************************************************************/
1904 kload_error
kload_set_load_addresses_from_kernel(
1907 kload_error result
= kload_error_none
;
1910 kmod_info_t
* loaded_modules
= NULL
;
1911 int loaded_bytecount
= 0;
1912 #endif /* not KERNEL */
1917 * We have to map the dgraph's modules before checking whether they've
1920 result
= kload_map_dgraph(dgraph
);
1921 if (result
!= kload_error_none
) {
1922 kload_log_error("can't map module files" KNL
);
1927 /* First clear all the load addresses.
1929 for (i
= 0; i
< dgraph
->length
; i
++) {
1930 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1931 entry
->loaded_address
= 0;
1935 * Find out which modules have already been loaded & verify
1936 * that loaded versions are same as requested.
1938 for (i
= 0; i
< dgraph
->length
; i
++) {
1939 kload_error cresult
;
1940 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
1942 /* If necessary, check whether the current module is already loaded.
1943 * (We already did the root module above.)
1945 cresult
= __kload_check_module_loaded(dgraph
, current_entry
, false);
1946 if ( ! (cresult
== kload_error_none
||
1947 cresult
== kload_error_already_loaded
) ) {
1950 if (current_entry
== dgraph
->root
&&
1951 cresult
== kload_error_already_loaded
) {
1961 #endif /* not KERNEL */
1963 /*******************************************************************************
1965 *******************************************************************************/
1967 extern kern_return_t
kmod_load_from_cache(const char * kmod_name
);
1970 static kmod_info_t
* __kload_find_kmod_info(const char * kmod_name
1973 kmod_info_t
* kmod_list
1974 #endif /* not KERNEL */
1980 for (i
= 0; ; i
++) {
1981 kmod_info_t
* current_kmod
= &(kmod_list
[i
]);
1982 if (0 == strcmp(current_kmod
->name
, kmod_name
)) {
1983 return current_kmod
;
1985 if (kmod_list
[i
].next
== 0) {
1992 info
= kmod_lookupbyname_locked(kmod_name
);
1993 if (!info
&& (KERN_SUCCESS
== kmod_load_from_cache(kmod_name
))) {
1994 info
= kmod_lookupbyname_locked(kmod_name
);
1997 #endif /* not KERNEL */
2000 /*******************************************************************************
2002 *******************************************************************************/
2004 kload_error
__kload_check_module_loaded(
2006 dgraph_entry_t
* entry
,
2008 kmod_info_t
* kmod_list
,
2009 #endif /* not KERNEL */
2012 kload_error result
= kload_error_none
;
2013 const char * kmod_name
;
2014 kmod_info_t
* current_kmod
= 0;
2016 VERS_version entry_vers
;
2017 VERS_version loaded_vers
;
2019 if (false && entry
->is_kernel_component
) {
2020 kmod_name
= entry
->name
;
2022 kmod_name
= entry
->expected_kmod_name
;
2023 if (log_level
>= kload_log_level_load_details
) {
2024 kload_log_message("checking whether module file %s is already loaded" KNL
,
2030 current_kmod
= __kload_find_kmod_info(kmod_name
, kmod_list
);
2032 current_kmod
= __kload_find_kmod_info(kmod_name
);
2033 #endif /* not KERNEL */
2035 if (!current_kmod
) {
2040 entry
->kmod_id
= current_kmod
->id
;
2041 entry
->loaded_address
= current_kmod
->address
;
2043 if (entry
->is_kernel_component
) {
2047 if (log_level
>= kload_log_level_load_details
) {
2048 kload_log_message("module file %s is loaded; checking status" KNL
,
2052 // We really want to move away from having this info in a kmod....
2054 loaded_vers
= VERS_parse_string(current_kmod
->version
);
2055 if (loaded_vers
< 0) {
2057 "can't parse version string \"%s\" of loaded module %s" KNL
,
2058 current_kmod
->version
,
2059 current_kmod
->name
);
2060 result
= kload_error_unspecified
;
2064 entry_vers
= VERS_parse_string(entry
->expected_kmod_vers
);
2065 if (entry_vers
< 0) {
2067 "can't parse version string \"%s\" of module file %s" KNL
,
2068 entry
->expected_kmod_name
,
2070 result
= kload_error_unspecified
;
2074 if (loaded_vers
!= entry_vers
) {
2076 "loaded version %s of module %s differs from "
2077 "requested version %s" KNL
,
2078 current_kmod
->version
,
2080 entry
->expected_kmod_name
);
2081 if (entry
== dgraph
->root
) {
2082 result
= kload_error_loaded_version_differs
;
2084 result
= kload_error_dependency_loaded_version_differs
;
2089 if (log_if_already
&& log_level
>=
2090 kload_log_level_load_basic
) {
2093 "module %s (identifier %s) is already loaded" KNL
,
2094 entry
->name
, kmod_name
);
2096 result
= kload_error_already_loaded
;
2102 // Do this ONLY if in the kernel!
2104 kfree(current_kmod
, sizeof(kmod_info_t
));
2110 /*******************************************************************************
2112 *******************************************************************************/
2114 kload_error
__kload_patch_dgraph(dgraph_t
* dgraph
2117 const char * kernel_file
2118 #endif /* not KERNEL */
2121 kload_error result
= kload_error_none
;
2125 if (!kld_file_merge_OSObjects(kernel_file
)) {
2126 result
= kload_error_link_load
;
2129 #endif /* not KERNEL */
2131 for (i
= 0; i
< dgraph
->length
; i
++) {
2132 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
2134 /* The kernel has already been patched.
2136 if (current_entry
->is_kernel_component
) {
2140 if (log_level
>= kload_log_level_load_details
) {
2141 kload_log_message("patching C++ code in module %s" KNL
,
2142 current_entry
->name
);
2146 /* In userland, we call the patch function for all kmods,
2147 * loaded or not, because we don't have all the info that
2148 * the kernel environment has.
2150 if (!kld_file_patch_OSObjects(current_entry
->name
)) {
2151 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2155 /* In the kernel, we call the merge function for already-loaded
2156 * kmods, since the kld patch environment retains info for kmods
2157 * that have already been patched. The patch function does a little
2158 * more work, and is only for kmods that haven't been processed yet.
2159 * NOTE: We are depending here on kload_check_module_loaded()
2160 * having been called, which is guaranteed by kload_load_dgraph()
2161 * is used, but not by its subroutines (such as
2162 * __kload_load_modules()).
2164 if (current_entry
->loaded_address
) {
2165 if (!kld_file_merge_OSObjects(current_entry
->name
)) {
2166 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2170 if (!kld_file_patch_OSObjects(current_entry
->name
)) {
2171 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2175 #endif /* not KERNEL */
2179 if (!kld_file_prepare_for_link()) {
2180 result
= kload_error_link_load
; // FIXME: need more specific error?
2189 /*******************************************************************************
2191 *******************************************************************************/
2192 #define __KLOAD_PATCH_EXTENSION ".patch"
2194 kload_error
__kload_output_patches(
2196 const char * patch_file
,
2197 const char * patch_dir
,
2198 int ask_overwrite_symbols
,
2199 int overwrite_symbols
)
2201 kload_error result
= kload_error_none
;
2203 char * allocated_filename
= NULL
;
2204 char * patch_filename
= NULL
;
2210 for (i
= 0; i
< dgraph
->length
; i
++) {
2212 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
2213 unsigned long length
;
2215 if (entry
->is_kernel_component
) {
2219 length
= strlen(patch_dir
) +
2220 strlen(entry
->expected_kmod_name
) +
2221 strlen(__KLOAD_PATCH_EXTENSION
) +
2222 1 + 1 ; // 1 for '/' added, 1 for terminating null
2223 if (length
>= MAXPATHLEN
) {
2225 "output filename \"%s/%s%s\" would be too long" KNL
,
2226 patch_dir
, entry
->expected_kmod_name
,
2227 __KLOAD_PATCH_EXTENSION
);
2228 result
= kload_error_invalid_argument
;
2232 allocated_filename
= (char *)malloc(length
);
2233 if (! allocated_filename
) {
2234 kload_log_error("malloc failure" KNL
);
2235 result
= kload_error_no_memory
;
2239 patch_filename
= allocated_filename
;
2240 strlcpy(patch_filename
, patch_dir
, length
);
2241 strlcat(patch_filename
, "/", length
);
2242 strlcat(patch_filename
, entry
->expected_kmod_name
, length
);
2243 strlcat(patch_filename
, __KLOAD_PATCH_EXTENSION
, length
);
2246 file_check
= kload_file_exists(patch_filename
);
2248 if (file_check
< 0) {
2249 kload_log_error("error checking existence of file %s" KNL
,
2251 } else if (file_check
> 0 && !overwrite_symbols
) {
2252 if (!ask_overwrite_symbols
) {
2254 "patch file %s exists; not overwriting" KNL
,
2258 int approve
= (*__kload_approve_func
)(1,
2259 "\nPatch file %s exists; overwrite", patch_filename
);
2262 result
= kload_error_unspecified
;
2265 output_patch
= approve
;
2271 if (log_level
>= kload_log_level_basic
) {
2272 kload_log_message("writing patch file %s" KNL
, patch_filename
);
2274 kld_file_debug_dump(entry
->name
, patch_filename
);
2277 if (allocated_filename
) free(allocated_filename
);
2278 allocated_filename
= NULL
;
2281 } else if (patch_file
) {
2283 file_check
= kload_file_exists(patch_file
);
2285 if (file_check
< 0) {
2286 kload_log_error("error checking existence of file %s" KNL
,
2288 } else if (file_check
> 0 && !overwrite_symbols
) {
2289 if (!ask_overwrite_symbols
) {
2290 kload_log_error("patch file %s exists; not overwriting" KNL
,
2294 int approve
= (*__kload_approve_func
)(1,
2295 "\nPatch file %s exists; overwrite", patch_filename
);
2298 result
= kload_error_unspecified
;
2301 output_patch
= approve
;
2307 if (log_level
>= kload_log_level_basic
) {
2308 kload_log_message("writing patch file %s" KNL
, patch_filename
);
2310 kld_file_debug_dump(dgraph
->root
->name
, patch_file
);
2315 if (allocated_filename
) free(allocated_filename
);
2319 #endif /* not KERNEL */
2321 /*******************************************************************************
2323 *******************************************************************************/
2325 kload_error
__kload_set_module_dependencies(dgraph_entry_t
* entry
) {
2326 kload_error result
= kload_error_none
;
2329 void * kmod_control_args
= 0;
2331 #endif /* not KERNEL */
2334 dgraph_entry_t
* current_dep
= NULL
;
2336 if (!entry
->do_load
) {
2337 result
= kload_error_already_loaded
;
2341 for (i
= 0; i
< entry
->num_dependencies
; i
++) {
2342 current_dep
= entry
->dependencies
[i
];
2344 if (log_level
>= kload_log_level_load_details
) {
2345 kload_log_message("adding reference from %s (%d) to %s (%d)" KNL
,
2346 entry
->expected_kmod_name
, entry
->kmod_id
,
2347 current_dep
->expected_kmod_name
, current_dep
->kmod_id
);
2350 packed_id
= KMOD_PACK_IDS(entry
->kmod_id
, current_dep
->kmod_id
);
2352 mach_result
= kmod_control(G_kernel_priv_port
,
2353 packed_id
, KMOD_CNTL_RETAIN
, &kmod_control_args
, &num_args
);
2355 mach_result
= kmod_retain(packed_id
);
2356 #endif /* not KERNEL */
2357 if (mach_result
!= KERN_SUCCESS
) {
2359 "kmod retain failed for %s; destroying kmod" KNL
,
2360 entry
->expected_kmod_name
);
2362 mach_result
= kmod_destroy(G_kernel_priv_port
, entry
->kmod_id
);
2364 mach_result
= kmod_destroy_internal(entry
->kmod_id
);
2365 #endif /* not KERNEL */
2366 if (mach_result
!= KERN_SUCCESS
) {
2367 kload_log_error("kmod destroy failed" KNL
);
2369 result
= kload_error_link_load
;
2374 if (log_level
>= kload_log_level_load_basic
) {
2375 kload_log_message("module # %d reference counts incremented" KNL
,
2383 /*******************************************************************************
2385 *******************************************************************************/
2387 kload_error
__kload_start_module(dgraph_entry_t
* entry
) {
2388 kload_error result
= kload_error_none
;
2391 void * kmod_control_args
= 0;
2393 #elif CONFIG_MACF_KEXT
2394 kmod_args_t kmod_args
= entry
->user_data
;
2395 mach_msg_type_number_t arg_size
= entry
->user_data_length
;
2396 #endif /* not KERNEL */
2398 if (!entry
->do_load
) {
2399 result
= kload_error_already_loaded
;
2404 mach_result
= kmod_control(G_kernel_priv_port
,
2405 entry
->kmod_id
, KMOD_CNTL_START
, &kmod_control_args
, &num_args
);
2406 #elif CONFIG_MACF_KEXT
2407 mach_result
= kmod_start_or_stop(entry
->kmod_id
, 1, &kmod_args
, &arg_size
);
2409 mach_result
= kmod_start_or_stop(entry
->kmod_id
, 1, 0, 0);
2410 #endif /* not KERNEL */
2412 if (mach_result
!= KERN_SUCCESS
) {
2414 "kmod_control/start failed for %s; destroying kmod" KNL
,
2415 entry
->expected_kmod_name
);
2417 mach_result
= kmod_destroy(G_kernel_priv_port
, entry
->kmod_id
);
2419 mach_result
= kmod_destroy_internal(entry
->kmod_id
);
2420 #endif /* not KERNEL */
2421 if (mach_result
!= KERN_SUCCESS
) {
2422 kload_log_error("kmod destroy failed" KNL
);
2424 result
= kload_error_link_load
;
2428 if (log_level
>= kload_log_level_load_basic
) {
2429 kload_log_message("module # %d started" KNL
,
2437 /*******************************************************************************
2438 *******************************************************************************/
2440 /*******************************************************************************
2441 * This function can only operate on 32 bit mach object file symbol table
2442 * graphs represented by G_current_load_entry.
2443 *******************************************************************************/
2445 unsigned long __kload_linkedit_address(
2447 unsigned long headers_size
)
2449 unsigned long round_segments_size
;
2450 unsigned long round_headers_size
;
2451 unsigned long round_size
;
2453 const struct machOMapping
{
2454 struct mach_header h
;
2455 struct segment_command seg
[1];
2458 if (!G_current_load_entry
) {
2462 // the actual size allocated by kld_load_from_memory()
2463 G_current_load_entry
->kernel_load_size
= size
;
2465 round_headers_size
= round_page(headers_size
);
2466 round_segments_size
= round_page(size
- headers_size
);
2467 round_size
= round_headers_size
+ round_segments_size
;
2469 G_current_load_entry
->kernel_alloc_size
= round_size
;
2471 // will need to be rounded *after* load/link
2472 G_current_load_entry
->kernel_hdr_size
= headers_size
;
2473 G_current_load_entry
->kernel_hdr_pad
= round_headers_size
- headers_size
;
2475 if (G_current_load_entry
->loaded_address
) {
2476 G_current_load_entry
->kernel_load_address
=
2477 G_current_load_entry
->loaded_address
+
2478 G_current_load_entry
->kernel_hdr_pad
;
2479 if (log_level
>= kload_log_level_load_basic
) {
2481 "using %s load address 0x%x (0x%x with header pad)" KNL
,
2482 G_current_load_entry
->kmod_id
? "existing" : "provided",
2483 G_current_load_entry
->loaded_address
,
2484 G_current_load_entry
->kernel_load_address
);
2486 return G_current_load_entry
->kernel_load_address
;
2489 machO
= (const struct machOMapping
*) G_current_load_entry
->object
;
2490 if (machO
->seg
[0].vmaddr
)
2492 G_current_load_entry
->loaded_address
= trunc_page(machO
->seg
[0].vmaddr
- machO
->seg
[0].fileoff
);
2494 G_current_load_entry
->kernel_load_address
= G_current_load_entry
->loaded_address
2495 + G_current_load_entry
->kernel_hdr_pad
;
2497 return G_current_load_entry
->kernel_load_address
;
2502 G_current_load_entry
->kernel_alloc_address
= G_prelink
->modules
[0].address
;
2503 G_prelink
->modules
[0].address
+= round_page(G_current_load_entry
->kernel_alloc_size
);
2504 mach_result
= KERN_SUCCESS
;
2506 } else if (G_syms_only
) {
2508 "internal error; asked to allocate kernel memory" KNL
);
2509 // FIXME: no provision for cleanup here
2510 return kload_error_unspecified
;
2513 #endif /* not KERNEL */
2517 mach_result
= vm_allocate(G_kernel_port
,
2518 &G_current_load_entry
->kernel_alloc_address
,
2519 G_current_load_entry
->kernel_alloc_size
, VM_FLAGS_ANYWHERE
);
2521 mach_result
= vm_allocate(kernel_map
,
2522 &G_current_load_entry
->kernel_alloc_address
,
2523 G_current_load_entry
->kernel_alloc_size
, VM_FLAGS_ANYWHERE
);
2524 #endif /* not KERNEL */
2527 if (mach_result
!= KERN_SUCCESS
) {
2528 kload_log_error("can't allocate kernel memory" KNL
);
2529 // FIXME: no provision for cleanup here
2530 return kload_error_kernel_error
;
2533 if (log_level
>= kload_log_level_load_basic
) {
2534 kload_log_message("allocated %ld bytes in kernel space at 0x%x" KNL
,
2535 G_current_load_entry
->kernel_alloc_size
,
2536 G_current_load_entry
->kernel_alloc_address
);
2539 G_current_load_entry
->kernel_load_address
=
2540 G_current_load_entry
->kernel_alloc_address
+
2541 G_current_load_entry
->kernel_hdr_pad
;
2543 G_current_load_entry
->loaded_address
= G_current_load_entry
->kernel_alloc_address
;
2545 if (log_level
>= kload_log_level_load_basic
) {
2547 "using load address of 0x%x" KNL
,
2548 G_current_load_entry
->kernel_alloc_address
);
2551 return G_current_load_entry
->kernel_load_address
;
2554 /*******************************************************************************
2556 *******************************************************************************/
2558 void __kload_clear_kld_globals(void) {
2559 G_current_load_entry
= NULL
;
2563 /*******************************************************************************
2565 *******************************************************************************/
2567 void __kload_clean_up_entry(dgraph_entry_t
* entry
) {
2570 if (entry
->need_cleanup
&& entry
->kernel_alloc_address
) {
2574 if ((entry
->kernel_alloc_address
+ entry
->kernel_alloc_size
) == G_prelink
->modules
[0].address
) {
2575 G_prelink
->modules
[0].address
= entry
->kernel_alloc_address
;
2578 "bad free load address of 0x%x (last 0x%x)" KNL
,
2579 entry
->kernel_alloc_address
, G_prelink
->modules
[0].address
);
2582 mach_result
= vm_deallocate(G_kernel_port
, entry
->kernel_alloc_address
,
2583 entry
->kernel_alloc_size
);
2586 mach_result
= vm_deallocate(kernel_map
, entry
->kernel_alloc_address
,
2587 entry
->kernel_alloc_size
);
2588 #endif /* not KERNEL */
2589 entry
->kernel_alloc_address
= 0;
2595 /*******************************************************************************
2597 *******************************************************************************/
2598 int kload_file_exists(const char * path
)
2600 int result
= 0; // assume it doesn't exist
2601 struct stat stat_buf
;
2603 if (stat(path
, &stat_buf
) == 0) {
2604 result
= 1; // the file does exist; we don't care beyond that
2610 result
= 0; // the file doesn't exist
2614 result
= -1; // unknown error
2622 #endif /* not KERNEL */
2624 /*******************************************************************************
2626 *******************************************************************************/
2628 void kload_set_log_level(kload_log_level level
)
2635 /*******************************************************************************
2637 *******************************************************************************/
2638 void kload_set_log_function(
2639 void (*func
)(const char * format
, ...))
2642 __kload_log_func
= &__kload_null_log
;
2644 __kload_log_func
= func
;
2649 /*******************************************************************************
2651 *******************************************************************************/
2652 void kload_set_error_log_function(
2653 void (*func
)(const char * format
, ...))
2656 __kload_err_log_func
= &__kload_null_err_log
;
2658 __kload_err_log_func
= func
;
2663 /*******************************************************************************
2665 *******************************************************************************/
2666 void kload_set_user_approve_function(
2667 int (*func
)(int default_answer
, const char * format
, ...))
2670 __kload_approve_func
= &__kload_null_approve
;
2672 __kload_approve_func
= func
;
2677 /*******************************************************************************
2679 *******************************************************************************/
2680 void kload_set_user_veto_function(
2681 int (*func
)(int default_answer
, const char * format
, ...))
2684 __kload_veto_func
= &__kload_null_veto
;
2686 __kload_veto_func
= func
;
2691 /*******************************************************************************
2693 *******************************************************************************/
2694 void kload_set_user_input_function(
2695 const char * (*func
)(const char * format
, ...))
2698 __kload_input_func
= &__kload_null_input
;
2700 __kload_input_func
= func
;
2705 /*******************************************************************************
2707 *******************************************************************************/
2709 void kload_log_message(const char * format
, ...)
2712 char fake_buffer
[2];
2714 char * output_string
;
2716 if (log_level
<= kload_log_level_silent
) {
2720 va_start(ap
, format
);
2721 output_length
= vsnprintf(fake_buffer
, 1, format
, ap
);
2724 output_string
= (char *)malloc(output_length
+ 1);
2725 if (!output_string
) {
2729 va_start(ap
, format
);
2730 vsprintf(output_string
, format
, ap
);
2733 __kload_log_func(output_string
);
2734 free(output_string
);
2739 /*******************************************************************************
2741 *******************************************************************************/
2743 void kload_log_error(const char * format
, ...)
2746 char fake_buffer
[2];
2748 char * output_string
;
2750 if (log_level
<= kload_log_level_silent
) {
2754 va_start(ap
, format
);
2755 output_length
= vsnprintf(fake_buffer
, 1, format
, ap
);
2758 output_string
= (char *)malloc(output_length
+ 1);
2759 if (!output_string
) {
2763 va_start(ap
, format
);
2764 vsprintf(output_string
, format
, ap
);
2767 __kload_err_log_func(output_string
);
2768 free(output_string
);
2772 /*******************************************************************************
2774 *******************************************************************************/
2775 void __kload_null_log(const char * format
, ...)
2780 /*******************************************************************************
2782 *******************************************************************************/
2783 void __kload_null_err_log(const char * format
, ...)
2788 /*******************************************************************************
2790 *******************************************************************************/
2791 int __kload_null_approve(int default_answer
, const char * format
, ...)
2796 /*******************************************************************************
2798 *******************************************************************************/
2799 int __kload_null_veto(int default_answer
, const char * format
, ...)
2804 /*******************************************************************************
2806 *******************************************************************************/
2807 const char * __kload_null_input(const char * format
, ...)
2812 /*******************************************************************************
2813 * The kld_patch.c module uses this function, if defined, to print errors. In
2814 * the kernel this function is defined in libsa/misc.c.
2815 *******************************************************************************/
2816 void kld_error_vprintf(const char * format
, va_list ap
) {
2817 if (log_level
<= kload_log_level_silent
) return;
2818 vfprintf(stderr
, format
, ap
);
2822 #endif /* not KERNEL */