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

  1. /* Display the symbols exported from the running kernel.
  2.    Copyright 1996, 1997 Linux International.
  3.  
  4.    New implementation contributed by Richard Henderson <rth@tamu.edu>
  5.    Based on original work by Bjorn Eckwall <bj0rn@blox.se>
  6.  
  7.    This file is part of the Linux modutils.
  8.  
  9.    This program is free software; you can redistribute it and/or modify it
  10.    under the terms of the GNU General Public License as published by the
  11.    Free Software Foundation; either version 2 of the License, or (at your
  12.    option) any later version.
  13.  
  14.    This program is distributed in the hope that it will be useful, but
  15.    WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.    General Public License for more details.
  18.  
  19.    You should have received a copy of the GNU General Public License
  20.    along with this program; if not, write to the Free Software Foundation,
  21.    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  22.  
  23. #ident "$Id: ksyms.c,v 1.1.1.1 1998/01/06 20:51:07 ewt Exp $"
  24.  
  25. #include <sys/types.h>
  26. #include <stdio.h>
  27. #include <errno.h>
  28. #include <unistd.h>
  29. #include <fcntl.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32.  
  33. #include "module.h"
  34. #include "util.h"
  35. #include "version.h"
  36.  
  37. #include "logger.h"
  38.  
  39.  
  40. /*======================================================================*/
  41.  
  42. int flag_allsyms = 0;
  43. int flag_mod_info = 0;
  44. int flag_print_header = 1;
  45.  
  46.  
  47. /*======================================================================*/
  48.  
  49. static inline void
  50. print_symbol(const char *name, unsigned long value, const char *module)
  51. {
  52.   if (module)
  53.     printf("%0*lx  %-32s  [%s]\n", (int)(2*sizeof(void*)),
  54.        value, name, module);
  55.   else
  56.     printf("%0*lx  %-32s\n", (int)(2*sizeof(void*)), value, name);
  57. }
  58.  
  59. static inline void
  60. print_mod_info(const char *module, unsigned long addr, unsigned long size)
  61. {
  62.   int o;
  63.  
  64.   o = printf("%0*lx  (%luk)", (int)(2*sizeof(void*)), addr,
  65.          (size / 1024) + ((size % 1024) != 0));
  66.  
  67.   o = 2*sizeof(void*)+2+32+2 - o;
  68.  
  69.   printf("%*s[%s]\n", o, "", module);
  70. }
  71.  
  72.  
  73. /* If we don't have query_module()... */
  74.  
  75. static int
  76. old_ksyms(void)
  77. {
  78.   struct old_kernel_sym *ksyms, *k;
  79.   int nsyms, i;
  80.   int kmem_fd = -1;
  81.   const char *module;
  82.  
  83.   nsyms = get_kernel_syms(NULL);
  84.   if (nsyms < 0)
  85.     {
  86.       perror("get_kernel_syms");
  87.       return 1;
  88.     }
  89.  
  90.   ksyms = xmalloc(nsyms * sizeof(*ksyms));
  91.  
  92.   if (get_kernel_syms(ksyms) != nsyms)
  93.     {
  94.       fprintf(stderr, "Inconsistency reading kernel symbols -- "
  95.           "is someone else playing with modules?\n");
  96.       return 1;
  97.     }
  98.  
  99.   /* If requested, open kmem so we can get at module information.  */
  100.  
  101.   if (flag_mod_info)
  102.     {
  103.       kmem_fd = open("/dev/kmem", O_RDONLY);
  104.       if (kmem_fd < 0)
  105.     {
  106.       perror("ksyms: open /dev/kmem");
  107.       return 1;
  108.     }
  109.     }
  110.  
  111.   module = NULL;
  112.   for (k = ksyms, i = 0; i < nsyms; ++i, ++k)
  113.     if (k->name[0] == '#')
  114.       {
  115.     if (k->name[1])
  116.       {
  117.         module = &k->name[1];
  118.         if (flag_mod_info)
  119.           {
  120.         struct old_module info;
  121.  
  122.         if (llseek(kmem_fd, (off_t)k->value, SEEK_SET) == -1
  123.             || read(kmem_fd, &info, sizeof(info)) != sizeof(info))
  124.           {
  125.             perror("ksyms: /dev/kmem");
  126.             return 1;
  127.           }
  128.         print_mod_info(module, info.addr, info.size * getpagesize());
  129.           }
  130.       }
  131.     else
  132.       {
  133.         if (!flag_allsyms)
  134.           break;
  135.         module = NULL;
  136.       }
  137.       }
  138.     else
  139.       print_symbol(k->name, k->value, module);
  140.  
  141.   free(ksyms);
  142.   if (flag_mod_info)
  143.     close(kmem_fd);
  144.  
  145.   return 0;
  146. }
  147.  
  148.  
  149. /* If we do have query_module()...  */
  150.  
  151. static int
  152. new_ksyms(void)
  153. {
  154.   char *modules;
  155.   size_t nmodules;
  156.   struct new_module_symbol *syms;
  157.   size_t nsymbols;
  158.  
  159.   ssize_t ret;
  160.   size_t bufsize;
  161.   size_t i, j;
  162.   char *m;
  163.   struct new_module_symbol *s;
  164.  
  165.   /* Query for the module names.  */
  166.  
  167.   modules = xmalloc(bufsize = 256);
  168. retry_modules_load:
  169.   if (query_module(NULL, QM_MODULES, modules, bufsize, &ret))
  170.     {
  171.       if (errno == ENOSPC)
  172.     {
  173.       modules = xrealloc(modules, bufsize = ret);
  174.       goto retry_modules_load;
  175.     }
  176.       perror("ksyms: QM_MODULES");
  177.       return 1;
  178.     }
  179.   nmodules = ret;
  180.  
  181.   /* Iterate over the modules, in order, and care for their symbols.  */
  182.  
  183.   syms = xmalloc(bufsize = 16*1024);
  184.   for (i = 0, m = modules; i < nmodules; ++i, m += strlen(m)+1)
  185.     {
  186.       if (flag_mod_info)
  187.     {
  188.       struct new_module_info info;
  189.       if (query_module(m, QM_INFO, &info, sizeof(info), &ret))
  190.         {
  191.           if (errno == ENOENT)
  192.         {
  193.           /* The module must have been removed in the interim: skip */
  194.           continue;
  195.         }
  196.           perror("ksyms: QM_INFO");
  197.           return 1;
  198.         }
  199.       print_mod_info(m, info.addr, info.size);
  200.     }
  201.  
  202.     retry_mod_symbol_load:
  203.       if (query_module(m, QM_SYMBOLS, syms, bufsize, &ret))
  204.     switch (errno)
  205.       {
  206.       case ENOSPC:
  207.         syms = xrealloc(syms, bufsize = ret);
  208.         goto retry_mod_symbol_load;
  209.       case ENOENT:
  210.         continue;
  211.       default:
  212.         perror("ksyms: QM_SYMBOLS");
  213.         return 1;
  214.       }
  215.       nsymbols = ret;
  216.  
  217.       for (j = 0, s = syms; j < nsymbols; ++j, ++s)
  218.     print_symbol((char *)syms + s->name, s->value, m);
  219.     }
  220.  
  221.   /* Now do the kernel itself.  */
  222.  
  223.   if (flag_allsyms)
  224.     {
  225.     retry_kern_symbol_load:
  226.       if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret))
  227.     {
  228.       if (errno == ENOSPC)
  229.         {
  230.           syms = xrealloc(syms, bufsize = ret);
  231.           goto retry_kern_symbol_load;
  232.         }
  233.       perror("ksyms: QM_SYMBOLS");
  234.       return 1;
  235.     }
  236.       nsymbols = ret;
  237.  
  238.       for (j = 0, s = syms; j < nsymbols; ++j, ++s)
  239.     print_symbol((char *)syms + s->name, s->value, NULL); 
  240.     }
  241.  
  242.   free(modules);
  243.   free(syms);
  244.  
  245.   return 0;
  246. }
  247.  
  248.  
  249. /*======================================================================*/
  250.  
  251. int main(int argc, char **argv)
  252. {
  253.   int i;
  254.  
  255.   error_file = "ksyms";
  256.  
  257.   while ((i = getopt(argc, argv, "amhV")) != EOF)
  258.     switch (i)
  259.       {
  260.       case 'a':
  261.     flag_allsyms = 1;
  262.     break;
  263.       case 'm':
  264.     flag_mod_info = 1;
  265.     break;
  266.       case 'h':
  267.     flag_print_header = 0;
  268.     break;
  269.       case 'V':
  270.         fputs("ksyms version " MODUTILS_VERSION "\n", stderr);
  271.         break;
  272.       }
  273.  
  274.   if (flag_print_header)
  275.     printf("%-*s  %-32s  Defined by\n", (int)(2*sizeof(void*)),
  276.        "Address", "Symbol");
  277.  
  278.   if (query_module(NULL, 0, NULL, 0, NULL) == 0)
  279.     return new_ksyms();
  280.   else
  281.     return old_ksyms();
  282. }
  283.