diff options
author | Karel Zak <kzak@redhat.com> | 2006-12-07 00:25:46 +0100 |
---|---|---|
committer | Karel Zak <kzak@redhat.com> | 2006-12-07 00:25:46 +0100 |
commit | c07ebfa1e02d208ab12430e6791ea147bcfaf9c0 (patch) | |
tree | d44a755098286f5d553c7aea1a73d98c2995d6ec /sys-utils/readprofile.c | |
parent | 66ee8158b69525e12060ef558cb5d77feadab1dc (diff) | |
download | util-linux-old-c07ebfa1e02d208ab12430e6791ea147bcfaf9c0.tar.gz |
Imported from util-linux-2.11b tarball.
Diffstat (limited to 'sys-utils/readprofile.c')
-rw-r--r-- | sys-utils/readprofile.c | 335 |
1 files changed, 174 insertions, 161 deletions
diff --git a/sys-utils/readprofile.c b/sys-utils/readprofile.c index b531fa90..18932262 100644 --- a/sys-utils/readprofile.c +++ b/sys-utils/readprofile.c @@ -19,10 +19,12 @@ */ /* - * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> + * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> * - added Native Language Support * 1999-09-01 Stephane Eranian <eranian@cello.hpl.hp.com> * - 64bit clean patch + * 3Feb2001 Andrew Morton <andrewm@uow.edu.au> + * - -M option to write profile multiplier. */ #include <errno.h> @@ -44,7 +46,7 @@ static char *prgname; /* These are the defaults */ static char defaultmap[]="/usr/src/linux/System.map"; static char defaultpro[]="/proc/profile"; -static char optstring[]="m:p:itvarV"; +static char optstring[]="M:m:p:itvarV"; static void usage(void) { @@ -52,6 +54,7 @@ usage(void) { _("%s: Usage: \"%s [options]\n" "\t -m <mapfile> (default = \"%s\")\n" "\t -p <pro-file> (default = \"%s\")\n" + "\t -M <mult> set the profiling multiplier to <mult>\n" "\t -i print only info about the sampling step\n" "\t -v print verbose data\n" "\t -a print all symbols, even if count is 0\n" @@ -63,171 +66,181 @@ usage(void) { static 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); + 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; - int proFd; - char *mapFile, *proFile; - unsigned long len=0, add0=0, indx=0; - unsigned int step; - unsigned int *buf, total, fn_len; - unsigned long fn_add, next_add; /* current and next address */ - char fn_name[S_LEN], next_name[S_LEN]; /* current and next name */ - char mode[8]; - int c; - int optAll=0, optInfo=0, optReset=0, optVerbose=0; - char mapline[S_LEN]; - int maplineno=1; - int popenMap; /* flag to tell if popen() has been used */ + FILE *map; + int proFd; + char *mapFile, *proFile, *mult=0; + unsigned long len=0, add0=0, indx=0; + unsigned int step; + unsigned int *buf, total, fn_len; + unsigned long fn_add, next_add; /* current and next address */ + char fn_name[S_LEN], next_name[S_LEN]; /* current and next name */ + char mode[8]; + int c; + int optAll=0, optInfo=0, optReset=0, optVerbose=0; + char mapline[S_LEN]; + int maplineno=1; + int popenMap; /* flag to tell if popen() has been used */ #define next (current^1) - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - prgname=argv[0]; - proFile=defaultpro; - mapFile=defaultmap; - - 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 'r': optReset++; break; - case 'v': optVerbose++; break; - case 'V': printf(_("%s Version %s\n"),prgname,RELEASE); exit(0); - default: usage(); - } - } - - if (optReset) - { - /* try to become root, just in case */ - setuid(0); - pro=fopen(defaultpro,"w"); - if (!pro) - {perror(proFile); exit(1);} - fprintf(pro,_("anything\n")); - fclose(pro); - exit(0); - } - - /* - * Use an fd for the profiling buffer, to skip stdio overhead - */ - if ( ((proFd=open(proFile,O_RDONLY)) < 0) - || ((int)(len=lseek(proFd,0,SEEK_END)) < 0) - || (lseek(proFd,0,SEEK_SET)<0) ) - { - fprintf(stderr,"%s: %s: %s\n",prgname,proFile,strerror(errno)); - exit(1); - } - - if ( !(buf=malloc(len)) ) - { fprintf(stderr,"%s: malloc(): %s\n",prgname, strerror(errno)); exit(1); } - - if (read(proFd,buf,len) != len) - { - fprintf(stderr,"%s: %s: %s\n",prgname,proFile,strerror(errno)); - exit(1); - } - close(proFd); - - step=buf[0]; - if (optInfo) - { - printf(_("Sampling_step: %i\n"),step); - exit(0); - } - - total=0; - - if (!(map=myopen(mapFile,"r",&popenMap))) - {fprintf(stderr,"%s: ",prgname);perror(mapFile);exit(1);} - - while(fgets(mapline,S_LEN,map)) - { - if (sscanf(mapline,"%lx %s %s",&fn_add,mode,fn_name)!=3) - { - fprintf(stderr,_("%s: %s(%i): wrong map line\n"), - prgname,mapFile, maplineno); - exit(1); - } - if (!strcmp(fn_name,"_stext")) /* only elf works like this */ - { - add0=fn_add; - break; - } - } - - if (!add0) - { - fprintf(stderr,_("%s: can't find \"_stext\" in %s\n"),prgname, mapFile); - exit(1); - } - - /* - * Main loop. - */ - while(fgets(mapline,S_LEN,map)) - { - unsigned int this=0; - - if (sscanf(mapline,"%lx %s %s",&next_add,mode,next_name)!=3) - { - fprintf(stderr,_("%s: %s(%i): wrong map line\n"), - prgname,mapFile, maplineno); - exit(1); - } - /* ignore any LEADING (before a '[tT]' symbol is found) Absolute symbols */ - if (*mode == 'A' && total == 0) continue; - if (*mode!='T' && *mode!='t') break; /* only text is profiled */ - - while (indx < (next_add-add0)/step) - this += buf[indx++]; - total += this; - - fn_len = next_add-fn_add; - if (fn_len && (this || optAll)) - { - if (optVerbose) - printf("%08lx %-40s %6i %8.4f\n", - fn_add,fn_name,this,this/(double)fn_len); - else - printf("%6i %-40s %8.4f\n", - this,fn_name,this/(double)fn_len); - } - fn_add=next_add; strcpy(fn_name,next_name); - } - /* trailer */ - if (optVerbose) - printf("%08x %-40s %6i %8.4f\n", - 0,"total",total,total/(double)(fn_add-add0)); - else - printf("%6i %-40s %8.4f\n", - total,_("total"),total/(double)(fn_add-add0)); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + prgname=argv[0]; + proFile=defaultpro; + mapFile=defaultmap; + + 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 'M': mult=optarg; break; + case 'r': optReset++; break; + case 'v': optVerbose++; break; + case 'V': printf(_("%s Version %s\n"),prgname,RELEASE); + exit(0); + default: usage(); + } + } + + if (optReset || mult) { + int multiplier, fd, to_write; + + /* + * When writing the multiplier, if the length of the write is + * not sizeof(int), the multiplier is not changed + */ + if (mult) { + multiplier = strtoul(mult, 0, 10); + to_write = sizeof(int); + } else { + multiplier = 0; + to_write = 1; /* sth different from sizeof(int) */ + } + /* try to become root, just in case */ + setuid(0); + fd = open(defaultpro,O_WRONLY); + if (fd < 0) { + perror(defaultpro); + exit(1); + } + if (write(fd, &multiplier, to_write) != to_write) { + fprintf(stderr, "readprofile: error writing %s: %s\n", + defaultpro, strerror(errno)); + exit(1); + } + close(fd); + exit(0); + } + + /* + * Use an fd for the profiling buffer, to skip stdio overhead + */ + if ( ((proFd=open(proFile,O_RDONLY)) < 0) + || ((int)(len=lseek(proFd,0,SEEK_END)) < 0) + || (lseek(proFd,0,SEEK_SET)<0) ) { + fprintf(stderr,"%s: %s: %s\n",prgname,proFile,strerror(errno)); + exit(1); + } + + if ( !(buf=malloc(len)) ) { + fprintf(stderr,"%s: malloc(): %s\n",prgname, strerror(errno)); + exit(1); + } + + if (read(proFd,buf,len) != len) { + fprintf(stderr,"%s: %s: %s\n",prgname,proFile,strerror(errno)); + exit(1); + } + close(proFd); + + step=buf[0]; + if (optInfo) { + printf(_("Sampling_step: %i\n"),step); + exit(0); + } + + total=0; + + if (!(map=myopen(mapFile,"r",&popenMap))) { + fprintf(stderr,"%s: ",prgname);perror(mapFile); + exit(1); + } + + while(fgets(mapline,S_LEN,map)) { + if (sscanf(mapline,"%lx %s %s",&fn_add,mode,fn_name)!=3) { + fprintf(stderr,_("%s: %s(%i): wrong map line\n"), + prgname,mapFile, maplineno); + exit(1); + } + if (!strcmp(fn_name,"_stext")) /* only elf works like this */ { + add0=fn_add; + break; + } + } + + if (!add0) { + fprintf(stderr,_("%s: can't find \"_stext\" in %s\n"), + prgname, mapFile); + exit(1); + } + + /* + * Main loop. + */ + while(fgets(mapline,S_LEN,map)) { + unsigned int this=0; + + if (sscanf(mapline,"%lx %s %s",&next_add,mode,next_name)!=3) { + fprintf(stderr,_("%s: %s(%i): wrong map line\n"), + prgname,mapFile, maplineno); + exit(1); + } + + /* ignore any LEADING (before a '[tT]' symbol is found) + Absolute symbols */ + if (*mode == 'A' && total == 0) continue; + if (*mode!='T' && *mode!='t') break;/* only text is profiled */ + + while (indx < (next_add-add0)/step) + this += buf[indx++]; + total += this; + + fn_len = next_add-fn_add; + if (fn_len && (this || optAll)) { + if (optVerbose) + printf("%08lx %-40s %6i %8.4f\n", fn_add, + fn_name,this,this/(double)fn_len); + else + printf("%6i %-40s %8.4f\n", + this,fn_name,this/(double)fn_len); + } + fn_add=next_add; strcpy(fn_name,next_name); + } + /* trailer */ + if (optVerbose) + printf("%08x %-40s %6i %8.4f\n", + 0,"total",total,total/(double)(fn_add-add0)); + else + printf("%6i %-40s %8.4f\n", + total,_("total"),total/(double)(fn_add-add0)); - popenMap ? pclose(map) : fclose(map); - exit(0); + popenMap ? pclose(map) : fclose(map); + exit(0); } - - - |