6 #include <CoreFoundation/CoreFoundation.h>
17 #include <sys/param.h>
18 #include <sys/types.h>
21 #include <mach/mach.h>
22 #include <mach/mach_init.h>
23 #include <mach/mach_error.h>
24 #include <mach/mach_host.h>
25 #include <mach/mach_port.h>
26 #include <mach-o/kld.h>
27 #include <mach-o/arch.h>
28 #include <mach-o/fat.h>
29 #include <mach-o/loader.h>
30 #include <mach-o/nlist.h>
31 #include <libkern/OSByteOrder.h>
33 #include "vers_rsrc.h"
37 #include <mach-o/kld.h>
38 #include <mach-o/loader.h>
39 #include <mach-o/nlist.h>
40 #include <libsa/vers_rsrc.h>
42 #endif /* not KERNEL */
46 #include "kld_patch.h"
58 #define PRIV_EXT __private_extern__
61 #define LOG_DELAY(x) IODelay((x) * 1000000)
62 #define VTYELLOW "\033[33m"
63 #define VTRESET "\033[0m"
70 #endif /* not KERNEL */
83 kmod_destroy_internal(kmod_t id
);
90 mach_msg_type_number_t
*dataCount
);
92 extern kern_return_t
kmod_retain(kmod_t id
);
93 extern kern_return_t
kmod_release(kmod_t id
);
95 extern void flush_dcache(vm_offset_t addr
, unsigned cnt
, int phys
);
96 extern void invalidate_icache(vm_offset_t addr
, unsigned cnt
, int phys
);
100 // Used to pass info between kld library and callbacks
101 static dgraph_entry_t
* G_current_load_entry
= NULL
;
104 static mach_port_t G_kernel_port
= PORT_NULL
;
105 static mach_port_t G_kernel_priv_port
= PORT_NULL
;
106 static int G_syms_only
;
109 register_prelink(dgraph_entry_t
* entry
,
110 kmod_info_t
* local_kmod_info
, vm_offset_t kernel_kmod_info
);
114 kmod_info_t modules
[1];
116 struct PrelinkState
* G_prelink
;
117 CFMutableDataRef G_prelink_data
;
118 CFMutableDataRef G_prelink_dependencies
;
120 #endif /* not KERNEL */
122 // used by dgraph.c so can't be static
123 kload_log_level log_level
= 0;
126 static void __kload_null_log(const char * format
, ...);
127 static void __kload_null_err_log(const char * format
, ...);
128 static int __kload_null_approve(int default_answer
, const char * format
, ...);
129 static int __kload_null_veto(int default_answer
, const char * format
, ...);
130 static const char * __kload_null_input(const char * format
, ...);
132 void (*__kload_log_func
)(const char * format
, ...) =
134 void (*__kload_err_log_func
)(const char * format
, ...) = &__kload_null_err_log
;
135 int (*__kload_approve_func
)(int default_answer
,
136 const char * format
, ...) = &__kload_null_approve
;
137 int (*__kload_veto_func
)(int default_answer
,
138 const char * format
, ...) = &__kload_null_veto
;
139 const char * (*__kload_input_func
)(const char * format
, ...) =
141 #endif /* not KERNEL */
143 static unsigned long __kload_linkedit_address(
145 unsigned long headers_size
);
146 static void __kload_clean_up_entry(dgraph_entry_t
* entry
);
147 static void __kload_clear_kld_globals(void);
148 static kload_error
__kload_patch_dgraph(dgraph_t
* dgraph
151 const char * kernel_file
152 #endif /* not KERNEL */
154 static kload_error
__kload_load_modules(dgraph_t
* dgraph
157 const char * kernel_file
,
158 const char * patch_file
, const char * patch_dir
,
159 const char * symbol_file
, const char * symbol_dir
,
160 int do_load
, int do_start_kmod
, int do_prelink
,
161 int interactive_level
,
162 int ask_overwrite_symbols
, int overwrite_symbols
163 #endif /* not KERNEL */
166 static kload_error
__kload_check_module_loaded(
168 dgraph_entry_t
* entry
,
170 kmod_info_t
* kmod_list
,
171 #endif /* not KERNEL */
174 static kload_error
__kload_load_module(dgraph_t
* dgraph
,
175 dgraph_entry_t
* entry
,
179 const char * symbol_file
,
180 const char * symbol_dir
,
182 int interactive_level
,
183 int ask_overwrite_symbols
,
184 int overwrite_symbols
185 #endif /* not KERNEL */
187 static kload_error
__kload_set_module_dependencies(dgraph_entry_t
* entry
);
188 static kload_error
__kload_start_module(dgraph_entry_t
* entry
);
191 static kload_error
__kload_output_patches(
193 const char * patch_file
,
194 const char * patch_dir
,
195 int ask_overwrite_symbols
,
196 int overwrite_symbols
);
198 Boolean
_IOReadBytesFromFile(CFAllocatorRef alloc
, const char *path
, void **bytes
,
199 CFIndex
*length
, CFIndex maxLength
);
200 Boolean
_IOWriteBytesToFile(const char *path
, const void *bytes
, CFIndex length
);
202 #endif /* not KERNEL */
204 /*******************************************************************************
206 *******************************************************************************/
208 kload_error
kload_load_dgraph(dgraph_t
* dgraph
211 const char * kernel_file
,
212 const char * patch_file
, const char * patch_dir
,
213 const char * symbol_file
, const char * symbol_dir
,
214 int do_load
, int do_start_kmod
, int do_prelink
,
215 int interactive_level
,
216 int ask_overwrite_symbols
, int overwrite_symbols
217 #endif /* not KERNEL */
220 kload_error result
= kload_error_none
;
221 int one_has_address
= 0;
222 int one_lacks_address
= 0;
227 syms_only
= (!do_load
) && (symbol_dir
|| symbol_file
);
229 if (log_level
>= kload_log_level_load_details
) {
230 kload_log_message("loading dependency graph:" KNL
);
234 if (syms_only
&& log_level
>= kload_log_level_load_details
) {
235 kload_log_message("loading for symbol generation only" KNL
);
239 * If we're not loading and have no request to emit a symbol
240 * or patch file, there's nothing to do!
242 if (!do_load
&& !symbol_dir
&& !symbol_file
&&
243 !patch_dir
&& !patch_file
) {
245 if (syms_only
&& log_level
>= kload_log_level_load_details
) {
246 kload_log_message("loader has no work to do" KNL
);
249 result
= kload_error_none
; // fixme: should this be USAGE error?
254 * If we're doing symbols only, then all entries in the dgraph must
255 * have addresses assigned, or none must.
258 if (log_level
>= kload_log_level_load_details
) {
259 kload_log_message("checking whether modules have addresses assigned" KNL
);
261 for (i
= 0; i
< dgraph
->length
; i
++) {
262 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
263 if (entry
->is_kernel_component
) {
266 if (entry
->loaded_address
!= 0) {
269 one_lacks_address
= 1;
273 #endif /* not KERNEL */
275 if (one_has_address
&& one_lacks_address
) {
277 "either all modules must have addresses set to nonzero values or "
279 result
= kload_error_invalid_argument
;
284 /* we need the priv port to check/load modules in the kernel.
286 if (PORT_NULL
== G_kernel_priv_port
) {
287 G_kernel_priv_port
= mach_host_self(); /* if we are privileged */
289 #endif /* not KERNEL */
292 * In the kernel, ALWAYS get load addresses of existing loaded kmods.
296 * If we don't have addresses, then get them from the kernel.
298 if (!one_has_address
&& !do_prelink
&& (do_load
|| symbol_file
|| symbol_dir
)) {
299 #endif /* not KERNEL */
300 if (log_level
>= kload_log_level_load_details
) {
301 kload_log_message("getting module addresses from kernel" KNL
);
304 result
= kload_set_load_addresses_from_kernel(dgraph
, kernel_file
,
307 result
= kload_set_load_addresses_from_kernel(dgraph
);
308 #endif /* not KERNEL */
309 if (result
== kload_error_already_loaded
) {
317 #endif /* not KERNEL */
319 } else if (result
!= kload_error_none
) {
320 kload_log_error("can't check load addresses of modules" KNL
);
325 #endif /* not KERNEL */
329 * At this point, if we're doing symbols only, it's an error to not
330 * have a load address for every module.
332 if (syms_only
&& !do_prelink
) {
333 if (log_level
>= kload_log_level_load_details
) {
334 kload_log_message("checking that all modules have addresses assigned" KNL
);
336 for (i
= 0; i
< dgraph
->length
; i
++) {
337 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
338 if (entry
->is_kernel_component
) {
341 if (!entry
->loaded_address
) {
343 "missing load address during symbol generation: %s" KNL
,
345 result
= kload_error_unspecified
;
355 CFAllocatorRef alloc
;
357 // We need a real allocator to pass to _IOReadBytesFromFile
358 alloc
= CFRetain(CFAllocatorGetDefault());
359 if (_IOReadBytesFromFile(alloc
, "prelinkstate", &bytes
, &length
, 0))
361 G_prelink_data
= CFDataCreateMutable(alloc
, 0);
362 CFDataAppendBytes(G_prelink_data
, (UInt8
*) bytes
, length
);
363 CFAllocatorDeallocate(alloc
, bytes
);
365 G_prelink_dependencies
= CFDataCreateMutable(alloc
, 0);
366 if (_IOReadBytesFromFile(alloc
, "prelinkdependencies", &bytes
, &length
, 0))
368 CFDataAppendBytes(G_prelink_dependencies
, (UInt8
*) bytes
, length
);
369 CFAllocatorDeallocate(alloc
, bytes
);
373 if (!G_prelink_data
) {
375 "can't get load address for prelink %s" KNL
, kernel_file
);
376 result
= kload_error_link_load
;
380 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
384 #endif /* not KERNEL */
388 result
= __kload_load_modules(dgraph
, kernel_file
,
389 patch_file
, patch_dir
, symbol_file
, symbol_dir
,
390 do_load
, do_start_kmod
, do_prelink
, interactive_level
,
391 ask_overwrite_symbols
, overwrite_symbols
);
393 result
= __kload_load_modules(dgraph
);
394 #endif /* not KERNEL */
399 /* Dispose of the host port to prevent security breaches and port
400 * leaks. We don't care about the kern_return_t value of this
401 * call for now as there's nothing we can do if it fails.
403 if (PORT_NULL
!= G_kernel_priv_port
) {
404 mach_port_deallocate(mach_task_self(), G_kernel_priv_port
);
405 G_kernel_priv_port
= PORT_NULL
;
407 #endif /* not KERNEL */
409 for (i
= 0; i
< dgraph
->length
; i
++) {
410 dgraph_entry_t
* current_entry
= dgraph
->graph
[i
];
411 __kload_clean_up_entry(current_entry
);
421 length
= CFDataGetLength(G_prelink_data
);
422 bytes
= (0 == length
) ? (const void *)"" : CFDataGetBytePtr(G_prelink_data
);
423 success
= _IOWriteBytesToFile("prelinkstate", bytes
, length
);
426 kload_log_error("write prelinkstate" KNL
);
427 result
= kload_error_link_load
;
429 length
= CFDataGetLength(G_prelink_dependencies
);
430 bytes
= (0 == length
) ? (const void *)"" : CFDataGetBytePtr(G_prelink_dependencies
);
431 success
= _IOWriteBytesToFile("prelinkdependencies", bytes
, length
);
434 kload_log_error("write prelinkdependencies" KNL
);
435 result
= kload_error_link_load
;
438 #endif /* not KERNEL */
444 /*******************************************************************************
445 * This function claims the option flags d and D for object file dependencies
446 * and in-kernel dependencies, respectively.
447 *******************************************************************************/
448 kload_error
kload_load_with_arglist(
449 int argc
, char **argv
,
450 const char * kernel_file
,
451 const char * patch_file
, const char * patch_dir
,
452 const char * symbol_file
, const char * symbol_dir
,
453 int do_load
, int do_start_kmod
,
454 int interactive_level
,
455 int ask_overwrite_symbols
, int overwrite_symbols
)
457 kload_error result
= kload_error_none
;
458 dgraph_error_t dgraph_result
;
459 int syms_only
= (!do_load
) && (symbol_file
|| symbol_dir
);
461 static dgraph_t dependency_graph
;
463 /* Zero out fields in dependency graph for proper error handling later.
465 bzero(&dependency_graph
, sizeof(dependency_graph
));
467 dgraph_result
= dgraph_init_with_arglist(&dependency_graph
,
468 syms_only
, "-d", "-D", argc
, argv
);
469 if (dgraph_result
== dgraph_error
) {
470 kload_log_error("error processing dependency list" KNL
);
471 result
= kload_error_unspecified
;
473 } else if (dgraph_result
== dgraph_invalid
) {
474 // anything to print here, or did init call print something?
475 result
= kload_error_invalid_argument
;
479 result
= kload_load_dgraph(&dependency_graph
, kernel_file
,
480 patch_file
, patch_dir
, symbol_file
, symbol_dir
,
481 do_load
, do_start_kmod
, false /* do_prelink */, interactive_level
,
482 ask_overwrite_symbols
, overwrite_symbols
);
487 #endif /* not KERNEL */
488 /*******************************************************************************
490 *******************************************************************************/
492 kload_error
__kload_keep_symbols(dgraph_entry_t
* entry
)
494 struct mach_header
* hdr
;
495 struct segment_command
* seg
;
497 struct symtab_command
* symcmd
;
498 unsigned long idx
, ncmds
;
503 return kload_error_none
;
505 hdr
= entry
->linked_image
;
507 seg
= (struct segment_command
*)(hdr
+ 1);
510 idx
++, seg
= (struct segment_command
*)(((vm_offset_t
)seg
) + seg
->cmdsize
))
512 if (LC_SYMTAB
== seg
->cmd
)
517 kload_log_error("no LC_SYMTAB" KNL
);
518 return kload_error_unspecified
;
521 symcmd
= (struct symtab_command
*) seg
;
524 struct mach_header hdr
;
525 struct segment_command seg
;
526 struct symtab_command symcmd
;
528 struct load_cmds
* cmd
;
529 unsigned int symtabsize
;
531 symtabsize
= symcmd
->stroff
+ symcmd
->strsize
- symcmd
->symoff
;
533 size
= sizeof(struct load_cmds
) + symtabsize
;
535 mem
= (vm_offset_t
) malloc(size
);
537 cmd
= (struct load_cmds
*) mem
;
538 sym
= (struct nlist
*) (cmd
+ 1);
541 cmd
->symcmd
= *symcmd
;
542 bcopy((const void *) (((vm_offset_t
) hdr
) + symcmd
->symoff
),
546 hdr
= (struct mach_header
*) mem
;
548 cmd
->hdr
.sizeofcmds
= sizeof(struct load_cmds
);
549 cmd
->hdr
.flags
&= ~MH_INCRLINK
;
551 cmd
->symcmd
.stroff
-= (symcmd
->symoff
- sizeof(struct load_cmds
));
552 cmd
->symcmd
.symoff
= sizeof(struct load_cmds
);
554 cmd
->seg
.cmd
= LC_SEGMENT
;
555 cmd
->seg
.cmdsize
= sizeof(struct segment_command
);
556 strcpy(cmd
->seg
.segname
, SEG_LINKEDIT
);
559 cmd
->seg
.fileoff
= cmd
->symcmd
.symoff
;
560 cmd
->seg
.filesize
= symtabsize
;
561 cmd
->seg
.maxprot
= 7;
562 cmd
->seg
.initprot
= 1;
566 sym
= (struct nlist
*) (cmd
+ 1);
567 for (idx
= 0; idx
< symcmd
->nsyms
; idx
++, sym
++)
569 if ( (sym
->n_type
& N_TYPE
) == N_SECT
) {
570 sym
->n_sect
= NO_SECT
;
571 sym
->n_type
= (sym
->n_type
& ~N_TYPE
) | N_ABS
;
574 if (log_level
>= kload_log_level_load_details
)
576 kload_log_message("__kload_keep_symbols %s, nsyms %ld, 0x%x bytes" KNL
,
577 entry
->name
, symcmd
->nsyms
, size
);
580 entry
->symbols
= mem
;
581 entry
->symbols_malloc
= mem
;
582 entry
->symbols_length
= size
;
584 return kload_error_none
;
589 kload_error
__kload_make_opaque_basefile(dgraph_t
* dgraph
, struct mach_header
* hdr
)
591 struct segment_command
* seg
;
592 struct segment_command
* data_seg
;
593 struct segment_command
* text_seg
;
594 struct section
* sec
;
597 unsigned long idx
, ncmds
;
599 vm_address_t mem
, out
;
600 static vm_address_t keep_base_image
;
601 static vm_size_t keep_base_size
;
603 if (dgraph
->opaque_base_image
)
604 return kload_error_none
;
608 dgraph
->opaque_base_image
= keep_base_image
;
609 dgraph
->opaque_base_length
= keep_base_size
;
610 return kload_error_none
;
613 data_seg
= text_seg
= NULL
;
615 seg
= (struct segment_command
*)(hdr
+ 1);
618 idx
++, seg
= (struct segment_command
*)(((vm_offset_t
)seg
) + seg
->cmdsize
))
620 if (LC_SEGMENT
!= seg
->cmd
)
622 if (!strcmp(SEG_TEXT
, seg
->segname
))
624 else if (!strcmp(SEG_DATA
, seg
->segname
))
627 if (!text_seg
|| !data_seg
)
629 kload_log_error("no SEG_TEXT or SEG_DATA" KNL
);
630 return kload_error_unspecified
;
633 size
= sizeof(struct mach_header
) + text_seg
->cmdsize
+ data_seg
->cmdsize
;
634 mem
= (vm_offset_t
) malloc(size
);
637 bcopy(hdr
, (void *) out
, sizeof(struct mach_header
));
638 hdr
= (struct mach_header
*) out
;
639 out
+= sizeof(struct mach_header
);
641 bcopy(text_seg
, (void *) out
, text_seg
->cmdsize
);
642 text_seg
= (struct segment_command
*) out
;
643 out
+= text_seg
->cmdsize
;
645 bcopy(data_seg
, (void *) out
, data_seg
->cmdsize
);
646 data_seg
= (struct segment_command
*) out
;
647 out
+= data_seg
->cmdsize
;
650 hdr
->sizeofcmds
= text_seg
->cmdsize
+ data_seg
->cmdsize
;
652 offset
= hdr
->sizeofcmds
;
654 text_seg
->fileoff
= offset
;
655 text_seg
->filesize
= 0;
657 sec
= (struct section
*)(text_seg
+ 1);
658 for (j
= 0; j
< text_seg
->nsects
; j
++, sec
++)
660 // sec->addr = (unsigned long) addr;
662 sec
->offset
= offset
;
666 data_seg
->fileoff
= offset
;
667 data_seg
->filesize
= 0;
669 sec
= (struct section
*)(data_seg
+ 1);
670 for (j
= 0; j
< data_seg
->nsects
; j
++, sec
++)
672 // sec->addr = (unsigned long) addr;
674 sec
->offset
= offset
;
678 dgraph
->opaque_base_image
= mem
;
679 dgraph
->opaque_base_length
= size
;
680 keep_base_image
= mem
;
681 keep_base_size
= size
;
683 return kload_error_none
;
686 /*******************************************************************************
688 *******************************************************************************/
690 kload_error
__kload_load_modules(dgraph_t
* dgraph
693 const char * kernel_file
,
694 const char * patch_file
,
695 const char * patch_dir
,
696 const char * symbol_file
,
697 const char * symbol_dir
,
701 int interactive_level
,
702 int ask_overwrite_symbols
,
703 int overwrite_symbols
704 #endif /* not KERNEL */
707 kload_error result
= kload_error_none
;
709 long int kernel_size
= 0;
710 kern_return_t mach_result
= KERN_SUCCESS
;
711 #endif /* not KERNEL */
712 char * kernel_base_addr
= 0;
714 Boolean cleanup_kld_loader
= false;
717 /* We have to map all object files to get their CFBundleIdentifier
721 result
= kload_map_dgraph(dgraph
, kernel_file
);
723 result
= kload_map_dgraph(dgraph
);
724 #endif /* not KERNEL */
725 if (result
!= kload_error_none
) {
726 kload_log_error("error mapping object files" KNL
);
731 result
= __kload_patch_dgraph(dgraph
, kernel_file
);
733 result
= __kload_patch_dgraph(dgraph
);
734 #endif /* not KERNEL */
735 if (result
!= kload_error_none
) {
736 // FIXME: print an error message here?
741 // FIXME: check error return
742 __kload_output_patches(dgraph
, patch_file
, patch_dir
,
743 ask_overwrite_symbols
, overwrite_symbols
);
746 * If we're not loading or writing symbols, we're done.
748 if (!do_load
&& !do_prelink
&& !symbol_file
&& !symbol_dir
) {
752 if (do_load
&& PORT_NULL
== G_kernel_port
) {
753 mach_result
= task_for_pid(mach_task_self(), 0, &G_kernel_port
);
754 if (mach_result
!= KERN_SUCCESS
) {
755 kload_log_error("unable to get kernel task port: %s" KNL
,
756 mach_error_string(mach_result
));
757 kload_log_error("you must be running as root to load "
758 "modules into the kernel" KNL
);
759 result
= kload_error_kernel_permission
;
763 #endif /* not KERNEL */
765 kld_address_func(&__kload_linkedit_address
);
768 G_syms_only
= (!do_load
) && (symbol_file
|| symbol_dir
|| patch_dir
);
770 kernel_base_addr
= kld_file_getaddr(kernel_file
, &kernel_size
);
771 if (!kernel_base_addr
) {
773 "can't get load address for kernel %s" KNL
, kernel_file
);
774 result
= kload_error_link_load
;
779 const char * kernel_file
= "(kernel)";
780 extern struct mach_header _mh_execute_header
;
781 kernel_base_addr
= (char *) &_mh_execute_header
;
783 #endif /* not KERNEL */
786 if (dgraph
->has_symbol_sets
)
788 result
= __kload_make_opaque_basefile(dgraph
, (struct mach_header
*) kernel_base_addr
);
789 if (result
!= kload_error_none
) {
790 kload_log_error("can't construct opaque base image from %s" KNL
, kernel_file
);
794 kld_result
= kld_load_basefile_from_memory(kernel_file
,
795 (char *) dgraph
->opaque_base_image
,
796 dgraph
->opaque_base_length
);
800 kld_result
= kld_load_basefile_from_memory(kernel_file
,
801 (char *) kernel_base_addr
, kernel_size
);
802 #endif /* not KERNEL */
805 kload_log_error("can't link base image %s" KNL
, kernel_file
);
806 result
= kload_error_link_load
;
810 cleanup_kld_loader
= true;
811 bool opaque_now
= false;
813 for (i
= 0; i
< dgraph
->length
; i
++) {
814 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
816 opaque_now
|= current_entry
->opaque_link
;
822 if (log_level
>= kload_log_level_load_details
)
824 kload_log_message("opaque link for %s" KNL
, current_entry
->name
);
827 kld_set_link_options(KLD_STRIP_ALL
); // KLD_STRIP_NONE
829 if (dgraph
->have_loaded_symbols
)
832 kld_result
= kld_load_basefile_from_memory(kernel_file
,
833 (char *) dgraph
->opaque_base_image
,
834 dgraph
->opaque_base_length
);
836 kload_log_error("can't link base image %s" KNL
, kernel_file
);
837 result
= kload_error_link_load
;
842 dgraph
->have_loaded_symbols
= false;
844 for (j
= 0; j
< dgraph
->length
; j
++)
847 (k
< current_entry
->num_dependencies
)
848 && (current_entry
->dependencies
[k
] != dgraph
->load_order
[j
]);
851 if (k
== current_entry
->num_dependencies
)
854 dgraph_entry_t
* image_dep
= current_entry
->dependencies
[k
];
855 if (!image_dep
->symbols
)
857 kload_log_error("internal error; no dependent symbols" KNL
);
858 result
= kload_error_link_load
;
863 struct mach_header
* kld_header
;
866 kld_result
= kld_load_from_memory(&kld_header
, image_dep
->name
,
867 (char *) image_dep
->symbols
, image_dep
->symbols_length
, NULL
);
869 kld_result
= kld_load_from_memory(&kld_header
, image_dep
->name
,
870 (char *) image_dep
->symbols
, image_dep
->symbols_length
);
871 #endif /* not KERNEL */
873 kload_log_error("can't link dependent image %s" KNL
, image_dep
->name
);
874 result
= kload_error_link_load
;
877 kld_forget_symbol("_kmod_info");
878 dgraph
->have_loaded_symbols
= true;
883 if (dgraph
->has_opaque_links
885 || symbol_file
|| symbol_dir
888 kld_set_link_options(KLD_STRIP_NONE
);
890 kld_set_link_options(KLD_STRIP_ALL
);
893 result
= __kload_load_module(dgraph
, current_entry
,
894 (current_entry
== dgraph
->root
),
895 symbol_file
, symbol_dir
, do_load
,
896 interactive_level
, ask_overwrite_symbols
, overwrite_symbols
);
898 result
= __kload_load_module(dgraph
, current_entry
,
899 (current_entry
== dgraph
->root
));
900 #endif /* not KERNEL */
901 if (result
!= kload_error_none
) {
905 if (dgraph
->has_opaque_links
&& (current_entry
!= dgraph
->root
))
907 result
= __kload_keep_symbols(current_entry
);
908 if (result
!= kload_error_none
) {
909 kload_log_error("__kload_keep_symbols() failed for module %s" KNL
,
910 current_entry
->name
);
916 if (do_load
&& current_entry
->do_load
) {
918 if (current_entry
->do_load
) {
919 #endif /* not KERNEL */
920 result
= __kload_set_module_dependencies(current_entry
);
921 if ( ! (result
== kload_error_none
||
922 result
== kload_error_already_loaded
) ) {
927 if ( (interactive_level
== 1 && current_entry
== dgraph
->root
) ||
928 (interactive_level
== 2) ) {
930 int approve
= (*__kload_approve_func
)(1,
931 "\nStart module %s (ansering no will abort the load)",
932 current_entry
->name
);
935 do_start_kmod
= true; // override 'cause user said so
937 kern_return_t mach_result
;
939 kload_log_message("error reading user response; "
940 "destroying loaded module" KNL
);
942 kload_log_message("user canceled module start; "
943 "destroying loaded module" KNL
);
945 mach_result
= kmod_destroy(G_kernel_priv_port
, current_entry
->kmod_id
);
946 if (mach_result
!= KERN_SUCCESS
) {
947 kload_log_error("kmod_destroy() failed" KNL
);
950 result
= kload_error_unspecified
;
953 result
= kload_error_user_abort
;
958 #endif /* not KERNEL */
961 if (current_entry
!= dgraph
->root
||
962 (current_entry
== dgraph
->root
&& do_start_kmod
)) {
963 #endif /* not KERNEL */
965 result
= __kload_start_module(current_entry
);
966 if ( ! (result
== kload_error_none
||
967 result
== kload_error_already_loaded
) ) {
970 } else if (interactive_level
||
971 log_level
>= kload_log_level_load_details
) {
973 } else if (log_level
>= kload_log_level_load_details
) {
974 #endif /* not KERNEL */
976 kload_log_message("started module %s" KNL
,
977 current_entry
->name
);
980 } /* current_entry... */
981 #endif /* not KERNEL */
988 #endif /* not KERNEL */
989 } /* for i, dgraph->length */
994 /* Dispose of the kernel port to prevent security breaches and port
995 * leaks. We don't care about the kern_return_t value of this
996 * call for now as there's nothing we can do if it fails.
998 if (PORT_NULL
!= G_kernel_port
) {
999 mach_port_deallocate(mach_task_self(), G_kernel_port
);
1000 G_kernel_port
= PORT_NULL
;
1002 #endif /* not KERNEL */
1004 if (cleanup_kld_loader
) {
1012 /*******************************************************************************
1014 *******************************************************************************/
1017 #define __KLOAD_SYMBOL_EXTENSION ".sym"
1018 #endif /* not KERNEL */
1021 kload_error
__kload_load_module(dgraph_t
* dgraph
,
1022 dgraph_entry_t
* entry
,
1026 const char * symbol_file
,
1027 const char * symbol_dir
,
1029 int interactive_level
,
1030 int ask_overwrite_symbols
,
1031 int overwrite_symbols
1032 #endif /* not KERNEL */
1035 kload_error result
= kload_error_none
;
1039 struct mach_header
* kld_header
;
1040 const char * kmod_symbol
= "_kmod_info";
1041 unsigned long kernel_kmod_info
;
1042 kmod_info_t
* local_kmod_info
= NULL
;
1043 char * dest_address
= 0;
1045 char * allocated_filename
= NULL
;
1046 char * symbol_filename
= NULL
;
1048 vm_address_t vm_buffer
= 0;
1049 #endif /* not KERNEL */
1051 /* A kernel component is by nature already linked and loaded and has
1052 * no work to be done upon it.
1054 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1055 result
= kload_error_none
;
1059 G_current_load_entry
= entry
;
1061 if (log_level
>= kload_log_level_load_basic
) {
1064 #endif /* not KERNEL */
1065 kload_log_message("link/loading file %s" KNL
, entry
->name
);
1068 kload_log_message("linking file %s" KNL
, entry
->name
);
1070 #endif /* not KERNEL */
1074 if (entry
->link_output_file
!= entry
->name
) {
1075 symbol_filename
= entry
->link_output_file
;
1078 if (symbol_filename
) {
1079 file_check
= kload_file_exists(symbol_filename
);
1080 if (file_check
< 0) {
1081 kload_log_error("error checking existence of file %s" KNL
,
1083 } else if (file_check
> 0 && !overwrite_symbols
) {
1085 if (!ask_overwrite_symbols
) {
1086 kload_log_message("symbol file %s exists; not overwriting" KNL
,
1088 symbol_filename
= NULL
;
1090 int approve
= (*__kload_approve_func
)(1,
1091 "\nSymbol file %s exists; overwrite", symbol_filename
);
1094 result
= kload_error_unspecified
;
1096 } else if (approve
== 0) {
1097 if (allocated_filename
) free(allocated_filename
);
1098 allocated_filename
= NULL
;
1099 symbol_filename
= NULL
;
1105 if (symbol_filename
&&
1106 (interactive_level
||
1107 log_level
>= kload_log_level_basic
) ) {
1109 kload_log_message("writing symbol file %s" KNL
, symbol_filename
);
1113 if (interactive_level
&& entry
->loaded_address
) {
1115 "module %s is already loaded as %s at address 0x%08x" KNL
,
1116 entry
->name
, entry
->expected_kmod_name
,
1117 entry
->loaded_address
);
1118 } else if ( (interactive_level
== 1 && is_root
) ||
1119 (interactive_level
== 2) ) {
1121 int approve
= (*__kload_approve_func
)(1,
1122 "\nLoad module %s", entry
->name
);
1125 result
= kload_error_unspecified
;
1127 } else if (approve
== 0) {
1128 result
= kload_error_user_abort
;
1133 #endif /* not KERNEL */
1135 entry
->object
= kld_file_getaddr(entry
->name
, &entry
->object_length
);
1136 if (!entry
->object
) {
1137 kload_log_error("kld_file_getaddr() failed for module %s" KNL
,
1139 __kload_clear_kld_globals();
1140 result
= kload_error_link_load
;
1144 if (entry
->is_symbol_set
) {
1145 entry
->symbols
= (vm_address_t
) entry
->object
;
1146 entry
->symbols_length
= entry
->object_length
;
1149 if (symbol_filename
) {
1150 if (!_IOWriteBytesToFile(symbol_filename
, (void *) entry
->symbols
, entry
->symbols_length
)) {
1151 kload_log_error("write symbol file failed for module %s" KNL
,
1153 __kload_clear_kld_globals();
1154 result
= kload_error_link_load
;
1157 symbol_filename
= 0;
1158 if (G_prelink
&& (entry
->name
!= entry
->link_output_file
))
1160 kload_log_error("prelink %s %s %s" KNL
,
1161 entry
->name
, entry
->link_output_file
, entry
->expected_kmod_name
);
1162 register_prelink(entry
, NULL
, NULL
);
1165 #endif /* not KERNEL */
1166 if (entry
->opaques
) {
1167 result
= kload_error_none
;
1173 kld_result
= kld_load_from_memory(&kld_header
, entry
->name
,
1174 entry
->object
, entry
->object_length
, symbol_filename
);
1176 kld_result
= kld_load_from_memory(&kld_header
, entry
->name
,
1177 entry
->object
, entry
->object_length
);
1178 #endif /* not KERNEL */
1183 #endif /* not KERNEL */
1185 dgraph
->have_loaded_symbols
= true;
1187 if (!kld_result
|| !entry
->kernel_load_address
) {
1188 kload_log_error("kld_load_from_memory() failed for module %s" KNL
,
1190 __kload_clear_kld_globals();
1191 entry
->need_cleanup
= 1;
1192 result
= kload_error_link_load
;
1196 if (entry
->is_symbol_set
) {
1197 result
= kload_error_none
;
1201 entry
->linked_image
= kld_header
;
1202 entry
->linked_image_length
= -1; // unknown!
1204 /* If we're in the kernel and not loading (as when handling an
1205 * already-loaded dependency), we don't need to waste any CPU
1206 * cycles looking up the kmod_info struct.
1209 if (entry
->do_load
) {
1212 kld_result
= kld_lookup(kmod_symbol
, &kernel_kmod_info
);
1214 kload_log_error("kld_lookup(\"%s\") failed for module %s" KNL
,
1215 kmod_symbol
, entry
->name
);
1216 entry
->need_cleanup
= 1;
1217 result
= kload_error_link_load
;
1225 kld_result
= kld_forget_symbol(kmod_symbol
);
1229 #endif /* not KERNEL */
1231 kload_log_error("kld_forget_symbol(\"%s\") failed for module %s" KNL
,
1232 kmod_symbol
, entry
->name
);
1233 entry
->need_cleanup
= 1;
1234 result
= kload_error_link_load
;
1238 /* This section is always done in userland, but in kernel space
1239 * only if we're loading the kext, because what we have in kernel
1240 * space for an already-loaded kext is the kext itself, which
1241 * must not be touched again after it's been loaded and started.
1249 /* Get the linked image's kmod_info by translating from the
1250 * destined kernel-space address at kernel_kmod_info to an
1251 * offset from kld_header.
1253 local_kmod_info
= (kmod_info_t
*)((unsigned long)kernel_kmod_info
-
1254 (unsigned long)G_current_load_entry
->kernel_load_address
+
1255 (unsigned long)kld_header
);
1257 /* Stamp the bundle ID and version from the entry over anything
1258 * resident inside the kmod.
1260 bzero(local_kmod_info
->name
, sizeof(local_kmod_info
->name
));
1261 strcpy(local_kmod_info
->name
, entry
->expected_kmod_name
);
1263 bzero(local_kmod_info
->version
, sizeof(local_kmod_info
->version
));
1264 strcpy(local_kmod_info
->version
, entry
->expected_kmod_vers
);
1266 if (log_level
>= kload_log_level_details
) {
1267 kload_log_message("kmod name: %s" KNL
, local_kmod_info
->name
);
1268 kload_log_message("kmod start @ 0x%x (offset 0x%lx)" KNL
,
1269 (vm_address_t
)local_kmod_info
->start
,
1270 (unsigned long)local_kmod_info
->start
- (unsigned long)G_current_load_entry
->kernel_load_address
);
1271 kload_log_message("kmod stop @ 0x%x (offset 0x%lx)" KNL
,
1272 (vm_address_t
)local_kmod_info
->stop
,
1273 (unsigned long)local_kmod_info
->stop
- (unsigned long)G_current_load_entry
->kernel_load_address
);
1276 if (!local_kmod_info
->start
|| !local_kmod_info
->start
) {
1278 "error for module file %s; start or stop address is zero" KNL
,
1280 entry
->need_cleanup
= 1;
1281 result
= kload_error_link_load
;
1285 /* Record link info into kmod_info struct, rounding the hdr_size
1286 * to fit the adjustment that was made in __kload_linkedit_address().
1288 if (entry
->kernel_alloc_address
) {
1289 local_kmod_info
->address
= entry
->kernel_alloc_address
;
1291 local_kmod_info
->address
= entry
->loaded_address
;
1293 local_kmod_info
->size
= entry
->kernel_alloc_size
;
1294 local_kmod_info
->hdr_size
= round_page(entry
->kernel_hdr_size
);
1299 if (G_prelink
&& (entry
->name
!= entry
->link_output_file
))
1301 register_prelink(entry
, local_kmod_info
, kernel_kmod_info
);
1304 if (do_load
&& entry
->do_load
) {
1305 mach_result
= vm_allocate(mach_task_self(), &vm_buffer
,
1306 entry
->kernel_alloc_size
, TRUE
);
1307 if (mach_result
!= KERN_SUCCESS
) {
1308 kload_log_error("unable to vm_allocate() copy buffer" KNL
);
1309 entry
->need_cleanup
= 1;
1310 result
= kload_error_no_memory
; // FIXME: kernel error?
1314 dest_address
= (char *)vm_buffer
;
1316 memcpy(dest_address
, kld_header
, entry
->kernel_hdr_size
);
1317 memcpy(dest_address
+ round_page(entry
->kernel_hdr_size
),
1318 (void *)((unsigned long)kld_header
+ entry
->kernel_hdr_size
),
1319 entry
->kernel_load_size
- entry
->kernel_hdr_size
);
1321 mach_result
= vm_write(G_kernel_port
, entry
->kernel_alloc_address
,
1322 vm_buffer
, entry
->kernel_alloc_size
);
1323 if (mach_result
!= KERN_SUCCESS
) {
1324 kload_log_error("unable to write module to kernel memory" KNL
);
1325 entry
->need_cleanup
= 1;
1326 result
= kload_error_kernel_error
;
1330 mach_result
= kmod_create(G_kernel_priv_port
,
1331 (vm_address_t
)kernel_kmod_info
, &(entry
->kmod_id
));
1334 if (entry
->do_load
) {
1335 dest_address
= (char *)entry
->kernel_alloc_address
;
1336 memcpy(dest_address
, kld_header
, entry
->kernel_hdr_size
);
1337 memcpy(dest_address
+ round_page(entry
->kernel_hdr_size
),
1338 (void *)((unsigned long)kld_header
+ entry
->kernel_hdr_size
),
1339 entry
->kernel_load_size
- entry
->kernel_hdr_size
);
1341 /* We've written data & instructions into kernel memory, so flush
1342 * the data cache and invalidate the instruction cache.
1344 flush_dcache(entry
->kernel_alloc_address
, entry
->kernel_alloc_size
, false);
1345 invalidate_icache(entry
->kernel_alloc_address
, entry
->kernel_alloc_size
, false);
1347 mach_result
= kmod_create_internal(
1348 (kmod_info_t
*)kernel_kmod_info
, &(entry
->kmod_id
));
1350 #endif /* not KERNEL */
1352 if (mach_result
!= KERN_SUCCESS
) {
1353 kload_log_error("unable to register module with kernel" KNL
);
1354 entry
->need_cleanup
= 1;
1355 result
= kload_error_kernel_error
;
1360 if (interactive_level
|| log_level
>= kload_log_level_load_basic
) {
1362 if (log_level
>= kload_log_level_load_basic
) {
1363 #endif /* not KERNEL */
1365 "module %s created as # %d at address 0x%x, size %ld" KNL
,
1366 entry
->expected_kmod_name
, entry
->kmod_id
,
1367 entry
->kernel_alloc_address
,
1368 entry
->kernel_alloc_size
);
1374 #endif /* not KERNEL */
1377 if (interactive_level
) {
1379 "You can now break to the debugger and set breakpoints "
1380 " for this extension." KNL
);
1382 #endif /* not KERNEL */
1388 #endif /* not KERNEL */
1393 if (allocated_filename
) {
1394 free(allocated_filename
);
1397 vm_deallocate(mach_task_self(), vm_buffer
, entry
->kernel_alloc_size
);
1399 #endif /* not KERNEL */
1400 __kload_clear_kld_globals();
1405 /*******************************************************************************
1406 *******************************************************************************/
1410 register_prelink(dgraph_entry_t
* entry
,
1411 kmod_info_t
* local_kmod_info
, vm_offset_t kernel_kmod_info
)
1413 CFIndex i
, j
, depoffset
;
1417 depoffset
= CFDataGetLength(G_prelink_dependencies
) / sizeof(CFIndex
);
1419 for (i
= 0; i
< entry
->num_dependencies
; i
++)
1422 for (j
= 1; (j
< (1 + G_prelink
->modules
[0].id
)); j
++)
1424 exists
= (0 == strcmp(entry
->dependencies
[i
]->expected_kmod_name
,
1425 G_prelink
->modules
[j
].name
));
1431 bzero(&desc
, sizeof(desc
));
1432 strcpy(desc
.name
, entry
->dependencies
[i
]->expected_kmod_name
);
1434 if (log_level
>= kload_log_level_basic
) {
1435 kload_log_message("[%d] (dep)\n %s" KNL
,
1436 G_prelink
->modules
[0].id
+ 1, desc
.name
);
1438 G_prelink
->modules
[0].id
++;
1439 CFDataAppendBytes(G_prelink_data
, (UInt8
*) &desc
, sizeof(desc
));
1440 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
1443 G_prelink
->modules
[0].reference_count
++;
1444 OSWriteBigInt32(&j
, 0, j
);
1445 CFDataAppendBytes(G_prelink_dependencies
, (UInt8
*) &j
, sizeof(j
));
1447 if (log_level
>= kload_log_level_basic
) {
1448 kload_log_message("[%d] 0x%08x info 0x%08x\n %s,\n %s" KNL
,
1449 G_prelink
->modules
[0].id
+ 1, entry
->kernel_load_address
,
1450 kernel_kmod_info
, entry
->link_output_file
, entry
->name
);
1453 if (local_kmod_info
)
1454 desc
= *local_kmod_info
;
1457 bzero(&desc
, sizeof(desc
));
1458 desc
.size
= entry
->symbols_length
;
1461 desc
.id
= kernel_kmod_info
;
1462 desc
.reference_count
= entry
->num_dependencies
;
1463 desc
.reference_list
= (kmod_reference_t
*) depoffset
;
1465 /* Stamp the bundle ID and version from the entry over anything
1466 * resident inside the kmod.
1468 bzero(desc
.name
, sizeof(local_kmod_info
->name
));
1469 strcpy(desc
.name
, entry
->expected_kmod_name
);
1470 bzero(desc
.version
, sizeof(local_kmod_info
->version
));
1471 strcpy(desc
.version
, entry
->expected_kmod_vers
);
1473 G_prelink
->modules
[0].id
++;
1474 CFDataAppendBytes(G_prelink_data
, (UInt8
*) &desc
, sizeof(desc
));
1475 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
1477 return kload_error_none
;
1482 /*******************************************************************************
1484 *******************************************************************************/
1487 kload_error
kload_map_dgraph(
1489 const char * kernel_file
)
1491 kload_error
kload_map_dgraph(
1493 #endif /* not KERNEL */
1495 kload_error result
= kload_error_none
;
1498 if (log_level
>= kload_log_level_load_details
) {
1500 kload_log_message("mapping the kernel file %s" KNL
, kernel_file
);
1502 kload_log_message("mapping the kernel" KNL
);
1503 #endif /* not KERNEL */
1507 if (!kld_file_map(kernel_file
)) {
1508 result
= kload_error_link_load
;
1511 #endif /* not KERNEL */
1513 for (i
= 0; i
< dgraph
->length
; i
++) {
1514 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1516 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1520 result
= kload_map_entry(entry
);
1521 if (result
!= kload_error_none
) {
1531 /*******************************************************************************
1533 *******************************************************************************/
1535 kload_error
kload_map_entry(dgraph_entry_t
* entry
)
1537 kload_error result
= kload_error_none
;
1539 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1540 kload_log_error("attempt to map kernel component %s" KNL
, entry
->name
);
1541 result
= kload_error_invalid_argument
;
1545 if (log_level
>= kload_log_level_load_details
) {
1546 kload_log_message("mapping module file %s" KNL
, entry
->name
);
1549 if (kld_file_getaddr(entry
->name
, NULL
)) {
1550 if (log_level
>= kload_log_level_load_details
) {
1551 kload_log_message("module file %s is already mapped" KNL
, entry
->name
);
1553 result
= kload_error_none
;
1558 if (!kld_file_map(entry
->name
)) {
1560 if (!kld_file_map(entry
->name
, entry
->object
, entry
->object_length
,
1561 entry
->object_is_kmem
)) {
1562 #endif /* not KERNEL */
1563 kload_log_error("error mapping module file %s" KNL
, entry
->name
);
1565 result
= kload_error_link_load
;
1571 #endif /* not KERNEL */
1573 entry
->is_mapped
= true;
1575 /* Clear these bits now, as the kld patch module now owns the info
1576 * and it is subject to change. We reset them in the entry from the
1577 * kld patch module as needed.
1580 entry
->object_length
= 0;
1582 entry
->object_is_kmem
= false;
1585 // FIXME: Stop using this symbol; have the info passed in by
1586 // FIXME: ...the kext management library.
1588 if (!entry
->is_kernel_component
&& !kld_file_lookupsymbol(entry
->name
, "_kmod_info")) {
1589 kload_log_error("%s does not not contain kernel extension code" KNL
,
1591 result
= kload_error_executable_bad
;
1594 #endif /* not KERNEL */
1601 /*******************************************************************************
1603 *******************************************************************************/
1604 kload_error
kload_request_load_addresses(
1606 const char * kernel_file
)
1608 kload_error result
= kload_error_none
;
1610 const char * user_response
= NULL
; // must free
1612 unsigned int address
;
1614 /* We have to map all object files to get their CFBundleIdentifier
1617 result
= kload_map_dgraph(dgraph
, kernel_file
);
1618 if (result
!= kload_error_none
) {
1619 kload_log_error("error mapping object files" KNL
);
1623 // fixme: this shouldn't be printf, should it?
1624 printf("enter the hexadecimal load addresses for these modules:\n");
1626 for (i
= 0; i
< dgraph
->length
; i
++) {
1627 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1630 result
= kload_error_unspecified
;
1634 if (entry
->is_kernel_component
) {
1638 if (!entry
->is_mapped
) {
1639 result
= kload_error_unspecified
;
1643 user_response
= __kload_input_func("%s:",
1644 entry
->expected_kmod_name
);
1645 if (!user_response
) {
1646 result
= kload_error_unspecified
;
1649 scan_result
= sscanf(user_response
, "%x", &address
);
1650 if (scan_result
< 1 || scan_result
== EOF
) {
1651 result
= kload_error_unspecified
;
1654 entry
->loaded_address
= address
;
1662 /*******************************************************************************
1663 * addresses is a NULL-terminated list of string of the form "module_id@address"
1664 *******************************************************************************/
1665 kload_error
kload_set_load_addresses_from_args(
1667 const char * kernel_file
,
1670 kload_error result
= kload_error_none
;
1674 /* We have to map all object files to get their CFBundleIdentifier
1677 result
= kload_map_dgraph(dgraph
, kernel_file
);
1678 if (result
!= kload_error_none
) {
1679 kload_log_error("error mapping object files" KNL
);
1684 * Run through and assign all addresses to their relevant module
1687 for (i
= 0; i
< dgraph
->length
; i
++) {
1688 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1691 result
= kload_error_unspecified
;
1695 if (entry
->is_kernel_component
) {
1699 if (!entry
->is_mapped
) {
1700 result
= kload_error_unspecified
;
1704 for (j
= 0; addresses
[j
]; j
++) {
1705 char * this_addr
= addresses
[j
];
1706 char * address_string
= NULL
;
1707 unsigned int address
;
1708 unsigned int module_namelen
= strlen(entry
->expected_kmod_name
);
1711 result
= kload_error_unspecified
;
1715 if (strncmp(this_addr
, entry
->expected_kmod_name
, module_namelen
)) {
1718 if (this_addr
[module_namelen
] != '@') {
1722 address_string
= index(this_addr
, '@');
1723 if (!address_string
) {
1724 result
= kload_error_unspecified
;
1728 address
= strtoul(address_string
, NULL
, 16);
1729 entry
->loaded_address
= address
;
1734 * Now that we've done that see that all non-kernel modules do have
1735 * addresses set. If even one doesn't, we can't complete the link
1736 * relocation of symbols, so return a usage error.
1738 for (i
= 0; i
< dgraph
->length
; i
++) {
1739 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1741 if (entry
->is_kernel_component
) {
1745 if (!entry
->loaded_address
) {
1746 result
= kload_error_invalid_argument
;
1756 /*******************************************************************************
1757 * This function requires G_kernel_priv_port to be set before it will work.
1758 *******************************************************************************/
1759 kload_error
kload_set_load_addresses_from_kernel(
1761 const char * kernel_file
,
1764 kload_error result
= kload_error_none
;
1766 kmod_info_t
* loaded_modules
= NULL
;
1767 int loaded_bytecount
= 0;
1772 * We have to map the dgraph's modules before checking whether they've
1775 result
= kload_map_dgraph(dgraph
, kernel_file
);
1776 if (result
!= kload_error_none
) {
1777 kload_log_error("can't map module files" KNL
);
1782 /* First clear all the load addresses.
1784 for (i
= 0; i
< dgraph
->length
; i
++) {
1785 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1786 entry
->loaded_address
= 0;
1789 mach_result
= kmod_get_info(G_kernel_priv_port
,
1790 (void *)&loaded_modules
, &loaded_bytecount
);
1791 if (mach_result
!= KERN_SUCCESS
) {
1792 kload_log_error("kmod_get_info() failed" KNL
);
1793 result
= kload_error_kernel_error
;
1798 * Find out which modules have already been loaded & verify
1799 * that loaded versions are same as requested.
1801 for (i
= 0; i
< dgraph
->length
; i
++) {
1802 kload_error cresult
;
1803 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
1805 /* If necessary, check whether the current module is already loaded.
1806 * (We already did the root module above.)
1808 cresult
= __kload_check_module_loaded(dgraph
, current_entry
,
1809 loaded_modules
, do_load
);
1810 if ( ! (cresult
== kload_error_none
||
1811 cresult
== kload_error_already_loaded
) ) {
1814 if (current_entry
== dgraph
->root
&&
1815 cresult
== kload_error_already_loaded
) {
1823 if (loaded_modules
) {
1824 vm_deallocate(mach_task_self(), (vm_address_t
)loaded_modules
,
1833 /*******************************************************************************
1835 *******************************************************************************/
1837 kload_error
kload_set_load_addresses_from_kernel(
1840 kload_error result
= kload_error_none
;
1843 kmod_info_t
* loaded_modules
= NULL
;
1844 int loaded_bytecount
= 0;
1845 #endif /* not KERNEL */
1850 * We have to map the dgraph's modules before checking whether they've
1853 result
= kload_map_dgraph(dgraph
);
1854 if (result
!= kload_error_none
) {
1855 kload_log_error("can't map module files" KNL
);
1860 /* First clear all the load addresses.
1862 for (i
= 0; i
< dgraph
->length
; i
++) {
1863 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1864 entry
->loaded_address
= 0;
1868 * Find out which modules have already been loaded & verify
1869 * that loaded versions are same as requested.
1871 for (i
= 0; i
< dgraph
->length
; i
++) {
1872 kload_error cresult
;
1873 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
1875 /* If necessary, check whether the current module is already loaded.
1876 * (We already did the root module above.)
1878 cresult
= __kload_check_module_loaded(dgraph
, current_entry
, false);
1879 if ( ! (cresult
== kload_error_none
||
1880 cresult
== kload_error_already_loaded
) ) {
1883 if (current_entry
== dgraph
->root
&&
1884 cresult
== kload_error_already_loaded
) {
1894 #endif /* not KERNEL */
1896 /*******************************************************************************
1898 *******************************************************************************/
1900 extern kern_return_t
kmod_load_from_cache(const char * kmod_name
);
1903 static kmod_info_t
* __kload_find_kmod_info(const char * kmod_name
1906 kmod_info_t
* kmod_list
1907 #endif /* not KERNEL */
1913 for (i
= 0; ; i
++) {
1914 kmod_info_t
* current_kmod
= &(kmod_list
[i
]);
1915 if (0 == strcmp(current_kmod
->name
, kmod_name
)) {
1916 return current_kmod
;
1918 if (kmod_list
[i
].next
== 0) {
1925 info
= kmod_lookupbyname_locked(kmod_name
);
1926 if (!info
&& (KERN_SUCCESS
== kmod_load_from_cache(kmod_name
))) {
1927 info
= kmod_lookupbyname_locked(kmod_name
);
1930 #endif /* not KERNEL */
1933 /*******************************************************************************
1935 *******************************************************************************/
1937 kload_error
__kload_check_module_loaded(
1939 dgraph_entry_t
* entry
,
1941 kmod_info_t
* kmod_list
,
1942 #endif /* not KERNEL */
1945 kload_error result
= kload_error_none
;
1946 const char * kmod_name
;
1947 kmod_info_t
* current_kmod
= 0;
1949 VERS_version entry_vers
;
1950 VERS_version loaded_vers
;
1952 if (false && entry
->is_kernel_component
) {
1953 kmod_name
= entry
->name
;
1955 kmod_name
= entry
->expected_kmod_name
;
1956 if (log_level
>= kload_log_level_load_details
) {
1957 kload_log_message("checking whether module file %s is already loaded" KNL
,
1963 current_kmod
= __kload_find_kmod_info(kmod_name
, kmod_list
);
1965 current_kmod
= __kload_find_kmod_info(kmod_name
);
1966 #endif /* not KERNEL */
1968 if (!current_kmod
) {
1973 entry
->kmod_id
= current_kmod
->id
;
1974 entry
->loaded_address
= current_kmod
->address
;
1976 if (entry
->is_kernel_component
) {
1980 if (log_level
>= kload_log_level_load_details
) {
1981 kload_log_message("module file %s is loaded; checking status" KNL
,
1985 // We really want to move away from having this info in a kmod....
1987 loaded_vers
= VERS_parse_string(current_kmod
->version
);
1988 if (loaded_vers
< 0) {
1990 "can't parse version string \"%s\" of loaded module %s" KNL
,
1991 current_kmod
->version
,
1992 current_kmod
->name
);
1993 result
= kload_error_unspecified
;
1997 entry_vers
= VERS_parse_string(entry
->expected_kmod_vers
);
1998 if (entry_vers
< 0) {
2000 "can't parse version string \"%s\" of module file %s" KNL
,
2001 entry
->expected_kmod_name
,
2003 result
= kload_error_unspecified
;
2007 if (loaded_vers
!= entry_vers
) {
2009 "loaded version %s of module %s differs from "
2010 "requested version %s" KNL
,
2011 current_kmod
->version
,
2013 entry
->expected_kmod_name
);
2014 if (entry
== dgraph
->root
) {
2015 result
= kload_error_loaded_version_differs
;
2017 result
= kload_error_dependency_loaded_version_differs
;
2022 if (log_if_already
&& log_level
>=
2023 kload_log_level_load_basic
) {
2026 "module %s (identifier %s) is already loaded" KNL
,
2027 entry
->name
, kmod_name
);
2029 result
= kload_error_already_loaded
;
2035 // Do this ONLY if in the kernel!
2037 kfree((unsigned int)current_kmod
, sizeof(kmod_info_t
));
2043 /*******************************************************************************
2045 *******************************************************************************/
2047 kload_error
__kload_patch_dgraph(dgraph_t
* dgraph
2050 const char * kernel_file
2051 #endif /* not KERNEL */
2054 kload_error result
= kload_error_none
;
2058 if (!kld_file_merge_OSObjects(kernel_file
)) {
2059 result
= kload_error_link_load
;
2062 #endif /* not KERNEL */
2064 for (i
= 0; i
< dgraph
->length
; i
++) {
2065 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
2067 /* The kernel has already been patched.
2069 if (current_entry
->is_kernel_component
) {
2073 if (log_level
>= kload_log_level_load_details
) {
2074 kload_log_message("patching C++ code in module %s" KNL
,
2075 current_entry
->name
);
2079 /* In userland, we call the patch function for all kmods,
2080 * loaded or not, because we don't have all the info that
2081 * the kernel environment has.
2083 if (!kld_file_patch_OSObjects(current_entry
->name
)) {
2084 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2088 /* In the kernel, we call the merge function for already-loaded
2089 * kmods, since the kld patch environment retains info for kmods
2090 * that have already been patched. The patch function does a little
2091 * more work, and is only for kmods that haven't been processed yet.
2092 * NOTE: We are depending here on kload_check_module_loaded()
2093 * having been called, which is guaranteed by kload_load_dgraph()
2094 * is used, but not by its subroutines (such as
2095 * __kload_load_modules()).
2097 if (current_entry
->loaded_address
) {
2098 if (!kld_file_merge_OSObjects(current_entry
->name
)) {
2099 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2103 if (!kld_file_patch_OSObjects(current_entry
->name
)) {
2104 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2108 #endif /* not KERNEL */
2112 if (!kld_file_prepare_for_link()) {
2113 result
= kload_error_link_load
; // FIXME: need more specific error?
2122 /*******************************************************************************
2124 *******************************************************************************/
2125 #define __KLOAD_PATCH_EXTENSION ".patch"
2127 kload_error
__kload_output_patches(
2129 const char * patch_file
,
2130 const char * patch_dir
,
2131 int ask_overwrite_symbols
,
2132 int overwrite_symbols
)
2134 kload_error result
= kload_error_none
;
2136 char * allocated_filename
= NULL
;
2137 char * patch_filename
= NULL
;
2143 for (i
= 0; i
< dgraph
->length
; i
++) {
2145 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
2146 unsigned long length
;
2148 if (entry
->is_kernel_component
) {
2152 length
= strlen(patch_dir
) +
2153 strlen(entry
->expected_kmod_name
) +
2154 strlen(__KLOAD_PATCH_EXTENSION
) +
2155 1 + 1 ; // 1 for '/' added, 1 for terminating null
2156 if (length
>= MAXPATHLEN
) {
2158 "output filename \"%s/%s%s\" would be too long" KNL
,
2159 patch_dir
, entry
->expected_kmod_name
,
2160 __KLOAD_PATCH_EXTENSION
);
2161 result
= kload_error_invalid_argument
;
2165 allocated_filename
= (char *)malloc(length
);
2166 if (! allocated_filename
) {
2167 kload_log_error("malloc failure" KNL
);
2168 result
= kload_error_no_memory
;
2172 patch_filename
= allocated_filename
;
2173 strcpy(patch_filename
, patch_dir
);
2174 strcat(patch_filename
, "/");
2175 strcat(patch_filename
, entry
->expected_kmod_name
);
2176 strcat(patch_filename
, __KLOAD_PATCH_EXTENSION
);
2179 file_check
= kload_file_exists(patch_filename
);
2181 if (file_check
< 0) {
2182 kload_log_error("error checking existence of file %s" KNL
,
2184 } else if (file_check
> 0 && !overwrite_symbols
) {
2185 if (!ask_overwrite_symbols
) {
2187 "patch file %s exists; not overwriting" KNL
,
2191 int approve
= (*__kload_approve_func
)(1,
2192 "\nPatch file %s exists; overwrite", patch_filename
);
2195 result
= kload_error_unspecified
;
2198 output_patch
= approve
;
2204 if (log_level
>= kload_log_level_basic
) {
2205 kload_log_message("writing patch file %s" KNL
, patch_filename
);
2207 kld_file_debug_dump(entry
->name
, patch_filename
);
2210 if (allocated_filename
) free(allocated_filename
);
2211 allocated_filename
= NULL
;
2214 } else if (patch_file
) {
2216 file_check
= kload_file_exists(patch_file
);
2218 if (file_check
< 0) {
2219 kload_log_error("error checking existence of file %s" KNL
,
2221 } else if (file_check
> 0 && !overwrite_symbols
) {
2222 if (!ask_overwrite_symbols
) {
2223 kload_log_error("patch file %s exists; not overwriting" KNL
,
2227 int approve
= (*__kload_approve_func
)(1,
2228 "\nPatch file %s exists; overwrite", patch_filename
);
2231 result
= kload_error_unspecified
;
2234 output_patch
= approve
;
2240 if (log_level
>= kload_log_level_basic
) {
2241 kload_log_message("writing patch file %s" KNL
, patch_filename
);
2243 kld_file_debug_dump(dgraph
->root
->name
, patch_file
);
2248 if (allocated_filename
) free(allocated_filename
);
2252 #endif /* not KERNEL */
2254 /*******************************************************************************
2256 *******************************************************************************/
2258 kload_error
__kload_set_module_dependencies(dgraph_entry_t
* entry
) {
2259 kload_error result
= kload_error_none
;
2262 void * kmod_control_args
= 0;
2264 #endif /* not KERNEL */
2267 dgraph_entry_t
* current_dep
= NULL
;
2269 if (!entry
->do_load
) {
2270 result
= kload_error_already_loaded
;
2274 for (i
= 0; i
< entry
->num_dependencies
; i
++) {
2275 current_dep
= entry
->dependencies
[i
];
2277 if (log_level
>= kload_log_level_load_details
) {
2278 kload_log_message("adding reference from %s (%d) to %s (%d)" KNL
,
2279 entry
->expected_kmod_name
, entry
->kmod_id
,
2280 current_dep
->expected_kmod_name
, current_dep
->kmod_id
);
2283 packed_id
= KMOD_PACK_IDS(entry
->kmod_id
, current_dep
->kmod_id
);
2285 mach_result
= kmod_control(G_kernel_priv_port
,
2286 packed_id
, KMOD_CNTL_RETAIN
, &kmod_control_args
, &num_args
);
2288 mach_result
= kmod_retain(packed_id
);
2289 #endif /* not KERNEL */
2290 if (mach_result
!= KERN_SUCCESS
) {
2292 "kmod retain failed for %s; destroying kmod" KNL
,
2293 entry
->expected_kmod_name
);
2295 mach_result
= kmod_destroy(G_kernel_priv_port
, entry
->kmod_id
);
2297 mach_result
= kmod_destroy_internal(entry
->kmod_id
);
2298 #endif /* not KERNEL */
2299 if (mach_result
!= KERN_SUCCESS
) {
2300 kload_log_error("kmod destroy failed" KNL
);
2302 result
= kload_error_link_load
;
2307 if (log_level
>= kload_log_level_load_basic
) {
2308 kload_log_message("module # %d reference counts incremented" KNL
,
2316 /*******************************************************************************
2318 *******************************************************************************/
2320 kload_error
__kload_start_module(dgraph_entry_t
* entry
) {
2321 kload_error result
= kload_error_none
;
2324 void * kmod_control_args
= 0;
2326 #endif /* not KERNEL */
2328 if (!entry
->do_load
) {
2329 result
= kload_error_already_loaded
;
2334 mach_result
= kmod_control(G_kernel_priv_port
,
2335 entry
->kmod_id
, KMOD_CNTL_START
, &kmod_control_args
, &num_args
);
2337 mach_result
= kmod_start_or_stop(entry
->kmod_id
, 1, 0, 0);
2338 #endif /* not KERNEL */
2340 if (mach_result
!= KERN_SUCCESS
) {
2342 "kmod_control/start failed for %s; destroying kmod" KNL
,
2343 entry
->expected_kmod_name
);
2345 mach_result
= kmod_destroy(G_kernel_priv_port
, entry
->kmod_id
);
2347 mach_result
= kmod_destroy_internal(entry
->kmod_id
);
2348 #endif /* not KERNEL */
2349 if (mach_result
!= KERN_SUCCESS
) {
2350 kload_log_error("kmod destroy failed" KNL
);
2352 result
= kload_error_link_load
;
2356 if (log_level
>= kload_log_level_load_basic
) {
2357 kload_log_message("module # %d started" KNL
,
2365 /*******************************************************************************
2366 *******************************************************************************/
2368 /*******************************************************************************
2370 *******************************************************************************/
2372 unsigned long __kload_linkedit_address(
2374 unsigned long headers_size
)
2376 unsigned long round_segments_size
;
2377 unsigned long round_headers_size
;
2378 unsigned long round_size
;
2380 const struct machOMapping
{
2381 struct mach_header h
;
2382 struct segment_command seg
[1];
2385 if (!G_current_load_entry
) {
2389 // the actual size allocated by kld_load_from_memory()
2390 G_current_load_entry
->kernel_load_size
= size
;
2392 round_headers_size
= round_page(headers_size
);
2393 round_segments_size
= round_page(size
- headers_size
);
2394 round_size
= round_headers_size
+ round_segments_size
;
2396 G_current_load_entry
->kernel_alloc_size
= round_size
;
2398 // will need to be rounded *after* load/link
2399 G_current_load_entry
->kernel_hdr_size
= headers_size
;
2400 G_current_load_entry
->kernel_hdr_pad
= round_headers_size
- headers_size
;
2402 if (G_current_load_entry
->loaded_address
) {
2403 G_current_load_entry
->kernel_load_address
=
2404 G_current_load_entry
->loaded_address
+
2405 G_current_load_entry
->kernel_hdr_pad
;
2406 if (log_level
>= kload_log_level_load_basic
) {
2408 "using %s load address 0x%x (0x%x with header pad)" KNL
,
2409 G_current_load_entry
->kmod_id
? "existing" : "provided",
2410 G_current_load_entry
->loaded_address
,
2411 G_current_load_entry
->kernel_load_address
);
2413 return G_current_load_entry
->kernel_load_address
;
2416 machO
= (const struct machOMapping
*) G_current_load_entry
->object
;
2417 if (machO
->seg
[0].vmaddr
)
2419 G_current_load_entry
->loaded_address
= trunc_page(machO
->seg
[0].vmaddr
- machO
->seg
[0].fileoff
);
2421 G_current_load_entry
->kernel_load_address
= G_current_load_entry
->loaded_address
2422 + G_current_load_entry
->kernel_hdr_pad
;
2424 return G_current_load_entry
->kernel_load_address
;
2429 G_current_load_entry
->kernel_alloc_address
= G_prelink
->modules
[0].address
;
2430 G_prelink
->modules
[0].address
+= round_page(G_current_load_entry
->kernel_alloc_size
);
2431 mach_result
= KERN_SUCCESS
;
2433 } else if (G_syms_only
) {
2435 "internal error; asked to allocate kernel memory" KNL
);
2436 // FIXME: no provision for cleanup here
2437 return kload_error_unspecified
;
2440 #endif /* not KERNEL */
2444 mach_result
= vm_allocate(G_kernel_port
,
2445 &G_current_load_entry
->kernel_alloc_address
,
2446 G_current_load_entry
->kernel_alloc_size
, TRUE
);
2448 mach_result
= vm_allocate(kernel_map
,
2449 &G_current_load_entry
->kernel_alloc_address
,
2450 G_current_load_entry
->kernel_alloc_size
, TRUE
);
2451 #endif /* not KERNEL */
2454 if (mach_result
!= KERN_SUCCESS
) {
2455 kload_log_error("can't allocate kernel memory" KNL
);
2456 // FIXME: no provision for cleanup here
2457 return kload_error_kernel_error
;
2460 if (log_level
>= kload_log_level_load_basic
) {
2461 kload_log_message("allocated %ld bytes in kernel space at 0x%x" KNL
,
2462 G_current_load_entry
->kernel_alloc_size
,
2463 G_current_load_entry
->kernel_alloc_address
);
2466 G_current_load_entry
->kernel_load_address
=
2467 G_current_load_entry
->kernel_alloc_address
+
2468 G_current_load_entry
->kernel_hdr_pad
;
2470 G_current_load_entry
->loaded_address
= G_current_load_entry
->kernel_alloc_address
;
2472 if (log_level
>= kload_log_level_load_basic
) {
2474 "using load address of 0x%x" KNL
,
2475 G_current_load_entry
->kernel_alloc_address
);
2478 return G_current_load_entry
->kernel_load_address
;
2481 /*******************************************************************************
2483 *******************************************************************************/
2485 void __kload_clear_kld_globals(void) {
2486 G_current_load_entry
= NULL
;
2490 /*******************************************************************************
2492 *******************************************************************************/
2494 void __kload_clean_up_entry(dgraph_entry_t
* entry
) {
2497 if (entry
->need_cleanup
&& entry
->kernel_alloc_address
) {
2501 if ((entry
->kernel_alloc_address
+ entry
->kernel_alloc_size
) == G_prelink
->modules
[0].address
) {
2502 G_prelink
->modules
[0].address
= entry
->kernel_alloc_address
;
2505 "bad free load address of 0x%x (last 0x%x)" KNL
,
2506 entry
->kernel_alloc_address
, G_prelink
->modules
[0].address
);
2509 mach_result
= vm_deallocate(G_kernel_port
, entry
->kernel_alloc_address
,
2510 entry
->kernel_alloc_size
);
2513 mach_result
= vm_deallocate(kernel_map
, entry
->kernel_alloc_address
,
2514 entry
->kernel_alloc_size
);
2515 #endif /* not KERNEL */
2516 entry
->kernel_alloc_address
= 0;
2522 /*******************************************************************************
2524 *******************************************************************************/
2525 int kload_file_exists(const char * path
)
2527 int result
= 0; // assume it doesn't exist
2528 struct stat stat_buf
;
2530 if (stat(path
, &stat_buf
) == 0) {
2531 result
= 1; // the file does exist; we don't care beyond that
2537 result
= 0; // the file doesn't exist
2541 result
= -1; // unknown error
2549 #endif /* not KERNEL */
2551 /*******************************************************************************
2553 *******************************************************************************/
2555 void kload_set_log_level(kload_log_level level
)
2562 /*******************************************************************************
2564 *******************************************************************************/
2565 void kload_set_log_function(
2566 void (*func
)(const char * format
, ...))
2569 __kload_log_func
= &__kload_null_log
;
2571 __kload_log_func
= func
;
2576 /*******************************************************************************
2578 *******************************************************************************/
2579 void kload_set_error_log_function(
2580 void (*func
)(const char * format
, ...))
2583 __kload_err_log_func
= &__kload_null_err_log
;
2585 __kload_err_log_func
= func
;
2590 /*******************************************************************************
2592 *******************************************************************************/
2593 void kload_set_user_approve_function(
2594 int (*func
)(int default_answer
, const char * format
, ...))
2597 __kload_approve_func
= &__kload_null_approve
;
2599 __kload_approve_func
= func
;
2604 /*******************************************************************************
2606 *******************************************************************************/
2607 void kload_set_user_veto_function(
2608 int (*func
)(int default_answer
, const char * format
, ...))
2611 __kload_veto_func
= &__kload_null_veto
;
2613 __kload_veto_func
= func
;
2618 /*******************************************************************************
2620 *******************************************************************************/
2621 void kload_set_user_input_function(
2622 const char * (*func
)(const char * format
, ...))
2625 __kload_input_func
= &__kload_null_input
;
2627 __kload_input_func
= func
;
2632 /*******************************************************************************
2634 *******************************************************************************/
2636 void kload_log_message(const char * format
, ...)
2639 char fake_buffer
[2];
2641 char * output_string
;
2643 if (log_level
<= kload_log_level_silent
) {
2647 va_start(ap
, format
);
2648 output_length
= vsnprintf(fake_buffer
, 1, format
, ap
);
2651 output_string
= (char *)malloc(output_length
+ 1);
2652 if (!output_string
) {
2656 va_start(ap
, format
);
2657 vsprintf(output_string
, format
, ap
);
2660 __kload_log_func(output_string
);
2661 free(output_string
);
2666 /*******************************************************************************
2668 *******************************************************************************/
2670 void kload_log_error(const char * format
, ...)
2673 char fake_buffer
[2];
2675 char * output_string
;
2677 if (log_level
<= kload_log_level_silent
) {
2681 va_start(ap
, format
);
2682 output_length
= vsnprintf(fake_buffer
, 1, format
, ap
);
2685 output_string
= (char *)malloc(output_length
+ 1);
2686 if (!output_string
) {
2690 va_start(ap
, format
);
2691 vsprintf(output_string
, format
, ap
);
2694 __kload_err_log_func(output_string
);
2695 free(output_string
);
2699 /*******************************************************************************
2701 *******************************************************************************/
2702 void __kload_null_log(const char * format
, ...)
2707 /*******************************************************************************
2709 *******************************************************************************/
2710 void __kload_null_err_log(const char * format
, ...)
2715 /*******************************************************************************
2717 *******************************************************************************/
2718 int __kload_null_approve(int default_answer
, const char * format
, ...)
2723 /*******************************************************************************
2725 *******************************************************************************/
2726 int __kload_null_veto(int default_answer
, const char * format
, ...)
2731 /*******************************************************************************
2733 *******************************************************************************/
2734 const char * __kload_null_input(const char * format
, ...)
2739 /*******************************************************************************
2740 * The kld_patch.c module uses this function, if defined, to print errors. In
2741 * the kernel this function is defined in libsa/misc.c.
2742 *******************************************************************************/
2743 void kld_error_vprintf(const char * format
, va_list ap
) {
2744 if (log_level
<= kload_log_level_silent
) return;
2745 vfprintf(stderr
, format
, ap
);
2749 #endif /* not KERNEL */