Patch by Kelledin to use the newer query_module function rather than
the old obsolete hack of stepping thru /dev/kmem.
This commit is contained in:
parent
b9c89af7a0
commit
a0304e96ac
274
ksym_mod.c
274
ksym_mod.c
@ -128,6 +128,8 @@ extern int getsyms(struct kernel_sym *);
|
|||||||
#define getsyms get_kernel_syms
|
#define getsyms get_kernel_syms
|
||||||
#endif /* __GLIBC__ */
|
#endif /* __GLIBC__ */
|
||||||
|
|
||||||
|
extern int query_module(const char *, int, void *, size_t, size_t *);
|
||||||
|
|
||||||
/* Variables static to this module. */
|
/* Variables static to this module. */
|
||||||
struct sym_table
|
struct sym_table
|
||||||
{
|
{
|
||||||
@ -148,7 +150,7 @@ struct Module
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int num_modules = 0;
|
static int num_modules = 0;
|
||||||
struct Module *sym_array_modules = (struct Module *) 0;
|
struct Module *sym_array_modules = NULL;
|
||||||
|
|
||||||
static int have_modules = 0;
|
static int have_modules = 0;
|
||||||
|
|
||||||
@ -161,8 +163,8 @@ extern int debugging;
|
|||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
static void FreeModules(void);
|
static void FreeModules(void);
|
||||||
static int AddSymbol(struct Module *mp, unsigned long, char *);
|
static int AddSymbol(struct Module *mp, unsigned long, const char *);
|
||||||
static int AddModule(unsigned long, char *);
|
static int AddModule(char *);
|
||||||
static int symsort(const void *, const void *);
|
static int symsort(const void *, const void *);
|
||||||
|
|
||||||
|
|
||||||
@ -185,81 +187,107 @@ static int symsort(const void *, const void *);
|
|||||||
extern int InitMsyms()
|
extern int InitMsyms()
|
||||||
|
|
||||||
{
|
{
|
||||||
auto int rtn,
|
auto size_t rtn;
|
||||||
tmp;
|
auto int tmp;
|
||||||
|
|
||||||
auto struct kernel_sym *ksym_table,
|
auto char **mod_table,
|
||||||
*p;
|
**p;
|
||||||
|
|
||||||
|
char *modbuf = NULL,
|
||||||
|
*newbuf;
|
||||||
|
|
||||||
|
int modsize = 32,
|
||||||
|
result;
|
||||||
|
|
||||||
|
|
||||||
/* Initialize the kernel module symbol table. */
|
/* Initialize the kernel module symbol table. */
|
||||||
FreeModules();
|
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
|
* First, we query for the list of loaded modules. We may
|
||||||
* essentialy two modes of operation. Called with a null pointer
|
* have to grow our buffer in size.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
if ( (rtn = getsyms((struct kernel_sym *) 0)) < 0 )
|
do {
|
||||||
{
|
modsize+=modsize;
|
||||||
if ( errno == ENOSYS )
|
newbuf=realloc(modbuf, modsize);
|
||||||
Syslog(LOG_INFO, "No module symbols loaded - "
|
|
||||||
"kernel modules not enabled.\n");
|
if (newbuf==NULL) {
|
||||||
else
|
/* Well, that sucks. */
|
||||||
Syslog(LOG_ERR, "Error loading kernel symbols " \
|
Syslog(LOG_ERR, "Error loading kernel symbols " \
|
||||||
"- %s\n", strerror(errno));
|
"- %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) {
|
||||||
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
if ( debugging )
|
if ( debugging )
|
||||||
fprintf(stderr, "Loading kernel module symbols - "
|
fprintf(stderr, "Loading kernel module symbols - "
|
||||||
"Size of table: %d\n", rtn);
|
"Size of table: %d\n", rtn);
|
||||||
|
|
||||||
ksym_table = (struct kernel_sym *) malloc(rtn * \
|
mod_table = (char **) malloc(rtn * sizeof(char *));
|
||||||
sizeof(struct kernel_sym));
|
if ( mod_table == NULL )
|
||||||
if ( ksym_table == (struct kernel_sym *) 0 )
|
|
||||||
{
|
{
|
||||||
Syslog(LOG_WARNING, " Failed memory allocation for kernel " \
|
Syslog(LOG_WARNING, " Failed memory allocation for kernel " \
|
||||||
"symbol table.\n");
|
"symbol table.\n");
|
||||||
return(0);
|
free(modbuf);
|
||||||
}
|
|
||||||
if ( (rtn = getsyms(ksym_table)) < 0 )
|
|
||||||
{
|
|
||||||
Syslog(LOG_WARNING, "Error reading kernel symbols - %s\n", \
|
|
||||||
strerror(errno));
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sym_array_modules = (struct Module *) malloc(rtn * sizeof(struct Module));
|
||||||
|
if ( sym_array_modules == NULL )
|
||||||
|
{
|
||||||
|
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
|
* Build a symbol table compatible with the other one used by
|
||||||
* klogd.
|
* klogd.
|
||||||
*/
|
*/
|
||||||
tmp = rtn;
|
newbuf=modbuf;
|
||||||
p = ksym_table;
|
for (tmp=rtn-1; tmp>=0; tmp--)
|
||||||
while ( 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 "
|
Syslog(LOG_WARNING, "Error adding kernel module table "
|
||||||
"entry.\n");
|
"entry.\n");
|
||||||
free(ksym_table);
|
free(mod_table);
|
||||||
|
free(modbuf);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
++p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
have_modules = 1;
|
||||||
|
|
||||||
/* Sort the symbol tables in each module. */
|
/* Sort the symbol tables in each module. */
|
||||||
for (rtn = tmp= 0; tmp < num_modules; ++tmp)
|
for (rtn = tmp= 0; tmp < num_modules; ++tmp)
|
||||||
{
|
{
|
||||||
@ -277,7 +305,8 @@ extern int InitMsyms()
|
|||||||
Syslog(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \
|
Syslog(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \
|
||||||
(rtn == 1) ? "symbol" : "symbols", \
|
(rtn == 1) ? "symbol" : "symbols", \
|
||||||
num_modules, (num_modules == 1) ? "." : "s.");
|
num_modules, (num_modules == 1) ? "." : "s.");
|
||||||
free(ksym_table);
|
free(mod_table);
|
||||||
|
free(modbuf);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,23 +351,23 @@ static void FreeModules()
|
|||||||
|
|
||||||
/* Check to see if the module symbol tables need to be cleared. */
|
/* Check to see if the module symbol tables need to be cleared. */
|
||||||
have_modules = 0;
|
have_modules = 0;
|
||||||
if ( num_modules == 0 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
if (sym_array_modules != NULL) {
|
||||||
|
for (nmods= 0; nmods < num_modules; ++nmods)
|
||||||
|
{
|
||||||
|
mp = &sym_array_modules[nmods];
|
||||||
|
if ( mp->num_syms == 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
for (nmods= 0; nmods < num_modules; ++nmods)
|
for (nsyms= 0; nsyms < mp->num_syms; ++nsyms)
|
||||||
{
|
free(mp->sym_array[nsyms].name);
|
||||||
mp = &sym_array_modules[nmods];
|
free(mp->sym_array);
|
||||||
if ( mp->num_syms == 0 )
|
}
|
||||||
continue;
|
|
||||||
|
|
||||||
for (nsyms= 0; nsyms < mp->num_syms; ++nsyms)
|
free(sym_array_modules);
|
||||||
free(mp->sym_array[nsyms].name);
|
sym_array_modules = NULL;
|
||||||
free(mp->sym_array);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(sym_array_modules);
|
|
||||||
sym_array_modules = (struct Module *) 0;
|
|
||||||
num_modules = 0;
|
num_modules = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -350,23 +379,25 @@ static void FreeModules()
|
|||||||
* Purpose: This function is responsible for adding a module to
|
* Purpose: This function is responsible for adding a module to
|
||||||
* the list of currently loaded modules.
|
* the list of currently loaded modules.
|
||||||
*
|
*
|
||||||
* Arguements: (unsigned long) address, (char *) symbol
|
* Arguements: (char *) symbol
|
||||||
*
|
|
||||||
* address:-> The address of the module.
|
|
||||||
*
|
*
|
||||||
* symbol:-> The name of the module.
|
* symbol:-> The name of the module.
|
||||||
*
|
*
|
||||||
* Return: int
|
* Return: int
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
static int AddModule(address, symbol)
|
static int AddModule(symbol)
|
||||||
|
|
||||||
unsigned long address;
|
|
||||||
|
|
||||||
char *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;
|
auto struct Module *mp;
|
||||||
|
|
||||||
@ -375,77 +406,74 @@ static int AddModule(address, symbol)
|
|||||||
if ( have_modules )
|
if ( have_modules )
|
||||||
return(1);
|
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
|
* First, we query for the list of exported symbols. We may
|
||||||
* whether or not we are done reading the list of modules.
|
* have to grow our buffer in size.
|
||||||
*/
|
*/
|
||||||
if ( symbol[0] == '#' )
|
do {
|
||||||
{
|
symsize+=symsize;
|
||||||
|
newbuf=realloc(symbuf, symsize);
|
||||||
|
|
||||||
if ( symbol[1] == '\0' )
|
if (newbuf==NULL) {
|
||||||
{
|
/* Well, that sucks. */
|
||||||
/*
|
Syslog(LOG_ERR, "Error loading kernel symbols " \
|
||||||
* A symbol which consists of a # sign only
|
"- %s\n", strerror(errno));
|
||||||
* signifies a a resident kernel segment. When we
|
if (symbuf!=NULL) free(symbuf);
|
||||||
* 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");
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
mp = &sym_array_modules[num_modules];
|
|
||||||
|
|
||||||
if ( (memfd = open("/dev/kmem", O_RDONLY)) < 0 )
|
symbuf=newbuf;
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* Save the module name. */
|
result=query_module(symbol, QM_SYMBOLS, symbuf, symsize, &rtn);
|
||||||
mp->name = (char *) malloc(strlen(&symbol[1]) + 1);
|
|
||||||
if ( mp->name == (char *) 0 )
|
|
||||||
return(0);
|
|
||||||
strcpy(mp->name, &symbol[1]);
|
|
||||||
|
|
||||||
mp->num_syms = 0;
|
if (result<0 && errno!=ENOSPC) {
|
||||||
mp->sym_array = (struct sym_table *) 0;
|
Syslog(LOG_ERR, "Error querying symbol list for %s " \
|
||||||
++num_modules;
|
"- %s\n", symbol, strerror(errno));
|
||||||
return(1);
|
free(symbuf);
|
||||||
}
|
return(0);
|
||||||
else
|
}
|
||||||
{
|
} while (result<0);
|
||||||
if (num_modules > 0)
|
|
||||||
mp = &sym_array_modules[num_modules - 1];
|
if ( rtn < 0 ) {
|
||||||
else
|
/* No symbols??? */
|
||||||
mp = &sym_array_modules[0];
|
Syslog(LOG_INFO, "No module symbols loaded - unknown error.\n");
|
||||||
AddSymbol(mp, address, symbol);
|
free(symbuf);
|
||||||
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cbuf=(char *)symbuf;
|
||||||
|
|
||||||
|
for (i=0; i<rtn; i++) {
|
||||||
|
if (num_modules > 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);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,7 +505,7 @@ static int AddSymbol(mp, address, symbol)
|
|||||||
|
|
||||||
unsigned long address;
|
unsigned long address;
|
||||||
|
|
||||||
char *symbol;
|
const char *symbol;
|
||||||
|
|
||||||
{
|
{
|
||||||
auto int tmp;
|
auto int tmp;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user