http://linuxfromscratch.org/pipermail/patches/2003-October/000432.html http://lists.infodrom.org/infodrom-sysklogd/2003/0024.html diff -Naur sysklogd-1.4.1-orig/ksym_mod.c sysklogd-1.4.1/ksym_mod.c --- sysklogd-1.4.1-orig/ksym_mod.c 2005-10-17 23:56:17.527192000 -0400 +++ sysklogd-1.4.1/ksym_mod.c 2005-10-18 00:07:36.817712908 -0400 @@ -128,6 +128,8 @@ #define getsyms get_kernel_syms #endif /* __GLIBC__ */ +extern int query_module(const char *, int, void *, size_t, size_t *); + /* Variables static to this module. */ struct sym_table { @@ -148,7 +150,7 @@ }; static int num_modules = 0; -struct Module *sym_array_modules = (struct Module *) 0; +struct Module *sym_array_modules = NULL; static int have_modules = 0; @@ -161,8 +163,8 @@ /* Function prototypes. */ static void FreeModules(void); -static int AddSymbol(struct Module *mp, unsigned long, char *); -static int AddModule(unsigned long, char *); +static int AddSymbol(struct Module *mp, unsigned long, const char *); +static int AddModule(char *); static int symsort(const void *, const void *); @@ -185,81 +187,107 @@ extern int InitMsyms() { - auto int rtn, - tmp; + auto size_t rtn; + auto int tmp; + + auto char **mod_table; + + char *modbuf = NULL, + *newbuf; - auto struct kernel_sym *ksym_table, - *p; + int modsize = 32, + result; /* Initialize the kernel module symbol table. */ FreeModules(); + /* + * New style symbol table parser. This uses the newer query_module + * function rather than the old obsolete hack of stepping thru + * /dev/kmem. + */ /* - * The system call which returns the kernel symbol table has - * essentialy two modes of operation. Called with a null pointer - * the system call returns the number of symbols defined in the - * the table. - * - * The second mode of operation is to pass a valid pointer to - * the call which will then load the current symbol table into - * the memory provided. - * - * Returning the symbol table is essentially an all or nothing - * proposition so we need to pre-allocate enough memory for the - * complete table regardless of how many symbols we need. - * - * Bummer. + * First, we query for the list of loaded modules. We may + * have to grow our buffer in size. */ - if ( (rtn = getsyms((struct kernel_sym *) 0)) < 0 ) - { - if ( errno == ENOSYS ) - Syslog(LOG_INFO, "No module symbols loaded - " - "kernel modules not enabled.\n"); - else + do { + modsize+=modsize; + newbuf=realloc(modbuf, modsize); + + if (newbuf==NULL) { + /* Well, that sucks. */ Syslog(LOG_ERR, "Error loading kernel symbols " \ "- %s\n", strerror(errno)); + if (modbuf!=NULL) free(modbuf); + return(0); + } + + modbuf=newbuf; + + result=query_module(NULL, QM_MODULES, modbuf, modsize, &rtn); + + if (result<0 && errno!=ENOSPC) { + if (errno != ENOSYS) + Syslog(LOG_ERR, "Error querying loaded modules " \ + "- %s\n", strerror(errno)); + free(modbuf); + return(0); + } + } while (result<0); + + if ( rtn <= 0 ) { + /* No modules??? */ + Syslog(LOG_INFO, "No module symbols loaded - " + "modules disabled?\n"); + free(modbuf); return(0); } if ( debugging ) fprintf(stderr, "Loading kernel module symbols - " "Size of table: %d\n", rtn); - ksym_table = (struct kernel_sym *) malloc(rtn * \ - sizeof(struct kernel_sym)); - if ( ksym_table == (struct kernel_sym *) 0 ) + mod_table = (char **) malloc(rtn * sizeof(char *)); + if ( mod_table == NULL ) { Syslog(LOG_WARNING, " Failed memory allocation for kernel " \ "symbol table.\n"); + free(modbuf); return(0); } - if ( (rtn = getsyms(ksym_table)) < 0 ) + + sym_array_modules = (struct Module *) malloc(rtn * sizeof(struct Module)); + if ( sym_array_modules == NULL ) { - Syslog(LOG_WARNING, "Error reading kernel symbols - %s\n", \ - strerror(errno)); + Syslog(LOG_WARNING, " Failed memory allocation for kernel " \ + "symbol table.\n"); + free(mod_table); + free(modbuf); return(0); } - /* * Build a symbol table compatible with the other one used by * klogd. */ - tmp = rtn; - p = ksym_table; - while ( tmp-- ) + newbuf=modbuf; + for (tmp=rtn-1; tmp>=0; tmp--) { - if ( !AddModule(p->value, p->name) ) + mod_table[tmp]=newbuf; + newbuf+=(strlen(newbuf)+1); + if ( !AddModule(mod_table[tmp]) ) { Syslog(LOG_WARNING, "Error adding kernel module table " "entry.\n"); - free(ksym_table); + free(mod_table); + free(modbuf); return(0); } - ++p; } + have_modules = 1; + /* Sort the symbol tables in each module. */ for (rtn = tmp= 0; tmp < num_modules; ++tmp) { @@ -277,7 +304,8 @@ Syslog(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \ (rtn == 1) ? "symbol" : "symbols", \ num_modules, (num_modules == 1) ? "." : "s."); - free(ksym_table); + free(mod_table); + free(modbuf); return(1); } @@ -322,23 +350,23 @@ /* Check to see if the module symbol tables need to be cleared. */ have_modules = 0; - if ( num_modules == 0 ) - return; - - for (nmods= 0; nmods < num_modules; ++nmods) - { - mp = &sym_array_modules[nmods]; - if ( mp->num_syms == 0 ) - continue; + if (sym_array_modules != NULL) { + 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); + for (nsyms= 0; nsyms < mp->num_syms; ++nsyms) + free(mp->sym_array[nsyms].name); + free(mp->sym_array); + } + + free(sym_array_modules); + sym_array_modules = NULL; } - free(sym_array_modules); - sym_array_modules = (struct Module *) 0; num_modules = 0; return; } @@ -350,23 +378,25 @@ * Purpose: This function is responsible for adding a module to * the list of currently loaded modules. * - * Arguements: (unsigned long) address, (char *) symbol - * - * address:-> The address of the module. + * Arguements: (char *) symbol * * symbol:-> The name of the module. * * Return: int **************************************************************************/ -static int AddModule(address, symbol) - - unsigned long address; +static int AddModule(symbol) char *symbol; { - auto int memfd; + size_t rtn; + size_t i; + const char *cbuf; + int symsize=128; + int result; + struct module_symbol *symbuf=NULL, + *newbuf; auto struct Module *mp; @@ -374,78 +404,75 @@ /* Return if we have loaded the modules. */ if ( have_modules ) return(1); + + /* We already have space for the module. */ + mp = &sym_array_modules[num_modules]; + + if (query_module(symbol, QM_INFO, &sym_array_modules[num_modules].module, + sizeof(struct module), &rtn)<0) + { + Syslog(LOG_WARNING, "Error reading module info for %s.\n", + symbol); + return(0); + } + + /* Save the module name. */ + mp->name = strdup(symbol); + if ( mp->name == NULL ) + return(0); + + mp->num_syms = 0; + mp->sym_array = NULL; + ++num_modules; /* - * The following section of code is responsible for determining - * whether or not we are done reading the list of modules. + * First, we query for the list of exported symbols. We may + * have to grow our buffer in size. */ - if ( symbol[0] == '#' ) - { + do { + symsize+=symsize; + newbuf=realloc(symbuf, symsize); - if ( symbol[1] == '\0' ) - { - /* - * A symbol which consists of a # sign only - * signifies a a resident kernel segment. When we - * hit one of these we are done reading the - * module list. - */ - have_modules = 1; - return(1); - } - /* Allocate space for the module. */ - sym_array_modules = (struct Module *) \ - realloc(sym_array_modules, \ - (num_modules+1) * sizeof(struct Module)); - if ( sym_array_modules == (struct Module *) 0 ) - { - Syslog(LOG_WARNING, "Cannot allocate Module array.\n"); + if (newbuf==NULL) { + /* Well, that sucks. */ + Syslog(LOG_ERR, "Error loading kernel symbols " \ + "- %s\n", strerror(errno)); + if (symbuf!=NULL) free(symbuf); return(0); } - mp = &sym_array_modules[num_modules]; - if ( (memfd = open("/dev/kmem", O_RDONLY)) < 0 ) - { - Syslog(LOG_WARNING, "Error opening /dev/kmem\n"); - return(0); - } - if ( lseek64(memfd, address, SEEK_SET) < 0 ) - { - Syslog(LOG_WARNING, "Error seeking in /dev/kmem\n"); - Syslog(LOG_WARNING, "Symbol %s, value %08x\n", symbol, address); - return(0); - } - if ( read(memfd, \ - (char *)&sym_array_modules[num_modules].module, \ - sizeof(struct module)) < 0 ) - { - Syslog(LOG_WARNING, "Error reading module " - "descriptor.\n"); - return(0); - } - close(memfd); + symbuf=newbuf; + + result=query_module(symbol, QM_SYMBOLS, symbuf, symsize, &rtn); - /* Save the module name. */ - mp->name = (char *) malloc(strlen(&symbol[1]) + 1); - if ( mp->name == (char *) 0 ) + if (result<0 && errno!=ENOSPC) { + Syslog(LOG_ERR, "Error querying symbol list for %s " \ + "- %s\n", symbol, strerror(errno)); + free(symbuf); return(0); - strcpy(mp->name, &symbol[1]); + } + } while (result<0); - mp->num_syms = 0; - mp->sym_array = (struct sym_table *) 0; - ++num_modules; - return(1); - } - else - { - if (num_modules > 0) - mp = &sym_array_modules[num_modules - 1]; - else - mp = &sym_array_modules[0]; - AddSymbol(mp, address, symbol); + if ( rtn < 0 ) { + /* No symbols??? */ + Syslog(LOG_INFO, "No module symbols loaded - unknown error.\n"); + free(symbuf); + return(0); } + cbuf=(char *)symbuf; + + for (i=0; i 0) + mp = &sym_array_modules[num_modules - 1]; + else + mp = &sym_array_modules[0]; + + AddSymbol(mp, symbuf[i].value, + cbuf+(unsigned long)(symbuf[i].name)); + } + free(symbuf); return(1); } @@ -477,7 +504,7 @@ unsigned long address; - char *symbol; + const char *symbol; { auto int tmp; diff -Naur sysklogd-1.4.1-orig/module.h sysklogd-1.4.1/module.h --- sysklogd-1.4.1-orig/module.h 2005-10-17 23:56:17.530192000 -0400 +++ sysklogd-1.4.1/module.h 2005-10-18 00:05:23.308858441 -0400 @@ -38,11 +38,24 @@ char name[MODULE_NAME_LEN]; }; +struct module_symbol +{ + unsigned long value; + const char *name; +}; struct list_head { struct list_head *next, *prev; }; +/* Values for query_module's which. */ + +#define QM_MODULES 1 +#define QM_DEPS 2 +#define QM_REFS 3 +#define QM_SYMBOLS 4 +#define QM_INFO 5 + struct module_info {