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

Cache object: e8a75e67755ca9134685116ed372d1df


[ 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.