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/dgraph.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-2007 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 
   29 #ifdef KERNEL
   30 #include <libsa/vers_rsrc.h>
   31 #else
   32 #include <libc.h>
   33 #include <stdlib.h>
   34 #include <stdarg.h>
   35 #include <stdio.h>
   36 #include <string.h>
   37 #include <unistd.h>
   38 
   39 #include "KXKext.h"
   40 #include "vers_rsrc.h"
   41 #endif /* KERNEL */
   42 
   43 #include "dgraph.h"
   44 #include "load.h"
   45 
   46 #ifdef KERNEL
   47 #include <sys/malloc.h>
   48 #endif
   49 
   50 static void __dgraph_entry_free(dgraph_entry_t * entry);
   51 
   52 #ifdef KERNEL
   53 #define dgstrdup(string) STRDUP(string, M_TEMP)
   54 #define dgfree(string) FREE(string, M_TEMP)
   55 #else
   56 #define dgstrdup strdup
   57 #define dgfree(string) free(string)
   58 #endif /* KERNEL */
   59 
   60 /*******************************************************************************
   61 *
   62 *******************************************************************************/
   63 dgraph_error_t dgraph_init(dgraph_t * dgraph)
   64 {
   65     bzero(dgraph, sizeof(dgraph_t));
   66 
   67     dgraph->capacity = (5);  // pulled from a hat
   68 
   69    /* Make sure list is big enough & graph has a good start size.
   70     */
   71     dgraph->graph = (dgraph_entry_t **)malloc(
   72         dgraph->capacity * sizeof(dgraph_entry_t *));
   73 
   74     if (!dgraph->graph) {
   75         return dgraph_error;
   76     }
   77 
   78     return dgraph_valid;
   79 }
   80 
   81 #ifndef KERNEL
   82 /*******************************************************************************
   83 *
   84 *******************************************************************************/
   85 dgraph_error_t dgraph_init_with_arglist(
   86     dgraph_t * dgraph,
   87     int expect_addresses,
   88     const char * dependency_delimiter,
   89     const char * kernel_dependency_delimiter,
   90     int argc,
   91     char * argv[])
   92 {
   93     dgraph_error_t result = dgraph_valid;
   94     unsigned int i;
   95     int found_zero_load_address = 0;
   96     int found_nonzero_load_address = 0;
   97     dgraph_entry_t * current_dependent = NULL;
   98     char kernel_dependencies = 0;
   99 
  100     result = dgraph_init(dgraph);
  101     if (result != dgraph_valid) {
  102         return result;
  103     }
  104 
  105     for (i = 0; i < argc; i++) {
  106         vm_address_t load_address = 0;
  107 
  108         if (0 == strcmp(argv[i], dependency_delimiter)) {
  109             kernel_dependencies = 0;
  110             current_dependent = NULL;
  111             continue;
  112         } else if (0 == strcmp(argv[i], kernel_dependency_delimiter)) {
  113             kernel_dependencies = 1;
  114             current_dependent = NULL;
  115             continue;
  116         }
  117 
  118         if (expect_addresses) {
  119             char * address = rindex(argv[i], '@');
  120             if (address) {
  121                 *address++ = 0;  // snip the address from the filename
  122                 load_address = strtoul(address, NULL, 0);
  123             }
  124         }
  125 
  126         if (!current_dependent) {
  127            current_dependent = dgraph_add_dependent(dgraph, argv[i],
  128                /* expected kmod name */ NULL, /* expected vers */ 0,
  129                load_address, 0);
  130            if (!current_dependent) {
  131                return dgraph_error;
  132            }
  133         } else {
  134             if (!dgraph_add_dependency(dgraph, current_dependent, argv[i],
  135                /* expected kmod name */ NULL, /* expected vers */ 0,
  136                load_address, kernel_dependencies)) {
  137 
  138                return dgraph_error;
  139             }
  140         }
  141     }
  142 
  143     dgraph->root = dgraph_find_root(dgraph);
  144     dgraph_establish_load_order(dgraph);
  145 
  146     if (!dgraph->root) {
  147         kload_log_error("dependency graph has no root" KNL);
  148         return dgraph_invalid;
  149     }
  150 
  151     if (dgraph->root->is_kernel_component && !dgraph->root->is_symbol_set) {
  152         kload_log_error("dependency graph root is a kernel component" KNL);
  153         return dgraph_invalid;
  154     }
  155 
  156     for (i = 0; i < dgraph->length; i++) {
  157         if (dgraph->graph[i]->loaded_address == 0) {
  158             found_zero_load_address = 1;
  159         } else {
  160             found_nonzero_load_address = 1;
  161         }
  162         if ( (i > 0) &&
  163              (found_zero_load_address && found_nonzero_load_address)) {
  164 
  165             kload_log_error(
  166                 "load addresses must be specified for all module files" KNL);
  167             return dgraph_invalid;
  168         }
  169     }
  170 
  171     return dgraph_valid;
  172 }
  173 #endif /* not KERNEL */
  174 
  175 /*******************************************************************************
  176 *
  177 *******************************************************************************/
  178 static void __dgraph_entry_free(dgraph_entry_t * entry)
  179 {
  180     if (entry->name) {
  181         dgfree(entry->name);
  182         entry->name = NULL;
  183     }
  184     if (entry->expected_kmod_name) {
  185         dgfree(entry->expected_kmod_name);
  186         entry->expected_kmod_name = NULL;
  187     }
  188     if (entry->expected_kmod_vers) {
  189         dgfree(entry->expected_kmod_vers);
  190         entry->expected_kmod_vers = NULL;
  191     }
  192     if (entry->dependencies) {
  193         free(entry->dependencies);
  194         entry->dependencies = NULL;
  195     }
  196     if (entry->symbols_malloc) {
  197         free((void *) entry->symbols_malloc);
  198         entry->symbols_malloc = 0;
  199     }
  200     free(entry);
  201     return;
  202 }
  203 
  204 /*******************************************************************************
  205 *
  206 *******************************************************************************/
  207 void dgraph_free(
  208     dgraph_t * dgraph,
  209     int free_graph)
  210 {
  211     unsigned int entry_index;
  212 
  213     if (!dgraph) {
  214         return;
  215     }
  216 
  217     for (entry_index = 0; entry_index < dgraph->length; entry_index++) {
  218         dgraph_entry_t * current = dgraph->graph[entry_index];
  219         __dgraph_entry_free(current);
  220     }
  221 
  222     if (dgraph->graph) {
  223         free(dgraph->graph);
  224         dgraph->graph = NULL;
  225     }
  226 
  227     if (dgraph->load_order) {
  228         free(dgraph->load_order);
  229         dgraph->load_order = NULL;
  230     }
  231 
  232     if (free_graph && dgraph) {
  233         free(dgraph);
  234     }
  235 
  236     return;
  237 }
  238 
  239 
  240 /*******************************************************************************
  241 *
  242 *******************************************************************************/
  243 dgraph_entry_t * dgraph_find_root(dgraph_t * dgraph) {
  244     dgraph_entry_t * root = NULL;
  245     dgraph_entry_t * candidate = NULL;
  246     unsigned int candidate_index;
  247     unsigned int scan_index;
  248     unsigned int dep_index;
  249 
  250 
  251    /* Scan each entry in the graph for one that isn't in any other entry's
  252     * dependencies.
  253     */
  254     for (candidate_index = 0; candidate_index < dgraph->length;
  255          candidate_index++) {
  256 
  257         candidate = dgraph->graph[candidate_index];
  258 
  259         for (scan_index = 0; scan_index < dgraph->length; scan_index++) {
  260 
  261             dgraph_entry_t * scan_entry = dgraph->graph[scan_index];
  262             if (candidate == scan_entry) {
  263                 // don't check yourself
  264                 continue;
  265             }
  266             for (dep_index = 0; dep_index < scan_entry->num_dependencies;
  267                  dep_index++) {
  268 
  269                /* If the dependency being checked is the candidate,
  270                 *  then the candidate can't be the root.
  271                 */
  272                 dgraph_entry_t * check = scan_entry->dependencies[dep_index];
  273 
  274                 if (check == candidate) {
  275                     candidate = NULL;
  276                     break;
  277                 }
  278             }
  279 
  280            /* If the candidate was rejected, then hop out of this loop.
  281             */
  282             if (!candidate) {
  283                 break;
  284             }
  285         }
  286 
  287        /* If we got here, the candidate is a valid one. However, if we already
  288         * found another, that means we have two possible roots (or more), which
  289         * is NOT ALLOWED.
  290         */
  291         if (candidate) {
  292             if (root) {
  293                 kload_log_error("dependency graph has multiple roots "
  294                     "(%s and %s)" KNL, root->name, candidate->name);
  295                 return NULL;  // two valid roots, illegal
  296             } else {
  297                 root = candidate;
  298             }
  299         }
  300     }
  301 
  302     if (!root) {
  303         kload_log_error("dependency graph has no root node" KNL);
  304     }
  305 
  306     return root;
  307 }
  308 
  309 /*******************************************************************************
  310 *
  311 *******************************************************************************/
  312 dgraph_entry_t ** fill_backward_load_order(
  313     dgraph_entry_t ** backward_load_order,
  314     unsigned int * list_length,
  315     dgraph_entry_t * first_entry,
  316     unsigned int * last_index /* out param */)
  317 {
  318     unsigned int i;
  319     unsigned int scan_index = 0;
  320     unsigned int add_index = 0;
  321     dgraph_entry_t * scan_entry;
  322 
  323     if (*list_length == 0) {
  324         if (backward_load_order) {
  325             free(backward_load_order);
  326             backward_load_order = NULL;
  327         }
  328         goto finish;
  329     }
  330 
  331     backward_load_order[add_index++] = first_entry;
  332 
  333     while (scan_index < add_index) {
  334 
  335         if (add_index > 255) {
  336             kload_log_error(
  337                 "dependency list for %s ridiculously long; probably a loop" KNL,
  338                 first_entry->name);
  339             if (backward_load_order) {
  340                 free(backward_load_order);
  341                 backward_load_order = NULL;
  342             }
  343             goto finish;
  344         }
  345 
  346         scan_entry = backward_load_order[scan_index++];
  347 
  348        /* Increase the load order list if needed.
  349         */
  350         if (add_index + scan_entry->num_dependencies > (*list_length)) {
  351             (*list_length) *= 2;
  352             backward_load_order = (dgraph_entry_t **)realloc(
  353                 backward_load_order,
  354                 (*list_length) * sizeof(dgraph_entry_t *));
  355             if (!backward_load_order) {
  356                 goto finish;
  357             }
  358         }
  359 
  360        /* Put the dependencies of the scanning entry into the list.
  361         */
  362         for (i = 0; i < scan_entry->num_dependencies; i++) {
  363             backward_load_order[add_index++] =
  364                 scan_entry->dependencies[i];
  365         }
  366     }
  367 
  368 finish:
  369 
  370     if (last_index) {
  371         *last_index = add_index;
  372     }
  373     return backward_load_order;
  374 }
  375 
  376 /*******************************************************************************
  377 *
  378 *******************************************************************************/
  379 int dgraph_establish_load_order(dgraph_t * dgraph) {
  380     unsigned int total_dependencies;
  381     unsigned int entry_index;
  382     unsigned int list_index;
  383     unsigned int backward_index;
  384     unsigned int forward_index;
  385     size_t load_order_size;
  386     size_t backward_load_order_size;
  387     dgraph_entry_t ** backward_load_order;
  388 
  389    /* Lose the old load_order list. Size can change, so it's easier to just
  390     * recreate from scratch.
  391     */
  392     if (dgraph->load_order) {
  393         free(dgraph->load_order);
  394         dgraph->load_order = NULL;
  395     }
  396 
  397    /* Figure how long the list needs to be to accommodate the max possible
  398     * entries from the graph. Duplicates get weeded out, but the list
  399     * initially has to accommodate them all.
  400     */
  401     total_dependencies = dgraph->length;
  402 
  403     for (entry_index = 0; entry_index < dgraph->length; entry_index ++) {
  404         dgraph_entry_t * curdep = dgraph->graph[entry_index];
  405         total_dependencies += curdep->num_dependencies;
  406     }
  407 
  408    /* Hmm, nothing to do!
  409     */
  410     if (!total_dependencies) {
  411         return 1;
  412     }
  413 
  414     backward_load_order_size = total_dependencies * sizeof(dgraph_entry_t *);
  415 
  416     backward_load_order = (dgraph_entry_t **)malloc(backward_load_order_size);
  417     if (!backward_load_order) {
  418         kload_log_error("malloc failure" KNL);
  419         return 0;
  420     }
  421     bzero(backward_load_order, backward_load_order_size);
  422 
  423     backward_load_order = fill_backward_load_order(backward_load_order,
  424         &total_dependencies, dgraph->root, &list_index);
  425     if (!backward_load_order) {
  426         kload_log_error("error establishing load order" KNL);
  427         return 0;
  428     }
  429 
  430     load_order_size = dgraph->length * sizeof(dgraph_entry_t *);
  431     dgraph->load_order = (dgraph_entry_t **)malloc(load_order_size);
  432     if (!dgraph->load_order) {
  433         kload_log_error("malloc failure" KNL);
  434         return 0;
  435     }
  436     bzero(dgraph->load_order, load_order_size);
  437 
  438 
  439    /* Reverse the list into the dgraph's load_order list,
  440     * removing any duplicates.
  441     */
  442     backward_index = list_index;
  443     //
  444     // the required 1 is taken off in loop below!
  445 
  446     forward_index = 0;
  447     do {
  448         dgraph_entry_t * current_entry;
  449         unsigned int already_got_it = 0;
  450 
  451         backward_index--;
  452 
  453        /* Get the entry to check.
  454         */
  455         current_entry = backward_load_order[backward_index];
  456 
  457        /* Did we already get it?
  458         */
  459         for (list_index = 0; list_index < forward_index; list_index++) {
  460             if (current_entry == dgraph->load_order[list_index]) {
  461                 already_got_it = 1;
  462                 break;
  463             }
  464         }
  465 
  466         if (already_got_it) {
  467             continue;
  468         }
  469 
  470        /* Haven't seen it before; tack it onto the load-order list.
  471         */
  472         dgraph->load_order[forward_index++] = current_entry;
  473 
  474     } while (backward_index > 0);
  475 
  476     free(backward_load_order);
  477 
  478     return 1;
  479 }
  480 
  481 /*******************************************************************************
  482 *
  483 *******************************************************************************/
  484 void dgraph_log(dgraph_t * depgraph)
  485 {
  486     unsigned int i, j;
  487 
  488     kload_log_message("flattened dependency list: " KNL);
  489     for (i = 0; i < depgraph->length; i++) {
  490         dgraph_entry_t * current = depgraph->graph[i];
  491 
  492         kload_log_message("    %s" KNL, current->name);
  493         kload_log_message("      is kernel component: %s" KNL,
  494             current->is_kernel_component ? "yes" : "no");
  495         kload_log_message("      expected kmod name: [%s]" KNL,
  496             current->expected_kmod_name);
  497         kload_log_message("      expected kmod vers: [%s]" KNL,
  498             current->expected_kmod_vers);
  499     }
  500     kload_log_message("" KNL);
  501 
  502     kload_log_message("load order dependency list: " KNL);
  503     for (i = 0; i < depgraph->length; i++) {
  504         dgraph_entry_t * current = depgraph->load_order[i];
  505         kload_log_message("    %s" KNL, current->name);
  506     }
  507     kload_log_message("" KNL);
  508 
  509     kload_log_message("dependency graph: " KNL);
  510     for (i = 0; i < depgraph->length; i++) {
  511         dgraph_entry_t * current = depgraph->graph[i];
  512         for (j = 0; j < current->num_dependencies; j++) {
  513             dgraph_entry_t * cdep = current->dependencies[j];
  514             kload_log_message("  %s -> %s" KNL, current->name, cdep->name);
  515         }
  516     }
  517     kload_log_message("" KNL);
  518 
  519     return;
  520 }
  521 
  522 /*******************************************************************************
  523 *
  524 *******************************************************************************/
  525 dgraph_entry_t * dgraph_find_dependent(dgraph_t * dgraph, const char * name)
  526 {
  527     unsigned int i;
  528 
  529     for (i = 0; i < dgraph->length; i++) {
  530         dgraph_entry_t * current_entry = dgraph->graph[i];
  531         if (0 == strcmp(name, current_entry->name)) {
  532             return current_entry;
  533         }
  534     }
  535 
  536     return NULL;
  537 }
  538 
  539 /*******************************************************************************
  540 *
  541 *******************************************************************************/
  542 dgraph_entry_t * dgraph_add_dependent(
  543     dgraph_t * dgraph,
  544     const char * name,
  545 #ifdef KERNEL
  546     void * object,
  547     size_t object_length,
  548     bool   object_is_kmem,
  549 #if CONFIG_MACF_KEXT
  550     kmod_args_t user_data,
  551     mach_msg_type_number_t user_data_length,
  552 #endif
  553 #endif /* KERNEL */
  554     const char * expected_kmod_name,
  555     const char * expected_kmod_vers,
  556     vm_address_t load_address,
  557     char is_kernel_component)
  558 {
  559     int error = 0;
  560     dgraph_entry_t * found_entry = NULL;
  561     dgraph_entry_t * new_entry = NULL;    // free on error
  562     dgraph_entry_t * the_entry = NULL;    // returned
  563 
  564    /* Already got it? Great!
  565     */
  566     found_entry = dgraph_find_dependent(dgraph, name);
  567     if (found_entry) {
  568         if (found_entry->is_kernel_component != is_kernel_component) {
  569             kload_log_error(
  570                 "%s is already defined as a %skernel component" KNL,
  571                 name, found_entry->is_kernel_component ? "" : "non-");
  572             error = 1;
  573             goto finish;
  574         }
  575 
  576         if (load_address != 0) {
  577             if (found_entry->loaded_address == 0) {
  578                 found_entry->do_load = 0;
  579                 found_entry->loaded_address = load_address;
  580             } else if (found_entry->loaded_address != load_address) {
  581                 kload_log_error(
  582                    "%s has been assigned two different addresses (0x%x, 0x%x) KNL",
  583                     found_entry->name,
  584                     found_entry->loaded_address,
  585                     load_address);
  586                 error = 1;
  587                 goto finish;
  588             }
  589         }
  590         the_entry = found_entry;
  591         goto finish;
  592     }
  593 
  594    /* If the graph is full, make it bigger.
  595     */
  596     if (dgraph->length == dgraph->capacity) {
  597         unsigned int old_capacity = dgraph->capacity;
  598         dgraph_entry_t ** newgraph;
  599 
  600         dgraph->capacity *= 2;
  601         newgraph = (dgraph_entry_t **)malloc(dgraph->capacity *
  602             sizeof(dgraph_entry_t *));
  603         if (!newgraph) {
  604             return NULL;
  605         }
  606         memcpy(newgraph, dgraph->graph, old_capacity * sizeof(dgraph_entry_t *));
  607         free(dgraph->graph);
  608         dgraph->graph = newgraph;
  609     }
  610 
  611     if (strlen(expected_kmod_name) > KMOD_MAX_NAME - 1) {
  612         kload_log_error("expected kmod name \"%s\" is too long" KNL,
  613             expected_kmod_name);
  614         error = 1;
  615         goto finish;
  616     }
  617 
  618    /* Fill it.
  619     */
  620     new_entry = (dgraph_entry_t *)malloc(sizeof(dgraph_entry_t));
  621     if (!new_entry) {
  622         error = 1;
  623         goto finish;
  624     }
  625     bzero(new_entry, sizeof(dgraph_entry_t));
  626     new_entry->expected_kmod_name = dgstrdup(expected_kmod_name);
  627     if (!new_entry->expected_kmod_name) {
  628         error = 1;
  629         goto finish;
  630     }
  631     new_entry->expected_kmod_vers = dgstrdup(expected_kmod_vers);
  632     if (!new_entry->expected_kmod_vers) {
  633         error = 1;
  634         goto finish;
  635     }
  636     new_entry->is_kernel_component = is_kernel_component;
  637 
  638     // /hacks
  639     new_entry->is_symbol_set = (2 & is_kernel_component);
  640 
  641     new_entry->opaques = 0;
  642     if (!strncmp(new_entry->expected_kmod_name, 
  643                                     "com.apple.kpi", strlen("com.apple.kpi")))
  644         new_entry->opaques |= kOpaqueLink;
  645     if (!strcmp(new_entry->expected_kmod_name, 
  646                                     "com.apple.kernel"))
  647         new_entry->opaques |= kOpaqueLink | kRawKernelLink;
  648     // hacks/
  649 
  650     dgraph->has_symbol_sets |= new_entry->is_symbol_set;
  651 
  652     new_entry->do_load = !is_kernel_component;
  653 
  654 #ifndef KERNEL
  655     new_entry->object = NULL;   // provided elswehere in userland
  656     new_entry->object_length = 0;
  657 #else
  658     new_entry->object = object;
  659     new_entry->object_length = object_length;
  660     new_entry->object_is_kmem = object_is_kmem;
  661 #if CONFIG_MACF_KEXT
  662     new_entry->user_data = user_data;
  663     new_entry->user_data_length = user_data_length;
  664 #endif
  665 #endif /* KERNEL */
  666     new_entry->name = dgstrdup(name);
  667     if (!new_entry->name) {
  668         error = 1;
  669         goto finish;
  670     }
  671     dgraph->graph[dgraph->length++] = new_entry;
  672 
  673 
  674    /* Create a dependency list for the entry. Start with 5 slots.
  675     */
  676     new_entry->dependencies_capacity = 5;
  677     new_entry->num_dependencies = 0;
  678     new_entry->dependencies = (dgraph_entry_t **)malloc(
  679         new_entry->dependencies_capacity * sizeof(dgraph_entry_t *));
  680     if (!new_entry->dependencies) {
  681         error = 1;
  682         goto finish;
  683     }
  684 
  685     if (new_entry->loaded_address == 0) {
  686         new_entry->loaded_address = load_address;
  687         if (load_address != 0) {
  688             new_entry->do_load = 0;
  689         }
  690     }
  691 
  692     the_entry = new_entry;
  693 
  694 finish:
  695     if (error) {
  696         if (new_entry) __dgraph_entry_free(new_entry);
  697         the_entry = new_entry = NULL;
  698     }
  699     return the_entry;
  700 }
  701 
  702 /*******************************************************************************
  703 *
  704 *******************************************************************************/
  705 dgraph_entry_t * dgraph_add_dependency(
  706     dgraph_t * dgraph,
  707     dgraph_entry_t * current_dependent,
  708     const char * name,
  709 #ifdef KERNEL
  710     void * object,
  711     size_t object_length,
  712     bool   object_is_kmem,
  713 #if CONFIG_MACF_KEXT
  714     kmod_args_t user_data,
  715     mach_msg_type_number_t user_data_length,
  716 #endif
  717 #endif /* KERNEL */
  718     const char * expected_kmod_name,
  719     const char * expected_kmod_vers,
  720     vm_address_t load_address,
  721     char is_kernel_component)
  722 {
  723     dgraph_entry_t * dependency = NULL;
  724     unsigned int i = 0;
  725 
  726    /* If the dependent's dependency list is full, make it bigger.
  727     */
  728     if (current_dependent->num_dependencies ==
  729         current_dependent->dependencies_capacity) {
  730 
  731         unsigned int old_capacity = current_dependent->dependencies_capacity;
  732         dgraph_entry_t ** newlist;
  733 
  734         current_dependent->dependencies_capacity *= 2;
  735         newlist = (dgraph_entry_t **)malloc(
  736             (current_dependent->dependencies_capacity *
  737              sizeof(dgraph_entry_t *)) );
  738 
  739         if (!newlist) {
  740             return NULL;
  741         }
  742         memcpy(newlist, current_dependent->dependencies,
  743             old_capacity * sizeof(dgraph_entry_t *));
  744         free(current_dependent->dependencies);
  745         current_dependent->dependencies = newlist;
  746     }
  747 
  748 
  749    /* Find or add the entry for the new dependency.
  750     */
  751     dependency = dgraph_add_dependent(dgraph, name,
  752 #ifdef KERNEL
  753          object, object_length, object_is_kmem,
  754 #if CONFIG_MACF_KEXT
  755          user_data, user_data_length,
  756 #endif
  757 #endif /* KERNEL */
  758          expected_kmod_name, expected_kmod_vers, load_address,
  759          is_kernel_component);
  760     if (!dependency) {
  761        return NULL;
  762     }
  763 
  764     if (dependency == current_dependent) {
  765         kload_log_error("attempt to set dependency on itself: %s" KNL,
  766             current_dependent->name);
  767         return NULL;
  768     }
  769 
  770     for (i = 0; i < current_dependent->num_dependencies; i++) {
  771         dgraph_entry_t * this_dependency = current_dependent->dependencies[i];
  772         if (this_dependency == dependency) {
  773             return dependency;
  774         }
  775     }
  776 
  777    /* Fill in the dependency.
  778     */
  779     current_dependent->dependencies[current_dependent->num_dependencies] =
  780         dependency;
  781     current_dependent->num_dependencies++;
  782 
  783     current_dependent->opaque_link |= dependency->opaques;
  784     dgraph->has_opaque_links       |= current_dependent->opaque_link;
  785 
  786     return dependency;
  787 }

Cache object: 29135c6ec42095c23fd8eea827d38d6f


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