📄 ksym_mod.c
字号:
* * Return: int **************************************************************************/static int AddModule(address, symbol) unsigned long address; char *symbol;{ auto int memfd; auto struct Module *mp; /* Return if we have loaded the modules. */ if ( have_modules ) return(1); /* * The following section of code is responsible for determining * whether or not we are done reading the list of modules. */ if ( symbol[0] == '#' ) { 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"); 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); /* Save the module name. */ mp->name = (char *) malloc(strlen(&symbol[1]) + 1); if ( mp->name == (char *) 0 ) return(0); strcpy(mp->name, &symbol[1]); 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); } return(1);}/************************************************************************** * Function: AddSymbol * * Purpose: This function is responsible for adding a symbol name * and its address to the symbol table. * * Arguements: (struct Module *) mp, (unsigned long) address, (char *) symbol * * mp:-> A pointer to the module which the symbol is * to be added to. * * address:-> The address of the symbol. * * symbol:-> The name of the symbol. * * Return: int * * A boolean value is assumed. True if the addition is * successful. False if not. **************************************************************************/static int AddSymbol(mp, address, symbol) struct Module *mp; unsigned long address; char *symbol; { auto int tmp; /* 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 *) 0 ) return(0); /* Then the space for the symbol. */ tmp = strlen(symbol); tmp += (strlen(mp->name) + 1); mp->sym_array[mp->num_syms].name = (char *) malloc(tmp + 1); if ( mp->sym_array[mp->num_syms].name == (char *) 0 ) return(0); memset(mp->sym_array[mp->num_syms].name, '\0', tmp + 1); /* Stuff interesting information into the module. */ mp->sym_array[mp->num_syms].value = address; strcpy(mp->sym_array[mp->num_syms].name, mp->name); strcat(mp->sym_array[mp->num_syms].name, ":"); strcat(mp->sym_array[mp->num_syms].name, symbol); ++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. **************************************************************************/extern char * LookupModuleSymbol(value, sym) unsigned long value; struct symbol *sym; { auto int nmod, nsym; auto struct sym_table *last; auto struct Module *mp; 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 ) { sym->offset = value - last->value; sym->size = mp->sym_array[nsym].value - \ last->value; return(last->name); } last = &mp->sym_array[nsym]; } /* * At this stage of the game we still cannot give up the * ghost. There is the possibility that the address is * from a module which has no symbols registered with * the kernel. The solution is to compare the address * against the starting address and extant of the module * If it is in this range we can at least return the * name of the module. */#if LINUX_VERSION_CODE < 0x20112 if ( (void *) value >= mp->module.addr && (void *) value <= (mp->module.addr + \ mp->module.size * 4096) )#else if ( value >= mp->module_info.addr && value <= (mp->module_info.addr + \ mp->module.size * 4096) )#endif { /* * A special case needs to be checked for. The above * conditional tells us that we are within the * extant of this module but symbol lookup has * failed. * * We need to check to see if any symbols have * been defined in this module. If there have been * symbols defined the assumption must be made that * the faulting address lies somewhere beyond the * last symbol. About the only thing we can do * at this point is use an offset from this * symbol. */ if ( mp->num_syms > 0 ) { last = &mp->sym_array[mp->num_syms - 1];#if LINUX_VERSION_CODE < 0x20112 sym->size = (int) mp->module.addr + \ (mp->module.size * 4096) - value;#else sym->size = (int) mp->module_info.addr + \ (mp->module.size * 4096) - value;#endif sym->offset = value - last->value; return(last->name); } /* * There were no symbols defined for this module. * Return the module name and the offset of the * faulting address in the module. */ sym->size = mp->module.size * 4096;#if LINUX_VERSION_CODE < 0x20112 sym->offset = (void *) value - mp->module.addr;#else sym->offset = value - mp->module_info.addr;#endif return(mp->name); } } /* It has been a hopeless exercise. */ return((char *) 0);}/* * Setting the -DTEST define enables the following code fragment to * be compiled. This produces a small standalone program which will * dump the current kernel symbol table. */#if defined(TEST)#include <stdarg.h>extern int main(int, char **);int main(argc, argv) int argc; char *argv[];{ auto int lp, syms; if ( !InitMsyms() ) { fprintf(stderr, "Cannot load module symbols.\n"); return(1); } printf("Number of modules: %d\n\n", num_modules); for(lp= 0; lp < num_modules; ++lp) { printf("Module #%d = %s, Number of symbols = %d\n", lp + 1, \ sym_array_modules[lp].name, \ sym_array_modules[lp].num_syms); for (syms= 0; syms < sym_array_modules[lp].num_syms; ++syms) { printf("\tSymbol #%d\n", syms + 1); printf("\tName: %s\n", \ sym_array_modules[lp].sym_array[syms].name); printf("\tAddress: %lx\n\n", \ sym_array_modules[lp].sym_array[syms].value); } } FreeModules(); return(0);}extern void Syslog(int priority, char *fmt, ...){ va_list ap; va_start(ap, fmt); fprintf(stdout, "Pr: %d, ", priority); vfprintf(stdout, fmt, ap); va_end(ap); fputc('\n', stdout); return;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -