home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1999 May / pcp151c.iso / misc / src / install / modutils / depmod / depmod.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-06  |  9.5 KB  |  465 lines

  1. /* Copyright 1997 Free Software Foundation, Inc.
  2.    Contributed by Marcin Dalecki <dalecki@sub994.sub.uni-goettingen.de>
  3.  
  4.    This file is part of the Linux modutils.
  5.  
  6.    This program is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU General Public License as published by the
  8.    Free Software Foundation; either version 2 of the License, or (at your
  9.    option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.    General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software Foundation,
  18.    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  19.  
  20. #ident "$Id: depmod.c,v 1.1.1.1 1998/01/06 20:51:07 ewt Exp $"
  21.  
  22. #include <stdio.h>
  23. #include <assert.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <unistd.h>
  27. #include <getopt.h>
  28. #include <errno.h>
  29. #include <elf.h>
  30. #include ELF_MACHINE_H
  31.  
  32. #include "util.h"
  33. #include "obj.h"
  34. #include "misc.h"
  35. #include "conf_file.h"
  36.  
  37. int n_objs = 0;
  38. int max_objs = 0;
  39. struct obj_file **objs;
  40. char **names;
  41.  
  42. /*======================================================================*/
  43.  
  44. static int flag_show_error = 0;
  45. static int flag_verbose = 0;
  46.  
  47. #ifndef NO_COMPAT
  48. static int flag_new_syscalls = 0;
  49. #endif
  50.  
  51. struct new_module_symbol *ksyms;
  52. size_t nksyms;
  53.  
  54. /*======================================================================*/
  55.  
  56. static void
  57. new_read_kernel_syms (void)
  58. {
  59.   struct new_module_symbol *syms, *s;
  60.   size_t ret, bufsize, nsyms, j;
  61.  
  62.   /* Collect the kernel's symbols.  */
  63.  
  64.   syms = xmalloc (bufsize = 16 * 1024);
  65. retry_kern_sym_load:
  66.   if (query_module (NULL, QM_SYMBOLS, syms, bufsize, &ret))
  67.     {
  68.       if (errno == ENOSPC)
  69.     {
  70.       syms = xrealloc (syms, bufsize = ret);
  71.       goto retry_kern_sym_load;
  72.     }
  73.       error ("kernel: QM_SYMBOLS: %m");
  74.       exit (1);
  75.     }
  76.   nksyms = nsyms = ret;
  77.   ksyms = syms;
  78.  
  79.   for (j = 0, s = syms; j < nsyms; ++j, ++s)
  80.     s->name += (unsigned long) syms;
  81. }
  82.  
  83. #ifndef NO_COMPAT
  84.  
  85. static void
  86. old_read_kernel_syms (void)
  87. {
  88.   struct old_kernel_sym *ks, *k;
  89.   struct new_module_symbol *s;
  90.   int nks, nms, i;
  91.  
  92.   nks = get_kernel_syms(NULL);
  93.   if (nks < 0)
  94.     {
  95.       error("get_kernel_syms: %m");
  96.       return;
  97.     }
  98.  
  99.   ks = k = xmalloc(nks * sizeof(*ks));
  100.   if (get_kernel_syms(ks) != nks)
  101.     {
  102.       error("inconsistency with get_kernel_syms -- is someone else "
  103.         "playing with modules?");
  104.       free(ks);
  105.       return;
  106.     }
  107.  
  108.   /* Collect the module information.  */
  109.  
  110.   while (k->name[0] != '#' || k->name[1])
  111.     ++k;
  112.   ++k;
  113.  
  114.   nksyms = nms = nks - (k - ks);
  115.   ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
  116.  
  117.   for (i = 0; i < nms; ++i, ++s, ++k)
  118.     {
  119.       s->name = (unsigned long)k->name;
  120.       s->value = k->value;
  121.     }
  122. }
  123.  
  124. #endif
  125.  
  126. /*
  127.  * Format the dependency list of a module into a simple makefile
  128.  */
  129. static void
  130. print_deps_file (const char *depfile)
  131. {
  132.   FILE *fout = stdout;
  133.   char **deps;
  134.   int max_deps = 64;
  135.   int o;
  136.  
  137.   deps = (char **) xmalloc (max_deps * sizeof (char *));
  138.  
  139.   if (depfile && !(fout = fopen (depfile, "w")))
  140.     {
  141.       lprintf ("can't open %s", depfile);
  142.       exit (1);
  143.     }
  144.  
  145.   /*
  146.    * Loop through all modules we visited and construct the dependencies.
  147.    */
  148.   for (o = 0; o < n_objs; ++o)
  149.     {
  150.       int errs = 0;
  151.       int n_deps = 0;
  152.       int i;
  153.  
  154.       /*
  155.        * Loop throught all undefined symbols of this object
  156.        */
  157.       for (i = 0; i < HASH_BUCKETS; ++i)
  158.     {
  159.       struct obj_symbol *sym;
  160.       for (sym = objs[o]->symtab[i]; sym; sym = sym->next)
  161.         {
  162.           int j;
  163.           int k;
  164.  
  165.           if (sym->secidx != SHN_UNDEF
  166.           || ELFW (ST_BIND) (sym->info) == STB_WEAK)
  167.         continue;
  168.  
  169.           /*
  170.            * Traverse all modules and search for one, where it may be
  171.            * defined.
  172.            */
  173.           for (j = 0; j < n_objs; ++j)
  174.         {
  175.           struct obj_symbol *tmp;
  176.           if (j == o)
  177.             continue;
  178.  
  179.           tmp = obj_find_symbol (objs[j], sym->name);
  180.           if (tmp && tmp->secidx != SHN_UNDEF)
  181.             break;
  182.         }
  183.           if (j == n_objs)
  184.         {
  185.           if (errs == 0)
  186.             lprintf ("%s: unresolved symbol(s)"
  187.                  ,names[o]);
  188.           if (flag_show_error)
  189.             lprintf ("\t%s", sym->name);
  190.           errs++;
  191.           continue;
  192.         }
  193.  
  194.           /*
  195.            * Look if it's allready there
  196.            */
  197.           for (k = 0; k < n_deps; ++k)
  198.         if (deps[k] == names[j])
  199.           break;
  200.           /*
  201.            * And add the dep info if neccessary.
  202.            */
  203.           if (k != n_deps)
  204.         continue;
  205.  
  206.           if (k == max_deps)
  207.         {
  208.           max_deps <<= 1;
  209.           deps = (char **)
  210.             xrealloc (deps, max_deps * sizeof (char *));
  211.         }
  212.           deps[k] = names[j];
  213.           ++n_deps;
  214.         }
  215.     }
  216.  
  217.       if (errs == 0 && flag_verbose)
  218.     printf ("%s\n", names[o]);
  219.       fprintf (fout, "%s:", names[o]);
  220.  
  221.       /*
  222.        * Print the dependencies for this module.
  223.        */
  224. #if 1
  225.       while (n_deps--)
  226.     fprintf (fout, " %s", deps[n_deps]);
  227. #else
  228.       for (i = 0; i < n_deps; ++i)
  229.     fprintf (fout, " %s", deps[i]);
  230. #endif
  231.       fprintf (fout, "\n\n");
  232.     }
  233.   if (fout != stdout)
  234.     fclose (fout);
  235.   free (deps);
  236. }
  237.  
  238. /*
  239.  * Load an object file and resolve all the symbols contained therein.
  240.  */
  241. static int
  242. load_obj_file (const char *module)
  243. {
  244.   FILE *fp;
  245.   struct obj_file *file;
  246.   struct obj_symbol *sym;
  247.   int i;
  248.  
  249.   if (!(fp = fopen (module, "r")))
  250.     {
  251.       error("%s: open: %m", module);
  252.       return 1;
  253.     }
  254.  
  255.   file = obj_load (fp);
  256.   fclose (fp);
  257.  
  258.   if (!file)
  259.     {
  260.       /* obj_load will already have printed an error message.  */
  261.       return 1;
  262.     }
  263.  
  264.   if (n_objs == max_objs)
  265.     {
  266.       max_objs <<= 2;
  267.       objs = (struct obj_file **)
  268.     xrealloc (objs, max_objs * sizeof (struct obj_file *));
  269.       names = (char **) xrealloc (names, max_objs * sizeof (char *));
  270.     }
  271.   objs[n_objs] = file;
  272.   names[n_objs] = xstrdup (module);
  273.  
  274.   /*
  275.    * Hide the kernel symbols...
  276.    */
  277.   for (i = 0; i < nksyms; ++i)
  278.     if ((sym = obj_find_symbol (file, (char *) ksyms[i].name)) != NULL)
  279.       sym->secidx = SHN_HIRESERVE + 1;
  280.  
  281.   /*
  282.    * Hide them they are used by insmod internally.
  283.    */
  284.   if ((sym = obj_find_symbol (file, "__this_module")) != NULL)
  285.     sym->secidx = SHN_HIRESERVE + 1;
  286.   if ((sym = obj_find_symbol (file, "mod_use_count_")) != NULL)
  287.     sym->secidx = SHN_HIRESERVE + 1;
  288.   ++n_objs;
  289.  
  290.   return 0;
  291. }
  292.  
  293. /*
  294.  * Print usage information ans exit.
  295.  */
  296. static void
  297. usage (void)
  298. {
  299.   puts(
  300.     "Usage: depmod [-e -s -v ] -a [FORCED_KERNEL_VER]\n"
  301.     "       depmod [-e -s -v ] MODULE_1.o MODULE_2.o ...\n"
  302.     "Create module-dependency information for modprobe.\n\n"
  303.     "  -a, --all                  visit all modules\n"
  304.     "  -d, --debug                run in debug mode\n"
  305.     "  -e                         output unresolved symbols\n"
  306.     "  -s, --system-log           use the system log for error reporting\n"
  307.     "      --help                 display this help and exit\n"
  308.     "  -v, --verbose              run in verbose mode\n"
  309.     "  -V, --version              output version information and exit"
  310.     );
  311. }
  312.  
  313. int
  314. main (int argc, char *argv[])
  315. {
  316.   int ret = 1;
  317.   int flag_stdmode = 0;
  318.  
  319.   int opt_tag;
  320.  
  321.   if (argc == 1)
  322.     {
  323.       usage ();
  324.       return 1;
  325.     }
  326.  
  327. #ifndef NO_COMPAT
  328.   flag_new_syscalls = !query_module (NULL, 0, NULL, 0, NULL);
  329.   if (!flag_new_syscalls)
  330.     old_read_kernel_syms ();
  331.   else
  332. #endif
  333.     new_read_kernel_syms ();
  334.  
  335.   /*
  336.    * Yes we are using getopts!
  337.    */
  338.   while (1)
  339.     {
  340.       static struct option long_opts[] =
  341.       {
  342.     {"all", 0, 0, 'a'},
  343.     {"debug", 0, 0, 'd'},
  344.     {"system-log", 0, 0, 's'},
  345.     {"verbose", 0, 0, 'v'},
  346.     {"version", 0, 0, 'V'},
  347.     {"help", 0, 0, 'h'},
  348.     {0, 0, 0, 0}        /* Table end tag */
  349.       };
  350.       int opt_ind = 0;
  351.  
  352.       opt_tag = getopt_long (argc, argv, "adesvV", long_opts,
  353.                  &opt_ind);
  354.       if (opt_tag == -1)
  355.     break;
  356.  
  357.       switch (opt_tag)
  358.     {
  359.     case 'a':
  360.       flag_stdmode = 1;
  361.       break;
  362.  
  363.     case 'd':
  364.       flag_debug = 1;
  365.       break;
  366.  
  367.     case 'e':
  368.       flag_show_error = 1;
  369.       break;
  370.  
  371.     case 's':
  372.       setsyslog ("depmod");    /* use the syslog for reporting */
  373.       break;
  374.  
  375.     case 'v':
  376.       flag_verbose = 1;    /* give terse informations during run */
  377.       break;
  378.  
  379.     case '?':
  380.     case 'h':
  381.       usage ();
  382.       exit (opt_tag == 'h' ? 0 : 1);
  383.       break;
  384.  
  385.     case 'V':
  386.       puts ("depmod (Linux modutils) " MODUTILS_VERSION);
  387.       if (argc != 2)
  388.         putchar ('\n');
  389.       break;
  390.  
  391.     default:
  392.       abort ();
  393.     }
  394.     }
  395.  
  396.   /*
  397.    * Skip all automatically processed options.
  398.    */
  399.   argc -= optind;
  400.   argv += optind;
  401.  
  402.   /*
  403.    * argv now points to the first non-option argument
  404.    * argc is the remaining argument count
  405.    */
  406.  
  407.   n_objs = 0;
  408.   max_objs = 64;
  409.   objs = (struct obj_file **) xmalloc (max_objs * sizeof (struct obj_file *));
  410.   names = (char **) xmalloc (max_objs * sizeof (char *));
  411.  
  412.   if (flag_stdmode)
  413.     {
  414.       struct mod_path *mods = NULL;
  415.       struct mod_path *tmp;
  416.  
  417.       if (argc > 0)
  418.     {
  419.       if (read_config_file (*argv))
  420.         {
  421.           lprintf ("%s does not exist", depfile);
  422.           return 1;
  423.         }
  424.     }
  425.       else
  426.     {
  427.       /* Read the default config file and don't complain if there
  428.          isn't one.  */
  429.       read_config_file (NULL);
  430.     }
  431.  
  432.       mods = find_matching_mods ("*", NULL, 1);
  433.       ret = 0;
  434.       while ((tmp = mods))
  435.     {
  436.       ret |= load_obj_file (mods->path);
  437.       mods = mods->next;
  438.       free (tmp->path);
  439.       free (tmp);
  440.     }
  441.       while ((tmp = mods))
  442.     {
  443.       mods = mods->next;
  444.       free (tmp->path);
  445.       free (tmp);
  446.     }
  447.  
  448.       if (!ret)
  449.     print_deps_file (depfile);
  450.     }
  451.   else
  452.     {
  453.       /*
  454.        * Process all modules which are explicitly specified on the command line
  455.        */
  456.  
  457.       for (ret = 0; argc > 0 && !ret; ++argv, --argc)
  458.     ret = load_obj_file (*argv);
  459.       if (!ret)
  460.     print_deps_file (NULL);
  461.     }
  462.  
  463.   return ret;
  464. }
  465.