The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/libsa/load.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28  
   29 /***************
   30 * HEADERS
   31 ***************/
   32 #ifndef KERNEL
   33 
   34 #include <CoreFoundation/CoreFoundation.h>
   35 
   36 #include <libc.h>
   37 #include <stdlib.h>
   38 #include <stdarg.h>
   39 #include <stdio.h>
   40 #include <string.h>
   41 #include <unistd.h>
   42 
   43 #include <sys/stat.h>
   44 #include <sys/file.h>
   45 #include <sys/param.h>
   46 #include <sys/types.h>
   47 #include <sys/mman.h>
   48 
   49 #include <mach/mach_types.h>
   50 #include <mach/mach.h>
   51 #include <mach/mach_init.h>
   52 #include <mach/mach_error.h>
   53 #include <mach/mach_host.h>
   54 #include <mach/mach_port.h>
   55 #include <mach-o/kld.h>
   56 #include <mach-o/arch.h>
   57 #include <mach-o/fat.h>
   58 #include <mach-o/loader.h>
   59 #include <mach-o/nlist.h>
   60 #include <kern/kern_types.h>
   61 #include <kern/kalloc.h>
   62 #include <libkern/OSByteOrder.h>
   63 
   64 #include "vers_rsrc.h"
   65 
   66 #else
   67 
   68 #include <mach-o/kld.h>
   69 #include <mach-o/loader.h>
   70 #include <mach-o/nlist.h>
   71 #include <libsa/vers_rsrc.h>
   72 
   73 #endif /* not KERNEL */
   74 
   75 #include "load.h"
   76 #include "dgraph.h"
   77 #include "kld_patch.h"
   78 
   79 /***************
   80 * MACROS
   81 ***************/
   82 
   83 #ifndef KERNEL
   84 
   85 #define PRIV_EXT
   86 
   87 #else
   88 
   89 #define PRIV_EXT  __private_extern__
   90 
   91 #ifdef DEBUG
   92 #define LOG_DELAY(x)    IODelay((x) * 1000000)
   93 #define VTYELLOW  "\033[33m"
   94 #define VTRESET   "\033[0m"
   95 #else
   96 #define LOG_DELAY()
   97 #define VTYELLOW
   98 #define VTRESET
   99 #endif /* DEBUG */
  100 
  101 #endif /* not KERNEL */
  102 
  103 /***************
  104 * FUNCTION PROTOS
  105 ***************/
  106 
  107 #ifdef KERNEL
  108 extern kern_return_t
  109 kmod_create_internal(
  110             kmod_info_t *info,
  111             kmod_t *id);
  112 
  113 extern kern_return_t
  114 kmod_destroy_internal(kmod_t id);
  115 
  116 extern kern_return_t
  117 kmod_start_or_stop(
  118     kmod_t id,
  119     int start,
  120     kmod_args_t *data,
  121     mach_msg_type_number_t *dataCount);
  122 
  123 extern kern_return_t kmod_retain(kmod_t id);
  124 extern kern_return_t kmod_release(kmod_t id);
  125 
  126 extern struct mach_header _mh_execute_header;
  127 #endif /* KERNEL */
  128 
  129 
  130 // Used to pass info between kld library and callbacks
  131 static dgraph_entry_t * G_current_load_entry = NULL;
  132 
  133 #ifndef KERNEL
  134 static mach_port_t G_kernel_port = PORT_NULL;
  135 static mach_port_t G_kernel_priv_port = PORT_NULL;
  136 static int G_syms_only;
  137 
  138 static kload_error
  139 register_prelink(dgraph_entry_t * entry,
  140                     kmod_info_t * local_kmod_info, vm_offset_t kernel_kmod_info);
  141 
  142 struct PrelinkState
  143 {
  144     kmod_info_t modules[1];
  145 };
  146 struct PrelinkState *   G_prelink;
  147 CFMutableDataRef        G_prelink_data;
  148 CFMutableDataRef        G_prelink_dependencies;
  149 
  150 #endif /* not KERNEL */
  151 
  152 // used by dgraph.c so can't be static
  153 kload_log_level log_level = 0;
  154 
  155 #ifndef KERNEL
  156 static void __kload_null_log(const char * format, ...);
  157 static void __kload_null_err_log(const char * format, ...);
  158 static int __kload_null_approve(int default_answer, const char * format, ...);
  159 static int __kload_null_veto(int default_answer, const char * format, ...);
  160 static const char * __kload_null_input(const char * format, ...);
  161 
  162 void (*__kload_log_func)(const char * format, ...) =
  163     &__kload_null_log;
  164 void (*__kload_err_log_func)(const char * format, ...) = &__kload_null_err_log;
  165 int (*__kload_approve_func)(int default_answer,
  166     const char * format, ...) = &__kload_null_approve;
  167 int (*__kload_veto_func)(int default_answer,
  168     const char * format, ...) = &__kload_null_veto;
  169 const char * (*__kload_input_func)(const char * format, ...) =
  170     &__kload_null_input;
  171 #endif /* not KERNEL */
  172 
  173 static unsigned long __kload_linkedit_address(
  174     unsigned long size,
  175     unsigned long headers_size);
  176 static void __kload_clean_up_entry(dgraph_entry_t * entry);
  177 static void __kload_clear_kld_globals(void);
  178 static kload_error __kload_patch_dgraph(dgraph_t * dgraph
  179 #ifndef KERNEL
  180     ,
  181     const char * kernel_file
  182 #endif /* not KERNEL */
  183     );
  184 static kload_error __kload_load_modules(dgraph_t * dgraph
  185 #ifndef KERNEL
  186     ,
  187     const char * kernel_file,
  188     const char * patch_file, const char * patch_dir,
  189     const char * symbol_file, const char * symbol_dir,
  190     int do_load, int do_start_kmod, int do_prelink,
  191     int interactive_level,
  192     int ask_overwrite_symbols, int overwrite_symbols
  193 #endif /* not KERNEL */
  194     );
  195 
  196 static kload_error __kload_check_module_loaded(
  197     dgraph_t * dgraph,
  198     dgraph_entry_t * entry,
  199 #ifndef KERNEL
  200     kmod_info_t * kmod_list,
  201 #endif /* not KERNEL */
  202     int log_if_already);
  203 
  204 static kload_error __kload_load_module(dgraph_t * dgraph,
  205     dgraph_entry_t * entry,
  206     int is_root
  207 #ifndef KERNEL
  208     ,
  209     const char * symbol_file,
  210     const char * symbol_dir,
  211     int do_load,
  212     int interactive_level,
  213     int ask_overwrite_symbols,
  214     int overwrite_symbols
  215 #endif /* not KERNEL */
  216     );
  217 static kload_error __kload_set_module_dependencies(dgraph_entry_t * entry);
  218 static kload_error __kload_start_module(dgraph_entry_t * entry);
  219 
  220 #ifndef KERNEL
  221 static kload_error __kload_output_patches(
  222     dgraph_t * dgraph,
  223     const char * patch_file,
  224     const char * patch_dir,
  225     int ask_overwrite_symbols,
  226     int overwrite_symbols);
  227 
  228 Boolean _IOReadBytesFromFile(CFAllocatorRef alloc, const char *path, void **bytes,
  229                                 CFIndex *length, CFIndex maxLength);
  230 Boolean _IOWriteBytesToFile(const char *path, const void *bytes, CFIndex length);
  231 
  232 #endif /* not KERNEL */
  233 
  234 /*******************************************************************************
  235 *
  236 *******************************************************************************/
  237 PRIV_EXT
  238 kload_error kload_load_dgraph(dgraph_t * dgraph
  239 #ifndef KERNEL
  240     ,
  241     const char * kernel_file,
  242     const char * patch_file, const char * patch_dir,
  243     const char * symbol_file, const char * symbol_dir,
  244     int do_load, int do_start_kmod, int do_prelink,
  245     int interactive_level,
  246     int ask_overwrite_symbols, int overwrite_symbols
  247 #endif /* not KERNEL */
  248     )
  249 {
  250     kload_error result = kload_error_none;
  251     int one_has_address = 0;
  252     int one_lacks_address = 0;
  253     unsigned int i;
  254 #ifndef KERNEL
  255     int syms_only;
  256 
  257     syms_only = (!do_load) && (symbol_dir || symbol_file);
  258 
  259     if (log_level >= kload_log_level_load_details) {
  260         kload_log_message("loading dependency graph:" KNL);
  261         dgraph_log(dgraph);
  262     }
  263 
  264     if (syms_only && log_level >= kload_log_level_load_details) {
  265         kload_log_message("loading for symbol generation only" KNL);
  266     }
  267 
  268    /*****
  269     * If we're not loading and have no request to emit a symbol
  270     * or patch file, there's nothing to do!
  271     */
  272     if (!do_load && !symbol_dir && !symbol_file &&
  273         !patch_dir && !patch_file) {
  274 
  275         if (syms_only && log_level >= kload_log_level_load_details) {
  276             kload_log_message("loader has no work to do" KNL);
  277         }
  278 
  279         result = kload_error_none;  // fixme: should this be USAGE error?
  280         goto finish;
  281     }
  282 
  283    /*****
  284     * If we're doing symbols only, then all entries in the dgraph must
  285     * have addresses assigned, or none must.
  286     */
  287     if (syms_only) {
  288         if (log_level >= kload_log_level_load_details) {
  289             kload_log_message("checking whether modules have addresses assigned" KNL);
  290         }
  291         for (i = 0; i < dgraph->length; i++) {
  292             struct dgraph_entry_t * entry = dgraph->load_order[i];
  293             if (entry->is_kernel_component) {
  294                 continue;
  295             }
  296             if (entry->loaded_address != 0) {
  297                 one_has_address = 1;
  298             } else {
  299                 one_lacks_address = 1;
  300             }
  301         }
  302     }
  303 #endif /* not KERNEL */
  304 
  305     if (one_has_address && one_lacks_address) {
  306         kload_log_error(
  307             "either all modules must have addresses set to nonzero values or "
  308             "none must" KNL);
  309         result = kload_error_invalid_argument;
  310         goto finish;
  311     }
  312 
  313 #ifndef KERNEL
  314    /* we need the priv port to check/load modules in the kernel.
  315     */
  316     if (PORT_NULL == G_kernel_priv_port) {
  317         G_kernel_priv_port = mach_host_self();  /* if we are privileged */
  318     }
  319 #endif /* not KERNEL */
  320 
  321 /*****
  322  * In the kernel, ALWAYS get load addresses of existing loaded kmods.
  323  */
  324 #ifndef KERNEL
  325    /*****
  326     * If we don't have addresses, then get them from the kernel.
  327     */
  328     if (!one_has_address && !do_prelink && (do_load || symbol_file || symbol_dir)) {
  329 #endif /* not KERNEL */
  330         if (log_level >= kload_log_level_load_details) {
  331             kload_log_message("getting module addresses from kernel" KNL);
  332         }
  333 #ifndef KERNEL
  334         result = kload_set_load_addresses_from_kernel(dgraph, kernel_file,
  335             do_load);
  336 #else
  337         result = kload_set_load_addresses_from_kernel(dgraph);
  338 #endif /* not KERNEL */
  339         if (result == kload_error_already_loaded) {
  340 
  341 #ifndef KERNEL
  342             if (do_load) {
  343                 goto finish;
  344             }
  345 #else
  346             goto finish;
  347 #endif /* not KERNEL */
  348 
  349         } else if (result != kload_error_none) {
  350             kload_log_error("can't check load addresses of modules" KNL);
  351             goto finish;
  352         }
  353 #ifndef KERNEL
  354     }
  355 #endif /* not KERNEL */
  356 
  357 #ifndef KERNEL
  358    /*****
  359     * At this point, if we're doing symbols only, it's an error to not
  360     * have a load address for every module.
  361     */
  362     if (syms_only && !do_prelink) {
  363         if (log_level >= kload_log_level_load_details) {
  364             kload_log_message("checking that all modules have addresses assigned" KNL);
  365         }
  366         for (i = 0; i < dgraph->length; i++) {
  367             struct dgraph_entry_t * entry = dgraph->load_order[i];
  368             if (entry->is_kernel_component) {
  369                 continue;
  370             }
  371             if (!entry->loaded_address) {
  372                 kload_log_error(
  373                     "missing load address during symbol generation: %s" KNL,
  374                     entry->name);
  375                 result = kload_error_unspecified;
  376                 goto finish;
  377             }
  378        }
  379     }
  380 
  381     if (do_prelink)
  382     {
  383         void *          bytes;
  384         CFIndex        length;
  385         CFAllocatorRef alloc;
  386 
  387         // We need a real allocator to pass to _IOReadBytesFromFile
  388         alloc = CFRetain(CFAllocatorGetDefault());
  389         if (_IOReadBytesFromFile(alloc, "prelinkstate", &bytes, &length, 0))
  390         {
  391             G_prelink_data = CFDataCreateMutable(alloc, 0);
  392             CFDataAppendBytes(G_prelink_data, (UInt8 *) bytes, length);
  393             CFAllocatorDeallocate(alloc, bytes);
  394         }
  395         G_prelink_dependencies = CFDataCreateMutable(alloc, 0);
  396         if (_IOReadBytesFromFile(alloc, "prelinkdependencies", &bytes, &length, 0))
  397         {
  398             CFDataAppendBytes(G_prelink_dependencies, (UInt8 *) bytes, length);
  399             CFAllocatorDeallocate(alloc, bytes);
  400         }
  401         CFRelease(alloc);
  402 
  403         if (!G_prelink_data) {
  404             kload_log_error(
  405                 "can't get load address for prelink %s" KNL, kernel_file);
  406             result = kload_error_link_load;
  407             goto finish;
  408         }
  409         else
  410             G_prelink = (struct PrelinkState *) CFDataGetMutableBytePtr(G_prelink_data);
  411     }
  412     else
  413         G_prelink = 0;
  414 #endif /* not KERNEL */
  415 
  416 #ifndef KERNEL
  417 
  418     result = __kload_load_modules(dgraph, kernel_file,
  419         patch_file, patch_dir, symbol_file, symbol_dir,
  420         do_load, do_start_kmod, do_prelink, interactive_level,
  421         ask_overwrite_symbols, overwrite_symbols);
  422 #else
  423     result = __kload_load_modules(dgraph);
  424 #endif /* not KERNEL */
  425 
  426 finish:
  427 
  428 #ifndef KERNEL
  429    /* Dispose of the host port to prevent security breaches and port
  430     * leaks. We don't care about the kern_return_t value of this
  431     * call for now as there's nothing we can do if it fails.
  432     */
  433     if (PORT_NULL != G_kernel_priv_port) {
  434         mach_port_deallocate(mach_task_self(), G_kernel_priv_port);
  435         G_kernel_priv_port = PORT_NULL;
  436     }
  437 #endif /* not KERNEL */
  438 
  439     for (i = 0; i < dgraph->length; i++) {
  440         dgraph_entry_t * current_entry = dgraph->graph[i];
  441         __kload_clean_up_entry(current_entry);
  442     }
  443 
  444 #ifndef KERNEL
  445     if (G_prelink)
  446     {
  447         SInt32       length;
  448         const void * bytes;
  449         Boolean      success;
  450 
  451         length = CFDataGetLength(G_prelink_data);
  452         bytes = (0 == length) ? (const void *)"" : CFDataGetBytePtr(G_prelink_data);
  453         success = _IOWriteBytesToFile("prelinkstate", bytes, length);
  454         if (!success)
  455         {
  456             kload_log_error("write prelinkstate" KNL);
  457             result = kload_error_link_load;
  458         }
  459         length = CFDataGetLength(G_prelink_dependencies);
  460         bytes = (0 == length) ? (const void *)"" : CFDataGetBytePtr(G_prelink_dependencies);
  461         success = _IOWriteBytesToFile("prelinkdependencies", bytes, length);
  462         if (!success)
  463         {
  464             kload_log_error("write prelinkdependencies" KNL);
  465             result = kload_error_link_load;
  466         }
  467     }
  468 #endif /* not KERNEL */
  469 
  470     return result;
  471 }
  472 
  473 #ifndef KERNEL
  474 /*******************************************************************************
  475 * This function claims the option flags d and D for object file dependencies
  476 * and in-kernel dependencies, respectively.
  477 *******************************************************************************/
  478 kload_error kload_load_with_arglist(
  479     int argc, char **argv,
  480     const char * kernel_file,
  481     const char * patch_file, const char * patch_dir,
  482     const char * symbol_file, const char * symbol_dir,
  483     int do_load, int do_start_kmod,
  484     int interactive_level,
  485     int ask_overwrite_symbols, int overwrite_symbols)
  486 {
  487     kload_error result = kload_error_none;
  488     dgraph_error_t dgraph_result;
  489     int syms_only = (!do_load) && (symbol_file || symbol_dir);
  490 
  491     static dgraph_t dependency_graph;
  492 
  493    /* Zero out fields in dependency graph for proper error handling later.
  494     */
  495     bzero(&dependency_graph, sizeof(dependency_graph));
  496 
  497     dgraph_result = dgraph_init_with_arglist(&dependency_graph,
  498         syms_only, "-d", "-D", argc, argv);
  499     if (dgraph_result == dgraph_error) {
  500         kload_log_error("error processing dependency list" KNL);
  501         result = kload_error_unspecified;
  502         goto finish;
  503     } else if (dgraph_result == dgraph_invalid) {
  504         // anything to print here, or did init call print something?
  505         result = kload_error_invalid_argument;
  506         goto finish;
  507     }
  508 
  509     result = kload_load_dgraph(&dependency_graph, kernel_file,
  510         patch_file, patch_dir, symbol_file, symbol_dir,
  511         do_load, do_start_kmod, false /* do_prelink */, interactive_level,
  512         ask_overwrite_symbols, overwrite_symbols);
  513 
  514 finish:
  515     return result;
  516 }
  517 #endif /* not KERNEL */
  518 /*******************************************************************************
  519 * This function can only operate on 32 bit mach object file symbol table
  520 * entries.
  521 *******************************************************************************/
  522 static
  523 kload_error __kload_keep_symbols(dgraph_entry_t * entry)
  524 {
  525     struct mach_header *        hdr;
  526     struct segment_command *    seg;
  527     struct nlist *              sym;
  528     struct symtab_command *     symcmd;
  529     unsigned long               idx, ncmds;
  530     vm_size_t                   size;
  531     vm_address_t                mem;
  532     struct load_cmds {
  533         struct mach_header     hdr;
  534         struct segment_command seg;
  535         struct symtab_command  symcmd;
  536     };
  537     struct load_cmds * cmd;
  538     unsigned int symtabsize;
  539 
  540     if (entry->symbols)
  541         return kload_error_none;
  542 
  543     hdr   = entry->linked_image;
  544     ncmds = hdr->ncmds;
  545     seg   = (struct segment_command *)(hdr + 1);
  546     for (idx = 0;
  547             idx < ncmds;
  548             idx++, seg = (struct segment_command *)(((vm_offset_t)seg) + seg->cmdsize))
  549     {
  550         if (LC_SYMTAB == seg->cmd)
  551             break;
  552     }
  553     if (idx >= ncmds)
  554     {
  555         kload_log_error("no LC_SYMTAB" KNL);
  556         return kload_error_unspecified;
  557     }
  558 
  559     symcmd = (struct symtab_command *) seg;
  560 
  561     symtabsize = symcmd->stroff + symcmd->strsize - symcmd->symoff;
  562 
  563     size = sizeof(struct load_cmds) + symtabsize;
  564 
  565     mem = (vm_offset_t) malloc(size);
  566 
  567     cmd = (struct load_cmds *) mem;
  568     sym = (struct nlist *) (cmd + 1);
  569 
  570     cmd->hdr    = *hdr;
  571     cmd->symcmd = *symcmd;
  572     bcopy((const void *) (((vm_offset_t) hdr) + symcmd->symoff), 
  573             sym,
  574             symtabsize);
  575 
  576     hdr                 = (struct mach_header *) mem;
  577     cmd->hdr.ncmds      = 2;
  578     cmd->hdr.sizeofcmds = sizeof(struct load_cmds) - sizeof(struct mach_header);
  579     cmd->hdr.flags     &= ~MH_INCRLINK;
  580 
  581     cmd->symcmd.stroff -= (symcmd->symoff - sizeof(struct load_cmds));
  582     cmd->symcmd.symoff  = sizeof(struct load_cmds);
  583 
  584     cmd->seg.cmd        = LC_SEGMENT;
  585     cmd->seg.cmdsize    = sizeof(struct segment_command);
  586     strlcpy(cmd->seg.segname, SEG_LINKEDIT, sizeof(cmd->seg.segname));
  587     cmd->seg.vmaddr     = 0;
  588     cmd->seg.vmsize     = 0;
  589     cmd->seg.fileoff    = cmd->symcmd.symoff;
  590     cmd->seg.filesize   = symtabsize;
  591     cmd->seg.maxprot    = 7;
  592     cmd->seg.initprot   = 1;
  593     cmd->seg.nsects     = 0;
  594     cmd->seg.flags      = 0;
  595 
  596     sym = (struct nlist *) (cmd + 1);
  597     for (idx = 0; idx < symcmd->nsyms; idx++, sym++)
  598     {
  599         if ( (sym->n_type & N_STAB) != 0)
  600         {
  601             sym->n_type = N_ABS;
  602             sym->n_desc  = 0;
  603             sym->n_value = sym->n_un.n_strx;
  604             sym->n_un.n_strx = 0;
  605             sym->n_sect = NO_SECT;
  606         }
  607         else if ( (sym->n_type & N_TYPE) == N_SECT)
  608         {
  609             sym->n_sect = NO_SECT;
  610             sym->n_type = (sym->n_type & ~N_TYPE) | N_ABS;
  611         }
  612     }
  613     if (log_level >= kload_log_level_load_details)
  614     {
  615         kload_log_message("__kload_keep_symbols %s, nsyms %ld, 0x%x bytes" KNL, 
  616                             entry->name, (unsigned long)symcmd->nsyms, size);
  617     }
  618 
  619     entry->symbols        = mem;
  620     entry->symbols_malloc = mem;
  621     entry->symbols_length = size;
  622 
  623     return kload_error_none;
  624 }
  625 
  626 
  627 /*******************************************************************************
  628 * This function can only operate on 32 bit mach object files
  629 *******************************************************************************/
  630 static
  631 kload_error __kload_make_opaque_basefile(dgraph_t * dgraph, struct mach_header * hdr)
  632 {
  633     struct segment_command *    seg;
  634     struct segment_command *    data_seg;
  635     struct segment_command *    text_seg;
  636     struct section *            sec;
  637     unsigned int                j;
  638     vm_offset_t                 offset;
  639     unsigned long               idx, ncmds;
  640     vm_size_t                   size;
  641     vm_address_t                mem, out;
  642     static vm_address_t         keep_base_image;
  643     static vm_size_t            keep_base_size;
  644 
  645     if (dgraph->opaque_base_image)
  646         return kload_error_none;
  647 
  648     if (keep_base_image)
  649     {
  650         dgraph->opaque_base_image  = keep_base_image;
  651         dgraph->opaque_base_length = keep_base_size;
  652         return kload_error_none;
  653     }
  654 
  655     data_seg = text_seg = NULL;
  656     ncmds = hdr->ncmds;
  657     seg = (struct segment_command *)(hdr + 1);
  658     for (idx = 0;
  659             idx < ncmds;
  660             idx++, seg = (struct segment_command *)(((vm_offset_t)seg) + seg->cmdsize))
  661     {
  662         if (LC_SEGMENT != seg->cmd)
  663             continue;
  664         if (!strcmp(SEG_TEXT, seg->segname))
  665             text_seg = seg;
  666         else if (!strcmp(SEG_DATA, seg->segname))
  667             data_seg = seg;
  668     }
  669     if (!text_seg || !data_seg)
  670     {
  671         kload_log_error("no SEG_TEXT or SEG_DATA" KNL);
  672         return kload_error_unspecified;
  673     }
  674 
  675     size = sizeof(struct mach_header) + text_seg->cmdsize + data_seg->cmdsize;
  676     mem = (vm_offset_t) malloc(size);
  677 
  678     out = mem;
  679     bcopy(hdr, (void *) out, sizeof(struct mach_header));
  680     hdr = (struct mach_header *) out;
  681     out += sizeof(struct mach_header);
  682 
  683     bcopy(text_seg, (void *) out, text_seg->cmdsize);
  684     text_seg = (struct segment_command *) out;
  685     out += text_seg->cmdsize;
  686 
  687     bcopy(data_seg, (void *) out, data_seg->cmdsize);
  688     data_seg = (struct segment_command *) out;
  689     out += data_seg->cmdsize;
  690 
  691     hdr->ncmds = 2;
  692     hdr->sizeofcmds = text_seg->cmdsize + data_seg->cmdsize;
  693 
  694     offset = hdr->sizeofcmds;
  695 
  696     text_seg->fileoff  = offset;
  697     text_seg->filesize = 0;
  698 
  699     sec = (struct section *)(text_seg + 1);
  700     for (j = 0; j < text_seg->nsects; j++, sec++)
  701     {
  702 //      sec->addr   = (unsigned long) addr;
  703         sec->size   = 0;
  704         sec->offset = offset;
  705         sec->nreloc = 0;
  706     }
  707 
  708     data_seg->fileoff  = offset;
  709     data_seg->filesize = 0;
  710 
  711     sec = (struct section *)(data_seg + 1);
  712     for (j = 0; j < data_seg->nsects; j++, sec++)
  713     {
  714 //      sec->addr   = (unsigned long) addr;
  715         sec->size   = 0;
  716         sec->offset = offset;
  717         sec->nreloc = 0;
  718     }
  719 
  720     dgraph->opaque_base_image  = mem;
  721     dgraph->opaque_base_length = size;
  722     keep_base_image            = mem;
  723     keep_base_size             = size;
  724 
  725     return kload_error_none;
  726 }
  727 
  728 /*******************************************************************************
  729 *
  730 *******************************************************************************/
  731 static
  732 kload_error __kload_load_modules(dgraph_t * dgraph
  733 #ifndef KERNEL
  734     ,
  735     const char * kernel_file,
  736     const char * patch_file,
  737     const char * patch_dir,
  738     const char * symbol_file,
  739     const char * symbol_dir,
  740     int do_load,
  741     int do_start_kmod,
  742     int do_prelink,
  743     int interactive_level,
  744     int ask_overwrite_symbols,
  745     int overwrite_symbols
  746 #endif /* not KERNEL */
  747     )
  748 {
  749     kload_error result = kload_error_none;
  750 #ifndef KERNEL
  751     unsigned long int kernel_size = 0;
  752     kern_return_t mach_result = KERN_SUCCESS;
  753 #else
  754         const char *kernel_file = "(kernel)";
  755 #endif /* not KERNEL */
  756         char *kernel_base_addr = NULL;
  757     int kld_result;
  758     Boolean cleanup_kld_loader = false;
  759     unsigned int i;
  760     char opaque_now = false;
  761 
  762    /* We have to map all object files to get their CFBundleIdentifier
  763     * names.
  764     */
  765 #ifndef KERNEL
  766     result = kload_map_dgraph(dgraph, kernel_file);
  767 #else
  768     result = kload_map_dgraph(dgraph);
  769 #endif /* not KERNEL */
  770     if (result != kload_error_none) {
  771         kload_log_error("error mapping object files" KNL);
  772         goto finish;
  773     }
  774 
  775 #ifndef KERNEL
  776     result = __kload_patch_dgraph(dgraph, kernel_file);
  777 #else
  778     result = __kload_patch_dgraph(dgraph);
  779 #endif /* not KERNEL */
  780     if (result != kload_error_none) {
  781         // FIXME: print an error message here?
  782         goto finish;
  783     }
  784 
  785 #ifndef KERNEL
  786     // FIXME: check error return
  787     __kload_output_patches(dgraph, patch_file, patch_dir,
  788         ask_overwrite_symbols, overwrite_symbols);
  789 
  790    /*****
  791     * If we're not loading or writing symbols, we're done.
  792     */
  793     if (!do_load && !do_prelink && !symbol_file && !symbol_dir) {
  794         goto finish;
  795     }
  796 
  797     if (do_load && PORT_NULL == G_kernel_port) {
  798         mach_result = task_for_pid(mach_task_self(), 0, &G_kernel_port);
  799         if (mach_result != KERN_SUCCESS) {
  800             kload_log_error("unable to get kernel task port: %s" KNL,
  801                 mach_error_string(mach_result));
  802             kload_log_error("you must be running as root to load "
  803                 "modules into the kernel" KNL);
  804             result = kload_error_kernel_permission;
  805             goto finish;
  806         }
  807     }
  808 #endif /* not KERNEL */
  809 
  810     kld_address_func(&__kload_linkedit_address);
  811 
  812 #ifndef KERNEL
  813     G_syms_only = (!do_load) && (symbol_file || symbol_dir || patch_dir);
  814 
  815     kernel_base_addr = kld_file_getaddr(kernel_file, &kernel_size);
  816     if (!kernel_base_addr) {
  817         kload_log_error(
  818             "can't get load address for kernel %s" KNL, kernel_file);
  819         result = kload_error_link_load;
  820         goto finish;
  821     }
  822 #else /* KERNEL */
  823 
  824     kernel_base_addr = (char *) &_mh_execute_header;
  825 
  826 #endif /* not KERNEL */
  827 
  828     kld_result = true;
  829     if (dgraph->has_symbol_sets)
  830     {
  831         result = __kload_make_opaque_basefile(dgraph, (struct mach_header *) kernel_base_addr);
  832         if (result != kload_error_none) {
  833             kload_log_error("can't construct opaque base image from %s" KNL, kernel_file);
  834             goto finish;
  835         }
  836 
  837         kld_result = kld_load_basefile_from_memory(kernel_file,
  838                             (char *)  dgraph->opaque_base_image, 
  839                                        dgraph->opaque_base_length);
  840     }
  841 #ifndef KERNEL
  842     else
  843         kld_result = kld_load_basefile_from_memory(kernel_file,
  844                             (char *)  kernel_base_addr, kernel_size);
  845 #endif /* not KERNEL */
  846 
  847     if (!kld_result) {
  848         kload_log_error("can't link base image %s" KNL, kernel_file);
  849         result = kload_error_link_load;
  850         goto finish;
  851     }
  852 
  853     cleanup_kld_loader = true;
  854 
  855     for (i = 0; i < dgraph->length; i++) {
  856         dgraph_entry_t * current_entry = dgraph->load_order[i];
  857 
  858         opaque_now |= current_entry->opaque_link;
  859 
  860         if (kOpaqueLink & opaque_now)
  861         {
  862             unsigned int k, j;
  863 
  864             if (log_level >= kload_log_level_load_details)
  865             {
  866                 kload_log_message("opaque link for %s" KNL, current_entry->name);
  867             }
  868 
  869             kld_set_link_options(KLD_STRIP_ALL);        // KLD_STRIP_NONE
  870 
  871             if (dgraph->have_loaded_symbols)
  872             {
  873                 kld_unload_all(1);
  874                 if (kRawKernelLink & current_entry->opaque_link) {
  875 #ifndef KERNEL
  876                     kld_result = kld_load_basefile_from_memory(kernel_file,
  877                                                        (char *)  kernel_base_addr, kernel_size);
  878 #endif
  879                 } else {
  880                     kld_result = kld_load_basefile_from_memory(kernel_file,
  881                                                         (char *)  dgraph->opaque_base_image, 
  882                                                                     dgraph->opaque_base_length);
  883                     dgraph->have_loaded_symbols = false;
  884                 }
  885                 if (!kld_result) {
  886                     kload_log_error("can't link base image %s" KNL, kernel_file);
  887                     result = kload_error_link_load;
  888                     goto finish;
  889                 }
  890             }
  891 
  892             for (j = 0; j < i; j++)
  893             {
  894 
  895                 dgraph_entry_t * image_dep = dgraph->load_order[j];
  896 
  897                 if (current_entry->opaque_link)
  898                 {
  899                     for (k = 0;
  900                         (k < current_entry->num_dependencies)
  901                         && (current_entry->dependencies[k] != image_dep);
  902                         k++)    {}
  903     
  904                     if (k == current_entry->num_dependencies)
  905                         continue;
  906                 }
  907 
  908                 if (!current_entry->opaque_link && image_dep->opaques)
  909                 {
  910                     // kpi not on direct dependency list
  911                     continue;
  912                 }
  913                 if (kRawKernelLink & image_dep->opaques)
  914                 {
  915                     // raw kernel already in base image
  916                     continue;
  917                 }
  918 
  919                 if (!image_dep->symbols)
  920                 {
  921                     kload_log_error("internal error; no dependent symbols" KNL);
  922                     result = kload_error_link_load;
  923                     goto finish;
  924                 }
  925                 else
  926                 {
  927                     struct mach_header * kld_header;
  928 
  929 #ifndef KERNEL
  930                     kld_result = kld_load_from_memory(&kld_header, image_dep->name,
  931                             (char *) image_dep->symbols, image_dep->symbols_length, NULL);
  932 #else
  933                     kld_result = kld_load_from_memory(&kld_header, image_dep->name,
  934                             (char *) image_dep->symbols, image_dep->symbols_length);
  935 #endif /* not KERNEL */
  936                     if (!kld_result) {
  937                         kload_log_error("can't link dependent image %s" KNL, image_dep->name);
  938                         result = kload_error_link_load;
  939                         goto finish;
  940                     }
  941                     kld_forget_symbol("_kmod_info");
  942                     dgraph->have_loaded_symbols = true;
  943                 }
  944             }
  945         } /* opaque_now */
  946 
  947         if (dgraph->has_opaque_links
  948 #ifndef KERNEL
  949             || symbol_file || symbol_dir
  950 #endif
  951             )
  952             kld_set_link_options(KLD_STRIP_NONE);
  953         else
  954             kld_set_link_options(KLD_STRIP_ALL);
  955 
  956 #ifndef KERNEL
  957         result = __kload_load_module(dgraph, current_entry,
  958             (current_entry == dgraph->root),
  959             symbol_file, symbol_dir, do_load,
  960             interactive_level, ask_overwrite_symbols, overwrite_symbols);
  961 #else
  962         result = __kload_load_module(dgraph, current_entry,
  963             (current_entry == dgraph->root));
  964 #endif /* not KERNEL */
  965         if (result != kload_error_none) {
  966             goto finish;
  967         }
  968 
  969         if (dgraph->has_opaque_links && (current_entry != dgraph->root))
  970         {
  971             if (!(kRawKernelLink & current_entry->opaques)) {
  972                 result = __kload_keep_symbols(current_entry);
  973             }
  974             if (result != kload_error_none) {
  975                 kload_log_error("__kload_keep_symbols() failed for module %s" KNL,
  976                     current_entry->name);
  977                 goto finish;
  978             }
  979         }
  980 
  981 #ifndef KERNEL
  982         if (do_load && current_entry->do_load) {
  983 #else
  984         if (current_entry->do_load) {
  985 #endif /* not KERNEL */
  986             result = __kload_set_module_dependencies(current_entry);
  987             if ( ! (result == kload_error_none ||
  988                     result == kload_error_already_loaded) ) {
  989                 goto finish;
  990             }
  991 
  992 #ifndef KERNEL
  993             if ( (interactive_level == 1 && current_entry == dgraph->root) ||
  994                  (interactive_level == 2) ) {
  995 
  996                 int approve = (*__kload_approve_func)(1,
  997                     "\nStart module %s (answering no will abort the load)",
  998                     current_entry->name);
  999 
 1000                 if (approve > 0) {
 1001                     do_start_kmod = true; // override 'cause user said so
 1002                 } else {
 1003                     kern_return_t mach_result;
 1004                     if (approve < 0) {
 1005                          kload_log_message("error reading user response; "
 1006                             "destroying loaded module" KNL);
 1007                     } else {
 1008                          kload_log_message("user canceled module start; "
 1009                             "destroying loaded module" KNL);
 1010                     }
 1011                     mach_result = kmod_destroy(G_kernel_priv_port, current_entry->kmod_id);
 1012                     if (mach_result != KERN_SUCCESS) {
 1013                         kload_log_error("kmod_destroy() failed" KNL);
 1014                     }
 1015                     if (approve < 0) {
 1016                         result = kload_error_unspecified;
 1017                         goto finish;
 1018                     } else {
 1019                         result = kload_error_user_abort;
 1020                         goto finish;
 1021                     }
 1022                 }
 1023             }
 1024 #endif /* not KERNEL */
 1025 
 1026 #ifndef KERNEL
 1027             if (current_entry != dgraph->root ||
 1028                 (current_entry == dgraph->root && do_start_kmod)) {
 1029 #endif /* not KERNEL */
 1030 
 1031                 result = __kload_start_module(current_entry);
 1032                 if ( ! (result == kload_error_none ||
 1033                         result == kload_error_already_loaded) ) {
 1034                     goto finish;
 1035 #ifndef KERNEL
 1036                 } else if (interactive_level ||
 1037                            log_level >= kload_log_level_load_details) {
 1038 #else
 1039                 } else if (log_level >= kload_log_level_load_details) {
 1040 #endif /* not KERNEL */
 1041 
 1042                      kload_log_message("started module %s" KNL,
 1043                         current_entry->name);
 1044                 } /* log_level */
 1045 #ifndef KERNEL
 1046             } /* current_entry... */
 1047 #endif /* not KERNEL */
 1048 
 1049 
 1050 #ifndef KERNEL
 1051         } /* if do_load */
 1052 #else
 1053         } /* if do_load */
 1054 #endif /* not KERNEL */
 1055     } /* for i, dgraph->length */
 1056 
 1057 finish:
 1058 
 1059 #ifndef KERNEL
 1060    /* Dispose of the kernel port to prevent security breaches and port
 1061     * leaks. We don't care about the kern_return_t value of this
 1062     * call for now as there's nothing we can do if it fails.
 1063     */
 1064     if (PORT_NULL != G_kernel_port) {
 1065         mach_port_deallocate(mach_task_self(), G_kernel_port);
 1066         G_kernel_port = PORT_NULL;
 1067     }
 1068 #endif /* not KERNEL */
 1069 
 1070     if (cleanup_kld_loader) {
 1071         kld_unload_all(1);
 1072     }
 1073 
 1074     return result;
 1075 }
 1076 
 1077 
 1078 /*******************************************************************************
 1079 *
 1080 *******************************************************************************/
 1081 
 1082 #ifndef KERNEL
 1083 #define __KLOAD_SYMBOL_EXTENSION   ".sym"
 1084 #endif /* not KERNEL */
 1085 
 1086 static
 1087 kload_error __kload_load_module(dgraph_t * dgraph,
 1088     dgraph_entry_t * entry,
 1089 #ifdef KERNEL
 1090     __unused int is_root
 1091 #else   /* not KERNEL */
 1092     int is_root,
 1093     const char * symbol_file,
 1094     const char * symbol_dir,
 1095     int do_load,
 1096     int interactive_level,
 1097     int ask_overwrite_symbols,
 1098     int overwrite_symbols
 1099     #endif /* not KERNEL */
 1100     )
 1101 {
 1102     kload_error result = kload_error_none;
 1103 
 1104     int kld_result;
 1105     int mach_result;
 1106     struct mach_header * kld_header;
 1107     const char * kmod_symbol = "_kmod_info";
 1108     unsigned long kernel_kmod_info;
 1109     kmod_info_t * local_kmod_info = NULL;
 1110     char * dest_address = 0;
 1111 #ifndef KERNEL
 1112     char * allocated_filename = NULL;
 1113     char * symbol_filename = NULL;
 1114     int file_check;
 1115     vm_address_t vm_buffer = 0;
 1116 #endif /* not KERNEL */
 1117 
 1118    /* A kernel component is by nature already linked and loaded and has
 1119     * no work to be done upon it.
 1120     */
 1121     if (entry->is_kernel_component && !entry->is_symbol_set) {
 1122         result = kload_error_none;
 1123         goto finish;
 1124     }
 1125 
 1126     G_current_load_entry = entry;
 1127 
 1128     if (log_level >= kload_log_level_load_basic) {
 1129 #ifndef KERNEL
 1130         if (do_load) {
 1131 #endif /* not KERNEL */
 1132             kload_log_message("link/loading file %s" KNL, entry->name);
 1133 #ifndef KERNEL
 1134         } else {
 1135             kload_log_message("linking file %s" KNL, entry->name);
 1136         }
 1137 #endif /* not KERNEL */
 1138     }
 1139 
 1140 #ifndef KERNEL
 1141     if (entry->link_output_file != entry->name) {
 1142         symbol_filename = entry->link_output_file;
 1143     }
 1144 
 1145     if (symbol_filename) {
 1146         file_check = kload_file_exists(symbol_filename);
 1147         if (file_check < 0) {
 1148             kload_log_error("error checking existence of file %s" KNL,
 1149                 symbol_filename);
 1150         } else if (file_check > 0 && !overwrite_symbols) {
 1151 
 1152             if (!ask_overwrite_symbols) {
 1153                 kload_log_message("symbol file %s exists; not overwriting" KNL,
 1154                     symbol_filename);
 1155                 symbol_filename = NULL;
 1156             } else {
 1157                 int approve = (*__kload_approve_func)(1,
 1158                     "\nSymbol file %s exists; overwrite", symbol_filename);
 1159 
 1160                 if (approve < 0) {
 1161                     result = kload_error_unspecified;
 1162                     goto finish;
 1163                 } else if (approve == 0) {
 1164                     if (allocated_filename) free(allocated_filename);
 1165                     allocated_filename = NULL;
 1166                     symbol_filename = NULL;
 1167                 }
 1168             }
 1169         }
 1170     }
 1171 
 1172     if (symbol_filename &&
 1173         (interactive_level ||
 1174          log_level >= kload_log_level_basic) ) {
 1175 
 1176         kload_log_message("writing symbol file %s" KNL, symbol_filename);
 1177     }
 1178 
 1179     if (do_load) {
 1180         if (interactive_level && entry->loaded_address) {
 1181             kload_log_message(
 1182                 "module %s is already loaded as %s at address 0x%08x" KNL,
 1183                 entry->name, entry->expected_kmod_name,
 1184                 entry->loaded_address);
 1185         } else if ( (interactive_level == 1 && is_root) ||
 1186              (interactive_level == 2) ) {
 1187 
 1188             int approve = (*__kload_approve_func)(1,
 1189                 "\nLoad module %s", entry->name);
 1190 
 1191             if (approve < 0) {
 1192                 result = kload_error_unspecified;
 1193                 goto finish;
 1194             } else if (approve == 0) {
 1195                 result = kload_error_user_abort;
 1196                 goto finish;
 1197             }
 1198         }
 1199     }
 1200 #endif /* not KERNEL */
 1201 
 1202     entry->object = kld_file_getaddr(entry->name, &entry->object_length);
 1203     if (!entry->object) {
 1204         kload_log_error("kld_file_getaddr() failed for module %s" KNL,
 1205             entry->name);
 1206         __kload_clear_kld_globals();
 1207         result = kload_error_link_load;
 1208         goto finish;
 1209     }
 1210 
 1211     if (entry->is_symbol_set) {
 1212         entry->symbols        = (vm_address_t) entry->object;
 1213         entry->symbols_length = entry->object_length;
 1214 
 1215 #ifndef KERNEL
 1216         if (symbol_filename) {
 1217             if (!_IOWriteBytesToFile(symbol_filename, (void *) entry->symbols, entry->symbols_length)) {
 1218                 kload_log_error("write symbol file failed for module %s" KNL,
 1219                     entry->name);
 1220                 __kload_clear_kld_globals();
 1221                 result = kload_error_link_load;
 1222                 goto finish;
 1223             }
 1224             symbol_filename = 0;
 1225             if (G_prelink && (entry->name != entry->link_output_file))
 1226             {
 1227                 kload_log_error("prelink %s %s %s" KNL,
 1228                     entry->name, entry->link_output_file, entry->expected_kmod_name);
 1229                 register_prelink(entry, NULL, NULL);
 1230             }
 1231         }
 1232 #endif /* not KERNEL */
 1233         if (entry->opaques) {
 1234             result = kload_error_none;
 1235             goto finish;
 1236         }
 1237     }
 1238 
 1239 #ifndef KERNEL
 1240     kld_result = kld_load_from_memory(&kld_header, entry->name,
 1241             entry->object, entry->object_length, symbol_filename);
 1242 #else
 1243     kld_result = kld_load_from_memory(&kld_header, entry->name,
 1244             entry->object, entry->object_length);
 1245 #endif /* not KERNEL */
 1246 
 1247 #ifndef KERNEL
 1248     fflush(stdout);
 1249     fflush(stderr);
 1250 #endif /* not KERNEL */
 1251 
 1252     dgraph->have_loaded_symbols = true;
 1253 
 1254     if (!kld_result || !entry->kernel_load_address) {
 1255         kload_log_error("kld_load_from_memory() failed for module %s" KNL,
 1256             entry->name);
 1257         __kload_clear_kld_globals();
 1258         entry->need_cleanup = 1;
 1259         result = kload_error_link_load;
 1260         goto finish;
 1261     }
 1262 
 1263     if (entry->is_symbol_set) {
 1264         result = kload_error_none;
 1265         goto finish;
 1266     }
 1267 
 1268     entry->linked_image = kld_header;
 1269     entry->linked_image_length = -1;    // unknown!
 1270 
 1271 /* If we're in the kernel and not loading (as when handling an
 1272  * already-loaded dependency), we don't need to waste any CPU
 1273  * cycles looking up the kmod_info struct.
 1274  */
 1275 #ifdef KERNEL
 1276     if (entry->do_load) {
 1277 #endif /* KERNEL */
 1278 
 1279     kld_result = kld_lookup(kmod_symbol, &kernel_kmod_info);
 1280     if (!kld_result) {
 1281         kload_log_error("kld_lookup(\"%s\") failed for module %s" KNL,
 1282             kmod_symbol, entry->name);
 1283         entry->need_cleanup = 1;
 1284         result = kload_error_link_load;
 1285         goto finish;
 1286     }
 1287 
 1288 #ifdef KERNEL
 1289     }
 1290 #endif /* KERNEL */
 1291 
 1292     kld_result = kld_forget_symbol(kmod_symbol);
 1293 #ifndef KERNEL
 1294     fflush(stdout);
 1295     fflush(stderr);
 1296 #endif /* not KERNEL */
 1297     if (!kld_result) {
 1298         kload_log_error("kld_forget_symbol(\"%s\") failed for module %s" KNL,
 1299             kmod_symbol, entry->name);
 1300         entry->need_cleanup = 1;
 1301         result = kload_error_link_load;
 1302         goto finish;
 1303     }
 1304 
 1305 /* This section is always done in userland, but in kernel space
 1306  * only if we're loading the kext, because what we have in kernel
 1307  * space for an already-loaded kext is the kext itself, which
 1308  * must not be touched again after it's been loaded and started.
 1309  */
 1310 #ifdef KERNEL
 1311     if (entry->do_load)
 1312 #endif /* KERNEL */
 1313     {
 1314 
 1315 
 1316    /* Get the linked image's kmod_info by translating from the
 1317     * destined kernel-space address at kernel_kmod_info to an
 1318     * offset from kld_header.
 1319     */
 1320     local_kmod_info = (kmod_info_t *)((unsigned long)kernel_kmod_info -
 1321         (unsigned long)G_current_load_entry->kernel_load_address +
 1322         (unsigned long)kld_header);
 1323 
 1324    /* Stamp the bundle ID and version from the entry over anything
 1325     * resident inside the kmod.
 1326     */
 1327     bzero(local_kmod_info->name, sizeof(local_kmod_info->name));
 1328     strlcpy(local_kmod_info->name, entry->expected_kmod_name, sizeof(local_kmod_info->name));
 1329 
 1330     bzero(local_kmod_info->version, sizeof(local_kmod_info->version));
 1331     strlcpy(local_kmod_info->version, entry->expected_kmod_vers, sizeof(local_kmod_info->version));
 1332 
 1333     if (log_level >= kload_log_level_details) {
 1334         kload_log_message("kmod name: %s" KNL, local_kmod_info->name);
 1335         kload_log_message("kmod start @ 0x%x (offset 0x%lx)" KNL,
 1336            (vm_address_t)local_kmod_info->start,
 1337            (unsigned long)local_kmod_info->start - (unsigned long)G_current_load_entry->kernel_load_address);
 1338         kload_log_message("kmod stop @ 0x%x (offset 0x%lx)" KNL,
 1339            (vm_address_t)local_kmod_info->stop,
 1340            (unsigned long)local_kmod_info->stop - (unsigned long)G_current_load_entry->kernel_load_address);
 1341     }
 1342 
 1343     if (!local_kmod_info->start || !local_kmod_info->start) {
 1344         kload_log_error(
 1345             "error for module file %s; start or stop address is zero" KNL,
 1346             entry->name);
 1347         entry->need_cleanup = 1;
 1348         result = kload_error_link_load;
 1349         goto finish;
 1350     }
 1351 
 1352    /* Record link info into kmod_info struct, rounding the hdr_size
 1353     * to fit the adjustment that was made in __kload_linkedit_address().
 1354     */
 1355     if (entry->kernel_alloc_address) {
 1356         local_kmod_info->address = entry->kernel_alloc_address;
 1357     } else {
 1358         local_kmod_info->address = entry->loaded_address;
 1359     }
 1360     local_kmod_info->size = entry->kernel_alloc_size;
 1361     local_kmod_info->hdr_size = round_page(entry->kernel_hdr_size);
 1362 
 1363     }
 1364 
 1365 #ifndef KERNEL
 1366     if (G_prelink && (entry->name != entry->link_output_file))
 1367     {
 1368         register_prelink(entry, local_kmod_info, kernel_kmod_info);
 1369     }
 1370 
 1371     if (do_load && entry->do_load) {
 1372         mach_result = vm_allocate(mach_task_self(), &vm_buffer,
 1373             entry->kernel_alloc_size, VM_FLAGS_ANYWHERE);
 1374         if (mach_result != KERN_SUCCESS) {
 1375             kload_log_error("unable to vm_allocate() copy buffer" KNL);
 1376             entry->need_cleanup = 1;
 1377             result = kload_error_no_memory;  // FIXME: kernel error?
 1378             goto finish;
 1379         }
 1380 
 1381         dest_address = (char *)vm_buffer;
 1382 
 1383         memcpy(dest_address, kld_header, entry->kernel_hdr_size);
 1384         memcpy(dest_address + round_page(entry->kernel_hdr_size),
 1385                (void *)((unsigned long)kld_header + entry->kernel_hdr_size),
 1386                entry->kernel_load_size - entry->kernel_hdr_size);
 1387 
 1388         mach_result = vm_write(G_kernel_port, entry->kernel_alloc_address,
 1389             vm_buffer, entry->kernel_alloc_size);
 1390         if (mach_result != KERN_SUCCESS) {
 1391             kload_log_error("unable to write module to kernel memory" KNL);
 1392             entry->need_cleanup = 1;
 1393             result = kload_error_kernel_error;
 1394             goto finish;
 1395         }
 1396 
 1397         mach_result = kmod_create(G_kernel_priv_port,
 1398             (vm_address_t)kernel_kmod_info, &(entry->kmod_id));
 1399 
 1400 #else
 1401     if (entry->do_load) {
 1402         dest_address = (char *)entry->kernel_alloc_address;
 1403         memcpy(dest_address, kld_header, entry->kernel_hdr_size);
 1404         memcpy(dest_address + round_page(entry->kernel_hdr_size),
 1405                (void *)((unsigned long)kld_header + entry->kernel_hdr_size),
 1406                entry->kernel_load_size - entry->kernel_hdr_size);
 1407 
 1408        /* We've written data & instructions into kernel memory, so flush
 1409         * the data cache and invalidate the instruction cache.
 1410         */
 1411         flush_dcache(entry->kernel_alloc_address, entry->kernel_alloc_size, false);
 1412         invalidate_icache(entry->kernel_alloc_address, entry->kernel_alloc_size, false);
 1413 
 1414         mach_result = kmod_create_internal(
 1415             (kmod_info_t *)kernel_kmod_info, &(entry->kmod_id));
 1416 
 1417 #endif /* not KERNEL */
 1418 
 1419         if (mach_result != KERN_SUCCESS) {
 1420             kload_log_error("unable to register module with kernel" KNL);
 1421             entry->need_cleanup = 1;
 1422             result = kload_error_kernel_error;
 1423             goto finish;
 1424         }
 1425 
 1426 #ifndef KERNEL
 1427         if (interactive_level || log_level >= kload_log_level_load_basic) {
 1428 #else
 1429         if (log_level >= kload_log_level_load_basic) {
 1430 #endif /* not KERNEL */
 1431             kload_log_message(
 1432                 "module %s created as # %d at address 0x%x, size %ld" KNL,
 1433                 entry->expected_kmod_name, entry->kmod_id,
 1434                 entry->kernel_alloc_address,
 1435                 entry->kernel_alloc_size);
 1436 
 1437 #ifndef KERNEL
 1438         }
 1439 #else
 1440         }
 1441 #endif /* not KERNEL */
 1442 
 1443 #ifndef KERNEL
 1444         if (interactive_level) {
 1445             kload_log_message(
 1446                 "You can now break to the debugger and set breakpoints "
 1447                 " for this extension." KNL);
 1448         }
 1449 #endif /* not KERNEL */
 1450 
 1451 #ifndef KERNEL
 1452     }
 1453 #else
 1454     }
 1455 #endif /* not KERNEL */
 1456 
 1457 finish:
 1458 
 1459 #ifndef KERNEL
 1460     if (allocated_filename) {
 1461         free(allocated_filename);
 1462     }
 1463     if (vm_buffer) {
 1464         vm_deallocate(mach_task_self(), vm_buffer, entry->kernel_alloc_size);
 1465     }
 1466 #endif /* not KERNEL */
 1467     __kload_clear_kld_globals();
 1468 
 1469     return result;
 1470 }
 1471 
 1472 /*******************************************************************************
 1473 *******************************************************************************/
 1474 
 1475 #ifndef KERNEL
 1476 static kload_error
 1477 register_prelink(dgraph_entry_t * entry, 
 1478                     kmod_info_t * local_kmod_info, vm_offset_t kernel_kmod_info)
 1479 {
 1480     CFIndex i, j, depoffset;
 1481     Boolean exists;
 1482     kmod_info_t desc;
 1483 
 1484     depoffset = CFDataGetLength(G_prelink_dependencies) / sizeof(CFIndex);
 1485 
 1486     for (i = 0; i < entry->num_dependencies; i++)
 1487     {
 1488         exists = false;
 1489         for (j = 1; (j < (1 + G_prelink->modules[0].id)); j++)
 1490         {
 1491             exists = (0 == strcmp(entry->dependencies[i]->expected_kmod_name,
 1492                                     G_prelink->modules[j].name));
 1493             if (exists)
 1494                 break;
 1495         }
 1496         if (!exists)
 1497         {
 1498             bzero(&desc, sizeof(desc));
 1499             strcpy(desc.name, entry->dependencies[i]->expected_kmod_name);
 1500 
 1501             if (log_level >= kload_log_level_basic) {
 1502                 kload_log_message("[%d] (dep)\n    %s" KNL, 
 1503                                     G_prelink->modules[0].id + 1, desc.name);
 1504             }
 1505             G_prelink->modules[0].id++;
 1506             CFDataAppendBytes(G_prelink_data, (UInt8 *) &desc, sizeof(desc));
 1507             G_prelink = (struct PrelinkState *) CFDataGetMutableBytePtr(G_prelink_data);
 1508         }
 1509 
 1510         G_prelink->modules[0].reference_count++;
 1511         OSWriteBigInt32(&j, 0, j);
 1512         CFDataAppendBytes(G_prelink_dependencies, (UInt8 *) &j, sizeof(j));
 1513     }
 1514     if (log_level >= kload_log_level_basic) {
 1515         kload_log_message("[%d] 0x%08x info 0x%08x\n    %s,\n    %s" KNL, 
 1516                             G_prelink->modules[0].id + 1, entry->kernel_load_address,
 1517                             kernel_kmod_info, entry->link_output_file, entry->name);
 1518     }
 1519 
 1520     if (local_kmod_info)
 1521         desc = *local_kmod_info;
 1522     else
 1523     {
 1524         bzero(&desc, sizeof(desc));
 1525         desc.size = entry->symbols_length;
 1526     }
 1527 
 1528     desc.id = kernel_kmod_info;
 1529     desc.reference_count = entry->num_dependencies;
 1530     desc.reference_list  = (kmod_reference_t *) depoffset;
 1531 
 1532     /* Stamp the bundle ID and version from the entry over anything
 1533     * resident inside the kmod.
 1534     */
 1535     bzero(desc.name, sizeof(local_kmod_info->name));
 1536     strcpy(desc.name, entry->expected_kmod_name);
 1537     bzero(desc.version, sizeof(local_kmod_info->version));
 1538     strcpy(desc.version, entry->expected_kmod_vers);
 1539 
 1540     G_prelink->modules[0].id++;
 1541     CFDataAppendBytes(G_prelink_data, (UInt8 *) &desc, sizeof(desc));
 1542     G_prelink = (struct PrelinkState *) CFDataGetMutableBytePtr(G_prelink_data);
 1543 
 1544     return kload_error_none;
 1545 }
 1546 
 1547 #endif
 1548 
 1549 /*******************************************************************************
 1550 *
 1551 *******************************************************************************/
 1552 PRIV_EXT
 1553 #ifndef KERNEL
 1554 kload_error kload_map_dgraph(
 1555     dgraph_t * dgraph,
 1556     const char * kernel_file)
 1557 #else
 1558 kload_error kload_map_dgraph(
 1559     dgraph_t * dgraph)
 1560 #endif /* not KERNEL */
 1561 {
 1562     kload_error result = kload_error_none;
 1563     unsigned int i;
 1564 
 1565     if (log_level >= kload_log_level_load_details) {
 1566 #ifndef KERNEL
 1567         kload_log_message("mapping the kernel file %s" KNL, kernel_file);
 1568 #else
 1569         kload_log_message("mapping the kernel" KNL);
 1570 #endif /* not KERNEL */
 1571     }
 1572 
 1573 #ifndef KERNEL
 1574     if (!kld_file_map(kernel_file)) {
 1575         result = kload_error_link_load;
 1576         goto finish;
 1577     }
 1578 #endif /* not KERNEL */
 1579 
 1580     for (i = 0; i < dgraph->length; i++) {
 1581         dgraph_entry_t * entry = dgraph->load_order[i];
 1582 
 1583         if (entry->is_kernel_component && !entry->is_symbol_set) {
 1584             continue;
 1585         }
 1586 
 1587         result = kload_map_entry(entry);
 1588         if (result != kload_error_none) {
 1589             goto finish;
 1590         }
 1591     }
 1592 
 1593 finish:
 1594     return result;
 1595 
 1596 }
 1597 
 1598 /*******************************************************************************
 1599 *
 1600 *******************************************************************************/
 1601 PRIV_EXT
 1602 kload_error kload_map_entry(dgraph_entry_t * entry)
 1603 {
 1604     kload_error result = kload_error_none;
 1605 
 1606     if (entry->is_kernel_component && !entry->is_symbol_set) {
 1607         kload_log_error("attempt to map kernel component %s" KNL, entry->name);
 1608         result = kload_error_invalid_argument;
 1609         goto finish;
 1610     }
 1611 
 1612     if (log_level >= kload_log_level_load_details) {
 1613         kload_log_message("mapping module file %s" KNL, entry->name);
 1614     }
 1615 
 1616     if (kld_file_getaddr(entry->name, NULL)) {
 1617         if (log_level >= kload_log_level_load_details) {
 1618             kload_log_message("module file %s is already mapped" KNL, entry->name);
 1619         }
 1620         result = kload_error_none;
 1621         goto finish;
 1622     }
 1623 
 1624 #ifndef KERNEL
 1625     if (!kld_file_map(entry->name)) {
 1626 #else
 1627     if (!kld_file_map(entry->name, entry->object, entry->object_length,
 1628          entry->object_is_kmem)) {
 1629 #endif /* not KERNEL */
 1630         kload_log_error("error mapping module file %s" KNL, entry->name);
 1631 
 1632         result = kload_error_link_load;
 1633         goto finish;
 1634 #ifndef KERNEL
 1635     }
 1636 #else
 1637     }
 1638 #endif /* not KERNEL */
 1639 
 1640     entry->is_mapped = true;
 1641     
 1642    /* Clear these bits now, as the kld patch module now owns the info
 1643     * and it is subject to change. We reset them in the entry from the
 1644     * kld patch module as needed.
 1645     */
 1646     entry->object = 0;
 1647     entry->object_length = 0;
 1648 #ifdef KERNEL
 1649     entry->object_is_kmem = false;
 1650 #endif /* KERNEL */
 1651 
 1652     // FIXME: Stop using this symbol; have the info passed in by
 1653     // FIXME: ...the kext management library.
 1654 #ifndef KERNEL
 1655     if (!entry->is_kernel_component && !kld_file_lookupsymbol(entry->name, "_kmod_info")) {
 1656         kload_log_error("%s does not not contain kernel extension code" KNL,
 1657             entry->name);
 1658         result = kload_error_executable_bad;
 1659         goto finish;
 1660     }
 1661 #endif /* not KERNEL */
 1662 
 1663 finish:
 1664     return result;
 1665 }
 1666 
 1667 #ifndef KERNEL
 1668 /*******************************************************************************
 1669 *
 1670 *******************************************************************************/
 1671 kload_error kload_request_load_addresses(
 1672     dgraph_t * dgraph,
 1673     const char * kernel_file)
 1674 {
 1675     kload_error result = kload_error_none;
 1676     int i;
 1677     const char * user_response = NULL;  // must free
 1678     int scan_result;
 1679     unsigned int address;
 1680 
 1681    /* We have to map all object files to get their CFBundleIdentifier
 1682     * names.
 1683     */
 1684     result = kload_map_dgraph(dgraph, kernel_file);
 1685     if (result != kload_error_none) {
 1686         kload_log_error("error mapping object files" KNL);
 1687         goto finish;
 1688     }
 1689 
 1690     // fixme: this shouldn't be printf, should it?
 1691     printf("enter the hexadecimal load addresses for these modules:\n");
 1692 
 1693     for (i = 0; i < dgraph->length; i++) {
 1694         dgraph_entry_t * entry = dgraph->load_order[i];
 1695 
 1696         if (!entry) {
 1697             result = kload_error_unspecified;
 1698             goto finish;
 1699         }
 1700 
 1701         if (entry->is_kernel_component) {
 1702             continue;
 1703         }
 1704 
 1705         if (!entry->is_mapped) {
 1706             result = kload_error_unspecified;
 1707             goto finish;
 1708         }
 1709 
 1710         user_response = __kload_input_func("%s:",
 1711             entry->expected_kmod_name);
 1712         if (!user_response) {
 1713             result = kload_error_unspecified;
 1714             goto finish;
 1715         }
 1716         scan_result = sscanf(user_response, "%x", &address);
 1717         if (scan_result < 1 || scan_result == EOF) {
 1718             result = kload_error_unspecified;
 1719             goto finish;
 1720         }
 1721         entry->loaded_address = address;
 1722     }
 1723 
 1724 finish:
 1725     return result;
 1726 
 1727 }
 1728 
 1729 /*******************************************************************************
 1730 * addresses is a NULL-terminated list of string of the form "module_id@address"
 1731 *******************************************************************************/
 1732 kload_error kload_set_load_addresses_from_args(
 1733     dgraph_t * dgraph,
 1734     const char * kernel_file,
 1735     char ** addresses)
 1736 {
 1737     kload_error result = kload_error_none;
 1738     int i, j;
 1739 
 1740 
 1741    /* We have to map all object files to get their CFBundleIdentifier
 1742     * names.
 1743     */
 1744     result = kload_map_dgraph(dgraph, kernel_file);
 1745     if (result != kload_error_none) {
 1746         kload_log_error("error mapping object files" KNL);
 1747         goto finish;
 1748     }
 1749 
 1750    /*****
 1751     * Run through and assign all addresses to their relevant module
 1752     * entries.
 1753     */
 1754     for (i = 0; i < dgraph->length; i++) {
 1755         dgraph_entry_t * entry = dgraph->load_order[i];
 1756 
 1757         if (!entry) {
 1758             result = kload_error_unspecified;
 1759             goto finish;
 1760         }
 1761 
 1762         if (entry->is_kernel_component) {
 1763             continue;
 1764         }
 1765 
 1766         if (!entry->is_mapped) {
 1767             result = kload_error_unspecified;
 1768             goto finish;
 1769         }
 1770 
 1771         for (j = 0; addresses[j]; j++) {
 1772             char * this_addr = addresses[j];
 1773             char * address_string = NULL;
 1774             unsigned int address;
 1775             unsigned int module_namelen = strlen(entry->expected_kmod_name);
 1776 
 1777             if (!this_addr) {
 1778                 result = kload_error_unspecified;
 1779                 goto finish;
 1780             }
 1781 
 1782             if (strncmp(this_addr, entry->expected_kmod_name, module_namelen)) {
 1783                 continue;
 1784             }
 1785             if (this_addr[module_namelen] != '@') {
 1786                 continue;
 1787             }
 1788 
 1789             address_string = index(this_addr, '@');
 1790             if (!address_string) {
 1791                 result = kload_error_unspecified;
 1792                 goto finish;
 1793             }
 1794             address_string++;
 1795             address = strtoul(address_string, NULL, 16);
 1796             entry->loaded_address = address;
 1797         }
 1798     }
 1799 
 1800    /*****
 1801     * Now that we've done that see that all non-kernel modules do have
 1802     * addresses set. If even one doesn't, we can't complete the link
 1803     * relocation of symbols, so return a usage error.
 1804     */
 1805     for (i = 0; i < dgraph->length; i++) {
 1806         dgraph_entry_t * entry = dgraph->load_order[i];
 1807 
 1808         if (entry->is_kernel_component) {
 1809             continue;
 1810         }
 1811 
 1812         if (!entry->loaded_address) {
 1813             result = kload_error_invalid_argument;
 1814             goto finish;
 1815         }
 1816     }
 1817 
 1818 finish:
 1819     return result;
 1820 
 1821 }
 1822 
 1823 /*******************************************************************************
 1824 * This function requires G_kernel_priv_port to be set before it will work.
 1825 *******************************************************************************/
 1826 kload_error kload_set_load_addresses_from_kernel(
 1827     dgraph_t * dgraph,
 1828     const char * kernel_file,
 1829     int do_load)
 1830 {
 1831     kload_error result = kload_error_none;
 1832     int mach_result;
 1833     kmod_info_t * loaded_modules = NULL;
 1834     int           loaded_bytecount = 0;
 1835     unsigned int i;
 1836 
 1837 
 1838    /*****
 1839     * We have to map the dgraph's modules before checking whether they've
 1840     * been loaded.
 1841     */
 1842     result = kload_map_dgraph(dgraph, kernel_file);
 1843     if (result != kload_error_none) {
 1844         kload_log_error("can't map module files" KNL);
 1845         goto finish;
 1846     }
 1847 
 1848 
 1849    /* First clear all the load addresses.
 1850     */
 1851     for (i = 0; i < dgraph->length; i++) {
 1852         struct dgraph_entry_t * entry = dgraph->load_order[i];
 1853         entry->loaded_address = 0;
 1854     }
 1855 
 1856     mach_result = kmod_get_info(G_kernel_priv_port,
 1857             (void *)&loaded_modules, &loaded_bytecount);
 1858     if (mach_result != KERN_SUCCESS) {
 1859         kload_log_error("kmod_get_info() failed" KNL);
 1860         result = kload_error_kernel_error;
 1861         goto finish;
 1862     }
 1863 
 1864    /*****
 1865     * Find out which modules have already been loaded & verify
 1866     * that loaded versions are same as requested.
 1867     */
 1868     for (i = 0; i < dgraph->length; i++) {
 1869         kload_error cresult;
 1870         dgraph_entry_t * current_entry = dgraph->load_order[i];
 1871 
 1872        /* If necessary, check whether the current module is already loaded.
 1873         * (We already did the root module above.)
 1874         */
 1875         cresult = __kload_check_module_loaded(dgraph, current_entry,
 1876             loaded_modules, do_load);
 1877         if ( ! (cresult == kload_error_none ||
 1878                 cresult == kload_error_already_loaded) ) {
 1879             goto finish;
 1880         }
 1881         if (current_entry == dgraph->root &&
 1882             cresult == kload_error_already_loaded) {
 1883 
 1884             result = cresult;
 1885         }
 1886     }
 1887 
 1888 finish:
 1889 
 1890     if (loaded_modules) {
 1891         vm_deallocate(mach_task_self(), (vm_address_t)loaded_modules,
 1892             loaded_bytecount);
 1893         loaded_modules = 0;
 1894     }
 1895 
 1896     return result;
 1897 }
 1898 
 1899 #else
 1900 /*******************************************************************************
 1901 *
 1902 *******************************************************************************/
 1903 PRIV_EXT
 1904 kload_error kload_set_load_addresses_from_kernel(
 1905     dgraph_t * dgraph)
 1906 {
 1907     kload_error result = kload_error_none;
 1908 #ifndef KERNEL
 1909     int mach_result;
 1910     kmod_info_t * loaded_modules = NULL;
 1911     int           loaded_bytecount = 0;
 1912 #endif /* not KERNEL */
 1913     unsigned int i;
 1914 
 1915 
 1916    /*****
 1917     * We have to map the dgraph's modules before checking whether they've
 1918     * been loaded.
 1919     */
 1920     result = kload_map_dgraph(dgraph);
 1921     if (result != kload_error_none) {
 1922         kload_log_error("can't map module files" KNL);
 1923         goto finish;
 1924     }
 1925 
 1926 
 1927    /* First clear all the load addresses.
 1928     */
 1929     for (i = 0; i < dgraph->length; i++) {
 1930         struct dgraph_entry_t * entry = dgraph->load_order[i];
 1931         entry->loaded_address = 0;
 1932     }
 1933 
 1934    /*****
 1935     * Find out which modules have already been loaded & verify
 1936     * that loaded versions are same as requested.
 1937     */
 1938     for (i = 0; i < dgraph->length; i++) {
 1939         kload_error cresult;
 1940         dgraph_entry_t * current_entry = dgraph->load_order[i];
 1941 
 1942        /* If necessary, check whether the current module is already loaded.
 1943         * (We already did the root module above.)
 1944         */
 1945         cresult = __kload_check_module_loaded(dgraph, current_entry, false);
 1946         if ( ! (cresult == kload_error_none ||
 1947                 cresult == kload_error_already_loaded) ) {
 1948             goto finish;
 1949         }
 1950         if (current_entry == dgraph->root &&
 1951             cresult == kload_error_already_loaded) {
 1952 
 1953             result = cresult;
 1954         }
 1955     }
 1956 
 1957 finish:
 1958 
 1959     return result;
 1960 }
 1961 #endif /* not KERNEL */
 1962 
 1963 /*******************************************************************************
 1964 *
 1965 *******************************************************************************/
 1966 #ifdef KERNEL
 1967 extern kern_return_t kmod_load_from_cache(const char * kmod_name);
 1968 #endif /* KERNEL */
 1969 
 1970 static kmod_info_t * __kload_find_kmod_info(const char * kmod_name
 1971 #ifndef KERNEL
 1972     ,
 1973     kmod_info_t * kmod_list
 1974 #endif /* not KERNEL */
 1975     )
 1976 {
 1977 #ifndef KERNEL
 1978     unsigned int i;
 1979 
 1980     for (i = 0; ; i++) {
 1981         kmod_info_t * current_kmod = &(kmod_list[i]);
 1982         if (0 == strcmp(current_kmod->name, kmod_name)) {
 1983             return current_kmod;
 1984         }
 1985         if (kmod_list[i].next == 0) {
 1986             break;
 1987         }
 1988     }
 1989     return NULL;
 1990 #else
 1991     kmod_info_t * info;
 1992     info = kmod_lookupbyname_locked(kmod_name);
 1993     if (!info && (KERN_SUCCESS == kmod_load_from_cache(kmod_name))) {
 1994         info = kmod_lookupbyname_locked(kmod_name);
 1995     }
 1996     return info;
 1997 #endif /* not KERNEL */
 1998 }
 1999 
 2000 /*******************************************************************************
 2001 *
 2002 *******************************************************************************/
 2003 static
 2004 kload_error __kload_check_module_loaded(
 2005     dgraph_t * dgraph,
 2006     dgraph_entry_t * entry,
 2007 #ifndef KERNEL
 2008     kmod_info_t * kmod_list,
 2009 #endif /* not KERNEL */
 2010     int log_if_already)
 2011 {
 2012     kload_error result = kload_error_none;
 2013     const char * kmod_name;
 2014     kmod_info_t * current_kmod = 0;
 2015 
 2016     VERS_version entry_vers;
 2017     VERS_version loaded_vers;
 2018 
 2019     if (false && entry->is_kernel_component) {
 2020         kmod_name = entry->name;
 2021     } else {
 2022         kmod_name = entry->expected_kmod_name;
 2023         if (log_level >= kload_log_level_load_details) {
 2024             kload_log_message("checking whether module file %s is already loaded" KNL,
 2025                 kmod_name);
 2026         }
 2027     }
 2028 
 2029 #ifndef KERNEL
 2030     current_kmod = __kload_find_kmod_info(kmod_name, kmod_list);
 2031 #else
 2032     current_kmod = __kload_find_kmod_info(kmod_name);
 2033 #endif /* not KERNEL */
 2034 
 2035     if (!current_kmod) {
 2036         goto finish;
 2037     }
 2038 
 2039     entry->do_load = 0;
 2040     entry->kmod_id = current_kmod->id;
 2041     entry->loaded_address = current_kmod->address;
 2042 
 2043     if (entry->is_kernel_component) {
 2044         goto finish;
 2045     }
 2046 
 2047     if (log_level >= kload_log_level_load_details) {
 2048         kload_log_message("module file %s is loaded; checking status" KNL,
 2049             kmod_name);
 2050     }
 2051 
 2052     // We really want to move away from having this info in a kmod....
 2053     //
 2054     loaded_vers = VERS_parse_string(current_kmod->version);
 2055     if (loaded_vers < 0) {
 2056         kload_log_error(
 2057             "can't parse version string \"%s\" of loaded module %s" KNL,
 2058             current_kmod->version,
 2059             current_kmod->name);
 2060         result = kload_error_unspecified;
 2061         goto finish;
 2062     }
 2063 
 2064     entry_vers = VERS_parse_string(entry->expected_kmod_vers);
 2065     if (entry_vers < 0) {
 2066         kload_log_error(
 2067             "can't parse version string \"%s\" of module file %s" KNL,
 2068             entry->expected_kmod_name,
 2069             kmod_name);
 2070         result = kload_error_unspecified;
 2071         goto finish;
 2072     }
 2073 
 2074     if (loaded_vers != entry_vers) {
 2075         kload_log_error(
 2076             "loaded version %s of module %s differs from "
 2077             "requested version %s" KNL,
 2078             current_kmod->version,
 2079             current_kmod->name,
 2080             entry->expected_kmod_name);
 2081         if (entry == dgraph->root) {
 2082             result = kload_error_loaded_version_differs;
 2083         } else {
 2084             result = kload_error_dependency_loaded_version_differs;
 2085         }
 2086         goto finish;
 2087     } else {
 2088 
 2089         if (log_if_already && log_level >=
 2090                 kload_log_level_load_basic) {
 2091 
 2092             kload_log_message(
 2093                 "module %s (identifier %s) is already loaded" KNL,
 2094                 entry->name, kmod_name);
 2095         }
 2096         result = kload_error_already_loaded;
 2097         goto finish;
 2098     }
 2099 
 2100 finish:
 2101 #ifdef KERNEL
 2102     // Do this ONLY if in the kernel!
 2103     if (current_kmod) {
 2104         kfree(current_kmod, sizeof(kmod_info_t));
 2105     }
 2106 #endif /* KERNEL */
 2107     return result;
 2108 }
 2109 
 2110 /*******************************************************************************
 2111 *
 2112 *******************************************************************************/
 2113 PRIV_EXT
 2114 kload_error __kload_patch_dgraph(dgraph_t * dgraph
 2115 #ifndef KERNEL
 2116     ,
 2117     const char * kernel_file
 2118 #endif /* not KERNEL */
 2119     )
 2120 {
 2121     kload_error result = kload_error_none;
 2122     unsigned int i;
 2123 
 2124 #ifndef KERNEL
 2125     if (!kld_file_merge_OSObjects(kernel_file)) {
 2126         result = kload_error_link_load;
 2127         goto finish;
 2128     }
 2129 #endif /* not KERNEL */
 2130 
 2131     for (i = 0; i < dgraph->length; i++) {
 2132         dgraph_entry_t * current_entry = dgraph->load_order[i];
 2133 
 2134        /* The kernel has already been patched.
 2135         */
 2136         if (current_entry->is_kernel_component) {
 2137             continue;
 2138         }
 2139 
 2140         if (log_level >= kload_log_level_load_details) {
 2141             kload_log_message("patching C++ code in module %s" KNL,
 2142                 current_entry->name);
 2143         }
 2144 
 2145 #ifndef KERNEL
 2146        /* In userland, we call the patch function for all kmods,
 2147         * loaded or not, because we don't have all the info that
 2148         * the kernel environment has.
 2149         */
 2150         if (!kld_file_patch_OSObjects(current_entry->name)) {
 2151             result = kload_error_link_load;   // FIXME: need a "patch" error?
 2152             goto finish;
 2153         }
 2154 #else
 2155        /* In the kernel, we call the merge function for already-loaded
 2156         * kmods, since the kld patch environment retains info for kmods
 2157         * that have already been patched. The patch function does a little
 2158         * more work, and is only for kmods that haven't been processed yet.
 2159         * NOTE: We are depending here on kload_check_module_loaded()
 2160         * having been called, which is guaranteed by kload_load_dgraph()
 2161         * is used, but not by its subroutines (such as
 2162         * __kload_load_modules()).
 2163         */
 2164         if (current_entry->loaded_address) {
 2165             if (!kld_file_merge_OSObjects(current_entry->name)) {
 2166                 result = kload_error_link_load;   // FIXME: need a "patch" error?
 2167                 goto finish;
 2168             }
 2169         } else {
 2170             if (!kld_file_patch_OSObjects(current_entry->name)) {
 2171                 result = kload_error_link_load;   // FIXME: need a "patch" error?
 2172                 goto finish;
 2173             }
 2174         }
 2175 #endif /* not KERNEL */
 2176 
 2177     }
 2178 
 2179     if (!kld_file_prepare_for_link()) {
 2180         result = kload_error_link_load;   // FIXME: need more specific error?
 2181         goto finish;
 2182     }
 2183 
 2184 finish:
 2185     return result;
 2186 }
 2187 
 2188 #ifndef KERNEL
 2189 /*******************************************************************************
 2190 *
 2191 *******************************************************************************/
 2192 #define __KLOAD_PATCH_EXTENSION ".patch"
 2193 
 2194 kload_error __kload_output_patches(
 2195     dgraph_t * dgraph,
 2196     const char * patch_file,
 2197     const char * patch_dir,
 2198     int ask_overwrite_symbols,
 2199     int overwrite_symbols)
 2200 {
 2201     kload_error result = kload_error_none;
 2202     unsigned int i;
 2203     char * allocated_filename = NULL;
 2204     char * patch_filename = NULL;
 2205     int file_check;
 2206     int output_patch;
 2207 
 2208     if (patch_dir) {
 2209 
 2210         for (i = 0; i < dgraph->length; i++) {
 2211 
 2212             struct dgraph_entry_t * entry = dgraph->load_order[i];
 2213             unsigned long length;
 2214 
 2215             if (entry->is_kernel_component) {
 2216                 continue;
 2217             }
 2218 
 2219             length = strlen(patch_dir) +
 2220                 strlen(entry->expected_kmod_name) +
 2221                 strlen(__KLOAD_PATCH_EXTENSION) +
 2222                 1 + 1 ;   // 1 for '/' added, 1 for terminating null
 2223             if (length >= MAXPATHLEN) {
 2224                 kload_log_error(
 2225                     "output filename \"%s/%s%s\" would be too long" KNL,
 2226                     patch_dir, entry->expected_kmod_name,
 2227                     __KLOAD_PATCH_EXTENSION);
 2228                 result = kload_error_invalid_argument;
 2229                 goto finish;
 2230             }
 2231 
 2232             allocated_filename = (char *)malloc(length);
 2233             if (! allocated_filename) {
 2234                 kload_log_error("malloc failure" KNL);
 2235                 result = kload_error_no_memory;
 2236                 goto finish;
 2237             }
 2238 
 2239             patch_filename = allocated_filename;
 2240             strlcpy(patch_filename, patch_dir, length);
 2241             strlcat(patch_filename, "/", length);
 2242             strlcat(patch_filename, entry->expected_kmod_name, length);
 2243             strlcat(patch_filename, __KLOAD_PATCH_EXTENSION, length);
 2244 
 2245             output_patch = 1;
 2246             file_check = kload_file_exists(patch_filename);
 2247 
 2248             if (file_check < 0) {
 2249                 kload_log_error("error checking existence of file %s" KNL,
 2250                     patch_filename);
 2251             } else if (file_check > 0 && !overwrite_symbols) {
 2252                 if (!ask_overwrite_symbols) {
 2253                     kload_log_error(
 2254                         "patch file %s exists; not overwriting" KNL,
 2255                         patch_filename);
 2256                     output_patch = 0;
 2257                 } else {
 2258                     int approve = (*__kload_approve_func)(1,
 2259                         "\nPatch file %s exists; overwrite", patch_filename);
 2260 
 2261                     if (approve < 0) {
 2262                         result = kload_error_unspecified;
 2263                         goto finish;
 2264                     } else {
 2265                         output_patch = approve;
 2266                     }
 2267                 }
 2268             }
 2269 
 2270             if (output_patch) {
 2271                 if (log_level >= kload_log_level_basic) {
 2272                     kload_log_message("writing patch file %s" KNL, patch_filename);
 2273                 }
 2274                 kld_file_debug_dump(entry->name, patch_filename);
 2275             }
 2276 
 2277             if (allocated_filename) free(allocated_filename);
 2278             allocated_filename = NULL;
 2279         }
 2280 
 2281     } else if (patch_file) {
 2282         output_patch = 1;
 2283         file_check = kload_file_exists(patch_file);
 2284 
 2285         if (file_check < 0) {
 2286             kload_log_error("error checking existence of file %s" KNL,
 2287                 patch_file);
 2288         } else if (file_check > 0 && !overwrite_symbols) {
 2289             if (!ask_overwrite_symbols) {
 2290                 kload_log_error("patch file %s exists; not overwriting" KNL,
 2291                     patch_filename);
 2292                 output_patch = 0;
 2293             } else {
 2294                 int approve = (*__kload_approve_func)(1,
 2295                     "\nPatch file %s exists; overwrite", patch_filename);
 2296 
 2297                 if (approve < 0) {
 2298                     result = kload_error_unspecified;
 2299                     goto finish;
 2300                 } else {
 2301                     output_patch = approve;
 2302                 }
 2303             }
 2304         }
 2305 
 2306         if (output_patch) {
 2307             if (log_level >= kload_log_level_basic) {
 2308                 kload_log_message("writing patch file %s" KNL, patch_filename);
 2309             }
 2310             kld_file_debug_dump(dgraph->root->name, patch_file);
 2311         }
 2312     }
 2313 
 2314 finish:
 2315     if (allocated_filename) free(allocated_filename);
 2316 
 2317     return result;
 2318 }
 2319 #endif /* not KERNEL */
 2320 
 2321 /*******************************************************************************
 2322 *
 2323 *******************************************************************************/
 2324 PRIV_EXT
 2325 kload_error __kload_set_module_dependencies(dgraph_entry_t * entry) {
 2326     kload_error result = kload_error_none;
 2327     int mach_result;
 2328 #ifndef KERNEL
 2329     void * kmod_control_args = 0;
 2330     int num_args = 0;
 2331 #endif /* not KERNEL */
 2332     kmod_t packed_id;
 2333     unsigned int i;
 2334     dgraph_entry_t * current_dep = NULL;
 2335 
 2336     if (!entry->do_load) {
 2337         result = kload_error_already_loaded;
 2338         goto finish;
 2339     }
 2340 
 2341     for (i = 0; i < entry->num_dependencies; i++) {
 2342         current_dep = entry->dependencies[i];
 2343 
 2344         if (log_level >= kload_log_level_load_details) {
 2345             kload_log_message("adding reference from %s (%d) to %s (%d)" KNL,
 2346                 entry->expected_kmod_name, entry->kmod_id,
 2347                 current_dep->expected_kmod_name, current_dep->kmod_id);
 2348         }
 2349 
 2350         packed_id = KMOD_PACK_IDS(entry->kmod_id, current_dep->kmod_id);
 2351 #ifndef KERNEL
 2352         mach_result = kmod_control(G_kernel_priv_port,
 2353                 packed_id, KMOD_CNTL_RETAIN, &kmod_control_args, &num_args);
 2354 #else
 2355         mach_result = kmod_retain(packed_id);
 2356 #endif /* not KERNEL */
 2357         if (mach_result != KERN_SUCCESS) {
 2358             kload_log_error(
 2359                 "kmod retain failed for %s; destroying kmod" KNL,
 2360                 entry->expected_kmod_name);
 2361 #ifndef KERNEL
 2362             mach_result = kmod_destroy(G_kernel_priv_port, entry->kmod_id);
 2363 #else
 2364             mach_result = kmod_destroy_internal(entry->kmod_id);
 2365 #endif /* not KERNEL */
 2366             if (mach_result != KERN_SUCCESS) {
 2367                 kload_log_error("kmod destroy failed" KNL);
 2368             }
 2369             result = kload_error_link_load;
 2370             goto finish;
 2371         }
 2372     }
 2373 
 2374     if (log_level >= kload_log_level_load_basic) {
 2375         kload_log_message("module # %d reference counts incremented" KNL,
 2376             entry->kmod_id);
 2377     }
 2378 
 2379 finish:
 2380     return result;
 2381 }
 2382 
 2383 /*******************************************************************************
 2384 *
 2385 *******************************************************************************/
 2386 PRIV_EXT
 2387 kload_error __kload_start_module(dgraph_entry_t * entry) {
 2388     kload_error result = kload_error_none;
 2389     int mach_result;
 2390 #ifndef KERNEL
 2391     void * kmod_control_args = 0;
 2392     int num_args = 0;
 2393 #elif CONFIG_MACF_KEXT
 2394     kmod_args_t kmod_args = entry->user_data;
 2395     mach_msg_type_number_t arg_size = entry->user_data_length;
 2396 #endif /* not KERNEL */
 2397 
 2398     if (!entry->do_load) {
 2399         result = kload_error_already_loaded;
 2400         goto finish;
 2401     }
 2402 
 2403 #ifndef KERNEL
 2404     mach_result = kmod_control(G_kernel_priv_port,
 2405             entry->kmod_id, KMOD_CNTL_START, &kmod_control_args, &num_args);
 2406 #elif CONFIG_MACF_KEXT
 2407     mach_result = kmod_start_or_stop(entry->kmod_id, 1, &kmod_args, &arg_size);
 2408 #else
 2409     mach_result = kmod_start_or_stop(entry->kmod_id, 1, 0, 0);
 2410 #endif /* not KERNEL */
 2411 
 2412     if (mach_result != KERN_SUCCESS) {
 2413         kload_log_error(
 2414             "kmod_control/start failed for %s; destroying kmod" KNL,
 2415             entry->expected_kmod_name);
 2416 #ifndef KERNEL
 2417         mach_result = kmod_destroy(G_kernel_priv_port, entry->kmod_id);
 2418 #else
 2419         mach_result = kmod_destroy_internal(entry->kmod_id);
 2420 #endif /* not KERNEL */
 2421         if (mach_result != KERN_SUCCESS) {
 2422             kload_log_error("kmod destroy failed" KNL);
 2423         }
 2424         result = kload_error_link_load;
 2425         goto finish;
 2426     }
 2427 
 2428     if (log_level >= kload_log_level_load_basic) {
 2429         kload_log_message("module # %d started" KNL,
 2430            entry->kmod_id);
 2431     }
 2432 
 2433 finish:
 2434     return result;
 2435 }
 2436 
 2437 /*******************************************************************************
 2438 *******************************************************************************/
 2439 
 2440 /*******************************************************************************
 2441 * This function can only operate on 32 bit mach object file symbol table
 2442 * graphs represented by G_current_load_entry.
 2443 *******************************************************************************/
 2444 static
 2445 unsigned long __kload_linkedit_address(
 2446     unsigned long size,
 2447     unsigned long headers_size)
 2448 {
 2449     unsigned long round_segments_size;
 2450     unsigned long round_headers_size;
 2451     unsigned long round_size;
 2452     int mach_result;
 2453     const struct machOMapping {
 2454         struct mach_header h;
 2455         struct segment_command seg[1];
 2456     } *machO;
 2457 
 2458     if (!G_current_load_entry) {
 2459         return 0;
 2460     }
 2461 
 2462     // the actual size allocated by kld_load_from_memory()
 2463     G_current_load_entry->kernel_load_size = size;
 2464 
 2465     round_headers_size = round_page(headers_size);
 2466     round_segments_size = round_page(size - headers_size);
 2467     round_size = round_headers_size + round_segments_size;
 2468 
 2469     G_current_load_entry->kernel_alloc_size = round_size;
 2470 
 2471     // will need to be rounded *after* load/link
 2472     G_current_load_entry->kernel_hdr_size = headers_size;
 2473     G_current_load_entry->kernel_hdr_pad = round_headers_size - headers_size;
 2474     
 2475     if (G_current_load_entry->loaded_address) {
 2476         G_current_load_entry->kernel_load_address =
 2477             G_current_load_entry->loaded_address +
 2478             G_current_load_entry->kernel_hdr_pad;
 2479         if (log_level >= kload_log_level_load_basic) {
 2480             kload_log_message(
 2481                 "using %s load address 0x%x (0x%x with header pad)" KNL,
 2482                 G_current_load_entry->kmod_id ? "existing" : "provided",
 2483                 G_current_load_entry->loaded_address,
 2484                 G_current_load_entry->kernel_load_address);
 2485         }
 2486         return G_current_load_entry->kernel_load_address;
 2487     }
 2488 
 2489     machO = (const struct machOMapping *) G_current_load_entry->object;
 2490     if (machO->seg[0].vmaddr)
 2491     {
 2492         G_current_load_entry->loaded_address = trunc_page(machO->seg[0].vmaddr - machO->seg[0].fileoff);
 2493 
 2494         G_current_load_entry->kernel_load_address = G_current_load_entry->loaded_address 
 2495                 + G_current_load_entry->kernel_hdr_pad;
 2496 
 2497         return G_current_load_entry->kernel_load_address;
 2498     }
 2499 
 2500 #ifndef KERNEL
 2501     if (G_prelink) {
 2502         G_current_load_entry->kernel_alloc_address = G_prelink->modules[0].address;
 2503         G_prelink->modules[0].address += round_page(G_current_load_entry->kernel_alloc_size);
 2504         mach_result = KERN_SUCCESS;
 2505         
 2506     } else if (G_syms_only) {
 2507         kload_log_error(
 2508             "internal error; asked to allocate kernel memory" KNL);
 2509         // FIXME: no provision for cleanup here
 2510         return kload_error_unspecified;
 2511 
 2512     } else
 2513 #endif /* not KERNEL */
 2514 
 2515     {
 2516 #ifndef KERNEL
 2517         mach_result = vm_allocate(G_kernel_port,
 2518                 &G_current_load_entry->kernel_alloc_address,
 2519                 G_current_load_entry->kernel_alloc_size, VM_FLAGS_ANYWHERE);
 2520 #else
 2521         mach_result = vm_allocate(kernel_map,
 2522             &G_current_load_entry->kernel_alloc_address,
 2523             G_current_load_entry->kernel_alloc_size, VM_FLAGS_ANYWHERE);
 2524 #endif /* not KERNEL */
 2525     }
 2526 
 2527     if (mach_result != KERN_SUCCESS) {
 2528         kload_log_error("can't allocate kernel memory" KNL);
 2529         // FIXME: no provision for cleanup here
 2530         return kload_error_kernel_error;
 2531     }
 2532 
 2533     if (log_level >= kload_log_level_load_basic) {
 2534         kload_log_message("allocated %ld bytes in kernel space at 0x%x" KNL,
 2535             G_current_load_entry->kernel_alloc_size,
 2536             G_current_load_entry->kernel_alloc_address);
 2537     }
 2538 
 2539     G_current_load_entry->kernel_load_address =
 2540         G_current_load_entry->kernel_alloc_address +
 2541         G_current_load_entry->kernel_hdr_pad;
 2542 
 2543     G_current_load_entry->loaded_address = G_current_load_entry->kernel_alloc_address;
 2544 
 2545     if (log_level >= kload_log_level_load_basic) {
 2546         kload_log_message(
 2547             "using load address of 0x%x" KNL,
 2548             G_current_load_entry->kernel_alloc_address);
 2549     }
 2550 
 2551     return G_current_load_entry->kernel_load_address;
 2552 }
 2553 
 2554 /*******************************************************************************
 2555 *
 2556 *******************************************************************************/
 2557 static
 2558 void __kload_clear_kld_globals(void) {
 2559     G_current_load_entry = NULL;
 2560     return;
 2561 }
 2562 
 2563 /*******************************************************************************
 2564 *
 2565 *******************************************************************************/
 2566 static
 2567 void __kload_clean_up_entry(dgraph_entry_t * entry) {
 2568     int mach_result;
 2569 
 2570     if (entry->need_cleanup && entry->kernel_alloc_address) {
 2571 #ifndef KERNEL
 2572         if (G_prelink) {
 2573 
 2574             if ((entry->kernel_alloc_address + entry->kernel_alloc_size) == G_prelink->modules[0].address) {
 2575                 G_prelink->modules[0].address = entry->kernel_alloc_address;
 2576             } else {
 2577                 kload_log_error(
 2578                     "bad free load address of 0x%x (last 0x%x)" KNL,
 2579                     entry->kernel_alloc_address, G_prelink->modules[0].address);
 2580             }
 2581         } else {
 2582             mach_result = vm_deallocate(G_kernel_port, entry->kernel_alloc_address,
 2583                 entry->kernel_alloc_size);
 2584         }
 2585 #else
 2586         mach_result = vm_deallocate(kernel_map, entry->kernel_alloc_address,
 2587             entry->kernel_alloc_size);
 2588 #endif /* not KERNEL */
 2589         entry->kernel_alloc_address = 0;
 2590     }
 2591     return;
 2592 }
 2593 
 2594 #ifndef KERNEL
 2595 /*******************************************************************************
 2596 *
 2597 *******************************************************************************/
 2598 int kload_file_exists(const char * path)
 2599 {
 2600     int result = 0;  // assume it doesn't exist
 2601     struct stat stat_buf;
 2602 
 2603     if (stat(path, &stat_buf) == 0) {
 2604         result = 1;  // the file does exist; we don't care beyond that
 2605         goto finish;
 2606     }
 2607 
 2608     switch (errno) {
 2609       case ENOENT:
 2610         result = 0;  // the file doesn't exist
 2611         goto finish;
 2612         break;
 2613       default:
 2614         result = -1;  // unknown error
 2615         goto finish;
 2616         break;
 2617     }
 2618 
 2619 finish:
 2620     return result;
 2621 }
 2622 #endif /* not KERNEL */
 2623 
 2624 /*******************************************************************************
 2625 *
 2626 *******************************************************************************/
 2627 PRIV_EXT
 2628 void kload_set_log_level(kload_log_level level)
 2629 {
 2630     log_level = level;
 2631     return;
 2632 }
 2633 
 2634 #ifndef KERNEL
 2635 /*******************************************************************************
 2636 *
 2637 *******************************************************************************/
 2638 void kload_set_log_function(
 2639     void (*func)(const char * format, ...))
 2640 {
 2641     if (!func) {
 2642         __kload_log_func = &__kload_null_log;
 2643     } else {
 2644         __kload_log_func = func;
 2645     }
 2646     return;
 2647 }
 2648 
 2649 /*******************************************************************************
 2650 *
 2651 *******************************************************************************/
 2652 void kload_set_error_log_function(
 2653     void (*func)(const char * format, ...))
 2654 {
 2655     if (!func) {
 2656         __kload_err_log_func = &__kload_null_err_log;
 2657     } else {
 2658         __kload_err_log_func = func;
 2659     }
 2660     return;
 2661 }
 2662 
 2663 /*******************************************************************************
 2664 *
 2665 *******************************************************************************/
 2666 void kload_set_user_approve_function(
 2667     int (*func)(int default_answer, const char * format, ...))
 2668 {
 2669     if (!func) {
 2670         __kload_approve_func = &__kload_null_approve;
 2671     } else {
 2672         __kload_approve_func = func;
 2673     }
 2674     return;
 2675 }
 2676 
 2677 /*******************************************************************************
 2678 *
 2679 *******************************************************************************/
 2680 void kload_set_user_veto_function(
 2681     int (*func)(int default_answer, const char * format, ...))
 2682 {
 2683     if (!func) {
 2684         __kload_veto_func = &__kload_null_veto;
 2685     } else {
 2686         __kload_veto_func = func;
 2687     }
 2688     return;
 2689 }
 2690 
 2691 /*******************************************************************************
 2692 *
 2693 *******************************************************************************/
 2694 void kload_set_user_input_function(
 2695     const char * (*func)(const char * format, ...))
 2696 {
 2697     if (!func) {
 2698         __kload_input_func = &__kload_null_input;
 2699     } else {
 2700         __kload_input_func = func;
 2701     }
 2702     return;
 2703 }
 2704 
 2705 /*******************************************************************************
 2706 *
 2707 *******************************************************************************/
 2708 PRIV_EXT
 2709 void kload_log_message(const char * format, ...)
 2710 {
 2711     va_list ap;
 2712     char fake_buffer[2];
 2713     int output_length;
 2714     char * output_string;
 2715 
 2716     if (log_level <= kload_log_level_silent) {
 2717         return;
 2718     }
 2719 
 2720     va_start(ap, format);
 2721     output_length = vsnprintf(fake_buffer, 1, format, ap);
 2722     va_end(ap);
 2723 
 2724     output_string = (char *)malloc(output_length + 1);
 2725     if (!output_string) {
 2726         return;
 2727     }
 2728 
 2729     va_start(ap, format);
 2730     vsprintf(output_string, format, ap);
 2731     va_end(ap);
 2732 
 2733     __kload_log_func(output_string);
 2734     free(output_string);
 2735 
 2736     return;
 2737 }
 2738 
 2739 /*******************************************************************************
 2740 *
 2741 *******************************************************************************/
 2742 PRIV_EXT
 2743 void kload_log_error(const char * format, ...)
 2744 {
 2745     va_list ap;
 2746     char fake_buffer[2];
 2747     int output_length;
 2748     char * output_string;
 2749 
 2750     if (log_level <= kload_log_level_silent) {
 2751         return;
 2752     }
 2753 
 2754     va_start(ap, format);
 2755     output_length = vsnprintf(fake_buffer, 1, format, ap);
 2756     va_end(ap);
 2757 
 2758     output_string = (char *)malloc(output_length + 1);
 2759     if (!output_string) {
 2760         return;
 2761     }
 2762 
 2763     va_start(ap, format);
 2764     vsprintf(output_string, format, ap);
 2765     va_end(ap);
 2766 
 2767     __kload_err_log_func(output_string);
 2768     free(output_string);
 2769 
 2770     return;
 2771 }
 2772 /*******************************************************************************
 2773 *
 2774 *******************************************************************************/
 2775 void __kload_null_log(const char * format, ...)
 2776 {
 2777     return;
 2778 }
 2779 
 2780 /*******************************************************************************
 2781 *
 2782 *******************************************************************************/
 2783 void __kload_null_err_log(const char * format, ...)
 2784 {
 2785     return;
 2786 }
 2787 
 2788 /*******************************************************************************
 2789 *
 2790 *******************************************************************************/
 2791 int __kload_null_approve(int default_answer, const char * format, ...)
 2792 {
 2793     return 0;
 2794 }
 2795 
 2796 /*******************************************************************************
 2797 *
 2798 *******************************************************************************/
 2799 int __kload_null_veto(int default_answer, const char * format, ...)
 2800 {
 2801     return 1;
 2802 }
 2803 
 2804 /*******************************************************************************
 2805 *
 2806 *******************************************************************************/
 2807 const char * __kload_null_input(const char * format, ...)
 2808 {
 2809     return NULL;
 2810 }
 2811 
 2812 /*******************************************************************************
 2813 * The kld_patch.c module uses this function, if defined, to print errors. In
 2814 * the kernel this function is defined in libsa/misc.c.
 2815 *******************************************************************************/
 2816 void kld_error_vprintf(const char * format, va_list ap) {
 2817     if (log_level <= kload_log_level_silent) return;
 2818     vfprintf(stderr, format, ap);
 2819     return;
 2820 }
 2821 
 2822 #endif /* not KERNEL */

Cache object: 0ec7edd2ebbc6f282ce722426adf237a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.