home *** CD-ROM | disk | FTP | other *** search
- /* Display the symbols exported from the running kernel.
- Copyright 1996, 1997 Linux International.
-
- New implementation contributed by Richard Henderson <rth@tamu.edu>
- Based on original work by Bjorn Eckwall <bj0rn@blox.se>
-
- This file is part of the Linux modutils.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
- #ident "$Id: ksyms.c,v 1.1.1.1 1998/01/06 20:51:07 ewt Exp $"
-
- #include <sys/types.h>
- #include <stdio.h>
- #include <errno.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "module.h"
- #include "util.h"
- #include "version.h"
-
- #include "logger.h"
-
-
- /*======================================================================*/
-
- int flag_allsyms = 0;
- int flag_mod_info = 0;
- int flag_print_header = 1;
-
-
- /*======================================================================*/
-
- static inline void
- print_symbol(const char *name, unsigned long value, const char *module)
- {
- if (module)
- printf("%0*lx %-32s [%s]\n", (int)(2*sizeof(void*)),
- value, name, module);
- else
- printf("%0*lx %-32s\n", (int)(2*sizeof(void*)), value, name);
- }
-
- static inline void
- print_mod_info(const char *module, unsigned long addr, unsigned long size)
- {
- int o;
-
- o = printf("%0*lx (%luk)", (int)(2*sizeof(void*)), addr,
- (size / 1024) + ((size % 1024) != 0));
-
- o = 2*sizeof(void*)+2+32+2 - o;
-
- printf("%*s[%s]\n", o, "", module);
- }
-
-
- /* If we don't have query_module()... */
-
- static int
- old_ksyms(void)
- {
- struct old_kernel_sym *ksyms, *k;
- int nsyms, i;
- int kmem_fd = -1;
- const char *module;
-
- nsyms = get_kernel_syms(NULL);
- if (nsyms < 0)
- {
- perror("get_kernel_syms");
- return 1;
- }
-
- ksyms = xmalloc(nsyms * sizeof(*ksyms));
-
- if (get_kernel_syms(ksyms) != nsyms)
- {
- fprintf(stderr, "Inconsistency reading kernel symbols -- "
- "is someone else playing with modules?\n");
- return 1;
- }
-
- /* If requested, open kmem so we can get at module information. */
-
- if (flag_mod_info)
- {
- kmem_fd = open("/dev/kmem", O_RDONLY);
- if (kmem_fd < 0)
- {
- perror("ksyms: open /dev/kmem");
- return 1;
- }
- }
-
- module = NULL;
- for (k = ksyms, i = 0; i < nsyms; ++i, ++k)
- if (k->name[0] == '#')
- {
- if (k->name[1])
- {
- module = &k->name[1];
- if (flag_mod_info)
- {
- struct old_module info;
-
- if (llseek(kmem_fd, (off_t)k->value, SEEK_SET) == -1
- || read(kmem_fd, &info, sizeof(info)) != sizeof(info))
- {
- perror("ksyms: /dev/kmem");
- return 1;
- }
- print_mod_info(module, info.addr, info.size * getpagesize());
- }
- }
- else
- {
- if (!flag_allsyms)
- break;
- module = NULL;
- }
- }
- else
- print_symbol(k->name, k->value, module);
-
- free(ksyms);
- if (flag_mod_info)
- close(kmem_fd);
-
- return 0;
- }
-
-
- /* If we do have query_module()... */
-
- static int
- new_ksyms(void)
- {
- char *modules;
- size_t nmodules;
- struct new_module_symbol *syms;
- size_t nsymbols;
-
- ssize_t ret;
- size_t bufsize;
- size_t i, j;
- char *m;
- struct new_module_symbol *s;
-
- /* Query for the module names. */
-
- modules = xmalloc(bufsize = 256);
- retry_modules_load:
- if (query_module(NULL, QM_MODULES, modules, bufsize, &ret))
- {
- if (errno == ENOSPC)
- {
- modules = xrealloc(modules, bufsize = ret);
- goto retry_modules_load;
- }
- perror("ksyms: QM_MODULES");
- return 1;
- }
- nmodules = ret;
-
- /* Iterate over the modules, in order, and care for their symbols. */
-
- syms = xmalloc(bufsize = 16*1024);
- for (i = 0, m = modules; i < nmodules; ++i, m += strlen(m)+1)
- {
- if (flag_mod_info)
- {
- struct new_module_info info;
- if (query_module(m, QM_INFO, &info, sizeof(info), &ret))
- {
- if (errno == ENOENT)
- {
- /* The module must have been removed in the interim: skip */
- continue;
- }
- perror("ksyms: QM_INFO");
- return 1;
- }
- print_mod_info(m, info.addr, info.size);
- }
-
- retry_mod_symbol_load:
- if (query_module(m, QM_SYMBOLS, syms, bufsize, &ret))
- switch (errno)
- {
- case ENOSPC:
- syms = xrealloc(syms, bufsize = ret);
- goto retry_mod_symbol_load;
- case ENOENT:
- continue;
- default:
- perror("ksyms: QM_SYMBOLS");
- return 1;
- }
- nsymbols = ret;
-
- for (j = 0, s = syms; j < nsymbols; ++j, ++s)
- print_symbol((char *)syms + s->name, s->value, m);
- }
-
- /* Now do the kernel itself. */
-
- if (flag_allsyms)
- {
- retry_kern_symbol_load:
- if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret))
- {
- if (errno == ENOSPC)
- {
- syms = xrealloc(syms, bufsize = ret);
- goto retry_kern_symbol_load;
- }
- perror("ksyms: QM_SYMBOLS");
- return 1;
- }
- nsymbols = ret;
-
- for (j = 0, s = syms; j < nsymbols; ++j, ++s)
- print_symbol((char *)syms + s->name, s->value, NULL);
- }
-
- free(modules);
- free(syms);
-
- return 0;
- }
-
-
- /*======================================================================*/
-
- int main(int argc, char **argv)
- {
- int i;
-
- error_file = "ksyms";
-
- while ((i = getopt(argc, argv, "amhV")) != EOF)
- switch (i)
- {
- case 'a':
- flag_allsyms = 1;
- break;
- case 'm':
- flag_mod_info = 1;
- break;
- case 'h':
- flag_print_header = 0;
- break;
- case 'V':
- fputs("ksyms version " MODUTILS_VERSION "\n", stderr);
- break;
- }
-
- if (flag_print_header)
- printf("%-*s %-32s Defined by\n", (int)(2*sizeof(void*)),
- "Address", "Symbol");
-
- if (query_module(NULL, 0, NULL, 0, NULL) == 0)
- return new_ksyms();
- else
- return old_ksyms();
- }
-