2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
36 #include <CoreFoundation/CoreFoundation.h>
47 #include <sys/param.h>
48 #include <sys/types.h>
51 #include <mach/mach_types.h>
52 #include <mach/mach.h>
53 #include <mach/mach_init.h>
54 #include <mach/mach_error.h>
55 #include <mach/mach_host.h>
56 #include <mach/mach_port.h>
57 #include <mach-o/kld.h>
58 #include <mach-o/arch.h>
59 #include <mach-o/fat.h>
60 #include <mach-o/loader.h>
61 #include <mach-o/nlist.h>
62 #include <kern/kern_types.h>
63 #include <kern/kalloc.h>
64 #include <libkern/OSByteOrder.h>
66 #include "vers_rsrc.h"
70 #include <mach-o/kld.h>
71 #include <mach-o/loader.h>
72 #include <mach-o/nlist.h>
73 #include <libsa/vers_rsrc.h>
75 #endif /* not KERNEL */
79 #include "kld_patch.h"
91 #define PRIV_EXT __private_extern__
94 #define LOG_DELAY(x) IODelay((x) * 1000000)
95 #define VTYELLOW "\033[33m"
96 #define VTRESET "\033[0m"
103 #endif /* not KERNEL */
111 kmod_create_internal(
116 kmod_destroy_internal(kmod_t id
);
123 mach_msg_type_number_t
*dataCount
);
125 extern kern_return_t
kmod_retain(kmod_t id
);
126 extern kern_return_t
kmod_release(kmod_t id
);
128 extern struct mach_header _mh_execute_header
;
132 // Used to pass info between kld library and callbacks
133 static dgraph_entry_t
* G_current_load_entry
= NULL
;
136 static mach_port_t G_kernel_port
= PORT_NULL
;
137 static mach_port_t G_kernel_priv_port
= PORT_NULL
;
138 static int G_syms_only
;
141 register_prelink(dgraph_entry_t
* entry
,
142 kmod_info_t
* local_kmod_info
, vm_offset_t kernel_kmod_info
);
146 kmod_info_t modules
[1];
148 struct PrelinkState
* G_prelink
;
149 CFMutableDataRef G_prelink_data
;
150 CFMutableDataRef G_prelink_dependencies
;
152 #endif /* not KERNEL */
154 // used by dgraph.c so can't be static
155 kload_log_level log_level
= 0;
158 static void __kload_null_log(const char * format
, ...);
159 static void __kload_null_err_log(const char * format
, ...);
160 static int __kload_null_approve(int default_answer
, const char * format
, ...);
161 static int __kload_null_veto(int default_answer
, const char * format
, ...);
162 static const char * __kload_null_input(const char * format
, ...);
164 void (*__kload_log_func
)(const char * format
, ...) =
166 void (*__kload_err_log_func
)(const char * format
, ...) = &__kload_null_err_log
;
167 int (*__kload_approve_func
)(int default_answer
,
168 const char * format
, ...) = &__kload_null_approve
;
169 int (*__kload_veto_func
)(int default_answer
,
170 const char * format
, ...) = &__kload_null_veto
;
171 const char * (*__kload_input_func
)(const char * format
, ...) =
173 #endif /* not KERNEL */
175 static unsigned long __kload_linkedit_address(
177 unsigned long headers_size
);
178 static void __kload_clean_up_entry(dgraph_entry_t
* entry
);
179 static void __kload_clear_kld_globals(void);
180 static kload_error
__kload_patch_dgraph(dgraph_t
* dgraph
183 const char * kernel_file
184 #endif /* not KERNEL */
186 static kload_error
__kload_load_modules(dgraph_t
* dgraph
189 const char * kernel_file
,
190 const char * patch_file
, const char * patch_dir
,
191 const char * symbol_file
, const char * symbol_dir
,
192 int do_load
, int do_start_kmod
, int do_prelink
,
193 int interactive_level
,
194 int ask_overwrite_symbols
, int overwrite_symbols
195 #endif /* not KERNEL */
198 static kload_error
__kload_check_module_loaded(
200 dgraph_entry_t
* entry
,
202 kmod_info_t
* kmod_list
,
203 #endif /* not KERNEL */
206 static kload_error
__kload_load_module(dgraph_t
* dgraph
,
207 dgraph_entry_t
* entry
,
211 const char * symbol_file
,
212 const char * symbol_dir
,
214 int interactive_level
,
215 int ask_overwrite_symbols
,
216 int overwrite_symbols
217 #endif /* not KERNEL */
219 static kload_error
__kload_set_module_dependencies(dgraph_entry_t
* entry
);
220 static kload_error
__kload_start_module(dgraph_entry_t
* entry
);
223 static kload_error
__kload_output_patches(
225 const char * patch_file
,
226 const char * patch_dir
,
227 int ask_overwrite_symbols
,
228 int overwrite_symbols
);
230 Boolean
_IOReadBytesFromFile(CFAllocatorRef alloc
, const char *path
, void **bytes
,
231 CFIndex
*length
, CFIndex maxLength
);
232 Boolean
_IOWriteBytesToFile(const char *path
, const void *bytes
, CFIndex length
);
234 #endif /* not KERNEL */
236 /*******************************************************************************
238 *******************************************************************************/
240 kload_error
kload_load_dgraph(dgraph_t
* dgraph
243 const char * kernel_file
,
244 const char * patch_file
, const char * patch_dir
,
245 const char * symbol_file
, const char * symbol_dir
,
246 int do_load
, int do_start_kmod
, int do_prelink
,
247 int interactive_level
,
248 int ask_overwrite_symbols
, int overwrite_symbols
249 #endif /* not KERNEL */
252 kload_error result
= kload_error_none
;
253 int one_has_address
= 0;
254 int one_lacks_address
= 0;
259 syms_only
= (!do_load
) && (symbol_dir
|| symbol_file
);
261 if (log_level
>= kload_log_level_load_details
) {
262 kload_log_message("loading dependency graph:" KNL
);
266 if (syms_only
&& log_level
>= kload_log_level_load_details
) {
267 kload_log_message("loading for symbol generation only" KNL
);
271 * If we're not loading and have no request to emit a symbol
272 * or patch file, there's nothing to do!
274 if (!do_load
&& !symbol_dir
&& !symbol_file
&&
275 !patch_dir
&& !patch_file
) {
277 if (syms_only
&& log_level
>= kload_log_level_load_details
) {
278 kload_log_message("loader has no work to do" KNL
);
281 result
= kload_error_none
; // fixme: should this be USAGE error?
286 * If we're doing symbols only, then all entries in the dgraph must
287 * have addresses assigned, or none must.
290 if (log_level
>= kload_log_level_load_details
) {
291 kload_log_message("checking whether modules have addresses assigned" KNL
);
293 for (i
= 0; i
< dgraph
->length
; i
++) {
294 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
295 if (entry
->is_kernel_component
) {
298 if (entry
->loaded_address
!= 0) {
301 one_lacks_address
= 1;
305 #endif /* not KERNEL */
307 if (one_has_address
&& one_lacks_address
) {
309 "either all modules must have addresses set to nonzero values or "
311 result
= kload_error_invalid_argument
;
316 /* we need the priv port to check/load modules in the kernel.
318 if (PORT_NULL
== G_kernel_priv_port
) {
319 G_kernel_priv_port
= mach_host_self(); /* if we are privileged */
321 #endif /* not KERNEL */
324 * In the kernel, ALWAYS get load addresses of existing loaded kmods.
328 * If we don't have addresses, then get them from the kernel.
330 if (!one_has_address
&& !do_prelink
&& (do_load
|| symbol_file
|| symbol_dir
)) {
331 #endif /* not KERNEL */
332 if (log_level
>= kload_log_level_load_details
) {
333 kload_log_message("getting module addresses from kernel" KNL
);
336 result
= kload_set_load_addresses_from_kernel(dgraph
, kernel_file
,
339 result
= kload_set_load_addresses_from_kernel(dgraph
);
340 #endif /* not KERNEL */
341 if (result
== kload_error_already_loaded
) {
349 #endif /* not KERNEL */
351 } else if (result
!= kload_error_none
) {
352 kload_log_error("can't check load addresses of modules" KNL
);
357 #endif /* not KERNEL */
361 * At this point, if we're doing symbols only, it's an error to not
362 * have a load address for every module.
364 if (syms_only
&& !do_prelink
) {
365 if (log_level
>= kload_log_level_load_details
) {
366 kload_log_message("checking that all modules have addresses assigned" KNL
);
368 for (i
= 0; i
< dgraph
->length
; i
++) {
369 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
370 if (entry
->is_kernel_component
) {
373 if (!entry
->loaded_address
) {
375 "missing load address during symbol generation: %s" KNL
,
377 result
= kload_error_unspecified
;
387 CFAllocatorRef alloc
;
389 // We need a real allocator to pass to _IOReadBytesFromFile
390 alloc
= CFRetain(CFAllocatorGetDefault());
391 if (_IOReadBytesFromFile(alloc
, "prelinkstate", &bytes
, &length
, 0))
393 G_prelink_data
= CFDataCreateMutable(alloc
, 0);
394 CFDataAppendBytes(G_prelink_data
, (UInt8
*) bytes
, length
);
395 CFAllocatorDeallocate(alloc
, bytes
);
397 G_prelink_dependencies
= CFDataCreateMutable(alloc
, 0);
398 if (_IOReadBytesFromFile(alloc
, "prelinkdependencies", &bytes
, &length
, 0))
400 CFDataAppendBytes(G_prelink_dependencies
, (UInt8
*) bytes
, length
);
401 CFAllocatorDeallocate(alloc
, bytes
);
405 if (!G_prelink_data
) {
407 "can't get load address for prelink %s" KNL
, kernel_file
);
408 result
= kload_error_link_load
;
412 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
416 #endif /* not KERNEL */
420 result
= __kload_load_modules(dgraph
, kernel_file
,
421 patch_file
, patch_dir
, symbol_file
, symbol_dir
,
422 do_load
, do_start_kmod
, do_prelink
, interactive_level
,
423 ask_overwrite_symbols
, overwrite_symbols
);
425 result
= __kload_load_modules(dgraph
);
426 #endif /* not KERNEL */
431 /* Dispose of the host port to prevent security breaches and port
432 * leaks. We don't care about the kern_return_t value of this
433 * call for now as there's nothing we can do if it fails.
435 if (PORT_NULL
!= G_kernel_priv_port
) {
436 mach_port_deallocate(mach_task_self(), G_kernel_priv_port
);
437 G_kernel_priv_port
= PORT_NULL
;
439 #endif /* not KERNEL */
441 for (i
= 0; i
< dgraph
->length
; i
++) {
442 dgraph_entry_t
* current_entry
= dgraph
->graph
[i
];
443 __kload_clean_up_entry(current_entry
);
453 length
= CFDataGetLength(G_prelink_data
);
454 bytes
= (0 == length
) ? (const void *)"" : CFDataGetBytePtr(G_prelink_data
);
455 success
= _IOWriteBytesToFile("prelinkstate", bytes
, length
);
458 kload_log_error("write prelinkstate" KNL
);
459 result
= kload_error_link_load
;
461 length
= CFDataGetLength(G_prelink_dependencies
);
462 bytes
= (0 == length
) ? (const void *)"" : CFDataGetBytePtr(G_prelink_dependencies
);
463 success
= _IOWriteBytesToFile("prelinkdependencies", bytes
, length
);
466 kload_log_error("write prelinkdependencies" KNL
);
467 result
= kload_error_link_load
;
470 #endif /* not KERNEL */
476 /*******************************************************************************
477 * This function claims the option flags d and D for object file dependencies
478 * and in-kernel dependencies, respectively.
479 *******************************************************************************/
480 kload_error
kload_load_with_arglist(
481 int argc
, char **argv
,
482 const char * kernel_file
,
483 const char * patch_file
, const char * patch_dir
,
484 const char * symbol_file
, const char * symbol_dir
,
485 int do_load
, int do_start_kmod
,
486 int interactive_level
,
487 int ask_overwrite_symbols
, int overwrite_symbols
)
489 kload_error result
= kload_error_none
;
490 dgraph_error_t dgraph_result
;
491 int syms_only
= (!do_load
) && (symbol_file
|| symbol_dir
);
493 static dgraph_t dependency_graph
;
495 /* Zero out fields in dependency graph for proper error handling later.
497 bzero(&dependency_graph
, sizeof(dependency_graph
));
499 dgraph_result
= dgraph_init_with_arglist(&dependency_graph
,
500 syms_only
, "-d", "-D", argc
, argv
);
501 if (dgraph_result
== dgraph_error
) {
502 kload_log_error("error processing dependency list" KNL
);
503 result
= kload_error_unspecified
;
505 } else if (dgraph_result
== dgraph_invalid
) {
506 // anything to print here, or did init call print something?
507 result
= kload_error_invalid_argument
;
511 result
= kload_load_dgraph(&dependency_graph
, kernel_file
,
512 patch_file
, patch_dir
, symbol_file
, symbol_dir
,
513 do_load
, do_start_kmod
, false /* do_prelink */, interactive_level
,
514 ask_overwrite_symbols
, overwrite_symbols
);
519 #endif /* not KERNEL */
520 /*******************************************************************************
521 * This function can only operate on 32 bit mach object file symbol table
523 *******************************************************************************/
525 kload_error
__kload_keep_symbols(dgraph_entry_t
* entry
)
527 struct mach_header
* hdr
;
528 struct segment_command
* seg
;
530 struct symtab_command
* symcmd
;
531 unsigned long idx
, ncmds
;
536 return kload_error_none
;
538 hdr
= entry
->linked_image
;
540 seg
= (struct segment_command
*)(hdr
+ 1);
543 idx
++, seg
= (struct segment_command
*)(((vm_offset_t
)seg
) + seg
->cmdsize
))
545 if (LC_SYMTAB
== seg
->cmd
)
550 kload_log_error("no LC_SYMTAB" KNL
);
551 return kload_error_unspecified
;
554 symcmd
= (struct symtab_command
*) seg
;
557 struct mach_header hdr
;
558 struct segment_command seg
;
559 struct symtab_command symcmd
;
561 struct load_cmds
* cmd
;
562 unsigned int symtabsize
;
564 symtabsize
= symcmd
->stroff
+ symcmd
->strsize
- symcmd
->symoff
;
566 size
= sizeof(struct load_cmds
) + symtabsize
;
568 mem
= (vm_offset_t
) malloc(size
);
570 cmd
= (struct load_cmds
*) mem
;
571 sym
= (struct nlist
*) (cmd
+ 1);
574 cmd
->symcmd
= *symcmd
;
575 bcopy((const void *) (((vm_offset_t
) hdr
) + symcmd
->symoff
),
579 hdr
= (struct mach_header
*) mem
;
581 cmd
->hdr
.sizeofcmds
= sizeof(struct load_cmds
) - sizeof(struct mach_header
);
582 cmd
->hdr
.flags
&= ~MH_INCRLINK
;
584 cmd
->symcmd
.stroff
-= (symcmd
->symoff
- sizeof(struct load_cmds
));
585 cmd
->symcmd
.symoff
= sizeof(struct load_cmds
);
587 cmd
->seg
.cmd
= LC_SEGMENT
;
588 cmd
->seg
.cmdsize
= sizeof(struct segment_command
);
589 strcpy(cmd
->seg
.segname
, SEG_LINKEDIT
);
592 cmd
->seg
.fileoff
= cmd
->symcmd
.symoff
;
593 cmd
->seg
.filesize
= symtabsize
;
594 cmd
->seg
.maxprot
= 7;
595 cmd
->seg
.initprot
= 1;
599 sym
= (struct nlist
*) (cmd
+ 1);
600 for (idx
= 0; idx
< symcmd
->nsyms
; idx
++, sym
++)
602 if ( (sym
->n_type
& N_STAB
) != 0)
606 sym
->n_value
= sym
->n_un
.n_strx
;
607 sym
->n_un
.n_strx
= 0;
608 sym
->n_sect
= NO_SECT
;
610 else if ( (sym
->n_type
& N_TYPE
) == N_SECT
)
612 sym
->n_sect
= NO_SECT
;
613 sym
->n_type
= (sym
->n_type
& ~N_TYPE
) | N_ABS
;
616 if (log_level
>= kload_log_level_load_details
)
618 kload_log_message("__kload_keep_symbols %s, nsyms %ld, 0x%x bytes" KNL
,
619 entry
->name
, symcmd
->nsyms
, size
);
622 entry
->symbols
= mem
;
623 entry
->symbols_malloc
= mem
;
624 entry
->symbols_length
= size
;
626 return kload_error_none
;
630 /*******************************************************************************
631 * This function can only operate on 32 bit mach object files
632 *******************************************************************************/
634 kload_error
__kload_make_opaque_basefile(dgraph_t
* dgraph
, struct mach_header
* hdr
)
636 struct segment_command
* seg
;
637 struct segment_command
* data_seg
;
638 struct segment_command
* text_seg
;
639 struct section
* sec
;
642 unsigned long idx
, ncmds
;
644 vm_address_t mem
, out
;
645 static vm_address_t keep_base_image
;
646 static vm_size_t keep_base_size
;
648 if (dgraph
->opaque_base_image
)
649 return kload_error_none
;
653 dgraph
->opaque_base_image
= keep_base_image
;
654 dgraph
->opaque_base_length
= keep_base_size
;
655 return kload_error_none
;
658 data_seg
= text_seg
= NULL
;
660 seg
= (struct segment_command
*)(hdr
+ 1);
663 idx
++, seg
= (struct segment_command
*)(((vm_offset_t
)seg
) + seg
->cmdsize
))
665 if (LC_SEGMENT
!= seg
->cmd
)
667 if (!strcmp(SEG_TEXT
, seg
->segname
))
669 else if (!strcmp(SEG_DATA
, seg
->segname
))
672 if (!text_seg
|| !data_seg
)
674 kload_log_error("no SEG_TEXT or SEG_DATA" KNL
);
675 return kload_error_unspecified
;
678 size
= sizeof(struct mach_header
) + text_seg
->cmdsize
+ data_seg
->cmdsize
;
679 mem
= (vm_offset_t
) malloc(size
);
682 bcopy(hdr
, (void *) out
, sizeof(struct mach_header
));
683 hdr
= (struct mach_header
*) out
;
684 out
+= sizeof(struct mach_header
);
686 bcopy(text_seg
, (void *) out
, text_seg
->cmdsize
);
687 text_seg
= (struct segment_command
*) out
;
688 out
+= text_seg
->cmdsize
;
690 bcopy(data_seg
, (void *) out
, data_seg
->cmdsize
);
691 data_seg
= (struct segment_command
*) out
;
692 out
+= data_seg
->cmdsize
;
695 hdr
->sizeofcmds
= text_seg
->cmdsize
+ data_seg
->cmdsize
;
697 offset
= hdr
->sizeofcmds
;
699 text_seg
->fileoff
= offset
;
700 text_seg
->filesize
= 0;
702 sec
= (struct section
*)(text_seg
+ 1);
703 for (j
= 0; j
< text_seg
->nsects
; j
++, sec
++)
705 // sec->addr = (unsigned long) addr;
707 sec
->offset
= offset
;
711 data_seg
->fileoff
= offset
;
712 data_seg
->filesize
= 0;
714 sec
= (struct section
*)(data_seg
+ 1);
715 for (j
= 0; j
< data_seg
->nsects
; j
++, sec
++)
717 // sec->addr = (unsigned long) addr;
719 sec
->offset
= offset
;
723 dgraph
->opaque_base_image
= mem
;
724 dgraph
->opaque_base_length
= size
;
725 keep_base_image
= mem
;
726 keep_base_size
= size
;
728 return kload_error_none
;
731 /*******************************************************************************
733 *******************************************************************************/
735 kload_error
__kload_load_modules(dgraph_t
* dgraph
738 const char * kernel_file
,
739 const char * patch_file
,
740 const char * patch_dir
,
741 const char * symbol_file
,
742 const char * symbol_dir
,
746 int interactive_level
,
747 int ask_overwrite_symbols
,
748 int overwrite_symbols
749 #endif /* not KERNEL */
752 kload_error result
= kload_error_none
;
754 long int kernel_size
= 0;
755 kern_return_t mach_result
= KERN_SUCCESS
;
756 #endif /* not KERNEL */
757 char * kernel_base_addr
= 0;
759 Boolean cleanup_kld_loader
= 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 const char * kernel_file
= "(kernel)";
825 kernel_base_addr
= (char *) &_mh_execute_header
;
827 #endif /* not KERNEL */
830 if (dgraph
->has_symbol_sets
)
832 result
= __kload_make_opaque_basefile(dgraph
, (struct mach_header
*) kernel_base_addr
);
833 if (result
!= kload_error_none
) {
834 kload_log_error("can't construct opaque base image from %s" KNL
, kernel_file
);
838 kld_result
= kld_load_basefile_from_memory(kernel_file
,
839 (char *) dgraph
->opaque_base_image
,
840 dgraph
->opaque_base_length
);
844 kld_result
= kld_load_basefile_from_memory(kernel_file
,
845 (char *) kernel_base_addr
, kernel_size
);
846 #endif /* not KERNEL */
849 kload_log_error("can't link base image %s" KNL
, kernel_file
);
850 result
= kload_error_link_load
;
854 cleanup_kld_loader
= true;
855 char opaque_now
= false;
857 for (i
= 0; i
< dgraph
->length
; i
++) {
858 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
860 opaque_now
|= current_entry
->opaque_link
;
862 if (kOpaqueLink
& opaque_now
)
866 if (log_level
>= kload_log_level_load_details
)
868 kload_log_message("opaque link for %s" KNL
, current_entry
->name
);
871 kld_set_link_options(KLD_STRIP_ALL
); // KLD_STRIP_NONE
873 if (dgraph
->have_loaded_symbols
)
876 if (kRawKernelLink
& current_entry
->opaque_link
) {
878 kld_result
= kld_load_basefile_from_memory(kernel_file
,
879 (char *) kernel_base_addr
, kernel_size
);
882 kld_result
= kld_load_basefile_from_memory(kernel_file
,
883 (char *) dgraph
->opaque_base_image
,
884 dgraph
->opaque_base_length
);
885 dgraph
->have_loaded_symbols
= false;
888 kload_log_error("can't link base image %s" KNL
, kernel_file
);
889 result
= kload_error_link_load
;
894 for (j
= 0; j
< i
; j
++)
897 dgraph_entry_t
* image_dep
= dgraph
->load_order
[j
];
899 if (current_entry
->opaque_link
)
902 (k
< current_entry
->num_dependencies
)
903 && (current_entry
->dependencies
[k
] != image_dep
);
906 if (k
== current_entry
->num_dependencies
)
910 if (!current_entry
->opaque_link
&& image_dep
->opaques
)
912 // kpi not on direct dependency list
915 if (kRawKernelLink
& image_dep
->opaques
)
917 // raw kernel already in base image
921 if (!image_dep
->symbols
)
923 kload_log_error("internal error; no dependent symbols" KNL
);
924 result
= kload_error_link_load
;
929 struct mach_header
* kld_header
;
932 kld_result
= kld_load_from_memory(&kld_header
, image_dep
->name
,
933 (char *) image_dep
->symbols
, image_dep
->symbols_length
, NULL
);
935 kld_result
= kld_load_from_memory(&kld_header
, image_dep
->name
,
936 (char *) image_dep
->symbols
, image_dep
->symbols_length
);
937 #endif /* not KERNEL */
939 kload_log_error("can't link dependent image %s" KNL
, image_dep
->name
);
940 result
= kload_error_link_load
;
943 kld_forget_symbol("_kmod_info");
944 dgraph
->have_loaded_symbols
= true;
949 if (dgraph
->has_opaque_links
951 || symbol_file
|| symbol_dir
954 kld_set_link_options(KLD_STRIP_NONE
);
956 kld_set_link_options(KLD_STRIP_ALL
);
959 result
= __kload_load_module(dgraph
, current_entry
,
960 (current_entry
== dgraph
->root
),
961 symbol_file
, symbol_dir
, do_load
,
962 interactive_level
, ask_overwrite_symbols
, overwrite_symbols
);
964 result
= __kload_load_module(dgraph
, current_entry
,
965 (current_entry
== dgraph
->root
));
966 #endif /* not KERNEL */
967 if (result
!= kload_error_none
) {
971 if (dgraph
->has_opaque_links
&& (current_entry
!= dgraph
->root
))
973 if (!(kRawKernelLink
& current_entry
->opaques
)) {
974 result
= __kload_keep_symbols(current_entry
);
976 if (result
!= kload_error_none
) {
977 kload_log_error("__kload_keep_symbols() failed for module %s" KNL
,
978 current_entry
->name
);
984 if (do_load
&& current_entry
->do_load
) {
986 if (current_entry
->do_load
) {
987 #endif /* not KERNEL */
988 result
= __kload_set_module_dependencies(current_entry
);
989 if ( ! (result
== kload_error_none
||
990 result
== kload_error_already_loaded
) ) {
995 if ( (interactive_level
== 1 && current_entry
== dgraph
->root
) ||
996 (interactive_level
== 2) ) {
998 int approve
= (*__kload_approve_func
)(1,
999 "\nStart module %s (ansering no will abort the load)",
1000 current_entry
->name
);
1003 do_start_kmod
= true; // override 'cause user said so
1005 kern_return_t mach_result
;
1007 kload_log_message("error reading user response; "
1008 "destroying loaded module" KNL
);
1010 kload_log_message("user canceled module start; "
1011 "destroying loaded module" KNL
);
1013 mach_result
= kmod_destroy(G_kernel_priv_port
, current_entry
->kmod_id
);
1014 if (mach_result
!= KERN_SUCCESS
) {
1015 kload_log_error("kmod_destroy() failed" KNL
);
1018 result
= kload_error_unspecified
;
1021 result
= kload_error_user_abort
;
1026 #endif /* not KERNEL */
1029 if (current_entry
!= dgraph
->root
||
1030 (current_entry
== dgraph
->root
&& do_start_kmod
)) {
1031 #endif /* not KERNEL */
1033 result
= __kload_start_module(current_entry
);
1034 if ( ! (result
== kload_error_none
||
1035 result
== kload_error_already_loaded
) ) {
1038 } else if (interactive_level
||
1039 log_level
>= kload_log_level_load_details
) {
1041 } else if (log_level
>= kload_log_level_load_details
) {
1042 #endif /* not KERNEL */
1044 kload_log_message("started module %s" KNL
,
1045 current_entry
->name
);
1048 } /* current_entry... */
1049 #endif /* not KERNEL */
1056 #endif /* not KERNEL */
1057 } /* for i, dgraph->length */
1062 /* Dispose of the kernel port to prevent security breaches and port
1063 * leaks. We don't care about the kern_return_t value of this
1064 * call for now as there's nothing we can do if it fails.
1066 if (PORT_NULL
!= G_kernel_port
) {
1067 mach_port_deallocate(mach_task_self(), G_kernel_port
);
1068 G_kernel_port
= PORT_NULL
;
1070 #endif /* not KERNEL */
1072 if (cleanup_kld_loader
) {
1080 /*******************************************************************************
1082 *******************************************************************************/
1085 #define __KLOAD_SYMBOL_EXTENSION ".sym"
1086 #endif /* not KERNEL */
1089 kload_error
__kload_load_module(dgraph_t
* dgraph
,
1090 dgraph_entry_t
* entry
,
1092 __unused
int is_root
1093 #else /* not KERNEL */
1095 const char * symbol_file
,
1096 const char * symbol_dir
,
1098 int interactive_level
,
1099 int ask_overwrite_symbols
,
1100 int overwrite_symbols
1101 #endif /* not KERNEL */
1104 kload_error result
= kload_error_none
;
1108 struct mach_header
* kld_header
;
1109 const char * kmod_symbol
= "_kmod_info";
1110 unsigned long kernel_kmod_info
;
1111 kmod_info_t
* local_kmod_info
= NULL
;
1112 char * dest_address
= 0;
1114 char * allocated_filename
= NULL
;
1115 char * symbol_filename
= NULL
;
1117 vm_address_t vm_buffer
= 0;
1118 #endif /* not KERNEL */
1120 /* A kernel component is by nature already linked and loaded and has
1121 * no work to be done upon it.
1123 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1124 result
= kload_error_none
;
1128 G_current_load_entry
= entry
;
1130 if (log_level
>= kload_log_level_load_basic
) {
1133 #endif /* not KERNEL */
1134 kload_log_message("link/loading file %s" KNL
, entry
->name
);
1137 kload_log_message("linking file %s" KNL
, entry
->name
);
1139 #endif /* not KERNEL */
1143 if (entry
->link_output_file
!= entry
->name
) {
1144 symbol_filename
= entry
->link_output_file
;
1147 if (symbol_filename
) {
1148 file_check
= kload_file_exists(symbol_filename
);
1149 if (file_check
< 0) {
1150 kload_log_error("error checking existence of file %s" KNL
,
1152 } else if (file_check
> 0 && !overwrite_symbols
) {
1154 if (!ask_overwrite_symbols
) {
1155 kload_log_message("symbol file %s exists; not overwriting" KNL
,
1157 symbol_filename
= NULL
;
1159 int approve
= (*__kload_approve_func
)(1,
1160 "\nSymbol file %s exists; overwrite", symbol_filename
);
1163 result
= kload_error_unspecified
;
1165 } else if (approve
== 0) {
1166 if (allocated_filename
) free(allocated_filename
);
1167 allocated_filename
= NULL
;
1168 symbol_filename
= NULL
;
1174 if (symbol_filename
&&
1175 (interactive_level
||
1176 log_level
>= kload_log_level_basic
) ) {
1178 kload_log_message("writing symbol file %s" KNL
, symbol_filename
);
1182 if (interactive_level
&& entry
->loaded_address
) {
1184 "module %s is already loaded as %s at address 0x%08x" KNL
,
1185 entry
->name
, entry
->expected_kmod_name
,
1186 entry
->loaded_address
);
1187 } else if ( (interactive_level
== 1 && is_root
) ||
1188 (interactive_level
== 2) ) {
1190 int approve
= (*__kload_approve_func
)(1,
1191 "\nLoad module %s", entry
->name
);
1194 result
= kload_error_unspecified
;
1196 } else if (approve
== 0) {
1197 result
= kload_error_user_abort
;
1202 #endif /* not KERNEL */
1204 entry
->object
= kld_file_getaddr(entry
->name
, &entry
->object_length
);
1205 if (!entry
->object
) {
1206 kload_log_error("kld_file_getaddr() failed for module %s" KNL
,
1208 __kload_clear_kld_globals();
1209 result
= kload_error_link_load
;
1213 if (entry
->is_symbol_set
) {
1214 entry
->symbols
= (vm_address_t
) entry
->object
;
1215 entry
->symbols_length
= entry
->object_length
;
1218 if (symbol_filename
) {
1219 if (!_IOWriteBytesToFile(symbol_filename
, (void *) entry
->symbols
, entry
->symbols_length
)) {
1220 kload_log_error("write symbol file failed for module %s" KNL
,
1222 __kload_clear_kld_globals();
1223 result
= kload_error_link_load
;
1226 symbol_filename
= 0;
1227 if (G_prelink
&& (entry
->name
!= entry
->link_output_file
))
1229 kload_log_error("prelink %s %s %s" KNL
,
1230 entry
->name
, entry
->link_output_file
, entry
->expected_kmod_name
);
1231 register_prelink(entry
, NULL
, NULL
);
1234 #endif /* not KERNEL */
1235 if (entry
->opaques
) {
1236 result
= kload_error_none
;
1242 kld_result
= kld_load_from_memory(&kld_header
, entry
->name
,
1243 entry
->object
, entry
->object_length
, symbol_filename
);
1245 kld_result
= kld_load_from_memory(&kld_header
, entry
->name
,
1246 entry
->object
, entry
->object_length
);
1247 #endif /* not KERNEL */
1252 #endif /* not KERNEL */
1254 dgraph
->have_loaded_symbols
= true;
1256 if (!kld_result
|| !entry
->kernel_load_address
) {
1257 kload_log_error("kld_load_from_memory() failed for module %s" KNL
,
1259 __kload_clear_kld_globals();
1260 entry
->need_cleanup
= 1;
1261 result
= kload_error_link_load
;
1265 if (entry
->is_symbol_set
) {
1266 result
= kload_error_none
;
1270 entry
->linked_image
= kld_header
;
1271 entry
->linked_image_length
= -1; // unknown!
1273 /* If we're in the kernel and not loading (as when handling an
1274 * already-loaded dependency), we don't need to waste any CPU
1275 * cycles looking up the kmod_info struct.
1278 if (entry
->do_load
) {
1281 kld_result
= kld_lookup(kmod_symbol
, &kernel_kmod_info
);
1283 kload_log_error("kld_lookup(\"%s\") failed for module %s" KNL
,
1284 kmod_symbol
, entry
->name
);
1285 entry
->need_cleanup
= 1;
1286 result
= kload_error_link_load
;
1294 kld_result
= kld_forget_symbol(kmod_symbol
);
1298 #endif /* not KERNEL */
1300 kload_log_error("kld_forget_symbol(\"%s\") failed for module %s" KNL
,
1301 kmod_symbol
, entry
->name
);
1302 entry
->need_cleanup
= 1;
1303 result
= kload_error_link_load
;
1307 /* This section is always done in userland, but in kernel space
1308 * only if we're loading the kext, because what we have in kernel
1309 * space for an already-loaded kext is the kext itself, which
1310 * must not be touched again after it's been loaded and started.
1318 /* Get the linked image's kmod_info by translating from the
1319 * destined kernel-space address at kernel_kmod_info to an
1320 * offset from kld_header.
1322 local_kmod_info
= (kmod_info_t
*)((unsigned long)kernel_kmod_info
-
1323 (unsigned long)G_current_load_entry
->kernel_load_address
+
1324 (unsigned long)kld_header
);
1326 /* Stamp the bundle ID and version from the entry over anything
1327 * resident inside the kmod.
1329 bzero(local_kmod_info
->name
, sizeof(local_kmod_info
->name
));
1330 strcpy(local_kmod_info
->name
, entry
->expected_kmod_name
);
1332 bzero(local_kmod_info
->version
, sizeof(local_kmod_info
->version
));
1333 strcpy(local_kmod_info
->version
, entry
->expected_kmod_vers
);
1335 if (log_level
>= kload_log_level_details
) {
1336 kload_log_message("kmod name: %s" KNL
, local_kmod_info
->name
);
1337 kload_log_message("kmod start @ 0x%x (offset 0x%lx)" KNL
,
1338 (vm_address_t
)local_kmod_info
->start
,
1339 (unsigned long)local_kmod_info
->start
- (unsigned long)G_current_load_entry
->kernel_load_address
);
1340 kload_log_message("kmod stop @ 0x%x (offset 0x%lx)" KNL
,
1341 (vm_address_t
)local_kmod_info
->stop
,
1342 (unsigned long)local_kmod_info
->stop
- (unsigned long)G_current_load_entry
->kernel_load_address
);
1345 if (!local_kmod_info
->start
|| !local_kmod_info
->start
) {
1347 "error for module file %s; start or stop address is zero" KNL
,
1349 entry
->need_cleanup
= 1;
1350 result
= kload_error_link_load
;
1354 /* Record link info into kmod_info struct, rounding the hdr_size
1355 * to fit the adjustment that was made in __kload_linkedit_address().
1357 if (entry
->kernel_alloc_address
) {
1358 local_kmod_info
->address
= entry
->kernel_alloc_address
;
1360 local_kmod_info
->address
= entry
->loaded_address
;
1362 local_kmod_info
->size
= entry
->kernel_alloc_size
;
1363 local_kmod_info
->hdr_size
= round_page(entry
->kernel_hdr_size
);
1368 if (G_prelink
&& (entry
->name
!= entry
->link_output_file
))
1370 register_prelink(entry
, local_kmod_info
, kernel_kmod_info
);
1373 if (do_load
&& entry
->do_load
) {
1374 mach_result
= vm_allocate(mach_task_self(), &vm_buffer
,
1375 entry
->kernel_alloc_size
, VM_FLAGS_ANYWHERE
);
1376 if (mach_result
!= KERN_SUCCESS
) {
1377 kload_log_error("unable to vm_allocate() copy buffer" KNL
);
1378 entry
->need_cleanup
= 1;
1379 result
= kload_error_no_memory
; // FIXME: kernel error?
1383 dest_address
= (char *)vm_buffer
;
1385 memcpy(dest_address
, kld_header
, entry
->kernel_hdr_size
);
1386 memcpy(dest_address
+ round_page(entry
->kernel_hdr_size
),
1387 (void *)((unsigned long)kld_header
+ entry
->kernel_hdr_size
),
1388 entry
->kernel_load_size
- entry
->kernel_hdr_size
);
1390 mach_result
= vm_write(G_kernel_port
, entry
->kernel_alloc_address
,
1391 vm_buffer
, entry
->kernel_alloc_size
);
1392 if (mach_result
!= KERN_SUCCESS
) {
1393 kload_log_error("unable to write module to kernel memory" KNL
);
1394 entry
->need_cleanup
= 1;
1395 result
= kload_error_kernel_error
;
1399 mach_result
= kmod_create(G_kernel_priv_port
,
1400 (vm_address_t
)kernel_kmod_info
, &(entry
->kmod_id
));
1403 if (entry
->do_load
) {
1404 dest_address
= (char *)entry
->kernel_alloc_address
;
1405 memcpy(dest_address
, kld_header
, entry
->kernel_hdr_size
);
1406 memcpy(dest_address
+ round_page(entry
->kernel_hdr_size
),
1407 (void *)((unsigned long)kld_header
+ entry
->kernel_hdr_size
),
1408 entry
->kernel_load_size
- entry
->kernel_hdr_size
);
1410 /* We've written data & instructions into kernel memory, so flush
1411 * the data cache and invalidate the instruction cache.
1413 flush_dcache(entry
->kernel_alloc_address
, entry
->kernel_alloc_size
, false);
1414 invalidate_icache(entry
->kernel_alloc_address
, entry
->kernel_alloc_size
, false);
1416 mach_result
= kmod_create_internal(
1417 (kmod_info_t
*)kernel_kmod_info
, &(entry
->kmod_id
));
1419 #endif /* not KERNEL */
1421 if (mach_result
!= KERN_SUCCESS
) {
1422 kload_log_error("unable to register module with kernel" KNL
);
1423 entry
->need_cleanup
= 1;
1424 result
= kload_error_kernel_error
;
1429 if (interactive_level
|| log_level
>= kload_log_level_load_basic
) {
1431 if (log_level
>= kload_log_level_load_basic
) {
1432 #endif /* not KERNEL */
1434 "module %s created as # %d at address 0x%x, size %ld" KNL
,
1435 entry
->expected_kmod_name
, entry
->kmod_id
,
1436 entry
->kernel_alloc_address
,
1437 entry
->kernel_alloc_size
);
1443 #endif /* not KERNEL */
1446 if (interactive_level
) {
1448 "You can now break to the debugger and set breakpoints "
1449 " for this extension." KNL
);
1451 #endif /* not KERNEL */
1457 #endif /* not KERNEL */
1462 if (allocated_filename
) {
1463 free(allocated_filename
);
1466 vm_deallocate(mach_task_self(), vm_buffer
, entry
->kernel_alloc_size
);
1468 #endif /* not KERNEL */
1469 __kload_clear_kld_globals();
1474 /*******************************************************************************
1475 *******************************************************************************/
1479 register_prelink(dgraph_entry_t
* entry
,
1480 kmod_info_t
* local_kmod_info
, vm_offset_t kernel_kmod_info
)
1482 CFIndex i
, j
, depoffset
;
1486 depoffset
= CFDataGetLength(G_prelink_dependencies
) / sizeof(CFIndex
);
1488 for (i
= 0; i
< entry
->num_dependencies
; i
++)
1491 for (j
= 1; (j
< (1 + G_prelink
->modules
[0].id
)); j
++)
1493 exists
= (0 == strcmp(entry
->dependencies
[i
]->expected_kmod_name
,
1494 G_prelink
->modules
[j
].name
));
1500 bzero(&desc
, sizeof(desc
));
1501 strcpy(desc
.name
, entry
->dependencies
[i
]->expected_kmod_name
);
1503 if (log_level
>= kload_log_level_basic
) {
1504 kload_log_message("[%d] (dep)\n %s" KNL
,
1505 G_prelink
->modules
[0].id
+ 1, desc
.name
);
1507 G_prelink
->modules
[0].id
++;
1508 CFDataAppendBytes(G_prelink_data
, (UInt8
*) &desc
, sizeof(desc
));
1509 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
1512 G_prelink
->modules
[0].reference_count
++;
1513 OSWriteBigInt32(&j
, 0, j
);
1514 CFDataAppendBytes(G_prelink_dependencies
, (UInt8
*) &j
, sizeof(j
));
1516 if (log_level
>= kload_log_level_basic
) {
1517 kload_log_message("[%d] 0x%08x info 0x%08x\n %s,\n %s" KNL
,
1518 G_prelink
->modules
[0].id
+ 1, entry
->kernel_load_address
,
1519 kernel_kmod_info
, entry
->link_output_file
, entry
->name
);
1522 if (local_kmod_info
)
1523 desc
= *local_kmod_info
;
1526 bzero(&desc
, sizeof(desc
));
1527 desc
.size
= entry
->symbols_length
;
1530 desc
.id
= kernel_kmod_info
;
1531 desc
.reference_count
= entry
->num_dependencies
;
1532 desc
.reference_list
= (kmod_reference_t
*) depoffset
;
1534 /* Stamp the bundle ID and version from the entry over anything
1535 * resident inside the kmod.
1537 bzero(desc
.name
, sizeof(local_kmod_info
->name
));
1538 strcpy(desc
.name
, entry
->expected_kmod_name
);
1539 bzero(desc
.version
, sizeof(local_kmod_info
->version
));
1540 strcpy(desc
.version
, entry
->expected_kmod_vers
);
1542 G_prelink
->modules
[0].id
++;
1543 CFDataAppendBytes(G_prelink_data
, (UInt8
*) &desc
, sizeof(desc
));
1544 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
1546 return kload_error_none
;
1551 /*******************************************************************************
1553 *******************************************************************************/
1556 kload_error
kload_map_dgraph(
1558 const char * kernel_file
)
1560 kload_error
kload_map_dgraph(
1562 #endif /* not KERNEL */
1564 kload_error result
= kload_error_none
;
1567 if (log_level
>= kload_log_level_load_details
) {
1569 kload_log_message("mapping the kernel file %s" KNL
, kernel_file
);
1571 kload_log_message("mapping the kernel" KNL
);
1572 #endif /* not KERNEL */
1576 if (!kld_file_map(kernel_file
)) {
1577 result
= kload_error_link_load
;
1580 #endif /* not KERNEL */
1582 for (i
= 0; i
< dgraph
->length
; i
++) {
1583 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1585 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1589 result
= kload_map_entry(entry
);
1590 if (result
!= kload_error_none
) {
1600 /*******************************************************************************
1602 *******************************************************************************/
1604 kload_error
kload_map_entry(dgraph_entry_t
* entry
)
1606 kload_error result
= kload_error_none
;
1608 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1609 kload_log_error("attempt to map kernel component %s" KNL
, entry
->name
);
1610 result
= kload_error_invalid_argument
;
1614 if (log_level
>= kload_log_level_load_details
) {
1615 kload_log_message("mapping module file %s" KNL
, entry
->name
);
1618 if (kld_file_getaddr(entry
->name
, NULL
)) {
1619 if (log_level
>= kload_log_level_load_details
) {
1620 kload_log_message("module file %s is already mapped" KNL
, entry
->name
);
1622 result
= kload_error_none
;
1627 if (!kld_file_map(entry
->name
)) {
1629 if (!kld_file_map(entry
->name
, entry
->object
, entry
->object_length
,
1630 entry
->object_is_kmem
)) {
1631 #endif /* not KERNEL */
1632 kload_log_error("error mapping module file %s" KNL
, entry
->name
);
1634 result
= kload_error_link_load
;
1640 #endif /* not KERNEL */
1642 entry
->is_mapped
= true;
1644 /* Clear these bits now, as the kld patch module now owns the info
1645 * and it is subject to change. We reset them in the entry from the
1646 * kld patch module as needed.
1649 entry
->object_length
= 0;
1651 entry
->object_is_kmem
= false;
1654 // FIXME: Stop using this symbol; have the info passed in by
1655 // FIXME: ...the kext management library.
1657 if (!entry
->is_kernel_component
&& !kld_file_lookupsymbol(entry
->name
, "_kmod_info")) {
1658 kload_log_error("%s does not not contain kernel extension code" KNL
,
1660 result
= kload_error_executable_bad
;
1663 #endif /* not KERNEL */
1670 /*******************************************************************************
1672 *******************************************************************************/
1673 kload_error
kload_request_load_addresses(
1675 const char * kernel_file
)
1677 kload_error result
= kload_error_none
;
1679 const char * user_response
= NULL
; // must free
1681 unsigned int address
;
1683 /* We have to map all object files to get their CFBundleIdentifier
1686 result
= kload_map_dgraph(dgraph
, kernel_file
);
1687 if (result
!= kload_error_none
) {
1688 kload_log_error("error mapping object files" KNL
);
1692 // fixme: this shouldn't be printf, should it?
1693 printf("enter the hexadecimal load addresses for these modules:\n");
1695 for (i
= 0; i
< dgraph
->length
; i
++) {
1696 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1699 result
= kload_error_unspecified
;
1703 if (entry
->is_kernel_component
) {
1707 if (!entry
->is_mapped
) {
1708 result
= kload_error_unspecified
;
1712 user_response
= __kload_input_func("%s:",
1713 entry
->expected_kmod_name
);
1714 if (!user_response
) {
1715 result
= kload_error_unspecified
;
1718 scan_result
= sscanf(user_response
, "%x", &address
);
1719 if (scan_result
< 1 || scan_result
== EOF
) {
1720 result
= kload_error_unspecified
;
1723 entry
->loaded_address
= address
;
1731 /*******************************************************************************
1732 * addresses is a NULL-terminated list of string of the form "module_id@address"
1733 *******************************************************************************/
1734 kload_error
kload_set_load_addresses_from_args(
1736 const char * kernel_file
,
1739 kload_error result
= kload_error_none
;
1743 /* We have to map all object files to get their CFBundleIdentifier
1746 result
= kload_map_dgraph(dgraph
, kernel_file
);
1747 if (result
!= kload_error_none
) {
1748 kload_log_error("error mapping object files" KNL
);
1753 * Run through and assign all addresses to their relevant module
1756 for (i
= 0; i
< dgraph
->length
; i
++) {
1757 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1760 result
= kload_error_unspecified
;
1764 if (entry
->is_kernel_component
) {
1768 if (!entry
->is_mapped
) {
1769 result
= kload_error_unspecified
;
1773 for (j
= 0; addresses
[j
]; j
++) {
1774 char * this_addr
= addresses
[j
];
1775 char * address_string
= NULL
;
1776 unsigned int address
;
1777 unsigned int module_namelen
= strlen(entry
->expected_kmod_name
);
1780 result
= kload_error_unspecified
;
1784 if (strncmp(this_addr
, entry
->expected_kmod_name
, module_namelen
)) {
1787 if (this_addr
[module_namelen
] != '@') {
1791 address_string
= index(this_addr
, '@');
1792 if (!address_string
) {
1793 result
= kload_error_unspecified
;
1797 address
= strtoul(address_string
, NULL
, 16);
1798 entry
->loaded_address
= address
;
1803 * Now that we've done that see that all non-kernel modules do have
1804 * addresses set. If even one doesn't, we can't complete the link
1805 * relocation of symbols, so return a usage error.
1807 for (i
= 0; i
< dgraph
->length
; i
++) {
1808 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1810 if (entry
->is_kernel_component
) {
1814 if (!entry
->loaded_address
) {
1815 result
= kload_error_invalid_argument
;
1825 /*******************************************************************************
1826 * This function requires G_kernel_priv_port to be set before it will work.
1827 *******************************************************************************/
1828 kload_error
kload_set_load_addresses_from_kernel(
1830 const char * kernel_file
,
1833 kload_error result
= kload_error_none
;
1835 kmod_info_t
* loaded_modules
= NULL
;
1836 int loaded_bytecount
= 0;
1841 * We have to map the dgraph's modules before checking whether they've
1844 result
= kload_map_dgraph(dgraph
, kernel_file
);
1845 if (result
!= kload_error_none
) {
1846 kload_log_error("can't map module files" KNL
);
1851 /* First clear all the load addresses.
1853 for (i
= 0; i
< dgraph
->length
; i
++) {
1854 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1855 entry
->loaded_address
= 0;
1858 mach_result
= kmod_get_info(G_kernel_priv_port
,
1859 (void *)&loaded_modules
, &loaded_bytecount
);
1860 if (mach_result
!= KERN_SUCCESS
) {
1861 kload_log_error("kmod_get_info() failed" KNL
);
1862 result
= kload_error_kernel_error
;
1867 * Find out which modules have already been loaded & verify
1868 * that loaded versions are same as requested.
1870 for (i
= 0; i
< dgraph
->length
; i
++) {
1871 kload_error cresult
;
1872 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
1874 /* If necessary, check whether the current module is already loaded.
1875 * (We already did the root module above.)
1877 cresult
= __kload_check_module_loaded(dgraph
, current_entry
,
1878 loaded_modules
, do_load
);
1879 if ( ! (cresult
== kload_error_none
||
1880 cresult
== kload_error_already_loaded
) ) {
1883 if (current_entry
== dgraph
->root
&&
1884 cresult
== kload_error_already_loaded
) {
1892 if (loaded_modules
) {
1893 vm_deallocate(mach_task_self(), (vm_address_t
)loaded_modules
,
1902 /*******************************************************************************
1904 *******************************************************************************/
1906 kload_error
kload_set_load_addresses_from_kernel(
1909 kload_error result
= kload_error_none
;
1912 kmod_info_t
* loaded_modules
= NULL
;
1913 int loaded_bytecount
= 0;
1914 #endif /* not KERNEL */
1919 * We have to map the dgraph's modules before checking whether they've
1922 result
= kload_map_dgraph(dgraph
);
1923 if (result
!= kload_error_none
) {
1924 kload_log_error("can't map module files" KNL
);
1929 /* First clear all the load addresses.
1931 for (i
= 0; i
< dgraph
->length
; i
++) {
1932 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1933 entry
->loaded_address
= 0;
1937 * Find out which modules have already been loaded & verify
1938 * that loaded versions are same as requested.
1940 for (i
= 0; i
< dgraph
->length
; i
++) {
1941 kload_error cresult
;
1942 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
1944 /* If necessary, check whether the current module is already loaded.
1945 * (We already did the root module above.)
1947 cresult
= __kload_check_module_loaded(dgraph
, current_entry
, false);
1948 if ( ! (cresult
== kload_error_none
||
1949 cresult
== kload_error_already_loaded
) ) {
1952 if (current_entry
== dgraph
->root
&&
1953 cresult
== kload_error_already_loaded
) {
1963 #endif /* not KERNEL */
1965 /*******************************************************************************
1967 *******************************************************************************/
1969 extern kern_return_t
kmod_load_from_cache(const char * kmod_name
);
1972 static kmod_info_t
* __kload_find_kmod_info(const char * kmod_name
1975 kmod_info_t
* kmod_list
1976 #endif /* not KERNEL */
1982 for (i
= 0; ; i
++) {
1983 kmod_info_t
* current_kmod
= &(kmod_list
[i
]);
1984 if (0 == strcmp(current_kmod
->name
, kmod_name
)) {
1985 return current_kmod
;
1987 if (kmod_list
[i
].next
== 0) {
1994 info
= kmod_lookupbyname_locked(kmod_name
);
1995 if (!info
&& (KERN_SUCCESS
== kmod_load_from_cache(kmod_name
))) {
1996 info
= kmod_lookupbyname_locked(kmod_name
);
1999 #endif /* not KERNEL */
2002 /*******************************************************************************
2004 *******************************************************************************/
2006 kload_error
__kload_check_module_loaded(
2008 dgraph_entry_t
* entry
,
2010 kmod_info_t
* kmod_list
,
2011 #endif /* not KERNEL */
2014 kload_error result
= kload_error_none
;
2015 const char * kmod_name
;
2016 kmod_info_t
* current_kmod
= 0;
2018 VERS_version entry_vers
;
2019 VERS_version loaded_vers
;
2021 if (false && entry
->is_kernel_component
) {
2022 kmod_name
= entry
->name
;
2024 kmod_name
= entry
->expected_kmod_name
;
2025 if (log_level
>= kload_log_level_load_details
) {
2026 kload_log_message("checking whether module file %s is already loaded" KNL
,
2032 current_kmod
= __kload_find_kmod_info(kmod_name
, kmod_list
);
2034 current_kmod
= __kload_find_kmod_info(kmod_name
);
2035 #endif /* not KERNEL */
2037 if (!current_kmod
) {
2042 entry
->kmod_id
= current_kmod
->id
;
2043 entry
->loaded_address
= current_kmod
->address
;
2045 if (entry
->is_kernel_component
) {
2049 if (log_level
>= kload_log_level_load_details
) {
2050 kload_log_message("module file %s is loaded; checking status" KNL
,
2054 // We really want to move away from having this info in a kmod....
2056 loaded_vers
= VERS_parse_string(current_kmod
->version
);
2057 if (loaded_vers
< 0) {
2059 "can't parse version string \"%s\" of loaded module %s" KNL
,
2060 current_kmod
->version
,
2061 current_kmod
->name
);
2062 result
= kload_error_unspecified
;
2066 entry_vers
= VERS_parse_string(entry
->expected_kmod_vers
);
2067 if (entry_vers
< 0) {
2069 "can't parse version string \"%s\" of module file %s" KNL
,
2070 entry
->expected_kmod_name
,
2072 result
= kload_error_unspecified
;
2076 if (loaded_vers
!= entry_vers
) {
2078 "loaded version %s of module %s differs from "
2079 "requested version %s" KNL
,
2080 current_kmod
->version
,
2082 entry
->expected_kmod_name
);
2083 if (entry
== dgraph
->root
) {
2084 result
= kload_error_loaded_version_differs
;
2086 result
= kload_error_dependency_loaded_version_differs
;
2091 if (log_if_already
&& log_level
>=
2092 kload_log_level_load_basic
) {
2095 "module %s (identifier %s) is already loaded" KNL
,
2096 entry
->name
, kmod_name
);
2098 result
= kload_error_already_loaded
;
2104 // Do this ONLY if in the kernel!
2106 kfree(current_kmod
, sizeof(kmod_info_t
));
2112 /*******************************************************************************
2114 *******************************************************************************/
2116 kload_error
__kload_patch_dgraph(dgraph_t
* dgraph
2119 const char * kernel_file
2120 #endif /* not KERNEL */
2123 kload_error result
= kload_error_none
;
2127 if (!kld_file_merge_OSObjects(kernel_file
)) {
2128 result
= kload_error_link_load
;
2131 #endif /* not KERNEL */
2133 for (i
= 0; i
< dgraph
->length
; i
++) {
2134 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
2136 /* The kernel has already been patched.
2138 if (current_entry
->is_kernel_component
) {
2142 if (log_level
>= kload_log_level_load_details
) {
2143 kload_log_message("patching C++ code in module %s" KNL
,
2144 current_entry
->name
);
2148 /* In userland, we call the patch function for all kmods,
2149 * loaded or not, because we don't have all the info that
2150 * the kernel environment has.
2152 if (!kld_file_patch_OSObjects(current_entry
->name
)) {
2153 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2157 /* In the kernel, we call the merge function for already-loaded
2158 * kmods, since the kld patch environment retains info for kmods
2159 * that have already been patched. The patch function does a little
2160 * more work, and is only for kmods that haven't been processed yet.
2161 * NOTE: We are depending here on kload_check_module_loaded()
2162 * having been called, which is guaranteed by kload_load_dgraph()
2163 * is used, but not by its subroutines (such as
2164 * __kload_load_modules()).
2166 if (current_entry
->loaded_address
) {
2167 if (!kld_file_merge_OSObjects(current_entry
->name
)) {
2168 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2172 if (!kld_file_patch_OSObjects(current_entry
->name
)) {
2173 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2177 #endif /* not KERNEL */
2181 if (!kld_file_prepare_for_link()) {
2182 result
= kload_error_link_load
; // FIXME: need more specific error?
2191 /*******************************************************************************
2193 *******************************************************************************/
2194 #define __KLOAD_PATCH_EXTENSION ".patch"
2196 kload_error
__kload_output_patches(
2198 const char * patch_file
,
2199 const char * patch_dir
,
2200 int ask_overwrite_symbols
,
2201 int overwrite_symbols
)
2203 kload_error result
= kload_error_none
;
2205 char * allocated_filename
= NULL
;
2206 char * patch_filename
= NULL
;
2212 for (i
= 0; i
< dgraph
->length
; i
++) {
2214 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
2215 unsigned long length
;
2217 if (entry
->is_kernel_component
) {
2221 length
= strlen(patch_dir
) +
2222 strlen(entry
->expected_kmod_name
) +
2223 strlen(__KLOAD_PATCH_EXTENSION
) +
2224 1 + 1 ; // 1 for '/' added, 1 for terminating null
2225 if (length
>= MAXPATHLEN
) {
2227 "output filename \"%s/%s%s\" would be too long" KNL
,
2228 patch_dir
, entry
->expected_kmod_name
,
2229 __KLOAD_PATCH_EXTENSION
);
2230 result
= kload_error_invalid_argument
;
2234 allocated_filename
= (char *)malloc(length
);
2235 if (! allocated_filename
) {
2236 kload_log_error("malloc failure" KNL
);
2237 result
= kload_error_no_memory
;
2241 patch_filename
= allocated_filename
;
2242 strcpy(patch_filename
, patch_dir
);
2243 strcat(patch_filename
, "/");
2244 strcat(patch_filename
, entry
->expected_kmod_name
);
2245 strcat(patch_filename
, __KLOAD_PATCH_EXTENSION
);
2248 file_check
= kload_file_exists(patch_filename
);
2250 if (file_check
< 0) {
2251 kload_log_error("error checking existence of file %s" KNL
,
2253 } else if (file_check
> 0 && !overwrite_symbols
) {
2254 if (!ask_overwrite_symbols
) {
2256 "patch file %s exists; not overwriting" KNL
,
2260 int approve
= (*__kload_approve_func
)(1,
2261 "\nPatch file %s exists; overwrite", patch_filename
);
2264 result
= kload_error_unspecified
;
2267 output_patch
= approve
;
2273 if (log_level
>= kload_log_level_basic
) {
2274 kload_log_message("writing patch file %s" KNL
, patch_filename
);
2276 kld_file_debug_dump(entry
->name
, patch_filename
);
2279 if (allocated_filename
) free(allocated_filename
);
2280 allocated_filename
= NULL
;
2283 } else if (patch_file
) {
2285 file_check
= kload_file_exists(patch_file
);
2287 if (file_check
< 0) {
2288 kload_log_error("error checking existence of file %s" KNL
,
2290 } else if (file_check
> 0 && !overwrite_symbols
) {
2291 if (!ask_overwrite_symbols
) {
2292 kload_log_error("patch file %s exists; not overwriting" KNL
,
2296 int approve
= (*__kload_approve_func
)(1,
2297 "\nPatch file %s exists; overwrite", patch_filename
);
2300 result
= kload_error_unspecified
;
2303 output_patch
= approve
;
2309 if (log_level
>= kload_log_level_basic
) {
2310 kload_log_message("writing patch file %s" KNL
, patch_filename
);
2312 kld_file_debug_dump(dgraph
->root
->name
, patch_file
);
2317 if (allocated_filename
) free(allocated_filename
);
2321 #endif /* not KERNEL */
2323 /*******************************************************************************
2325 *******************************************************************************/
2327 kload_error
__kload_set_module_dependencies(dgraph_entry_t
* entry
) {
2328 kload_error result
= kload_error_none
;
2331 void * kmod_control_args
= 0;
2333 #endif /* not KERNEL */
2336 dgraph_entry_t
* current_dep
= NULL
;
2338 if (!entry
->do_load
) {
2339 result
= kload_error_already_loaded
;
2343 for (i
= 0; i
< entry
->num_dependencies
; i
++) {
2344 current_dep
= entry
->dependencies
[i
];
2346 if (log_level
>= kload_log_level_load_details
) {
2347 kload_log_message("adding reference from %s (%d) to %s (%d)" KNL
,
2348 entry
->expected_kmod_name
, entry
->kmod_id
,
2349 current_dep
->expected_kmod_name
, current_dep
->kmod_id
);
2352 packed_id
= KMOD_PACK_IDS(entry
->kmod_id
, current_dep
->kmod_id
);
2354 mach_result
= kmod_control(G_kernel_priv_port
,
2355 packed_id
, KMOD_CNTL_RETAIN
, &kmod_control_args
, &num_args
);
2357 mach_result
= kmod_retain(packed_id
);
2358 #endif /* not KERNEL */
2359 if (mach_result
!= KERN_SUCCESS
) {
2361 "kmod retain failed for %s; destroying kmod" KNL
,
2362 entry
->expected_kmod_name
);
2364 mach_result
= kmod_destroy(G_kernel_priv_port
, entry
->kmod_id
);
2366 mach_result
= kmod_destroy_internal(entry
->kmod_id
);
2367 #endif /* not KERNEL */
2368 if (mach_result
!= KERN_SUCCESS
) {
2369 kload_log_error("kmod destroy failed" KNL
);
2371 result
= kload_error_link_load
;
2376 if (log_level
>= kload_log_level_load_basic
) {
2377 kload_log_message("module # %d reference counts incremented" KNL
,
2385 /*******************************************************************************
2387 *******************************************************************************/
2389 kload_error
__kload_start_module(dgraph_entry_t
* entry
) {
2390 kload_error result
= kload_error_none
;
2393 void * kmod_control_args
= 0;
2395 #endif /* not KERNEL */
2397 if (!entry
->do_load
) {
2398 result
= kload_error_already_loaded
;
2403 mach_result
= kmod_control(G_kernel_priv_port
,
2404 entry
->kmod_id
, KMOD_CNTL_START
, &kmod_control_args
, &num_args
);
2406 mach_result
= kmod_start_or_stop(entry
->kmod_id
, 1, 0, 0);
2407 #endif /* not KERNEL */
2409 if (mach_result
!= KERN_SUCCESS
) {
2411 "kmod_control/start failed for %s; destroying kmod" KNL
,
2412 entry
->expected_kmod_name
);
2414 mach_result
= kmod_destroy(G_kernel_priv_port
, entry
->kmod_id
);
2416 mach_result
= kmod_destroy_internal(entry
->kmod_id
);
2417 #endif /* not KERNEL */
2418 if (mach_result
!= KERN_SUCCESS
) {
2419 kload_log_error("kmod destroy failed" KNL
);
2421 result
= kload_error_link_load
;
2425 if (log_level
>= kload_log_level_load_basic
) {
2426 kload_log_message("module # %d started" KNL
,
2434 /*******************************************************************************
2435 *******************************************************************************/
2437 /*******************************************************************************
2438 * This function can only operate on 32 bit mach object file symbol table
2439 * graphs represented by G_current_load_entry.
2440 *******************************************************************************/
2442 unsigned long __kload_linkedit_address(
2444 unsigned long headers_size
)
2446 unsigned long round_segments_size
;
2447 unsigned long round_headers_size
;
2448 unsigned long round_size
;
2450 const struct machOMapping
{
2451 struct mach_header h
;
2452 struct segment_command seg
[1];
2455 if (!G_current_load_entry
) {
2459 // the actual size allocated by kld_load_from_memory()
2460 G_current_load_entry
->kernel_load_size
= size
;
2462 round_headers_size
= round_page(headers_size
);
2463 round_segments_size
= round_page(size
- headers_size
);
2464 round_size
= round_headers_size
+ round_segments_size
;
2466 G_current_load_entry
->kernel_alloc_size
= round_size
;
2468 // will need to be rounded *after* load/link
2469 G_current_load_entry
->kernel_hdr_size
= headers_size
;
2470 G_current_load_entry
->kernel_hdr_pad
= round_headers_size
- headers_size
;
2472 if (G_current_load_entry
->loaded_address
) {
2473 G_current_load_entry
->kernel_load_address
=
2474 G_current_load_entry
->loaded_address
+
2475 G_current_load_entry
->kernel_hdr_pad
;
2476 if (log_level
>= kload_log_level_load_basic
) {
2478 "using %s load address 0x%x (0x%x with header pad)" KNL
,
2479 G_current_load_entry
->kmod_id
? "existing" : "provided",
2480 G_current_load_entry
->loaded_address
,
2481 G_current_load_entry
->kernel_load_address
);
2483 return G_current_load_entry
->kernel_load_address
;
2486 machO
= (const struct machOMapping
*) G_current_load_entry
->object
;
2487 if (machO
->seg
[0].vmaddr
)
2489 G_current_load_entry
->loaded_address
= trunc_page(machO
->seg
[0].vmaddr
- machO
->seg
[0].fileoff
);
2491 G_current_load_entry
->kernel_load_address
= G_current_load_entry
->loaded_address
2492 + G_current_load_entry
->kernel_hdr_pad
;
2494 return G_current_load_entry
->kernel_load_address
;
2499 G_current_load_entry
->kernel_alloc_address
= G_prelink
->modules
[0].address
;
2500 G_prelink
->modules
[0].address
+= round_page(G_current_load_entry
->kernel_alloc_size
);
2501 mach_result
= KERN_SUCCESS
;
2503 } else if (G_syms_only
) {
2505 "internal error; asked to allocate kernel memory" KNL
);
2506 // FIXME: no provision for cleanup here
2507 return kload_error_unspecified
;
2510 #endif /* not KERNEL */
2514 mach_result
= vm_allocate(G_kernel_port
,
2515 &G_current_load_entry
->kernel_alloc_address
,
2516 G_current_load_entry
->kernel_alloc_size
, VM_FLAGS_ANYWHERE
);
2518 mach_result
= vm_allocate(kernel_map
,
2519 &G_current_load_entry
->kernel_alloc_address
,
2520 G_current_load_entry
->kernel_alloc_size
, VM_FLAGS_ANYWHERE
);
2521 #endif /* not KERNEL */
2524 if (mach_result
!= KERN_SUCCESS
) {
2525 kload_log_error("can't allocate kernel memory" KNL
);
2526 // FIXME: no provision for cleanup here
2527 return kload_error_kernel_error
;
2530 if (log_level
>= kload_log_level_load_basic
) {
2531 kload_log_message("allocated %ld bytes in kernel space at 0x%x" KNL
,
2532 G_current_load_entry
->kernel_alloc_size
,
2533 G_current_load_entry
->kernel_alloc_address
);
2536 G_current_load_entry
->kernel_load_address
=
2537 G_current_load_entry
->kernel_alloc_address
+
2538 G_current_load_entry
->kernel_hdr_pad
;
2540 G_current_load_entry
->loaded_address
= G_current_load_entry
->kernel_alloc_address
;
2542 if (log_level
>= kload_log_level_load_basic
) {
2544 "using load address of 0x%x" KNL
,
2545 G_current_load_entry
->kernel_alloc_address
);
2548 return G_current_load_entry
->kernel_load_address
;
2551 /*******************************************************************************
2553 *******************************************************************************/
2555 void __kload_clear_kld_globals(void) {
2556 G_current_load_entry
= NULL
;
2560 /*******************************************************************************
2562 *******************************************************************************/
2564 void __kload_clean_up_entry(dgraph_entry_t
* entry
) {
2567 if (entry
->need_cleanup
&& entry
->kernel_alloc_address
) {
2571 if ((entry
->kernel_alloc_address
+ entry
->kernel_alloc_size
) == G_prelink
->modules
[0].address
) {
2572 G_prelink
->modules
[0].address
= entry
->kernel_alloc_address
;
2575 "bad free load address of 0x%x (last 0x%x)" KNL
,
2576 entry
->kernel_alloc_address
, G_prelink
->modules
[0].address
);
2579 mach_result
= vm_deallocate(G_kernel_port
, entry
->kernel_alloc_address
,
2580 entry
->kernel_alloc_size
);
2583 mach_result
= vm_deallocate(kernel_map
, entry
->kernel_alloc_address
,
2584 entry
->kernel_alloc_size
);
2585 #endif /* not KERNEL */
2586 entry
->kernel_alloc_address
= 0;
2592 /*******************************************************************************
2594 *******************************************************************************/
2595 int kload_file_exists(const char * path
)
2597 int result
= 0; // assume it doesn't exist
2598 struct stat stat_buf
;
2600 if (stat(path
, &stat_buf
) == 0) {
2601 result
= 1; // the file does exist; we don't care beyond that
2607 result
= 0; // the file doesn't exist
2611 result
= -1; // unknown error
2619 #endif /* not KERNEL */
2621 /*******************************************************************************
2623 *******************************************************************************/
2625 void kload_set_log_level(kload_log_level level
)
2632 /*******************************************************************************
2634 *******************************************************************************/
2635 void kload_set_log_function(
2636 void (*func
)(const char * format
, ...))
2639 __kload_log_func
= &__kload_null_log
;
2641 __kload_log_func
= func
;
2646 /*******************************************************************************
2648 *******************************************************************************/
2649 void kload_set_error_log_function(
2650 void (*func
)(const char * format
, ...))
2653 __kload_err_log_func
= &__kload_null_err_log
;
2655 __kload_err_log_func
= func
;
2660 /*******************************************************************************
2662 *******************************************************************************/
2663 void kload_set_user_approve_function(
2664 int (*func
)(int default_answer
, const char * format
, ...))
2667 __kload_approve_func
= &__kload_null_approve
;
2669 __kload_approve_func
= func
;
2674 /*******************************************************************************
2676 *******************************************************************************/
2677 void kload_set_user_veto_function(
2678 int (*func
)(int default_answer
, const char * format
, ...))
2681 __kload_veto_func
= &__kload_null_veto
;
2683 __kload_veto_func
= func
;
2688 /*******************************************************************************
2690 *******************************************************************************/
2691 void kload_set_user_input_function(
2692 const char * (*func
)(const char * format
, ...))
2695 __kload_input_func
= &__kload_null_input
;
2697 __kload_input_func
= func
;
2702 /*******************************************************************************
2704 *******************************************************************************/
2706 void kload_log_message(const char * format
, ...)
2709 char fake_buffer
[2];
2711 char * output_string
;
2713 if (log_level
<= kload_log_level_silent
) {
2717 va_start(ap
, format
);
2718 output_length
= vsnprintf(fake_buffer
, 1, format
, ap
);
2721 output_string
= (char *)malloc(output_length
+ 1);
2722 if (!output_string
) {
2726 va_start(ap
, format
);
2727 vsprintf(output_string
, format
, ap
);
2730 __kload_log_func(output_string
);
2731 free(output_string
);
2736 /*******************************************************************************
2738 *******************************************************************************/
2740 void kload_log_error(const char * format
, ...)
2743 char fake_buffer
[2];
2745 char * output_string
;
2747 if (log_level
<= kload_log_level_silent
) {
2751 va_start(ap
, format
);
2752 output_length
= vsnprintf(fake_buffer
, 1, format
, ap
);
2755 output_string
= (char *)malloc(output_length
+ 1);
2756 if (!output_string
) {
2760 va_start(ap
, format
);
2761 vsprintf(output_string
, format
, ap
);
2764 __kload_err_log_func(output_string
);
2765 free(output_string
);
2769 /*******************************************************************************
2771 *******************************************************************************/
2772 void __kload_null_log(const char * format
, ...)
2777 /*******************************************************************************
2779 *******************************************************************************/
2780 void __kload_null_err_log(const char * format
, ...)
2785 /*******************************************************************************
2787 *******************************************************************************/
2788 int __kload_null_approve(int default_answer
, const char * format
, ...)
2793 /*******************************************************************************
2795 *******************************************************************************/
2796 int __kload_null_veto(int default_answer
, const char * format
, ...)
2801 /*******************************************************************************
2803 *******************************************************************************/
2804 const char * __kload_null_input(const char * format
, ...)
2809 /*******************************************************************************
2810 * The kld_patch.c module uses this function, if defined, to print errors. In
2811 * the kernel this function is defined in libsa/misc.c.
2812 *******************************************************************************/
2813 void kld_error_vprintf(const char * format
, va_list ap
) {
2814 if (log_level
<= kload_log_level_silent
) return;
2815 vfprintf(stderr
, format
, ap
);
2819 #endif /* not KERNEL */