2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
28 #include <CoreFoundation/CoreFoundation.h>
39 #include <sys/param.h>
40 #include <sys/types.h>
43 #include <mach/mach_types.h>
44 #include <mach/mach.h>
45 #include <mach/mach_init.h>
46 #include <mach/mach_error.h>
47 #include <mach/mach_host.h>
48 #include <mach/mach_port.h>
49 #include <mach-o/kld.h>
50 #include <mach-o/arch.h>
51 #include <mach-o/fat.h>
52 #include <mach-o/loader.h>
53 #include <mach-o/nlist.h>
54 #include <kern/kern_types.h>
55 #include <kern/kalloc.h>
56 #include <libkern/OSByteOrder.h>
58 #include "vers_rsrc.h"
62 #include <mach-o/kld.h>
63 #include <mach-o/loader.h>
64 #include <mach-o/nlist.h>
65 #include <libsa/vers_rsrc.h>
67 #endif /* not KERNEL */
71 #include "kld_patch.h"
83 #define PRIV_EXT __private_extern__
86 #define LOG_DELAY(x) IODelay((x) * 1000000)
87 #define VTYELLOW "\033[33m"
88 #define VTRESET "\033[0m"
95 #endif /* not KERNEL */
103 kmod_create_internal(
108 kmod_destroy_internal(kmod_t id
);
115 mach_msg_type_number_t
*dataCount
);
117 extern kern_return_t
kmod_retain(kmod_t id
);
118 extern kern_return_t
kmod_release(kmod_t id
);
120 extern struct mach_header _mh_execute_header
;
124 // Used to pass info between kld library and callbacks
125 static dgraph_entry_t
* G_current_load_entry
= NULL
;
128 static mach_port_t G_kernel_port
= PORT_NULL
;
129 static mach_port_t G_kernel_priv_port
= PORT_NULL
;
130 static int G_syms_only
;
133 register_prelink(dgraph_entry_t
* entry
,
134 kmod_info_t
* local_kmod_info
, vm_offset_t kernel_kmod_info
);
138 kmod_info_t modules
[1];
140 struct PrelinkState
* G_prelink
;
141 CFMutableDataRef G_prelink_data
;
142 CFMutableDataRef G_prelink_dependencies
;
144 #endif /* not KERNEL */
146 // used by dgraph.c so can't be static
147 kload_log_level log_level
= 0;
150 static void __kload_null_log(const char * format
, ...);
151 static void __kload_null_err_log(const char * format
, ...);
152 static int __kload_null_approve(int default_answer
, const char * format
, ...);
153 static int __kload_null_veto(int default_answer
, const char * format
, ...);
154 static const char * __kload_null_input(const char * format
, ...);
156 void (*__kload_log_func
)(const char * format
, ...) =
158 void (*__kload_err_log_func
)(const char * format
, ...) = &__kload_null_err_log
;
159 int (*__kload_approve_func
)(int default_answer
,
160 const char * format
, ...) = &__kload_null_approve
;
161 int (*__kload_veto_func
)(int default_answer
,
162 const char * format
, ...) = &__kload_null_veto
;
163 const char * (*__kload_input_func
)(const char * format
, ...) =
165 #endif /* not KERNEL */
167 static unsigned long __kload_linkedit_address(
169 unsigned long headers_size
);
170 static void __kload_clean_up_entry(dgraph_entry_t
* entry
);
171 static void __kload_clear_kld_globals(void);
172 static kload_error
__kload_patch_dgraph(dgraph_t
* dgraph
175 const char * kernel_file
176 #endif /* not KERNEL */
178 static kload_error
__kload_load_modules(dgraph_t
* dgraph
181 const char * kernel_file
,
182 const char * patch_file
, const char * patch_dir
,
183 const char * symbol_file
, const char * symbol_dir
,
184 int do_load
, int do_start_kmod
, int do_prelink
,
185 int interactive_level
,
186 int ask_overwrite_symbols
, int overwrite_symbols
187 #endif /* not KERNEL */
190 static kload_error
__kload_check_module_loaded(
192 dgraph_entry_t
* entry
,
194 kmod_info_t
* kmod_list
,
195 #endif /* not KERNEL */
198 static kload_error
__kload_load_module(dgraph_t
* dgraph
,
199 dgraph_entry_t
* entry
,
203 const char * symbol_file
,
204 const char * symbol_dir
,
206 int interactive_level
,
207 int ask_overwrite_symbols
,
208 int overwrite_symbols
209 #endif /* not KERNEL */
211 static kload_error
__kload_set_module_dependencies(dgraph_entry_t
* entry
);
212 static kload_error
__kload_start_module(dgraph_entry_t
* entry
);
215 static kload_error
__kload_output_patches(
217 const char * patch_file
,
218 const char * patch_dir
,
219 int ask_overwrite_symbols
,
220 int overwrite_symbols
);
222 Boolean
_IOReadBytesFromFile(CFAllocatorRef alloc
, const char *path
, void **bytes
,
223 CFIndex
*length
, CFIndex maxLength
);
224 Boolean
_IOWriteBytesToFile(const char *path
, const void *bytes
, CFIndex length
);
226 #endif /* not KERNEL */
228 /*******************************************************************************
230 *******************************************************************************/
232 kload_error
kload_load_dgraph(dgraph_t
* dgraph
235 const char * kernel_file
,
236 const char * patch_file
, const char * patch_dir
,
237 const char * symbol_file
, const char * symbol_dir
,
238 int do_load
, int do_start_kmod
, int do_prelink
,
239 int interactive_level
,
240 int ask_overwrite_symbols
, int overwrite_symbols
241 #endif /* not KERNEL */
244 kload_error result
= kload_error_none
;
245 int one_has_address
= 0;
246 int one_lacks_address
= 0;
251 syms_only
= (!do_load
) && (symbol_dir
|| symbol_file
);
253 if (log_level
>= kload_log_level_load_details
) {
254 kload_log_message("loading dependency graph:" KNL
);
258 if (syms_only
&& log_level
>= kload_log_level_load_details
) {
259 kload_log_message("loading for symbol generation only" KNL
);
263 * If we're not loading and have no request to emit a symbol
264 * or patch file, there's nothing to do!
266 if (!do_load
&& !symbol_dir
&& !symbol_file
&&
267 !patch_dir
&& !patch_file
) {
269 if (syms_only
&& log_level
>= kload_log_level_load_details
) {
270 kload_log_message("loader has no work to do" KNL
);
273 result
= kload_error_none
; // fixme: should this be USAGE error?
278 * If we're doing symbols only, then all entries in the dgraph must
279 * have addresses assigned, or none must.
282 if (log_level
>= kload_log_level_load_details
) {
283 kload_log_message("checking whether modules have addresses assigned" KNL
);
285 for (i
= 0; i
< dgraph
->length
; i
++) {
286 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
287 if (entry
->is_kernel_component
) {
290 if (entry
->loaded_address
!= 0) {
293 one_lacks_address
= 1;
297 #endif /* not KERNEL */
299 if (one_has_address
&& one_lacks_address
) {
301 "either all modules must have addresses set to nonzero values or "
303 result
= kload_error_invalid_argument
;
308 /* we need the priv port to check/load modules in the kernel.
310 if (PORT_NULL
== G_kernel_priv_port
) {
311 G_kernel_priv_port
= mach_host_self(); /* if we are privileged */
313 #endif /* not KERNEL */
316 * In the kernel, ALWAYS get load addresses of existing loaded kmods.
320 * If we don't have addresses, then get them from the kernel.
322 if (!one_has_address
&& !do_prelink
&& (do_load
|| symbol_file
|| symbol_dir
)) {
323 #endif /* not KERNEL */
324 if (log_level
>= kload_log_level_load_details
) {
325 kload_log_message("getting module addresses from kernel" KNL
);
328 result
= kload_set_load_addresses_from_kernel(dgraph
, kernel_file
,
331 result
= kload_set_load_addresses_from_kernel(dgraph
);
332 #endif /* not KERNEL */
333 if (result
== kload_error_already_loaded
) {
341 #endif /* not KERNEL */
343 } else if (result
!= kload_error_none
) {
344 kload_log_error("can't check load addresses of modules" KNL
);
349 #endif /* not KERNEL */
353 * At this point, if we're doing symbols only, it's an error to not
354 * have a load address for every module.
356 if (syms_only
&& !do_prelink
) {
357 if (log_level
>= kload_log_level_load_details
) {
358 kload_log_message("checking that all modules have addresses assigned" KNL
);
360 for (i
= 0; i
< dgraph
->length
; i
++) {
361 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
362 if (entry
->is_kernel_component
) {
365 if (!entry
->loaded_address
) {
367 "missing load address during symbol generation: %s" KNL
,
369 result
= kload_error_unspecified
;
379 CFAllocatorRef alloc
;
381 // We need a real allocator to pass to _IOReadBytesFromFile
382 alloc
= CFRetain(CFAllocatorGetDefault());
383 if (_IOReadBytesFromFile(alloc
, "prelinkstate", &bytes
, &length
, 0))
385 G_prelink_data
= CFDataCreateMutable(alloc
, 0);
386 CFDataAppendBytes(G_prelink_data
, (UInt8
*) bytes
, length
);
387 CFAllocatorDeallocate(alloc
, bytes
);
389 G_prelink_dependencies
= CFDataCreateMutable(alloc
, 0);
390 if (_IOReadBytesFromFile(alloc
, "prelinkdependencies", &bytes
, &length
, 0))
392 CFDataAppendBytes(G_prelink_dependencies
, (UInt8
*) bytes
, length
);
393 CFAllocatorDeallocate(alloc
, bytes
);
397 if (!G_prelink_data
) {
399 "can't get load address for prelink %s" KNL
, kernel_file
);
400 result
= kload_error_link_load
;
404 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
408 #endif /* not KERNEL */
412 result
= __kload_load_modules(dgraph
, kernel_file
,
413 patch_file
, patch_dir
, symbol_file
, symbol_dir
,
414 do_load
, do_start_kmod
, do_prelink
, interactive_level
,
415 ask_overwrite_symbols
, overwrite_symbols
);
417 result
= __kload_load_modules(dgraph
);
418 #endif /* not KERNEL */
423 /* Dispose of the host port to prevent security breaches and port
424 * leaks. We don't care about the kern_return_t value of this
425 * call for now as there's nothing we can do if it fails.
427 if (PORT_NULL
!= G_kernel_priv_port
) {
428 mach_port_deallocate(mach_task_self(), G_kernel_priv_port
);
429 G_kernel_priv_port
= PORT_NULL
;
431 #endif /* not KERNEL */
433 for (i
= 0; i
< dgraph
->length
; i
++) {
434 dgraph_entry_t
* current_entry
= dgraph
->graph
[i
];
435 __kload_clean_up_entry(current_entry
);
445 length
= CFDataGetLength(G_prelink_data
);
446 bytes
= (0 == length
) ? (const void *)"" : CFDataGetBytePtr(G_prelink_data
);
447 success
= _IOWriteBytesToFile("prelinkstate", bytes
, length
);
450 kload_log_error("write prelinkstate" KNL
);
451 result
= kload_error_link_load
;
453 length
= CFDataGetLength(G_prelink_dependencies
);
454 bytes
= (0 == length
) ? (const void *)"" : CFDataGetBytePtr(G_prelink_dependencies
);
455 success
= _IOWriteBytesToFile("prelinkdependencies", bytes
, length
);
458 kload_log_error("write prelinkdependencies" KNL
);
459 result
= kload_error_link_load
;
462 #endif /* not KERNEL */
468 /*******************************************************************************
469 * This function claims the option flags d and D for object file dependencies
470 * and in-kernel dependencies, respectively.
471 *******************************************************************************/
472 kload_error
kload_load_with_arglist(
473 int argc
, char **argv
,
474 const char * kernel_file
,
475 const char * patch_file
, const char * patch_dir
,
476 const char * symbol_file
, const char * symbol_dir
,
477 int do_load
, int do_start_kmod
,
478 int interactive_level
,
479 int ask_overwrite_symbols
, int overwrite_symbols
)
481 kload_error result
= kload_error_none
;
482 dgraph_error_t dgraph_result
;
483 int syms_only
= (!do_load
) && (symbol_file
|| symbol_dir
);
485 static dgraph_t dependency_graph
;
487 /* Zero out fields in dependency graph for proper error handling later.
489 bzero(&dependency_graph
, sizeof(dependency_graph
));
491 dgraph_result
= dgraph_init_with_arglist(&dependency_graph
,
492 syms_only
, "-d", "-D", argc
, argv
);
493 if (dgraph_result
== dgraph_error
) {
494 kload_log_error("error processing dependency list" KNL
);
495 result
= kload_error_unspecified
;
497 } else if (dgraph_result
== dgraph_invalid
) {
498 // anything to print here, or did init call print something?
499 result
= kload_error_invalid_argument
;
503 result
= kload_load_dgraph(&dependency_graph
, kernel_file
,
504 patch_file
, patch_dir
, symbol_file
, symbol_dir
,
505 do_load
, do_start_kmod
, false /* do_prelink */, interactive_level
,
506 ask_overwrite_symbols
, overwrite_symbols
);
511 #endif /* not KERNEL */
512 /*******************************************************************************
513 * This function can only operate on 32 bit mach object file symbol table
515 *******************************************************************************/
517 kload_error
__kload_keep_symbols(dgraph_entry_t
* entry
)
519 struct mach_header
* hdr
;
520 struct segment_command
* seg
;
522 struct symtab_command
* symcmd
;
523 unsigned long idx
, ncmds
;
528 return kload_error_none
;
530 hdr
= entry
->linked_image
;
532 seg
= (struct segment_command
*)(hdr
+ 1);
535 idx
++, seg
= (struct segment_command
*)(((vm_offset_t
)seg
) + seg
->cmdsize
))
537 if (LC_SYMTAB
== seg
->cmd
)
542 kload_log_error("no LC_SYMTAB" KNL
);
543 return kload_error_unspecified
;
546 symcmd
= (struct symtab_command
*) seg
;
549 struct mach_header hdr
;
550 struct segment_command seg
;
551 struct symtab_command symcmd
;
553 struct load_cmds
* cmd
;
554 unsigned int symtabsize
;
556 symtabsize
= symcmd
->stroff
+ symcmd
->strsize
- symcmd
->symoff
;
558 size
= sizeof(struct load_cmds
) + symtabsize
;
560 mem
= (vm_offset_t
) malloc(size
);
562 cmd
= (struct load_cmds
*) mem
;
563 sym
= (struct nlist
*) (cmd
+ 1);
566 cmd
->symcmd
= *symcmd
;
567 bcopy((const void *) (((vm_offset_t
) hdr
) + symcmd
->symoff
),
571 hdr
= (struct mach_header
*) mem
;
573 cmd
->hdr
.sizeofcmds
= sizeof(struct load_cmds
) - sizeof(struct mach_header
);
574 cmd
->hdr
.flags
&= ~MH_INCRLINK
;
576 cmd
->symcmd
.stroff
-= (symcmd
->symoff
- sizeof(struct load_cmds
));
577 cmd
->symcmd
.symoff
= sizeof(struct load_cmds
);
579 cmd
->seg
.cmd
= LC_SEGMENT
;
580 cmd
->seg
.cmdsize
= sizeof(struct segment_command
);
581 strcpy(cmd
->seg
.segname
, SEG_LINKEDIT
);
584 cmd
->seg
.fileoff
= cmd
->symcmd
.symoff
;
585 cmd
->seg
.filesize
= symtabsize
;
586 cmd
->seg
.maxprot
= 7;
587 cmd
->seg
.initprot
= 1;
591 sym
= (struct nlist
*) (cmd
+ 1);
592 for (idx
= 0; idx
< symcmd
->nsyms
; idx
++, sym
++)
594 if ( (sym
->n_type
& N_STAB
) != 0)
598 sym
->n_value
= sym
->n_un
.n_strx
;
599 sym
->n_un
.n_strx
= 0;
600 sym
->n_sect
= NO_SECT
;
602 else if ( (sym
->n_type
& N_TYPE
) == N_SECT
)
604 sym
->n_sect
= NO_SECT
;
605 sym
->n_type
= (sym
->n_type
& ~N_TYPE
) | N_ABS
;
608 if (log_level
>= kload_log_level_load_details
)
610 kload_log_message("__kload_keep_symbols %s, nsyms %ld, 0x%x bytes" KNL
,
611 entry
->name
, symcmd
->nsyms
, size
);
614 entry
->symbols
= mem
;
615 entry
->symbols_malloc
= mem
;
616 entry
->symbols_length
= size
;
618 return kload_error_none
;
622 /*******************************************************************************
623 * This function can only operate on 32 bit mach object files
624 *******************************************************************************/
626 kload_error
__kload_make_opaque_basefile(dgraph_t
* dgraph
, struct mach_header
* hdr
)
628 struct segment_command
* seg
;
629 struct segment_command
* data_seg
;
630 struct segment_command
* text_seg
;
631 struct section
* sec
;
634 unsigned long idx
, ncmds
;
636 vm_address_t mem
, out
;
637 static vm_address_t keep_base_image
;
638 static vm_size_t keep_base_size
;
640 if (dgraph
->opaque_base_image
)
641 return kload_error_none
;
645 dgraph
->opaque_base_image
= keep_base_image
;
646 dgraph
->opaque_base_length
= keep_base_size
;
647 return kload_error_none
;
650 data_seg
= text_seg
= NULL
;
652 seg
= (struct segment_command
*)(hdr
+ 1);
655 idx
++, seg
= (struct segment_command
*)(((vm_offset_t
)seg
) + seg
->cmdsize
))
657 if (LC_SEGMENT
!= seg
->cmd
)
659 if (!strcmp(SEG_TEXT
, seg
->segname
))
661 else if (!strcmp(SEG_DATA
, seg
->segname
))
664 if (!text_seg
|| !data_seg
)
666 kload_log_error("no SEG_TEXT or SEG_DATA" KNL
);
667 return kload_error_unspecified
;
670 size
= sizeof(struct mach_header
) + text_seg
->cmdsize
+ data_seg
->cmdsize
;
671 mem
= (vm_offset_t
) malloc(size
);
674 bcopy(hdr
, (void *) out
, sizeof(struct mach_header
));
675 hdr
= (struct mach_header
*) out
;
676 out
+= sizeof(struct mach_header
);
678 bcopy(text_seg
, (void *) out
, text_seg
->cmdsize
);
679 text_seg
= (struct segment_command
*) out
;
680 out
+= text_seg
->cmdsize
;
682 bcopy(data_seg
, (void *) out
, data_seg
->cmdsize
);
683 data_seg
= (struct segment_command
*) out
;
684 out
+= data_seg
->cmdsize
;
687 hdr
->sizeofcmds
= text_seg
->cmdsize
+ data_seg
->cmdsize
;
689 offset
= hdr
->sizeofcmds
;
691 text_seg
->fileoff
= offset
;
692 text_seg
->filesize
= 0;
694 sec
= (struct section
*)(text_seg
+ 1);
695 for (j
= 0; j
< text_seg
->nsects
; j
++, sec
++)
697 // sec->addr = (unsigned long) addr;
699 sec
->offset
= offset
;
703 data_seg
->fileoff
= offset
;
704 data_seg
->filesize
= 0;
706 sec
= (struct section
*)(data_seg
+ 1);
707 for (j
= 0; j
< data_seg
->nsects
; j
++, sec
++)
709 // sec->addr = (unsigned long) addr;
711 sec
->offset
= offset
;
715 dgraph
->opaque_base_image
= mem
;
716 dgraph
->opaque_base_length
= size
;
717 keep_base_image
= mem
;
718 keep_base_size
= size
;
720 return kload_error_none
;
723 /*******************************************************************************
725 *******************************************************************************/
727 kload_error
__kload_load_modules(dgraph_t
* dgraph
730 const char * kernel_file
,
731 const char * patch_file
,
732 const char * patch_dir
,
733 const char * symbol_file
,
734 const char * symbol_dir
,
738 int interactive_level
,
739 int ask_overwrite_symbols
,
740 int overwrite_symbols
741 #endif /* not KERNEL */
744 kload_error result
= kload_error_none
;
746 long int kernel_size
= 0;
747 kern_return_t mach_result
= KERN_SUCCESS
;
748 #endif /* not KERNEL */
749 char * kernel_base_addr
= 0;
751 Boolean cleanup_kld_loader
= false;
754 /* We have to map all object files to get their CFBundleIdentifier
758 result
= kload_map_dgraph(dgraph
, kernel_file
);
760 result
= kload_map_dgraph(dgraph
);
761 #endif /* not KERNEL */
762 if (result
!= kload_error_none
) {
763 kload_log_error("error mapping object files" KNL
);
768 result
= __kload_patch_dgraph(dgraph
, kernel_file
);
770 result
= __kload_patch_dgraph(dgraph
);
771 #endif /* not KERNEL */
772 if (result
!= kload_error_none
) {
773 // FIXME: print an error message here?
778 // FIXME: check error return
779 __kload_output_patches(dgraph
, patch_file
, patch_dir
,
780 ask_overwrite_symbols
, overwrite_symbols
);
783 * If we're not loading or writing symbols, we're done.
785 if (!do_load
&& !do_prelink
&& !symbol_file
&& !symbol_dir
) {
789 if (do_load
&& PORT_NULL
== G_kernel_port
) {
790 mach_result
= task_for_pid(mach_task_self(), 0, &G_kernel_port
);
791 if (mach_result
!= KERN_SUCCESS
) {
792 kload_log_error("unable to get kernel task port: %s" KNL
,
793 mach_error_string(mach_result
));
794 kload_log_error("you must be running as root to load "
795 "modules into the kernel" KNL
);
796 result
= kload_error_kernel_permission
;
800 #endif /* not KERNEL */
802 kld_address_func(&__kload_linkedit_address
);
805 G_syms_only
= (!do_load
) && (symbol_file
|| symbol_dir
|| patch_dir
);
807 kernel_base_addr
= kld_file_getaddr(kernel_file
, &kernel_size
);
808 if (!kernel_base_addr
) {
810 "can't get load address for kernel %s" KNL
, kernel_file
);
811 result
= kload_error_link_load
;
816 const char * kernel_file
= "(kernel)";
817 kernel_base_addr
= (char *) &_mh_execute_header
;
819 #endif /* not KERNEL */
822 if (dgraph
->has_symbol_sets
)
824 result
= __kload_make_opaque_basefile(dgraph
, (struct mach_header
*) kernel_base_addr
);
825 if (result
!= kload_error_none
) {
826 kload_log_error("can't construct opaque base image from %s" KNL
, kernel_file
);
830 kld_result
= kld_load_basefile_from_memory(kernel_file
,
831 (char *) dgraph
->opaque_base_image
,
832 dgraph
->opaque_base_length
);
836 kld_result
= kld_load_basefile_from_memory(kernel_file
,
837 (char *) kernel_base_addr
, kernel_size
);
838 #endif /* not KERNEL */
841 kload_log_error("can't link base image %s" KNL
, kernel_file
);
842 result
= kload_error_link_load
;
846 cleanup_kld_loader
= true;
847 char opaque_now
= false;
849 for (i
= 0; i
< dgraph
->length
; i
++) {
850 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
852 opaque_now
|= current_entry
->opaque_link
;
854 if (kOpaqueLink
& opaque_now
)
858 if (log_level
>= kload_log_level_load_details
)
860 kload_log_message("opaque link for %s" KNL
, current_entry
->name
);
863 kld_set_link_options(KLD_STRIP_ALL
); // KLD_STRIP_NONE
865 if (dgraph
->have_loaded_symbols
)
868 if (kRawKernelLink
& current_entry
->opaque_link
) {
870 kld_result
= kld_load_basefile_from_memory(kernel_file
,
871 (char *) kernel_base_addr
, kernel_size
);
874 kld_result
= kld_load_basefile_from_memory(kernel_file
,
875 (char *) dgraph
->opaque_base_image
,
876 dgraph
->opaque_base_length
);
877 dgraph
->have_loaded_symbols
= false;
880 kload_log_error("can't link base image %s" KNL
, kernel_file
);
881 result
= kload_error_link_load
;
886 for (j
= 0; j
< i
; j
++)
889 dgraph_entry_t
* image_dep
= dgraph
->load_order
[j
];
891 if (current_entry
->opaque_link
)
894 (k
< current_entry
->num_dependencies
)
895 && (current_entry
->dependencies
[k
] != image_dep
);
898 if (k
== current_entry
->num_dependencies
)
902 if (!current_entry
->opaque_link
&& image_dep
->opaques
)
904 // kpi not on direct dependency list
907 if (kRawKernelLink
& image_dep
->opaques
)
909 // raw kernel already in base image
913 if (!image_dep
->symbols
)
915 kload_log_error("internal error; no dependent symbols" KNL
);
916 result
= kload_error_link_load
;
921 struct mach_header
* kld_header
;
924 kld_result
= kld_load_from_memory(&kld_header
, image_dep
->name
,
925 (char *) image_dep
->symbols
, image_dep
->symbols_length
, NULL
);
927 kld_result
= kld_load_from_memory(&kld_header
, image_dep
->name
,
928 (char *) image_dep
->symbols
, image_dep
->symbols_length
);
929 #endif /* not KERNEL */
931 kload_log_error("can't link dependent image %s" KNL
, image_dep
->name
);
932 result
= kload_error_link_load
;
935 kld_forget_symbol("_kmod_info");
936 dgraph
->have_loaded_symbols
= true;
941 if (dgraph
->has_opaque_links
943 || symbol_file
|| symbol_dir
946 kld_set_link_options(KLD_STRIP_NONE
);
948 kld_set_link_options(KLD_STRIP_ALL
);
951 result
= __kload_load_module(dgraph
, current_entry
,
952 (current_entry
== dgraph
->root
),
953 symbol_file
, symbol_dir
, do_load
,
954 interactive_level
, ask_overwrite_symbols
, overwrite_symbols
);
956 result
= __kload_load_module(dgraph
, current_entry
,
957 (current_entry
== dgraph
->root
));
958 #endif /* not KERNEL */
959 if (result
!= kload_error_none
) {
963 if (dgraph
->has_opaque_links
&& (current_entry
!= dgraph
->root
))
965 if (!(kRawKernelLink
& current_entry
->opaques
)) {
966 result
= __kload_keep_symbols(current_entry
);
968 if (result
!= kload_error_none
) {
969 kload_log_error("__kload_keep_symbols() failed for module %s" KNL
,
970 current_entry
->name
);
976 if (do_load
&& current_entry
->do_load
) {
978 if (current_entry
->do_load
) {
979 #endif /* not KERNEL */
980 result
= __kload_set_module_dependencies(current_entry
);
981 if ( ! (result
== kload_error_none
||
982 result
== kload_error_already_loaded
) ) {
987 if ( (interactive_level
== 1 && current_entry
== dgraph
->root
) ||
988 (interactive_level
== 2) ) {
990 int approve
= (*__kload_approve_func
)(1,
991 "\nStart module %s (ansering no will abort the load)",
992 current_entry
->name
);
995 do_start_kmod
= true; // override 'cause user said so
997 kern_return_t mach_result
;
999 kload_log_message("error reading user response; "
1000 "destroying loaded module" KNL
);
1002 kload_log_message("user canceled module start; "
1003 "destroying loaded module" KNL
);
1005 mach_result
= kmod_destroy(G_kernel_priv_port
, current_entry
->kmod_id
);
1006 if (mach_result
!= KERN_SUCCESS
) {
1007 kload_log_error("kmod_destroy() failed" KNL
);
1010 result
= kload_error_unspecified
;
1013 result
= kload_error_user_abort
;
1018 #endif /* not KERNEL */
1021 if (current_entry
!= dgraph
->root
||
1022 (current_entry
== dgraph
->root
&& do_start_kmod
)) {
1023 #endif /* not KERNEL */
1025 result
= __kload_start_module(current_entry
);
1026 if ( ! (result
== kload_error_none
||
1027 result
== kload_error_already_loaded
) ) {
1030 } else if (interactive_level
||
1031 log_level
>= kload_log_level_load_details
) {
1033 } else if (log_level
>= kload_log_level_load_details
) {
1034 #endif /* not KERNEL */
1036 kload_log_message("started module %s" KNL
,
1037 current_entry
->name
);
1040 } /* current_entry... */
1041 #endif /* not KERNEL */
1048 #endif /* not KERNEL */
1049 } /* for i, dgraph->length */
1054 /* Dispose of the kernel port to prevent security breaches and port
1055 * leaks. We don't care about the kern_return_t value of this
1056 * call for now as there's nothing we can do if it fails.
1058 if (PORT_NULL
!= G_kernel_port
) {
1059 mach_port_deallocate(mach_task_self(), G_kernel_port
);
1060 G_kernel_port
= PORT_NULL
;
1062 #endif /* not KERNEL */
1064 if (cleanup_kld_loader
) {
1072 /*******************************************************************************
1074 *******************************************************************************/
1077 #define __KLOAD_SYMBOL_EXTENSION ".sym"
1078 #endif /* not KERNEL */
1081 kload_error
__kload_load_module(dgraph_t
* dgraph
,
1082 dgraph_entry_t
* entry
,
1084 __unused
int is_root
1085 #else /* not KERNEL */
1087 const char * symbol_file
,
1088 const char * symbol_dir
,
1090 int interactive_level
,
1091 int ask_overwrite_symbols
,
1092 int overwrite_symbols
1093 #endif /* not KERNEL */
1096 kload_error result
= kload_error_none
;
1100 struct mach_header
* kld_header
;
1101 const char * kmod_symbol
= "_kmod_info";
1102 unsigned long kernel_kmod_info
;
1103 kmod_info_t
* local_kmod_info
= NULL
;
1104 char * dest_address
= 0;
1106 char * allocated_filename
= NULL
;
1107 char * symbol_filename
= NULL
;
1109 vm_address_t vm_buffer
= 0;
1110 #endif /* not KERNEL */
1112 /* A kernel component is by nature already linked and loaded and has
1113 * no work to be done upon it.
1115 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1116 result
= kload_error_none
;
1120 G_current_load_entry
= entry
;
1122 if (log_level
>= kload_log_level_load_basic
) {
1125 #endif /* not KERNEL */
1126 kload_log_message("link/loading file %s" KNL
, entry
->name
);
1129 kload_log_message("linking file %s" KNL
, entry
->name
);
1131 #endif /* not KERNEL */
1135 if (entry
->link_output_file
!= entry
->name
) {
1136 symbol_filename
= entry
->link_output_file
;
1139 if (symbol_filename
) {
1140 file_check
= kload_file_exists(symbol_filename
);
1141 if (file_check
< 0) {
1142 kload_log_error("error checking existence of file %s" KNL
,
1144 } else if (file_check
> 0 && !overwrite_symbols
) {
1146 if (!ask_overwrite_symbols
) {
1147 kload_log_message("symbol file %s exists; not overwriting" KNL
,
1149 symbol_filename
= NULL
;
1151 int approve
= (*__kload_approve_func
)(1,
1152 "\nSymbol file %s exists; overwrite", symbol_filename
);
1155 result
= kload_error_unspecified
;
1157 } else if (approve
== 0) {
1158 if (allocated_filename
) free(allocated_filename
);
1159 allocated_filename
= NULL
;
1160 symbol_filename
= NULL
;
1166 if (symbol_filename
&&
1167 (interactive_level
||
1168 log_level
>= kload_log_level_basic
) ) {
1170 kload_log_message("writing symbol file %s" KNL
, symbol_filename
);
1174 if (interactive_level
&& entry
->loaded_address
) {
1176 "module %s is already loaded as %s at address 0x%08x" KNL
,
1177 entry
->name
, entry
->expected_kmod_name
,
1178 entry
->loaded_address
);
1179 } else if ( (interactive_level
== 1 && is_root
) ||
1180 (interactive_level
== 2) ) {
1182 int approve
= (*__kload_approve_func
)(1,
1183 "\nLoad module %s", entry
->name
);
1186 result
= kload_error_unspecified
;
1188 } else if (approve
== 0) {
1189 result
= kload_error_user_abort
;
1194 #endif /* not KERNEL */
1196 entry
->object
= kld_file_getaddr(entry
->name
, &entry
->object_length
);
1197 if (!entry
->object
) {
1198 kload_log_error("kld_file_getaddr() failed for module %s" KNL
,
1200 __kload_clear_kld_globals();
1201 result
= kload_error_link_load
;
1205 if (entry
->is_symbol_set
) {
1206 entry
->symbols
= (vm_address_t
) entry
->object
;
1207 entry
->symbols_length
= entry
->object_length
;
1210 if (symbol_filename
) {
1211 if (!_IOWriteBytesToFile(symbol_filename
, (void *) entry
->symbols
, entry
->symbols_length
)) {
1212 kload_log_error("write symbol file failed for module %s" KNL
,
1214 __kload_clear_kld_globals();
1215 result
= kload_error_link_load
;
1218 symbol_filename
= 0;
1219 if (G_prelink
&& (entry
->name
!= entry
->link_output_file
))
1221 kload_log_error("prelink %s %s %s" KNL
,
1222 entry
->name
, entry
->link_output_file
, entry
->expected_kmod_name
);
1223 register_prelink(entry
, NULL
, NULL
);
1226 #endif /* not KERNEL */
1227 if (entry
->opaques
) {
1228 result
= kload_error_none
;
1234 kld_result
= kld_load_from_memory(&kld_header
, entry
->name
,
1235 entry
->object
, entry
->object_length
, symbol_filename
);
1237 kld_result
= kld_load_from_memory(&kld_header
, entry
->name
,
1238 entry
->object
, entry
->object_length
);
1239 #endif /* not KERNEL */
1244 #endif /* not KERNEL */
1246 dgraph
->have_loaded_symbols
= true;
1248 if (!kld_result
|| !entry
->kernel_load_address
) {
1249 kload_log_error("kld_load_from_memory() failed for module %s" KNL
,
1251 __kload_clear_kld_globals();
1252 entry
->need_cleanup
= 1;
1253 result
= kload_error_link_load
;
1257 if (entry
->is_symbol_set
) {
1258 result
= kload_error_none
;
1262 entry
->linked_image
= kld_header
;
1263 entry
->linked_image_length
= -1; // unknown!
1265 /* If we're in the kernel and not loading (as when handling an
1266 * already-loaded dependency), we don't need to waste any CPU
1267 * cycles looking up the kmod_info struct.
1270 if (entry
->do_load
) {
1273 kld_result
= kld_lookup(kmod_symbol
, &kernel_kmod_info
);
1275 kload_log_error("kld_lookup(\"%s\") failed for module %s" KNL
,
1276 kmod_symbol
, entry
->name
);
1277 entry
->need_cleanup
= 1;
1278 result
= kload_error_link_load
;
1286 kld_result
= kld_forget_symbol(kmod_symbol
);
1290 #endif /* not KERNEL */
1292 kload_log_error("kld_forget_symbol(\"%s\") failed for module %s" KNL
,
1293 kmod_symbol
, entry
->name
);
1294 entry
->need_cleanup
= 1;
1295 result
= kload_error_link_load
;
1299 /* This section is always done in userland, but in kernel space
1300 * only if we're loading the kext, because what we have in kernel
1301 * space for an already-loaded kext is the kext itself, which
1302 * must not be touched again after it's been loaded and started.
1310 /* Get the linked image's kmod_info by translating from the
1311 * destined kernel-space address at kernel_kmod_info to an
1312 * offset from kld_header.
1314 local_kmod_info
= (kmod_info_t
*)((unsigned long)kernel_kmod_info
-
1315 (unsigned long)G_current_load_entry
->kernel_load_address
+
1316 (unsigned long)kld_header
);
1318 /* Stamp the bundle ID and version from the entry over anything
1319 * resident inside the kmod.
1321 bzero(local_kmod_info
->name
, sizeof(local_kmod_info
->name
));
1322 strcpy(local_kmod_info
->name
, entry
->expected_kmod_name
);
1324 bzero(local_kmod_info
->version
, sizeof(local_kmod_info
->version
));
1325 strcpy(local_kmod_info
->version
, entry
->expected_kmod_vers
);
1327 if (log_level
>= kload_log_level_details
) {
1328 kload_log_message("kmod name: %s" KNL
, local_kmod_info
->name
);
1329 kload_log_message("kmod start @ 0x%x (offset 0x%lx)" KNL
,
1330 (vm_address_t
)local_kmod_info
->start
,
1331 (unsigned long)local_kmod_info
->start
- (unsigned long)G_current_load_entry
->kernel_load_address
);
1332 kload_log_message("kmod stop @ 0x%x (offset 0x%lx)" KNL
,
1333 (vm_address_t
)local_kmod_info
->stop
,
1334 (unsigned long)local_kmod_info
->stop
- (unsigned long)G_current_load_entry
->kernel_load_address
);
1337 if (!local_kmod_info
->start
|| !local_kmod_info
->start
) {
1339 "error for module file %s; start or stop address is zero" KNL
,
1341 entry
->need_cleanup
= 1;
1342 result
= kload_error_link_load
;
1346 /* Record link info into kmod_info struct, rounding the hdr_size
1347 * to fit the adjustment that was made in __kload_linkedit_address().
1349 if (entry
->kernel_alloc_address
) {
1350 local_kmod_info
->address
= entry
->kernel_alloc_address
;
1352 local_kmod_info
->address
= entry
->loaded_address
;
1354 local_kmod_info
->size
= entry
->kernel_alloc_size
;
1355 local_kmod_info
->hdr_size
= round_page(entry
->kernel_hdr_size
);
1360 if (G_prelink
&& (entry
->name
!= entry
->link_output_file
))
1362 register_prelink(entry
, local_kmod_info
, kernel_kmod_info
);
1365 if (do_load
&& entry
->do_load
) {
1366 mach_result
= vm_allocate(mach_task_self(), &vm_buffer
,
1367 entry
->kernel_alloc_size
, VM_FLAGS_ANYWHERE
);
1368 if (mach_result
!= KERN_SUCCESS
) {
1369 kload_log_error("unable to vm_allocate() copy buffer" KNL
);
1370 entry
->need_cleanup
= 1;
1371 result
= kload_error_no_memory
; // FIXME: kernel error?
1375 dest_address
= (char *)vm_buffer
;
1377 memcpy(dest_address
, kld_header
, entry
->kernel_hdr_size
);
1378 memcpy(dest_address
+ round_page(entry
->kernel_hdr_size
),
1379 (void *)((unsigned long)kld_header
+ entry
->kernel_hdr_size
),
1380 entry
->kernel_load_size
- entry
->kernel_hdr_size
);
1382 mach_result
= vm_write(G_kernel_port
, entry
->kernel_alloc_address
,
1383 vm_buffer
, entry
->kernel_alloc_size
);
1384 if (mach_result
!= KERN_SUCCESS
) {
1385 kload_log_error("unable to write module to kernel memory" KNL
);
1386 entry
->need_cleanup
= 1;
1387 result
= kload_error_kernel_error
;
1391 mach_result
= kmod_create(G_kernel_priv_port
,
1392 (vm_address_t
)kernel_kmod_info
, &(entry
->kmod_id
));
1395 if (entry
->do_load
) {
1396 dest_address
= (char *)entry
->kernel_alloc_address
;
1397 memcpy(dest_address
, kld_header
, entry
->kernel_hdr_size
);
1398 memcpy(dest_address
+ round_page(entry
->kernel_hdr_size
),
1399 (void *)((unsigned long)kld_header
+ entry
->kernel_hdr_size
),
1400 entry
->kernel_load_size
- entry
->kernel_hdr_size
);
1402 /* We've written data & instructions into kernel memory, so flush
1403 * the data cache and invalidate the instruction cache.
1405 flush_dcache(entry
->kernel_alloc_address
, entry
->kernel_alloc_size
, false);
1406 invalidate_icache(entry
->kernel_alloc_address
, entry
->kernel_alloc_size
, false);
1408 mach_result
= kmod_create_internal(
1409 (kmod_info_t
*)kernel_kmod_info
, &(entry
->kmod_id
));
1411 #endif /* not KERNEL */
1413 if (mach_result
!= KERN_SUCCESS
) {
1414 kload_log_error("unable to register module with kernel" KNL
);
1415 entry
->need_cleanup
= 1;
1416 result
= kload_error_kernel_error
;
1421 if (interactive_level
|| log_level
>= kload_log_level_load_basic
) {
1423 if (log_level
>= kload_log_level_load_basic
) {
1424 #endif /* not KERNEL */
1426 "module %s created as # %d at address 0x%x, size %ld" KNL
,
1427 entry
->expected_kmod_name
, entry
->kmod_id
,
1428 entry
->kernel_alloc_address
,
1429 entry
->kernel_alloc_size
);
1435 #endif /* not KERNEL */
1438 if (interactive_level
) {
1440 "You can now break to the debugger and set breakpoints "
1441 " for this extension." KNL
);
1443 #endif /* not KERNEL */
1449 #endif /* not KERNEL */
1454 if (allocated_filename
) {
1455 free(allocated_filename
);
1458 vm_deallocate(mach_task_self(), vm_buffer
, entry
->kernel_alloc_size
);
1460 #endif /* not KERNEL */
1461 __kload_clear_kld_globals();
1466 /*******************************************************************************
1467 *******************************************************************************/
1471 register_prelink(dgraph_entry_t
* entry
,
1472 kmod_info_t
* local_kmod_info
, vm_offset_t kernel_kmod_info
)
1474 CFIndex i
, j
, depoffset
;
1478 depoffset
= CFDataGetLength(G_prelink_dependencies
) / sizeof(CFIndex
);
1480 for (i
= 0; i
< entry
->num_dependencies
; i
++)
1483 for (j
= 1; (j
< (1 + G_prelink
->modules
[0].id
)); j
++)
1485 exists
= (0 == strcmp(entry
->dependencies
[i
]->expected_kmod_name
,
1486 G_prelink
->modules
[j
].name
));
1492 bzero(&desc
, sizeof(desc
));
1493 strcpy(desc
.name
, entry
->dependencies
[i
]->expected_kmod_name
);
1495 if (log_level
>= kload_log_level_basic
) {
1496 kload_log_message("[%d] (dep)\n %s" KNL
,
1497 G_prelink
->modules
[0].id
+ 1, desc
.name
);
1499 G_prelink
->modules
[0].id
++;
1500 CFDataAppendBytes(G_prelink_data
, (UInt8
*) &desc
, sizeof(desc
));
1501 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
1504 G_prelink
->modules
[0].reference_count
++;
1505 OSWriteBigInt32(&j
, 0, j
);
1506 CFDataAppendBytes(G_prelink_dependencies
, (UInt8
*) &j
, sizeof(j
));
1508 if (log_level
>= kload_log_level_basic
) {
1509 kload_log_message("[%d] 0x%08x info 0x%08x\n %s,\n %s" KNL
,
1510 G_prelink
->modules
[0].id
+ 1, entry
->kernel_load_address
,
1511 kernel_kmod_info
, entry
->link_output_file
, entry
->name
);
1514 if (local_kmod_info
)
1515 desc
= *local_kmod_info
;
1518 bzero(&desc
, sizeof(desc
));
1519 desc
.size
= entry
->symbols_length
;
1522 desc
.id
= kernel_kmod_info
;
1523 desc
.reference_count
= entry
->num_dependencies
;
1524 desc
.reference_list
= (kmod_reference_t
*) depoffset
;
1526 /* Stamp the bundle ID and version from the entry over anything
1527 * resident inside the kmod.
1529 bzero(desc
.name
, sizeof(local_kmod_info
->name
));
1530 strcpy(desc
.name
, entry
->expected_kmod_name
);
1531 bzero(desc
.version
, sizeof(local_kmod_info
->version
));
1532 strcpy(desc
.version
, entry
->expected_kmod_vers
);
1534 G_prelink
->modules
[0].id
++;
1535 CFDataAppendBytes(G_prelink_data
, (UInt8
*) &desc
, sizeof(desc
));
1536 G_prelink
= (struct PrelinkState
*) CFDataGetMutableBytePtr(G_prelink_data
);
1538 return kload_error_none
;
1543 /*******************************************************************************
1545 *******************************************************************************/
1548 kload_error
kload_map_dgraph(
1550 const char * kernel_file
)
1552 kload_error
kload_map_dgraph(
1554 #endif /* not KERNEL */
1556 kload_error result
= kload_error_none
;
1559 if (log_level
>= kload_log_level_load_details
) {
1561 kload_log_message("mapping the kernel file %s" KNL
, kernel_file
);
1563 kload_log_message("mapping the kernel" KNL
);
1564 #endif /* not KERNEL */
1568 if (!kld_file_map(kernel_file
)) {
1569 result
= kload_error_link_load
;
1572 #endif /* not KERNEL */
1574 for (i
= 0; i
< dgraph
->length
; i
++) {
1575 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1577 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1581 result
= kload_map_entry(entry
);
1582 if (result
!= kload_error_none
) {
1592 /*******************************************************************************
1594 *******************************************************************************/
1596 kload_error
kload_map_entry(dgraph_entry_t
* entry
)
1598 kload_error result
= kload_error_none
;
1600 if (entry
->is_kernel_component
&& !entry
->is_symbol_set
) {
1601 kload_log_error("attempt to map kernel component %s" KNL
, entry
->name
);
1602 result
= kload_error_invalid_argument
;
1606 if (log_level
>= kload_log_level_load_details
) {
1607 kload_log_message("mapping module file %s" KNL
, entry
->name
);
1610 if (kld_file_getaddr(entry
->name
, NULL
)) {
1611 if (log_level
>= kload_log_level_load_details
) {
1612 kload_log_message("module file %s is already mapped" KNL
, entry
->name
);
1614 result
= kload_error_none
;
1619 if (!kld_file_map(entry
->name
)) {
1621 if (!kld_file_map(entry
->name
, entry
->object
, entry
->object_length
,
1622 entry
->object_is_kmem
)) {
1623 #endif /* not KERNEL */
1624 kload_log_error("error mapping module file %s" KNL
, entry
->name
);
1626 result
= kload_error_link_load
;
1632 #endif /* not KERNEL */
1634 entry
->is_mapped
= true;
1636 /* Clear these bits now, as the kld patch module now owns the info
1637 * and it is subject to change. We reset them in the entry from the
1638 * kld patch module as needed.
1641 entry
->object_length
= 0;
1643 entry
->object_is_kmem
= false;
1646 // FIXME: Stop using this symbol; have the info passed in by
1647 // FIXME: ...the kext management library.
1649 if (!entry
->is_kernel_component
&& !kld_file_lookupsymbol(entry
->name
, "_kmod_info")) {
1650 kload_log_error("%s does not not contain kernel extension code" KNL
,
1652 result
= kload_error_executable_bad
;
1655 #endif /* not KERNEL */
1662 /*******************************************************************************
1664 *******************************************************************************/
1665 kload_error
kload_request_load_addresses(
1667 const char * kernel_file
)
1669 kload_error result
= kload_error_none
;
1671 const char * user_response
= NULL
; // must free
1673 unsigned int address
;
1675 /* We have to map all object files to get their CFBundleIdentifier
1678 result
= kload_map_dgraph(dgraph
, kernel_file
);
1679 if (result
!= kload_error_none
) {
1680 kload_log_error("error mapping object files" KNL
);
1684 // fixme: this shouldn't be printf, should it?
1685 printf("enter the hexadecimal load addresses for these modules:\n");
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 user_response
= __kload_input_func("%s:",
1705 entry
->expected_kmod_name
);
1706 if (!user_response
) {
1707 result
= kload_error_unspecified
;
1710 scan_result
= sscanf(user_response
, "%x", &address
);
1711 if (scan_result
< 1 || scan_result
== EOF
) {
1712 result
= kload_error_unspecified
;
1715 entry
->loaded_address
= address
;
1723 /*******************************************************************************
1724 * addresses is a NULL-terminated list of string of the form "module_id@address"
1725 *******************************************************************************/
1726 kload_error
kload_set_load_addresses_from_args(
1728 const char * kernel_file
,
1731 kload_error result
= kload_error_none
;
1735 /* We have to map all object files to get their CFBundleIdentifier
1738 result
= kload_map_dgraph(dgraph
, kernel_file
);
1739 if (result
!= kload_error_none
) {
1740 kload_log_error("error mapping object files" KNL
);
1745 * Run through and assign all addresses to their relevant module
1748 for (i
= 0; i
< dgraph
->length
; i
++) {
1749 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1752 result
= kload_error_unspecified
;
1756 if (entry
->is_kernel_component
) {
1760 if (!entry
->is_mapped
) {
1761 result
= kload_error_unspecified
;
1765 for (j
= 0; addresses
[j
]; j
++) {
1766 char * this_addr
= addresses
[j
];
1767 char * address_string
= NULL
;
1768 unsigned int address
;
1769 unsigned int module_namelen
= strlen(entry
->expected_kmod_name
);
1772 result
= kload_error_unspecified
;
1776 if (strncmp(this_addr
, entry
->expected_kmod_name
, module_namelen
)) {
1779 if (this_addr
[module_namelen
] != '@') {
1783 address_string
= index(this_addr
, '@');
1784 if (!address_string
) {
1785 result
= kload_error_unspecified
;
1789 address
= strtoul(address_string
, NULL
, 16);
1790 entry
->loaded_address
= address
;
1795 * Now that we've done that see that all non-kernel modules do have
1796 * addresses set. If even one doesn't, we can't complete the link
1797 * relocation of symbols, so return a usage error.
1799 for (i
= 0; i
< dgraph
->length
; i
++) {
1800 dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1802 if (entry
->is_kernel_component
) {
1806 if (!entry
->loaded_address
) {
1807 result
= kload_error_invalid_argument
;
1817 /*******************************************************************************
1818 * This function requires G_kernel_priv_port to be set before it will work.
1819 *******************************************************************************/
1820 kload_error
kload_set_load_addresses_from_kernel(
1822 const char * kernel_file
,
1825 kload_error result
= kload_error_none
;
1827 kmod_info_t
* loaded_modules
= NULL
;
1828 int loaded_bytecount
= 0;
1833 * We have to map the dgraph's modules before checking whether they've
1836 result
= kload_map_dgraph(dgraph
, kernel_file
);
1837 if (result
!= kload_error_none
) {
1838 kload_log_error("can't map module files" KNL
);
1843 /* First clear all the load addresses.
1845 for (i
= 0; i
< dgraph
->length
; i
++) {
1846 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1847 entry
->loaded_address
= 0;
1850 mach_result
= kmod_get_info(G_kernel_priv_port
,
1851 (void *)&loaded_modules
, &loaded_bytecount
);
1852 if (mach_result
!= KERN_SUCCESS
) {
1853 kload_log_error("kmod_get_info() failed" KNL
);
1854 result
= kload_error_kernel_error
;
1859 * Find out which modules have already been loaded & verify
1860 * that loaded versions are same as requested.
1862 for (i
= 0; i
< dgraph
->length
; i
++) {
1863 kload_error cresult
;
1864 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
1866 /* If necessary, check whether the current module is already loaded.
1867 * (We already did the root module above.)
1869 cresult
= __kload_check_module_loaded(dgraph
, current_entry
,
1870 loaded_modules
, do_load
);
1871 if ( ! (cresult
== kload_error_none
||
1872 cresult
== kload_error_already_loaded
) ) {
1875 if (current_entry
== dgraph
->root
&&
1876 cresult
== kload_error_already_loaded
) {
1884 if (loaded_modules
) {
1885 vm_deallocate(mach_task_self(), (vm_address_t
)loaded_modules
,
1894 /*******************************************************************************
1896 *******************************************************************************/
1898 kload_error
kload_set_load_addresses_from_kernel(
1901 kload_error result
= kload_error_none
;
1904 kmod_info_t
* loaded_modules
= NULL
;
1905 int loaded_bytecount
= 0;
1906 #endif /* not KERNEL */
1911 * We have to map the dgraph's modules before checking whether they've
1914 result
= kload_map_dgraph(dgraph
);
1915 if (result
!= kload_error_none
) {
1916 kload_log_error("can't map module files" KNL
);
1921 /* First clear all the load addresses.
1923 for (i
= 0; i
< dgraph
->length
; i
++) {
1924 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
1925 entry
->loaded_address
= 0;
1929 * Find out which modules have already been loaded & verify
1930 * that loaded versions are same as requested.
1932 for (i
= 0; i
< dgraph
->length
; i
++) {
1933 kload_error cresult
;
1934 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
1936 /* If necessary, check whether the current module is already loaded.
1937 * (We already did the root module above.)
1939 cresult
= __kload_check_module_loaded(dgraph
, current_entry
, false);
1940 if ( ! (cresult
== kload_error_none
||
1941 cresult
== kload_error_already_loaded
) ) {
1944 if (current_entry
== dgraph
->root
&&
1945 cresult
== kload_error_already_loaded
) {
1955 #endif /* not KERNEL */
1957 /*******************************************************************************
1959 *******************************************************************************/
1961 extern kern_return_t
kmod_load_from_cache(const char * kmod_name
);
1964 static kmod_info_t
* __kload_find_kmod_info(const char * kmod_name
1967 kmod_info_t
* kmod_list
1968 #endif /* not KERNEL */
1974 for (i
= 0; ; i
++) {
1975 kmod_info_t
* current_kmod
= &(kmod_list
[i
]);
1976 if (0 == strcmp(current_kmod
->name
, kmod_name
)) {
1977 return current_kmod
;
1979 if (kmod_list
[i
].next
== 0) {
1986 info
= kmod_lookupbyname_locked(kmod_name
);
1987 if (!info
&& (KERN_SUCCESS
== kmod_load_from_cache(kmod_name
))) {
1988 info
= kmod_lookupbyname_locked(kmod_name
);
1991 #endif /* not KERNEL */
1994 /*******************************************************************************
1996 *******************************************************************************/
1998 kload_error
__kload_check_module_loaded(
2000 dgraph_entry_t
* entry
,
2002 kmod_info_t
* kmod_list
,
2003 #endif /* not KERNEL */
2006 kload_error result
= kload_error_none
;
2007 const char * kmod_name
;
2008 kmod_info_t
* current_kmod
= 0;
2010 VERS_version entry_vers
;
2011 VERS_version loaded_vers
;
2013 if (false && entry
->is_kernel_component
) {
2014 kmod_name
= entry
->name
;
2016 kmod_name
= entry
->expected_kmod_name
;
2017 if (log_level
>= kload_log_level_load_details
) {
2018 kload_log_message("checking whether module file %s is already loaded" KNL
,
2024 current_kmod
= __kload_find_kmod_info(kmod_name
, kmod_list
);
2026 current_kmod
= __kload_find_kmod_info(kmod_name
);
2027 #endif /* not KERNEL */
2029 if (!current_kmod
) {
2034 entry
->kmod_id
= current_kmod
->id
;
2035 entry
->loaded_address
= current_kmod
->address
;
2037 if (entry
->is_kernel_component
) {
2041 if (log_level
>= kload_log_level_load_details
) {
2042 kload_log_message("module file %s is loaded; checking status" KNL
,
2046 // We really want to move away from having this info in a kmod....
2048 loaded_vers
= VERS_parse_string(current_kmod
->version
);
2049 if (loaded_vers
< 0) {
2051 "can't parse version string \"%s\" of loaded module %s" KNL
,
2052 current_kmod
->version
,
2053 current_kmod
->name
);
2054 result
= kload_error_unspecified
;
2058 entry_vers
= VERS_parse_string(entry
->expected_kmod_vers
);
2059 if (entry_vers
< 0) {
2061 "can't parse version string \"%s\" of module file %s" KNL
,
2062 entry
->expected_kmod_name
,
2064 result
= kload_error_unspecified
;
2068 if (loaded_vers
!= entry_vers
) {
2070 "loaded version %s of module %s differs from "
2071 "requested version %s" KNL
,
2072 current_kmod
->version
,
2074 entry
->expected_kmod_name
);
2075 if (entry
== dgraph
->root
) {
2076 result
= kload_error_loaded_version_differs
;
2078 result
= kload_error_dependency_loaded_version_differs
;
2083 if (log_if_already
&& log_level
>=
2084 kload_log_level_load_basic
) {
2087 "module %s (identifier %s) is already loaded" KNL
,
2088 entry
->name
, kmod_name
);
2090 result
= kload_error_already_loaded
;
2096 // Do this ONLY if in the kernel!
2098 kfree(current_kmod
, sizeof(kmod_info_t
));
2104 /*******************************************************************************
2106 *******************************************************************************/
2108 kload_error
__kload_patch_dgraph(dgraph_t
* dgraph
2111 const char * kernel_file
2112 #endif /* not KERNEL */
2115 kload_error result
= kload_error_none
;
2119 if (!kld_file_merge_OSObjects(kernel_file
)) {
2120 result
= kload_error_link_load
;
2123 #endif /* not KERNEL */
2125 for (i
= 0; i
< dgraph
->length
; i
++) {
2126 dgraph_entry_t
* current_entry
= dgraph
->load_order
[i
];
2128 /* The kernel has already been patched.
2130 if (current_entry
->is_kernel_component
) {
2134 if (log_level
>= kload_log_level_load_details
) {
2135 kload_log_message("patching C++ code in module %s" KNL
,
2136 current_entry
->name
);
2140 /* In userland, we call the patch function for all kmods,
2141 * loaded or not, because we don't have all the info that
2142 * the kernel environment has.
2144 if (!kld_file_patch_OSObjects(current_entry
->name
)) {
2145 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2149 /* In the kernel, we call the merge function for already-loaded
2150 * kmods, since the kld patch environment retains info for kmods
2151 * that have already been patched. The patch function does a little
2152 * more work, and is only for kmods that haven't been processed yet.
2153 * NOTE: We are depending here on kload_check_module_loaded()
2154 * having been called, which is guaranteed by kload_load_dgraph()
2155 * is used, but not by its subroutines (such as
2156 * __kload_load_modules()).
2158 if (current_entry
->loaded_address
) {
2159 if (!kld_file_merge_OSObjects(current_entry
->name
)) {
2160 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2164 if (!kld_file_patch_OSObjects(current_entry
->name
)) {
2165 result
= kload_error_link_load
; // FIXME: need a "patch" error?
2169 #endif /* not KERNEL */
2173 if (!kld_file_prepare_for_link()) {
2174 result
= kload_error_link_load
; // FIXME: need more specific error?
2183 /*******************************************************************************
2185 *******************************************************************************/
2186 #define __KLOAD_PATCH_EXTENSION ".patch"
2188 kload_error
__kload_output_patches(
2190 const char * patch_file
,
2191 const char * patch_dir
,
2192 int ask_overwrite_symbols
,
2193 int overwrite_symbols
)
2195 kload_error result
= kload_error_none
;
2197 char * allocated_filename
= NULL
;
2198 char * patch_filename
= NULL
;
2204 for (i
= 0; i
< dgraph
->length
; i
++) {
2206 struct dgraph_entry_t
* entry
= dgraph
->load_order
[i
];
2207 unsigned long length
;
2209 if (entry
->is_kernel_component
) {
2213 length
= strlen(patch_dir
) +
2214 strlen(entry
->expected_kmod_name
) +
2215 strlen(__KLOAD_PATCH_EXTENSION
) +
2216 1 + 1 ; // 1 for '/' added, 1 for terminating null
2217 if (length
>= MAXPATHLEN
) {
2219 "output filename \"%s/%s%s\" would be too long" KNL
,
2220 patch_dir
, entry
->expected_kmod_name
,
2221 __KLOAD_PATCH_EXTENSION
);
2222 result
= kload_error_invalid_argument
;
2226 allocated_filename
= (char *)malloc(length
);
2227 if (! allocated_filename
) {
2228 kload_log_error("malloc failure" KNL
);
2229 result
= kload_error_no_memory
;
2233 patch_filename
= allocated_filename
;
2234 strcpy(patch_filename
, patch_dir
);
2235 strcat(patch_filename
, "/");
2236 strcat(patch_filename
, entry
->expected_kmod_name
);
2237 strcat(patch_filename
, __KLOAD_PATCH_EXTENSION
);
2240 file_check
= kload_file_exists(patch_filename
);
2242 if (file_check
< 0) {
2243 kload_log_error("error checking existence of file %s" KNL
,
2245 } else if (file_check
> 0 && !overwrite_symbols
) {
2246 if (!ask_overwrite_symbols
) {
2248 "patch file %s exists; not overwriting" KNL
,
2252 int approve
= (*__kload_approve_func
)(1,
2253 "\nPatch file %s exists; overwrite", patch_filename
);
2256 result
= kload_error_unspecified
;
2259 output_patch
= approve
;
2265 if (log_level
>= kload_log_level_basic
) {
2266 kload_log_message("writing patch file %s" KNL
, patch_filename
);
2268 kld_file_debug_dump(entry
->name
, patch_filename
);
2271 if (allocated_filename
) free(allocated_filename
);
2272 allocated_filename
= NULL
;
2275 } else if (patch_file
) {
2277 file_check
= kload_file_exists(patch_file
);
2279 if (file_check
< 0) {
2280 kload_log_error("error checking existence of file %s" KNL
,
2282 } else if (file_check
> 0 && !overwrite_symbols
) {
2283 if (!ask_overwrite_symbols
) {
2284 kload_log_error("patch file %s exists; not overwriting" KNL
,
2288 int approve
= (*__kload_approve_func
)(1,
2289 "\nPatch file %s exists; overwrite", patch_filename
);
2292 result
= kload_error_unspecified
;
2295 output_patch
= approve
;
2301 if (log_level
>= kload_log_level_basic
) {
2302 kload_log_message("writing patch file %s" KNL
, patch_filename
);
2304 kld_file_debug_dump(dgraph
->root
->name
, patch_file
);
2309 if (allocated_filename
) free(allocated_filename
);
2313 #endif /* not KERNEL */
2315 /*******************************************************************************
2317 *******************************************************************************/
2319 kload_error
__kload_set_module_dependencies(dgraph_entry_t
* entry
) {
2320 kload_error result
= kload_error_none
;
2323 void * kmod_control_args
= 0;
2325 #endif /* not KERNEL */
2328 dgraph_entry_t
* current_dep
= NULL
;
2330 if (!entry
->do_load
) {
2331 result
= kload_error_already_loaded
;
2335 for (i
= 0; i
< entry
->num_dependencies
; i
++) {
2336 current_dep
= entry
->dependencies
[i
];
2338 if (log_level
>= kload_log_level_load_details
) {
2339 kload_log_message("adding reference from %s (%d) to %s (%d)" KNL
,
2340 entry
->expected_kmod_name
, entry
->kmod_id
,
2341 current_dep
->expected_kmod_name
, current_dep
->kmod_id
);
2344 packed_id
= KMOD_PACK_IDS(entry
->kmod_id
, current_dep
->kmod_id
);
2346 mach_result
= kmod_control(G_kernel_priv_port
,
2347 packed_id
, KMOD_CNTL_RETAIN
, &kmod_control_args
, &num_args
);
2349 mach_result
= kmod_retain(packed_id
);
2350 #endif /* not KERNEL */
2351 if (mach_result
!= KERN_SUCCESS
) {
2353 "kmod retain failed for %s; destroying kmod" KNL
,
2354 entry
->expected_kmod_name
);
2356 mach_result
= kmod_destroy(G_kernel_priv_port
, entry
->kmod_id
);
2358 mach_result
= kmod_destroy_internal(entry
->kmod_id
);
2359 #endif /* not KERNEL */
2360 if (mach_result
!= KERN_SUCCESS
) {
2361 kload_log_error("kmod destroy failed" KNL
);
2363 result
= kload_error_link_load
;
2368 if (log_level
>= kload_log_level_load_basic
) {
2369 kload_log_message("module # %d reference counts incremented" KNL
,
2377 /*******************************************************************************
2379 *******************************************************************************/
2381 kload_error
__kload_start_module(dgraph_entry_t
* entry
) {
2382 kload_error result
= kload_error_none
;
2385 void * kmod_control_args
= 0;
2387 #endif /* not KERNEL */
2389 if (!entry
->do_load
) {
2390 result
= kload_error_already_loaded
;
2395 mach_result
= kmod_control(G_kernel_priv_port
,
2396 entry
->kmod_id
, KMOD_CNTL_START
, &kmod_control_args
, &num_args
);
2398 mach_result
= kmod_start_or_stop(entry
->kmod_id
, 1, 0, 0);
2399 #endif /* not KERNEL */
2401 if (mach_result
!= KERN_SUCCESS
) {
2403 "kmod_control/start failed for %s; destroying kmod" KNL
,
2404 entry
->expected_kmod_name
);
2406 mach_result
= kmod_destroy(G_kernel_priv_port
, entry
->kmod_id
);
2408 mach_result
= kmod_destroy_internal(entry
->kmod_id
);
2409 #endif /* not KERNEL */
2410 if (mach_result
!= KERN_SUCCESS
) {
2411 kload_log_error("kmod destroy failed" KNL
);
2413 result
= kload_error_link_load
;
2417 if (log_level
>= kload_log_level_load_basic
) {
2418 kload_log_message("module # %d started" KNL
,
2426 /*******************************************************************************
2427 *******************************************************************************/
2429 /*******************************************************************************
2430 * This function can only operate on 32 bit mach object file symbol table
2431 * graphs represented by G_current_load_entry.
2432 *******************************************************************************/
2434 unsigned long __kload_linkedit_address(
2436 unsigned long headers_size
)
2438 unsigned long round_segments_size
;
2439 unsigned long round_headers_size
;
2440 unsigned long round_size
;
2442 const struct machOMapping
{
2443 struct mach_header h
;
2444 struct segment_command seg
[1];
2447 if (!G_current_load_entry
) {
2451 // the actual size allocated by kld_load_from_memory()
2452 G_current_load_entry
->kernel_load_size
= size
;
2454 round_headers_size
= round_page(headers_size
);
2455 round_segments_size
= round_page(size
- headers_size
);
2456 round_size
= round_headers_size
+ round_segments_size
;
2458 G_current_load_entry
->kernel_alloc_size
= round_size
;
2460 // will need to be rounded *after* load/link
2461 G_current_load_entry
->kernel_hdr_size
= headers_size
;
2462 G_current_load_entry
->kernel_hdr_pad
= round_headers_size
- headers_size
;
2464 if (G_current_load_entry
->loaded_address
) {
2465 G_current_load_entry
->kernel_load_address
=
2466 G_current_load_entry
->loaded_address
+
2467 G_current_load_entry
->kernel_hdr_pad
;
2468 if (log_level
>= kload_log_level_load_basic
) {
2470 "using %s load address 0x%x (0x%x with header pad)" KNL
,
2471 G_current_load_entry
->kmod_id
? "existing" : "provided",
2472 G_current_load_entry
->loaded_address
,
2473 G_current_load_entry
->kernel_load_address
);
2475 return G_current_load_entry
->kernel_load_address
;
2478 machO
= (const struct machOMapping
*) G_current_load_entry
->object
;
2479 if (machO
->seg
[0].vmaddr
)
2481 G_current_load_entry
->loaded_address
= trunc_page(machO
->seg
[0].vmaddr
- machO
->seg
[0].fileoff
);
2483 G_current_load_entry
->kernel_load_address
= G_current_load_entry
->loaded_address
2484 + G_current_load_entry
->kernel_hdr_pad
;
2486 return G_current_load_entry
->kernel_load_address
;
2491 G_current_load_entry
->kernel_alloc_address
= G_prelink
->modules
[0].address
;
2492 G_prelink
->modules
[0].address
+= round_page(G_current_load_entry
->kernel_alloc_size
);
2493 mach_result
= KERN_SUCCESS
;
2495 } else if (G_syms_only
) {
2497 "internal error; asked to allocate kernel memory" KNL
);
2498 // FIXME: no provision for cleanup here
2499 return kload_error_unspecified
;
2502 #endif /* not KERNEL */
2506 mach_result
= vm_allocate(G_kernel_port
,
2507 &G_current_load_entry
->kernel_alloc_address
,
2508 G_current_load_entry
->kernel_alloc_size
, VM_FLAGS_ANYWHERE
);
2510 mach_result
= vm_allocate(kernel_map
,
2511 &G_current_load_entry
->kernel_alloc_address
,
2512 G_current_load_entry
->kernel_alloc_size
, VM_FLAGS_ANYWHERE
);
2513 #endif /* not KERNEL */
2516 if (mach_result
!= KERN_SUCCESS
) {
2517 kload_log_error("can't allocate kernel memory" KNL
);
2518 // FIXME: no provision for cleanup here
2519 return kload_error_kernel_error
;
2522 if (log_level
>= kload_log_level_load_basic
) {
2523 kload_log_message("allocated %ld bytes in kernel space at 0x%x" KNL
,
2524 G_current_load_entry
->kernel_alloc_size
,
2525 G_current_load_entry
->kernel_alloc_address
);
2528 G_current_load_entry
->kernel_load_address
=
2529 G_current_load_entry
->kernel_alloc_address
+
2530 G_current_load_entry
->kernel_hdr_pad
;
2532 G_current_load_entry
->loaded_address
= G_current_load_entry
->kernel_alloc_address
;
2534 if (log_level
>= kload_log_level_load_basic
) {
2536 "using load address of 0x%x" KNL
,
2537 G_current_load_entry
->kernel_alloc_address
);
2540 return G_current_load_entry
->kernel_load_address
;
2543 /*******************************************************************************
2545 *******************************************************************************/
2547 void __kload_clear_kld_globals(void) {
2548 G_current_load_entry
= NULL
;
2552 /*******************************************************************************
2554 *******************************************************************************/
2556 void __kload_clean_up_entry(dgraph_entry_t
* entry
) {
2559 if (entry
->need_cleanup
&& entry
->kernel_alloc_address
) {
2563 if ((entry
->kernel_alloc_address
+ entry
->kernel_alloc_size
) == G_prelink
->modules
[0].address
) {
2564 G_prelink
->modules
[0].address
= entry
->kernel_alloc_address
;
2567 "bad free load address of 0x%x (last 0x%x)" KNL
,
2568 entry
->kernel_alloc_address
, G_prelink
->modules
[0].address
);
2571 mach_result
= vm_deallocate(G_kernel_port
, entry
->kernel_alloc_address
,
2572 entry
->kernel_alloc_size
);
2575 mach_result
= vm_deallocate(kernel_map
, entry
->kernel_alloc_address
,
2576 entry
->kernel_alloc_size
);
2577 #endif /* not KERNEL */
2578 entry
->kernel_alloc_address
= 0;
2584 /*******************************************************************************
2586 *******************************************************************************/
2587 int kload_file_exists(const char * path
)
2589 int result
= 0; // assume it doesn't exist
2590 struct stat stat_buf
;
2592 if (stat(path
, &stat_buf
) == 0) {
2593 result
= 1; // the file does exist; we don't care beyond that
2599 result
= 0; // the file doesn't exist
2603 result
= -1; // unknown error
2611 #endif /* not KERNEL */
2613 /*******************************************************************************
2615 *******************************************************************************/
2617 void kload_set_log_level(kload_log_level level
)
2624 /*******************************************************************************
2626 *******************************************************************************/
2627 void kload_set_log_function(
2628 void (*func
)(const char * format
, ...))
2631 __kload_log_func
= &__kload_null_log
;
2633 __kload_log_func
= func
;
2638 /*******************************************************************************
2640 *******************************************************************************/
2641 void kload_set_error_log_function(
2642 void (*func
)(const char * format
, ...))
2645 __kload_err_log_func
= &__kload_null_err_log
;
2647 __kload_err_log_func
= func
;
2652 /*******************************************************************************
2654 *******************************************************************************/
2655 void kload_set_user_approve_function(
2656 int (*func
)(int default_answer
, const char * format
, ...))
2659 __kload_approve_func
= &__kload_null_approve
;
2661 __kload_approve_func
= func
;
2666 /*******************************************************************************
2668 *******************************************************************************/
2669 void kload_set_user_veto_function(
2670 int (*func
)(int default_answer
, const char * format
, ...))
2673 __kload_veto_func
= &__kload_null_veto
;
2675 __kload_veto_func
= func
;
2680 /*******************************************************************************
2682 *******************************************************************************/
2683 void kload_set_user_input_function(
2684 const char * (*func
)(const char * format
, ...))
2687 __kload_input_func
= &__kload_null_input
;
2689 __kload_input_func
= func
;
2694 /*******************************************************************************
2696 *******************************************************************************/
2698 void kload_log_message(const char * format
, ...)
2701 char fake_buffer
[2];
2703 char * output_string
;
2705 if (log_level
<= kload_log_level_silent
) {
2709 va_start(ap
, format
);
2710 output_length
= vsnprintf(fake_buffer
, 1, format
, ap
);
2713 output_string
= (char *)malloc(output_length
+ 1);
2714 if (!output_string
) {
2718 va_start(ap
, format
);
2719 vsprintf(output_string
, format
, ap
);
2722 __kload_log_func(output_string
);
2723 free(output_string
);
2728 /*******************************************************************************
2730 *******************************************************************************/
2732 void kload_log_error(const char * format
, ...)
2735 char fake_buffer
[2];
2737 char * output_string
;
2739 if (log_level
<= kload_log_level_silent
) {
2743 va_start(ap
, format
);
2744 output_length
= vsnprintf(fake_buffer
, 1, format
, ap
);
2747 output_string
= (char *)malloc(output_length
+ 1);
2748 if (!output_string
) {
2752 va_start(ap
, format
);
2753 vsprintf(output_string
, format
, ap
);
2756 __kload_err_log_func(output_string
);
2757 free(output_string
);
2761 /*******************************************************************************
2763 *******************************************************************************/
2764 void __kload_null_log(const char * format
, ...)
2769 /*******************************************************************************
2771 *******************************************************************************/
2772 void __kload_null_err_log(const char * format
, ...)
2777 /*******************************************************************************
2779 *******************************************************************************/
2780 int __kload_null_approve(int default_answer
, const char * format
, ...)
2785 /*******************************************************************************
2787 *******************************************************************************/
2788 int __kload_null_veto(int default_answer
, const char * format
, ...)
2793 /*******************************************************************************
2795 *******************************************************************************/
2796 const char * __kload_null_input(const char * format
, ...)
2801 /*******************************************************************************
2802 * The kld_patch.c module uses this function, if defined, to print errors. In
2803 * the kernel this function is defined in libsa/misc.c.
2804 *******************************************************************************/
2805 void kld_error_vprintf(const char * format
, va_list ap
) {
2806 if (log_level
<= kload_log_level_silent
) return;
2807 vfprintf(stderr
, format
, ap
);
2811 #endif /* not KERNEL */