summaryrefslogtreecommitdiffstats
path: root/sys-utils/readprofile.c
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:34 +0100
committerKarel Zak2006-12-07 00:25:34 +0100
commitfd6b7a7ffc50400704beb41d5a23af5f9edb1eed (patch)
tree997c0ca2abc018369babd7da59bcd0afe492068e /sys-utils/readprofile.c
parentImported from util-linux-2.5 tarball. (diff)
downloadkernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.tar.gz
kernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.tar.xz
kernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.zip
Imported from util-linux-2.7.1 tarball.
Diffstat (limited to 'sys-utils/readprofile.c')
-rw-r--r--sys-utils/readprofile.c227
1 files changed, 111 insertions, 116 deletions
diff --git a/sys-utils/readprofile.c b/sys-utils/readprofile.c
index 58234f6af..4c52cf1fa 100644
--- a/sys-utils/readprofile.c
+++ b/sys-utils/readprofile.c
@@ -1,7 +1,7 @@
/*
* readprofile.c - used to read /proc/profile
*
- * Copyright (C) 1994 Alessandro Rubini
+ * Copyright (C) 1994,1996 Alessandro Rubini (rubini@ipvvis.unipv.it)
*
* 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
@@ -18,20 +18,23 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h> /* getopt() */
+#include <unistd.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
-#define RELEASE "1.1, Jan 1995"
+#define RELEASE "2.0, May 1996"
#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";
+/* These are the defaults */
+static char defaultmap[]="/usr/src/linux/System.map";
static char defaultpro[]="/proc/profile";
static char optstring[]="m:p:itvarV";
@@ -42,12 +45,11 @@ void usage()
"\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);
+ ,prgname,prgname,defaultmap,defaultpro);
exit(1);
}
@@ -56,11 +58,11 @@ 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=1;
+ sprintf(cmdline,"zcat %s", name);
+ return popen(cmdline,mode);
+ }
*flag=0;
return fopen(name,mode);
}
@@ -69,24 +71,24 @@ 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 */
+int proFd;
+char *mapFile, *proFile;
+unsigned int len, add0=0, step, index=0;
+unsigned int *buf, total, fn_len;
+unsigned int 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 i,c,current=0;
-int optAll=0, optInfo=0, optReset=0, optTerse=0, optVerbose=0;
+int c;
+int optAll=0, optInfo=0, optReset=0, optVerbose=0;
char mapline[S_LEN];
int maplineno=1;
-int popenMap, popenPro; /* flags to tell if popen() is used */
+int popenMap; /* flag to tell if popen() has been used */
#define next (current^1)
prgname=argv[0];
proFile=defaultpro;
- mapFile=defaultmap1;
+ mapFile=defaultmap;
while ((c=getopt(argc,argv,optstring))!=-1)
{
@@ -96,128 +98,121 @@ int popenMap, popenPro; /* flags to tell if popen() is used */
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);
+ 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);
+ {
+ /* 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);
- }
-
- 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
+ * Use an fd for the profiling buffer, to skip stdio overhead
*/
- 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)
+ if ( ((proFd=open(proFile,O_RDONLY)) < 0)
+ || ((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);
+ }
- /*
- * 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);
+ 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(optTerse ? "%i\n" : "The sampling step in the kernel is %i bytes\n",
- step);
+ printf("Sampling_step: %i\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;
+ total=0;
+ if (!(map=myopen(mapFile,"r",&popenMap)))
+ {fprintf(stderr,"%s: ",prgname);perror(mapFile);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);
- }
+ while(fgets(mapline,S_LEN,map))
+ {
+ if (sscanf(mapline,"%x %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 (!(fn_len=fn_add[next]-fn_add[current]))
- continue;
+ if (!add0)
+ {
+ fprintf(stderr,"%s: can't find \"_stext\" in %s\n",prgname, mapFile);
+ exit(1);
+ }
- if (*mode=='d' || *mode=='D') break; /* only text is profiled */
+ /*
+ * Main loop.
+ */
+ while(fgets(mapline,S_LEN,map))
+ {
+ unsigned int this=0;
- while (add<fn_add[next])
+ if (sscanf(mapline,"%x %s %s",&next_add,mode,next_name)!=3)
{
- if (!NEXT_WORD(&l))
- {
- fprintf(stderr,"%s: %s: premature EOF\n",prgname,proFile);
- exit(1);
- }
- count+=l; add+=step;
+ fprintf(stderr,"%s: %s(%i): wrong map line\n",
+ prgname,mapFile, maplineno);
+ exit(1);
}
+ if (*mode!='T' && *mode!='t') break; /* only text is profiled */
+
+ while (index < (next_add-add0)/step)
+ this += buf[index++];
+ total += this;
- 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);
- }
+ fn_len = next_add-fn_add;
+ if (fn_len && (this || optAll))
+ {
+ if (optVerbose)
+ printf("%08x %-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));
- popenPro ? pclose(pro) : fclose(pro);
popenMap ? pclose(map) : fclose(map);
exit(0);
}
+