?? ksym.c
字號:
/* * Copyright 1998-2003 by Albert Cahalan; all rights reserved. * This file may be used subject to the terms and conditions of the * GNU Library General Public License Version 2, or any later version * at your option, as published by the Free Software Foundation. * This program 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 Library General Public License for more details. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <stdarg.h>#include <fcntl.h>#include <errno.h>#include <unistd.h>#include <sys/stat.h>#include <sys/mman.h>#include <sys/utsname.h>#include "procps.h"#include "version.h"#include "sysinfo.h" /* smp_num_cpus */#include "wchan.h" // to verify prototypes#define KSYMS_FILENAME "/proc/ksyms"#if 0#undef KSYMS_FILENAME#define KSYMS_FILENAME "/would/be/nice/to/have/this/file"#define SYSMAP_FILENAME "/home/albert/ps/45621/System.map-hacked"#define linux_version_code 131598 /* ? */#define smp_num_cpus 2#endif#if 0#undef KSYMS_FILENAME#define KSYMS_FILENAME "/home/albert/ps/45621/ksyms-2.3.12"#define SYSMAP_FILENAME "/home/albert/ps/45621/System.map-2.3.12"#define linux_version_code 131852 /* 2.3.12 */#define smp_num_cpus 2#endif#if 0#undef KSYMS_FILENAME#define KSYMS_FILENAME "/home/albert/ps/45621/ksyms-2.3.18ac8-MODVERS"#define SYSMAP_FILENAME "/home/albert/ps/45621/System.map-2.3.18ac8-MODVERS"#define linux_version_code 131858 /* 2.3.18ac8 */#define smp_num_cpus 2#endif#if 0#undef KSYMS_FILENAME#define KSYMS_FILENAME "/home/albert/ps/45621/ksyms-2.3.18ac8-NOMODVERS"#define SYSMAP_FILENAME "/home/albert/ps/45621/System.map-2.3.18ac8-NOMODVERS"#define linux_version_code 131858 /* 2.3.18ac8 */#define smp_num_cpus 2#endif/* These are the symbol types, with relative popularity: * ? w machine type junk for Alpha -- odd syntax * ? S not for i386 * 4 W not for i386 * 60 R * 100 A * 125 r * 363 s not for i386 * 858 B * 905 g generated by modutils? * 929 G generated by modutils? * 1301 b * 2750 D * 4481 d * 11417 ? * 13666 t * 15442 T * * For i386, that is: "RArBbDd?tT" */#define SYMBOL_TYPE_CHARS "Tt?dDbBrARGgsWS"/* * '?' is a symbol type * '.' is part of a name (versioning?) * "\t[]" are for the module name in /proc/ksyms */#define LEGAL_SYSMAP_CHARS "0123456789_ ?.\n\t[]" \ "abcdefghijklmnopqrstuvwxyz" \ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"/* System.map lines look like: * hex num, space, one of SYMBOL_TYPE_CHARS, space, LEGAL_SYSMAP_CHARS, \n * * Alpha systems can start with a few lines that have the address replaced * by space padding and a 'w' for the type. For those lines, the last space * is followed by something like: mikasa_primo_mv p2k_mv sable_gamma_mv * (just one of those, always with a "_mv", then the newline) * * The /proc/ksyms lines are like System.map lines w/o the symbol type char. * When odd features are used, the name part contains: * "(.*)_R(smp_|smp2gig_|2gig_)?[0-9a-fA-F]{8,}" * It is likely that more crap will be added... */typedef struct symb { unsigned KLONG addr; const char *name;} symb;/* These mostly rely on POSIX to make them zero. */static symb hashtable[256];static char *sysmap_data;static unsigned sysmap_room;static symb *sysmap_index;static unsigned sysmap_count;static char *ksyms_data;static unsigned ksyms_room = 4096;static symb *ksyms_index;static unsigned ksyms_count;static unsigned idx_room;/*********************************//* Kill this: _R(smp_?|smp2gig_?|2gig_?)?[0-9a-f]{8,}$ * We kill: (_R[^A-Z]*[0-9a-f]{8,})+$ * * The loop should almost never be taken, but it has to be there. * It gets rid of anything that _looks_ like a version code, even * if a real version code has already been found. This is because * the inability to perfectly recognize a version code may lead to * symbol mangling, which in turn leads to mismatches between the * /proc/ksyms and System.map data files. */#if 0static char *chop_version(char *arg){ char *cp; cp = strchr(arg,'\t'); if(cp) *cp = '\0'; /* kill trailing module name first */ for(;;){ char *p; int len = 0; cp = strrchr(arg, 'R'); if(!cp || cp<=arg+1 || cp[-1]!='_') break; for(p=cp; *++p; ){ switch(*p){ default: goto out; case '0' ... '9': case 'a' ... 'f': len++; continue; case 'g' ... 'z': case '_': len=0; continue; } } if(len<8) break; cp[-1] = '\0'; }out: if(*arg=='G'){ int len = strlen(arg); while( len>8 && !memcmp(arg,"GPLONLY_",8) ){ arg += 8; len -= 8; } } return arg;}#endifstatic char *chop_version(char *arg){ char *cp; cp = strchr(arg,'\t'); if(cp) *cp = '\0'; /* kill trailing module name first */ for(;;){ int len; cp = strrchr(arg, 'R'); if(!cp || cp<=arg+1 || cp[-1]!='_') break; len=strlen(cp); if(len<9) break; if(strpbrk(cp+1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ")) break; if(strspn(cp+len-8,"0123456789abcdef")!=8) break; cp[-1] = '\0'; } if(*arg=='G'){ int len = strlen(arg); while( len>8 && !memcmp(arg,"GPLONLY_",8) ){ arg += 8; len -= 8; } } return arg;}/***********************************/static const symb *search(unsigned KLONG address, symb *idx, unsigned count){ unsigned left; unsigned mid; unsigned right; if(!idx) return NULL; /* maybe not allocated */ if(address < idx[0].addr) return NULL; if(address >= idx[count-1].addr) return idx+count-1; left = 0; right = count-1; for(;;){ mid = (left + right) / 2; if(address >= idx[mid].addr) left = mid; if(address <= idx[mid].addr) right = mid; if(right-left <= 1) break; } if(address == idx[right].addr) return idx+right; return idx+left;}/*********************************//* allocate if needed, read, and return buffer size */static void read_file(const char *restrict filename, char **bufp, unsigned *restrict roomp) { int fd = 0; ssize_t done; char *buf = *bufp; ssize_t total = 0; unsigned room = *roomp; if(!room) goto hell; /* failed before */ if(!buf) buf = malloc(room); if(!buf) goto hell;open_again: fd = open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK); if(fd<0){ switch(errno){ case EINTR: goto open_again; default: _exit(101); case EACCES: /* somebody screwing around? */ /* FIXME: set a flag to disable symbol lookup? */ case ENOENT:; /* no module support */ } goto hell; } for(;;){ done = read(fd, buf+total, room-total-1); if(done==0) break; /* nothing left */ if(done==-1){ if(errno==EINTR) continue; /* try again */ perror(""); goto hell; } if(done==(ssize_t)room-total-1){ char *tmp; total += done; /* more to go, but no room in buffer */ room *= 2; tmp = realloc(buf, room); if(!tmp) goto hell; buf = tmp; continue; } if(done>0 && done<(ssize_t)room-total-1){ total += done; continue; /* OK, we read some. Go do more. */ } fprintf(stderr,"%ld can't happen\n", (long)done); /* FIXME: memory leak */ _exit(42); } buf[total] = '\0'; // parse_ksyms() expects NUL-terminated file *bufp = buf; *roomp = room; close(fd); return;hell: if(buf) free(buf); *bufp = NULL; *roomp = 0; /* this function will never work again */ total = 0; if(fd>0) close(fd); return;}/*********************************/static int parse_ksyms(void) { char *endp; if(!ksyms_room || !ksyms_data) goto quiet_goodbye; endp = ksyms_data; ksyms_count = 0; if(idx_room) goto bypass; /* some space already allocated */ idx_room = 512; for(;;){ void *vp; idx_room *= 2; vp = realloc(ksyms_index, sizeof(symb)*idx_room); if(!vp) goto bad_alloc; ksyms_index = vp;bypass: for(;;){ char *saved; if(!*endp) return 1; saved = endp; ksyms_index[ksyms_count].addr = STRTOUKL(endp, &endp, 16); if(endp==saved || *endp != ' ') goto bad_parse; endp++; saved = endp; endp = strchr(endp,'\n'); if(!endp) goto bad_parse; /* no newline */ *endp = '\0'; ksyms_index[ksyms_count].name = chop_version(saved); ++endp; if(++ksyms_count >= idx_room) break; /* need more space */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -