]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - sys-utils/readprofile.c
2 * readprofile.c - used to read /proc/profile
4 * Copyright (C) 1994,1996 Alessandro Rubini (rubini@ipvvis.unipv.it)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
23 * - added Native Language Support
24 * 1999-09-01 Stephane Eranian <eranian@cello.hpl.hp.com>
26 * 3Feb2001 Andrew Morton <andrewm@uow.edu.au>
27 * - -M option to write profile multiplier.
28 * 2001-11-07 Werner Almesberger <wa@almesberger.net>
29 * - byte order auto-detection and -n option
30 * 2001-11-09 Werner Almesberger <wa@almesberger.net>
31 * - skip step size (index 0)
39 #include <sys/types.h>
44 #define RELEASE "2.0, May 1996"
50 /* These are the defaults */
51 static char defaultmap
[]="/usr/src/linux/System.map";
52 static char defaultpro
[]="/proc/profile";
53 static char optstring
[]="M:m:np:itvarV";
58 _("%s: Usage: \"%s [options]\n"
59 "\t -m <mapfile> (default = \"%s\")\n"
60 "\t -p <pro-file> (default = \"%s\")\n"
61 "\t -M <mult> set the profiling multiplier to <mult>\n"
62 "\t -i print only info about the sampling step\n"
63 "\t -v print verbose data\n"
64 "\t -a print all symbols, even if count is 0\n"
65 "\t -r reset all the counters (root only)\n"
66 "\t -n disable byte order auto-detection\n"
67 "\t -V print version and exit\n")
68 ,prgname
,prgname
,defaultmap
,defaultpro
);
73 xmalloc (size_t size
) {
81 fprintf(stderr
, _("out of memory"));
89 myopen(char *name
, char *mode
, int *flag
) {
90 int len
= strlen(name
);
92 if (!strcmp(name
+len
-3,".gz")) {
94 char *cmdline
= xmalloc(len
+6);
95 sprintf(cmdline
, "zcat %s", name
);
96 res
= popen(cmdline
,mode
);
102 return fopen(name
,mode
);
106 main (int argc
, char **argv
) {
109 char *mapFile
, *proFile
, *mult
=0;
110 unsigned long len
=0, add0
=0, indx
=1;
112 unsigned int *buf
, total
, fn_len
;
113 unsigned long fn_add
, next_add
; /* current and next address */
114 char fn_name
[S_LEN
], next_name
[S_LEN
]; /* current and next name */
117 int optAll
=0, optInfo
=0, optReset
=0, optVerbose
=0, optNative
=0;
120 int popenMap
; /* flag to tell if popen() has been used */
122 #define next (current^1)
124 setlocale(LC_ALL
, "");
125 bindtextdomain(PACKAGE
, LOCALEDIR
);
132 while ((c
=getopt(argc
,argv
,optstring
))!=-1) {
134 case 'm': mapFile
=optarg
; break;
135 case 'n': optNative
++; break;
136 case 'p': proFile
=optarg
; break;
137 case 'a': optAll
++; break;
138 case 'i': optInfo
++; break;
139 case 'M': mult
=optarg
; break;
140 case 'r': optReset
++; break;
141 case 'v': optVerbose
++; break;
142 case 'V': printf(_("%s Version %s\n"),prgname
,RELEASE
);
148 if (optReset
|| mult
) {
149 int multiplier
, fd
, to_write
;
152 * When writing the multiplier, if the length of the write is
153 * not sizeof(int), the multiplier is not changed
156 multiplier
= strtoul(mult
, 0, 10);
157 to_write
= sizeof(int);
160 to_write
= 1; /* sth different from sizeof(int) */
162 /* try to become root, just in case */
164 fd
= open(defaultpro
,O_WRONLY
);
169 if (write(fd
, &multiplier
, to_write
) != to_write
) {
170 fprintf(stderr
, "readprofile: error writing %s: %s\n",
171 defaultpro
, strerror(errno
));
179 * Use an fd for the profiling buffer, to skip stdio overhead
181 if ( ((proFd
=open(proFile
,O_RDONLY
)) < 0)
182 || ((int)(len
=lseek(proFd
,0,SEEK_END
)) < 0)
183 || (lseek(proFd
,0,SEEK_SET
)<0) ) {
184 fprintf(stderr
,"%s: %s: %s\n",prgname
,proFile
,strerror(errno
));
188 if ( !(buf
=malloc(len
)) ) {
189 fprintf(stderr
,"%s: malloc(): %s\n",prgname
, strerror(errno
));
193 if (read(proFd
,buf
,len
) != len
) {
194 fprintf(stderr
,"%s: %s: %s\n",prgname
,proFile
,strerror(errno
));
200 int entries
= len
/sizeof(*buf
);
201 int big
= 0,small
= 0,i
;
204 for (p
= buf
+1; p
< buf
+entries
; p
++)
206 if (*p
>= 1 << (sizeof(*buf
)/2)) big
++;
210 fprintf(stderr
,"Assuming reversed byte order. "
211 "Use -n to force native byte order.\n");
212 for (p
= buf
; p
< buf
+entries
; p
++)
213 for (i
= 0; i
< sizeof(*buf
)/2; i
++) {
214 unsigned char *b
= (unsigned char *) p
;
218 b
[i
] = b
[sizeof(*buf
)-i
-1];
219 b
[sizeof(*buf
)-i
-1] = tmp
;
226 printf(_("Sampling_step: %i\n"),step
);
232 if (!(map
=myopen(mapFile
,"r",&popenMap
))) {
233 fprintf(stderr
,"%s: ",prgname
);perror(mapFile
);
237 while(fgets(mapline
,S_LEN
,map
)) {
238 if (sscanf(mapline
,"%lx %s %s",&fn_add
,mode
,fn_name
)!=3) {
239 fprintf(stderr
,_("%s: %s(%i): wrong map line\n"),
240 prgname
,mapFile
, maplineno
);
243 if (!strcmp(fn_name
,"_stext")) /* only elf works like this */ {
250 fprintf(stderr
,_("%s: can't find \"_stext\" in %s\n"),
258 while(fgets(mapline
,S_LEN
,map
)) {
261 if (sscanf(mapline
,"%lx %s %s",&next_add
,mode
,next_name
)!=3) {
262 fprintf(stderr
,_("%s: %s(%i): wrong map line\n"),
263 prgname
,mapFile
, maplineno
);
267 /* ignore any LEADING (before a '[tT]' symbol is found)
269 if (*mode
== 'A' && total
== 0) continue;
270 if (*mode
!='T' && *mode
!='t') break;/* only text is profiled */
272 if (indx
>= len
/ sizeof(*buf
)) {
273 fprintf(stderr
, _("%s: profile address out of range. "
274 "Wrong map file?\n"), prgname
);
278 while (indx
< (next_add
-add0
)/step
)
282 fn_len
= next_add
-fn_add
;
283 if (fn_len
&& (this || optAll
)) {
285 printf("%08lx %-40s %6i %8.4f\n", fn_add
,
286 fn_name
,this,this/(double)fn_len
);
288 printf("%6i %-40s %8.4f\n",
289 this,fn_name
,this/(double)fn_len
);
291 fn_add
=next_add
; strcpy(fn_name
,next_name
);
295 printf("%08x %-40s %6i %8.4f\n",
296 0,"total",total
,total
/(double)(fn_add
-add0
));
298 printf("%6i %-40s %8.4f\n",
299 total
,_("total"),total
/(double)(fn_add
-add0
));
301 popenMap
? pclose(map
) : fclose(map
);