diff options
author | Karel Zak | 2006-12-07 00:25:32 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:32 +0100 |
commit | 6dbe3af945a63f025561abb83275cee9ff06c57b (patch) | |
tree | 19e59eac8ac465b5bc409b5adf815b582c92f633 /sys-utils/readprofile.c | |
download | kernel-qcow2-util-linux-6dbe3af945a63f025561abb83275cee9ff06c57b.tar.gz kernel-qcow2-util-linux-6dbe3af945a63f025561abb83275cee9ff06c57b.tar.xz kernel-qcow2-util-linux-6dbe3af945a63f025561abb83275cee9ff06c57b.zip |
Imported from util-linux-2.2 tarball.
Diffstat (limited to 'sys-utils/readprofile.c')
-rw-r--r-- | sys-utils/readprofile.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/sys-utils/readprofile.c b/sys-utils/readprofile.c new file mode 100644 index 000000000..58234f6af --- /dev/null +++ b/sys-utils/readprofile.c @@ -0,0 +1,223 @@ +/* + * readprofile.c - used to read /proc/profile + * + * Copyright (C) 1994 Alessandro Rubini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> /* getopt() */ +#include <string.h> + +#define RELEASE "1.1, Jan 1995" + +#define S_LEN 128 + +static char *prgname; + +/* These are the defaults and they cna be changed */ +static char defaultmap1[]="/usr/src/linux/System.map"; +static char defaultmap2[]="/usr/src/linux/zSystem.map"; +static char defaultpro[]="/proc/profile"; +static char optstring[]="m:p:itvarV"; + +void usage() +{ + fprintf(stderr, + "%s: Usage: \"%s [options]\n" + "\t -m <mapfile> (default = \"%s\")\n" + "\t -p <pro-file> (default = \"%s\")\n" + "\t -i print only info about the sampling step\n" + "\t -t print terse data\n" + "\t -v print verbose data\n" + "\t -a print all symbols, even if count is 0\n" + "\t -r reset all the counters (root only)\n" + "\t -V print version and exit\n" + ,prgname,prgname,defaultmap1,defaultpro); + exit(1); +} + +FILE *myopen(char *name, char *mode, int *flag) +{ +static char cmdline[S_LEN]; + + if (!strcmp(name+strlen(name)-3,".gz")) + { + *flag=1; + sprintf(cmdline,"zcat %s", name); + return popen(cmdline,mode); + } + *flag=0; + return fopen(name,mode); +} + +int main (int argc, char **argv) +{ +FILE *pro; +FILE *map; +unsigned long l; +char *proFile; +char *mapFile; +int add, step; +int fn_add[2]; /* current and next address */ +char fn_name[2][S_LEN]; /* current and next name */ +char mode[8]; +int i,c,current=0; +int optAll=0, optInfo=0, optReset=0, optTerse=0, optVerbose=0; +char mapline[S_LEN]; +int maplineno=1; +int popenMap, popenPro; /* flags to tell if popen() is used */ + +#define next (current^1) + + prgname=argv[0]; + proFile=defaultpro; + mapFile=defaultmap1; + + while ((c=getopt(argc,argv,optstring))!=-1) + { + switch(c) + { + case 'm': mapFile=optarg; break; + case 'p': proFile=optarg; break; + case 'a': optAll++; break; + case 'i': optInfo++; break; + case 't': optTerse++; break; + case 'r': optReset++; break; + case 'v': optVerbose++; break; + case 'V': printf("%s Version %s\n",prgname,RELEASE); exit(0); + default: usage(); + } + } + + if (optReset) + { + pro=fopen(defaultpro,"w"); + if (!pro) + {perror(proFile); exit(1);} + fprintf(pro,"anything\n"); + fclose(pro); + exit(0); + } + + if (!(pro=myopen(proFile,"r",&popenPro))) + {fprintf(stderr,"%s: ",prgname);perror(proFile);exit(1);} + + /* + * In opening the map file, try both the default names, but exit + * at first fail if the filename was specified on cmdline + */ + for (map=NULL; map==NULL; ) + { + if (!(map=myopen(mapFile,"r",&popenMap))) + { + fprintf(stderr,"%s: ",prgname);perror(mapFile); + if (mapFile!=defaultmap1) exit(1); + mapFile=defaultmap2; + } + } + +#define NEXT_WORD(where) \ + (fread((void *)where, 1,sizeof(unsigned long),pro), feof(pro) ? 0 : 1) + + /* + * Init the 'next' field + */ + if (!fgets(mapline,S_LEN,map)) + { + fprintf(stderr,"%s: %s(%i): premature EOF\n",prgname,mapFile,maplineno); + exit(1); + } + if (sscanf(mapline,"%x %s %s",&(fn_add[next]),mode,fn_name[next])!=3) + { + fprintf(stderr,"%s: %s(%i): wrong map line\n",prgname,mapFile, maplineno); + exit(1); + } + + add=0; + + if (!NEXT_WORD(&step)) + { + fprintf(stderr,"%s: %s: premature EOF\n",prgname,proFile); + exit(1); + } + + if (optInfo) + { + printf(optTerse ? "%i\n" : "The sampling step in the kernel is %i bytes\n", + step); + exit(0); + } + + /* + * The main loop is build around the mapfile + */ + + while(current^=1, maplineno++, fgets(mapline,S_LEN,map)) + { + int fn_len; + int count=0; + + + if (sscanf(mapline,"%x %s %s",&(fn_add[next]),mode,fn_name[next])!=3) + { + fprintf(stderr,"%s: %s(%i): wrong map line\n", + prgname,mapFile, maplineno); + exit(1); + } + + if (!(fn_len=fn_add[next]-fn_add[current])) + continue; + + if (*mode=='d' || *mode=='D') break; /* only text is profiled */ + + while (add<fn_add[next]) + { + if (!NEXT_WORD(&l)) + { + fprintf(stderr,"%s: %s: premature EOF\n",prgname,proFile); + exit(1); + } + count+=l; add+=step; + } + + if (count || optAll) + { + if (optTerse) + printf("%i %s %lg\n", + count,fn_name[current],count/(double)fn_len); + else if (optVerbose) + printf("%08x %-40s %6i %8.4lf\n", + fn_add[current],fn_name[current],count,count/(double)fn_len); + else + printf("%6i %-40s %8.4lf\n", + count,fn_name[current],count/(double)fn_len); + } + } + + if (feof(map)) + { + fprintf(stderr,"%s: %s(%i): premature EOF\n",prgname,mapFile,maplineno); + exit(1); + } + + popenPro ? pclose(pro) : fclose(pro); + popenMap ? pclose(map) : fclose(map); + exit(0); +} + + |