diff options
Diffstat (limited to 'plugins/imklog/ksym_mod.c')
-rw-r--r-- | plugins/imklog/ksym_mod.c | 485 |
1 files changed, 0 insertions, 485 deletions
diff --git a/plugins/imklog/ksym_mod.c b/plugins/imklog/ksym_mod.c deleted file mode 100644 index 82978892..00000000 --- a/plugins/imklog/ksym_mod.c +++ /dev/null @@ -1,485 +0,0 @@ -/* ksym_mod.c - functions for building symbol lookup tables for klogd - * Copyright (c) 1995, 1996 Dr. G.W. Wettstein <greg@wind.rmcc.com> - * Copyright (c) 1996 Enjellic Systems Development - * Copyright (c) 1998-2007 Martin Schulze <joey@infodrom.org> - * Copyright (C) 2007-2009 Rainer Gerhards <rgerhards@adiscon.com> - * - * This file is part of rsyslog. - * - * Rsyslog 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 3 of the License, or - * (at your option) any later version. - * - * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>. - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. -*/ - -/* - * This file implements functions which are useful for building - * a symbol lookup table based on the in kernel symbol table - * maintained by the Linux kernel. - * - * Proper logging of kernel panics generated by loadable modules - * tends to be difficult. Since the modules are loaded dynamically - * their addresses are not known at kernel load time. A general - * protection fault (Oops) cannot be properly deciphered with - * classic methods using the static symbol map produced at link time. - * - * One solution to this problem is to have klogd attempt to translate - * addresses from module when the fault occurs. By referencing the - * the kernel symbol table proper resolution of these symbols is made - * possible. - * - * At least that is the plan. - * - * Wed Aug 21 09:20:09 CDT 1996: Dr. Wettstein - * The situation where no module support has been compiled into a - * kernel is now detected. An informative message is output indicating - * that the kernel has no loadable module support whenever kernel - * module symbols are loaded. - * - * An informative message is printed indicating the number of kernel - * modules and the number of symbols loaded from these modules. - * - * Sun Jun 15 16:23:29 MET DST 1997: Michael Alan Dorman - * Some more glibc patches made by <mdorman@debian.org>. - * - * Sat Jan 10 15:00:18 CET 1998: Martin Schulze <joey@infodrom.north.de> - * Fixed problem with klogd not being able to be built on a kernel - * newer than 2.1.18. It was caused by modified structures - * inside the kernel that were included. I have worked in a - * patch from Alessandro Suardi <asuardi@uninetcom.it>. - * - * Sun Jan 25 20:57:34 CET 1998: Martin Schulze <joey@infodrom.north.de> - * Another patch for Linux/alpha by Christopher C Chimelis - * <chris@classnet.med.miami.edu>. - * - * Thu Mar 19 23:39:29 CET 1998: Manuel Rodrigues <pmanuel@cindy.fe.up.pt> - * Changed lseek() to llseek() in order to support > 2GB address - * space which provided by kernels > 2.1.70. - * - * Mon Apr 13 18:18:45 CEST 1998: Martin Schulze <joey@infodrom.north.de> - * Removed <sys/module.h> as it's no longer part of recent glibc - * versions. Added prototyp for llseek() which has been - * forgotton in <unistd.h> from glibc. Added more log - * information if problems occurred while reading a system map - * file, by submission from Mark Simon Phillips <M.S.Phillips@nortel.co.uk>. - * - * Sun Jan 3 18:38:03 CET 1999: Martin Schulze <joey@infodrom.north.de> - * Corrected return value of AddModule if /dev/kmem can't be - * loaded. This will prevent klogd from segfaulting if /dev/kmem - * is not available. Patch from Topi Miettinen <tom@medialab.sonera.net>. - * - * Tue Sep 12 23:11:13 CEST 2000: Martin Schulze <joey@infodrom.ffis.de> - * Changed llseek() to lseek64() in order to skip a libc warning. - */ - -/* Includes. */ -#include "config.h" -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <unistd.h> -#include <signal.h> -#include <string.h> -#include <errno.h> -#include <sys/fcntl.h> -#include <sys/stat.h> -#if !defined(__GLIBC__) -#include <linux/time.h> -#include <linux/module.h> -#else /* __GLIBC__ */ -#include "module.h" -#endif /* __GLIBC__ */ -#include <stdarg.h> -#include <paths.h> -#include <linux/version.h> - -#include "rsyslog.h" -#include "imklog.h" -#include "ksyms.h" -#include "debug.h" - -#define KSYMS "/proc/kallsyms" - -static int num_modules = 0; -struct Module *sym_array_modules = (struct Module *) NULL; - -static int have_modules = 0; - - -/* Function prototypes. */ -static void FreeModules(void); -static int AddSymbol(const char *); -struct Module *AddModule(const char *); -static int symsort(const void *, const void *); - -/* Imported from ksym.c */ -extern int num_syms; - - -/************************************************************************** - * Function: InitMsyms - * - * Purpose: This function is responsible for building a symbol - * table which can be used to resolve addresses for - * loadable modules. - * - * Arguements: Void - * - * Return: A boolean return value is assumed. - * - * A false value indicates that something went wrong. - * - * True if loading is successful. - **************************************************************************/ -extern int InitMsyms(void) -{ - - auto int rtn, - tmp; - FILE *ksyms; - char buf[128]; - char *p; - - /* Initialize the kernel module symbol table. */ - FreeModules(); - - ksyms = fopen(KSYMS, "r"); - - if ( ksyms == NULL ) { - if ( errno == ENOENT ) - imklogLogIntMsg(LOG_INFO, "No module symbols loaded - " - "kernel modules not enabled.\n"); - else - imklogLogIntMsg(LOG_ERR, "Error loading kernel symbols " \ - "- %s\n", strerror(errno)); - return(0); - } - - dbgprintf("Loading kernel module symbols - Source: %s\n", KSYMS); - - while ( fgets(buf, sizeof(buf), ksyms) != NULL ) { - if (num_syms > 0 && index(buf, '[') == NULL) - continue; - - p = index(buf, ' '); - - if ( p == NULL ) - continue; - - if ( buf[strlen(buf)-1] == '\n' ) - buf[strlen(buf)-1] = '\0'; - /* overlong lines will be ignored above */ - - AddSymbol(buf); - } - - if(ksyms != NULL) - fclose(ksyms); - - have_modules = 1; - - /* Sort the symbol tables in each module. */ - for (rtn = tmp = 0; tmp < num_modules; ++tmp) { - rtn += sym_array_modules[tmp].num_syms; - if ( sym_array_modules[tmp].num_syms < 2 ) - continue; - qsort(sym_array_modules[tmp].sym_array, \ - sym_array_modules[tmp].num_syms, \ - sizeof(struct sym_table), symsort); - } - - if ( rtn == 0 ) - imklogLogIntMsg(LOG_INFO, "No module symbols loaded."); - else - imklogLogIntMsg(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \ - (rtn == 1) ? "symbol" : "symbols", \ - num_modules, (num_modules == 1) ? "." : "s."); - - return(1); -} - - -static int symsort(const void *p1, const void *p2) -{ - auto const struct sym_table *sym1 = p1, - *sym2 = p2; - - if ( sym1->value < sym2->value ) - return(-1); - if ( sym1->value == sym2->value ) - return(0); - return(1); -} - - -extern void DeinitMsyms(void) -{ - FreeModules(); -} - - -/************************************************************************** - * Function: FreeModules - * - * Purpose: This function is used to free all memory which has been - * allocated for the modules and their symbols. - * - * Arguements: None specified. - * - * Return: void - **************************************************************************/ -static void FreeModules() -{ - auto int nmods, - nsyms; - auto struct Module *mp; - - /* Check to see if the module symbol tables need to be cleared. */ - have_modules = 0; - if ( num_modules == 0 ) - return; - - if ( sym_array_modules == NULL ) - return; - - for (nmods = 0; nmods < num_modules; ++nmods) { - mp = &sym_array_modules[nmods]; - if ( mp->num_syms == 0 ) - continue; - - for (nsyms= 0; nsyms < mp->num_syms; ++nsyms) - free(mp->sym_array[nsyms].name); - free(mp->sym_array); - if ( mp->name != NULL ) - free(mp->name); - } - - free(sym_array_modules); - sym_array_modules = (struct Module *) NULL; - num_modules = 0; - return; -} - - -/************************************************************************** - * Function: AddModule - * - * Purpose: This function is responsible for adding a module to - * the list of currently loaded modules. - * - * Arguments: (const char *) module - * - * module:-> The name of the module. - * - * Return: struct Module * - **************************************************************************/ - -struct Module *AddModule(module) - const char *module; -{ - struct Module *mp; - - if ( num_modules == 0 ) { - sym_array_modules = (struct Module *)MALLOC(sizeof(struct Module)); - - if ( sym_array_modules == NULL ) - { - imklogLogIntMsg(LOG_WARNING, "Cannot allocate Module array.\n"); - return NULL; - } - mp = sym_array_modules; - } else { - /* Allocate space for the module. */ - mp = (struct Module *) \ - realloc(sym_array_modules, \ - (num_modules+1) * sizeof(struct Module)); - - if ( mp == NULL ) - { - imklogLogIntMsg(LOG_WARNING, "Cannot allocate Module array.\n"); - return NULL; - } - - sym_array_modules = mp; - mp = &sym_array_modules[num_modules]; - } - - num_modules++; - mp->sym_array = NULL; - mp->num_syms = 0; - - if ( module != NULL ) - mp->name = strdup(module); - else - mp->name = NULL; - - return mp; -} - - -/************************************************************************** - * Function: AddSymbol - * - * Purpose: This function is responsible for adding a symbol name - * and its address to the symbol table. - * - * Arguements: const char * - * - * Return: int - * - * A boolean value is assumed. True if the addition is - * successful. False if not. - **************************************************************************/ -static int AddSymbol(line) - const char *line; -{ - char *module; - unsigned long address; - char *p; - static char *lastmodule = NULL; - struct Module *mp; - - module = index(line, '['); - - if ( module != NULL ) { - p = index(module, ']'); - if ( p != NULL ) - *p = '\0'; - p = module++; - while ( isspace(*(--p)) ) - /*SKIP*/; - *(++p) = '\0'; - } - - p = index(line, ' '); - - if ( p == NULL ) - return(0); - - *p = '\0'; - - address = strtoul(line, (char **) 0, 16); - - p += 3; - - if ( num_modules == 0 || - ( lastmodule == NULL && module != NULL ) || - ( module == NULL && lastmodule != NULL) || - ( module != NULL && strcmp(module, lastmodule))) { - mp = AddModule(module); - - if ( mp == NULL ) - return(0); - } else - mp = &sym_array_modules[num_modules-1]; - - lastmodule = mp->name; - - /* Allocate space for the symbol table entry. */ - mp->sym_array = (struct sym_table *) realloc(mp->sym_array, \ - (mp->num_syms+1) * sizeof(struct sym_table)); - - if ( mp->sym_array == (struct sym_table *) NULL ) - return(0); - - mp->sym_array[mp->num_syms].name = strdup(p); - if ( mp->sym_array[mp->num_syms].name == (char *) NULL ) - return(0); - - /* Stuff interesting information into the module. */ - mp->sym_array[mp->num_syms].value = address; - ++mp->num_syms; - - return(1); -} - - - -/************************************************************************** - * Function: LookupModuleSymbol - * - * Purpose: Find the symbol which is related to the given address from - * a kernel module. - * - * Arguements: (long int) value, (struct symbol *) sym - * - * value:-> The address to be located. - * - * sym:-> A pointer to a structure which will be - * loaded with the symbol's parameters. - * - * Return: (char *) - * - * If a match cannot be found a diagnostic string is printed. - * If a match is found the pointer to the symbolic name most - * closely matching the address is returned. - * - * TODO: We are using int values for the offset, but longs for the value - * values. This may create some trouble in the future (on 64 Bit OS?). - * Anyhow, I have not changed this, because we do not seem to have any - * issue and my understanding of this code is limited (and I don't see - * need to invest more time to dig much deeper). - * rgerhards, 2009-04-17 - **************************************************************************/ -extern char * LookupModuleSymbol(value, sym) - unsigned long value; - struct symbol *sym; -{ - int nmod, nsym; - struct sym_table *last; - struct Module *mp; - static char ret[100]; - - sym->size = 0; - sym->offset = 0; - if ( num_modules == 0 ) - return((char *) 0); - - for (nmod = 0; nmod < num_modules; ++nmod) { - mp = &sym_array_modules[nmod]; - - /* Run through the list of symbols in this module and - * see if the address can be resolved. - */ - for(nsym = 1, last = &mp->sym_array[0]; - nsym < mp->num_syms; - ++nsym) { - if ( mp->sym_array[nsym].value > value ) - { - if ( sym->size == 0 || - (int) (value - last->value) < sym->offset || - ( (sym->offset == (int) (value - last->value)) && - (int) (mp->sym_array[nsym].value-last->value) < sym->size ) ) - { - sym->offset = value - last->value; - sym->size = mp->sym_array[nsym].value - last->value; - ret[sizeof(ret)-1] = '\0'; - if ( mp->name == NULL ) - snprintf(ret, sizeof(ret)-1, - "%s", last->name); - else - snprintf(ret, sizeof(ret)-1, - "%s:%s", mp->name, last->name); - } - break; - } - last = &mp->sym_array[nsym]; - } - } - - if ( sym->size > 0 ) - return(ret); - - /* It has been a hopeless exercise. */ - return(NULL); -} |