📄 ksym.c
字号:
/* * We should now have the version string in the vstring variable in * the same format that it is stored in by the kernel. We now * ask the kernel for its version information and compare the two * values to determine if our system map matches the kernel * version level. */ if ( uname(&utsname) < 0 ) { Syslog(LOG_ERR, "Cannot get kernel version information."); return(0); } if ( debugging ) fprintf(stderr, "Comparing kernel %s with symbol table %s.\n",\ utsname.release, vstring); if ( sscanf (utsname.release, "%d.%d.%d", &major, &minor, &patch) < 3 ) { Syslog(LOG_ERR, "Kernel send bogus release string `%s'.", utsname.release); return(0); } /* Compute the version code from data sent by the kernel */ kvnum = (major << 16) | (minor << 8) | patch; /* Failure. */ if ( vnum != kvnum ) return(-1); /* Success. */#endif return(1);}/************************************************************************** * Function: CheckMapVersion * * Purpose: This function is responsible for determining whether or * the system map being loaded matches the version of the * currently running kernel. It uses CheckVersion as * backend. * * Arguements: (char *) fname * * fname:-> A pointer to the string which * references the system map file to * be used. * * Return: int * * -1:-> The currently running kernel version does * not match the version in the given file. * * 0:-> No system map file or no version information. * * 1:-> The executing kernel is of the same version * as the version of the map file. **************************************************************************/static int CheckMapVersion(fname) char *fname; { int version; FILE *sym_file; auto unsigned long int address; auto char type, sym[512]; if ( (sym_file = fopen(fname, "r")) != (FILE *) 0 ) { /* * At this point a map file was successfully opened. We * now need to search this file and look for version * information. */ Syslog(LOG_INFO, "Inspecting %s", fname); version = 0; while ( !feof(sym_file) && (version == 0) ) { if ( fscanf(sym_file, "%lx %c %s\n", &address, \ &type, sym) != 3 ) { Syslog(LOG_ERR, "Error in symbol table input (#2)."); fclose(sym_file); return(0); } if ( VERBOSE_DEBUGGING && debugging ) fprintf(stderr, "Address: %lx, Type: %c, " \ "Symbol: %s\n", address, type, sym); version = CheckVersion(sym); } fclose(sym_file); switch ( version ) { case -1: Syslog(LOG_ERR, "Symbol table has incorrect " \ "version number.\n"); break; case 0: if ( debugging ) fprintf(stderr, "No version information " \ "found.\n"); break; case 1: if ( debugging ) fprintf(stderr, "Found table with " \ "matching version number.\n"); break; } return(version); } return(0);} /************************************************************************** * Function: AddSymbol * * Purpose: This function is responsible for adding a symbol name * and its address to the symbol table. * * Arguements: (unsigned long) address, (char *) symbol * * Return: int * * A boolean value is assumed. True if the addition is * successful. False if not. **************************************************************************/static int AddSymbol(address, symbol) unsigned long address; char *symbol; { /* Allocate the the symbol table entry. */ sym_array = (struct sym_table *) realloc(sym_array, (num_syms+1) * \ sizeof(struct sym_table)); if ( sym_array == (struct sym_table *) 0 ) return(0); /* Then the space for the symbol. */ sym_array[num_syms].name = (char *) malloc(strlen(symbol)*sizeof(char)\ + 1); if ( sym_array[num_syms].name == (char *) 0 ) return(0); sym_array[num_syms].value = address; strcpy(sym_array[num_syms].name, symbol); ++num_syms; return(1);}/************************************************************************** * Function: LookupSymbol * * Purpose: Find the symbol which is related to the given kernel * address. * * 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. **************************************************************************/char * LookupSymbol(value, sym) unsigned long value; struct symbol *sym; { auto int lp; auto char *last; if (!sym_array) return((char *) 0); last = sym_array[0].name; sym->offset = 0; sym->size = 0; if ( value < sym_array[0].value ) return((char *) 0); for(lp= 0; lp <= num_syms; ++lp) { if ( sym_array[lp].value > value ) { sym->offset = value - sym_array[lp-1].value; sym->size = sym_array[lp].value - \ sym_array[lp-1].value; return(last); } last = sym_array[lp].name; } if ( (last = LookupModuleSymbol(value, sym)) != (char *) 0 ) return(last); return((char *) 0);}/************************************************************************** * Function: FreeSymbols * * Purpose: This function is responsible for freeing all memory which * has been allocated to hold the static symbol table. It * also initializes the symbol count and in general prepares * for a re-read of a static symbol table. * * Arguements: void * * Return: void **************************************************************************/static void FreeSymbols(){ auto int lp; /* Free each piece of memory allocated for symbol names. */ for(lp= 0; lp < num_syms; ++lp) free(sym_array[lp].name); /* Whack the entire array and initialize everything. */ free(sym_array); sym_array = (struct sym_table *) 0; num_syms = 0; return;}/************************************************************************** * Function: LogExpanded * * Purpose: This function is responsible for logging a kernel message * line after all potential numeric kernel addresses have * been resolved symolically. * * Arguements: (char *) line, (char *) el * * line:-> A pointer to the buffer containing the kernel * message to be expanded and logged. * * el:-> A pointer to the buffer into which the expanded * kernel line will be written. * * Return: void **************************************************************************/extern char * ExpandKadds(line, el) char *line; char *el; { auto char dlm, *kp, *sl = line, *elp = el, *symbol; char num[15]; auto unsigned long int value; auto struct symbol sym; /* * This is as handy a place to put this as anyplace. * * Since the insertion of kernel modules can occur in a somewhat * dynamic fashion we need some mechanism to insure that the * kernel symbol tables get read just prior to when they are * needed. * * To accomplish this we look for the Oops string and use its * presence as a signal to load the module symbols. * * This is not the best solution of course, especially if the * kernel is rapidly going out to lunch. What really needs to * be done is to somehow generate a callback from the * kernel whenever a module is loaded or unloaded. I am * open for patches. */ if ( i_am_paranoid && (strstr(line, "Oops:") != (char *) 0) && !InitMsyms() ) Syslog(LOG_WARNING, "Cannot load kernel module symbols.\n"); /* * Early return if there do not appear to be any kernel * messages in this line. */ if ( (num_syms == 0) || (kp = strstr(line, "[<")) == (char *) 0 ) { strcpy(el, line); return(el); } /* Loop through and expand all kernel messages. */ do { while ( sl < kp+1 ) *elp++ = *sl++; /* Now poised at a kernel delimiter. */ if ( (kp = strstr(sl, ">]")) == (char *) 0 ) { strcpy(el, sl); return(el); } dlm = *kp; strncpy(num,sl+1,kp-sl-1); num[kp-sl-1] = '\0'; value = strtoul(num, (char **) 0, 16); if ( (symbol = LookupSymbol(value, &sym)) == (char *) 0 ) symbol = sl; strcat(elp, symbol); elp += strlen(symbol); if ( debugging ) fprintf(stderr, "Symbol: %s = %lx = %s, %x/%d\n", \ sl+1, value, \ (sym.size==0) ? symbol+1 : symbol, \ sym.offset, sym.size); value = 2; if ( sym.size != 0 ) { --value; ++kp; elp += sprintf(elp, "+%x/%d", sym.offset, sym.size); } strncat(elp, kp, value); elp += value; sl = kp + value; if ( (kp = strstr(sl, "[<")) == (char *) 0 ) strcat(elp, sl); } while ( kp != (char *) 0); if ( debugging ) fprintf(stderr, "Expanded line: %s\n", el); return(el);}/************************************************************************** * Function: SetParanoiaLevel * * Purpose: This function is an interface function for setting the * mode of loadable module symbol lookups. Probably overkill * but it does slay another global variable. * * Arguements: (int) level * * level:-> The amount of paranoia which is to be * present when resolving kernel exceptions. * Return: void **************************************************************************/extern void SetParanoiaLevel(level) int level;{ i_am_paranoid = level; return;}/* * Setting the -DTEST define enables the following code fragment to * be compiled. This produces a small standalone program which will * echo the standard input of the process to stdout while translating * all numeric kernel addresses into their symbolic equivalent. */#if defined(TEST)#include <stdarg.h>extern int main(int, char **);extern int main(int argc, char *argv[]){ auto char line[1024], eline[2048]; debugging = 1; if ( !InitKsyms((char *) 0) ) { fputs("ksym: Error loading system map.\n", stderr); return(1); } while ( !feof(stdin) ) { fgets(line, sizeof(line), stdin); if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0'; /* Trash NL char */ memset(eline, '\0', sizeof(eline)); ExpandKadds(line, eline); fprintf(stdout, "%s\n", eline); } 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 + -