source: MondoRescue/branches/3.3/mindi-busybox/util-linux/readprofile.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 6.9 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * readprofile.c - used to read /proc/profile
4 *
5 * Copyright (C) 1994,1996 Alessandro Rubini (rubini@ipvvis.unipv.it)
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9
10/*
11 * 1999-02-22 Arkadiusz Mickiewicz <misiek@pld.ORG.PL>
12 * - added Native Language Support
13 * 1999-09-01 Stephane Eranian <eranian@cello.hpl.hp.com>
14 * - 64bit clean patch
15 * 3Feb2001 Andrew Morton <andrewm@uow.edu.au>
16 * - -M option to write profile multiplier.
17 * 2001-11-07 Werner Almesberger <wa@almesberger.net>
18 * - byte order auto-detection and -n option
19 * 2001-11-09 Werner Almesberger <wa@almesberger.net>
20 * - skip step size (index 0)
21 * 2002-03-09 John Levon <moz@compsoc.man.ac.uk>
22 * - make maplineno do something
23 * 2002-11-28 Mads Martin Joergensen +
24 * - also try /boot/System.map-`uname -r`
25 * 2003-04-09 Werner Almesberger <wa@almesberger.net>
26 * - fixed off-by eight error and improved heuristics in byte order detection
27 * 2003-08-12 Nikita Danilov <Nikita@Namesys.COM>
28 * - added -s option; example of use:
29 * "readprofile -s -m /boot/System.map-test | grep __d_lookup | sort -n -k3"
30 *
31 * Taken from util-linux and adapted for busybox by
32 * Paul Mundt <lethal@linux-sh.org>.
33 */
34
35//usage:#define readprofile_trivial_usage
36//usage: "[OPTIONS]"
37//usage:#define readprofile_full_usage "\n\n"
38//usage: " -m mapfile (Default: /boot/System.map)"
39//usage: "\n -p profile (Default: /proc/profile)"
40//usage: "\n -M NUM Set the profiling multiplier to NUM"
41//usage: "\n -i Print only info about the sampling step"
42//usage: "\n -v Verbose"
43//usage: "\n -a Print all symbols, even if count is 0"
44//usage: "\n -b Print individual histogram-bin counts"
45//usage: "\n -s Print individual counters within functions"
46//usage: "\n -r Reset all the counters (root only)"
47//usage: "\n -n Disable byte order auto-detection"
48
49#include "libbb.h"
50#include <sys/utsname.h>
51
52#define S_LEN 128
53
54/* These are the defaults */
55static const char defaultmap[] ALIGN1 = "/boot/System.map";
56static const char defaultpro[] ALIGN1 = "/proc/profile";
57
58int readprofile_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
59int readprofile_main(int argc UNUSED_PARAM, char **argv)
60{
61 FILE *map;
62 const char *mapFile, *proFile;
63 unsigned long indx = 1;
64 size_t len;
65 uint64_t add0 = 0;
66 unsigned int step;
67 unsigned int *buf, total, fn_len;
68 unsigned long long fn_add, next_add; /* current and next address */
69 char fn_name[S_LEN], next_name[S_LEN]; /* current and next name */
70 char mapline[S_LEN];
71 char mode[8];
72 int maplineno = 1;
73 int header_printed;
74 int multiplier = 0;
75 unsigned opt;
76 enum {
77 OPT_M = (1 << 0),
78 OPT_m = (1 << 1),
79 OPT_p = (1 << 2),
80 OPT_n = (1 << 3),
81 OPT_a = (1 << 4),
82 OPT_b = (1 << 5),
83 OPT_s = (1 << 6),
84 OPT_i = (1 << 7),
85 OPT_r = (1 << 8),
86 OPT_v = (1 << 9),
87 };
88#define optMult (opt & OPT_M)
89#define optNative (opt & OPT_n)
90#define optAll (opt & OPT_a)
91#define optBins (opt & OPT_b)
92#define optSub (opt & OPT_s)
93#define optInfo (opt & OPT_i)
94#define optReset (opt & OPT_r)
95#define optVerbose (opt & OPT_v)
96
97#define next (current^1)
98
99 proFile = defaultpro;
100 mapFile = defaultmap;
101
102 opt_complementary = "M+"; /* -M N */
103 opt = getopt32(argv, "M:m:p:nabsirv", &multiplier, &mapFile, &proFile);
104
105 if (opt & (OPT_M|OPT_r)) { /* mult or reset, or both */
106 int fd, to_write;
107
108 /*
109 * When writing the multiplier, if the length of the write is
110 * not sizeof(int), the multiplier is not changed
111 */
112 to_write = sizeof(int);
113 if (!optMult)
114 to_write = 1; /* sth different from sizeof(int) */
115
116 fd = xopen(defaultpro, O_WRONLY);
117 xwrite(fd, &multiplier, to_write);
118 close(fd);
119 return EXIT_SUCCESS;
120 }
121
122 /*
123 * Use an fd for the profiling buffer, to skip stdio overhead
124 */
125 len = MAXINT(ssize_t);
126 buf = xmalloc_xopen_read_close(proFile, &len);
127 if (!optNative) {
128 int entries = len / sizeof(*buf);
129 int big = 0, small = 0, i;
130 unsigned *p;
131
132 for (p = buf+1; p < buf+entries; p++) {
133 if (*p & ~0U << (sizeof(*buf)*4))
134 big++;
135 if (*p & ((1 << (sizeof(*buf)*4))-1))
136 small++;
137 }
138 if (big > small) {
139 bb_error_msg("assuming reversed byte order, "
140 "use -n to force native byte order");
141 for (p = buf; p < buf+entries; p++)
142 for (i = 0; i < sizeof(*buf)/2; i++) {
143 unsigned char *b = (unsigned char *) p;
144 unsigned char tmp;
145
146 tmp = b[i];
147 b[i] = b[sizeof(*buf)-i-1];
148 b[sizeof(*buf)-i-1] = tmp;
149 }
150 }
151 }
152
153 step = buf[0];
154 if (optInfo) {
155 printf("Sampling_step: %u\n", step);
156 return EXIT_SUCCESS;
157 }
158
159 total = 0;
160
161 map = xfopen_for_read(mapFile);
162
163 while (fgets(mapline, S_LEN, map)) {
164 if (sscanf(mapline, "%llx %s %s", &fn_add, mode, fn_name) != 3)
165 bb_error_msg_and_die("%s(%i): wrong map line",
166 mapFile, maplineno);
167
168 if (!strcmp(fn_name, "_stext")) /* only elf works like this */ {
169 add0 = fn_add;
170 break;
171 }
172 maplineno++;
173 }
174
175 if (!add0)
176 bb_error_msg_and_die("can't find \"_stext\" in %s", mapFile);
177
178 /*
179 * Main loop.
180 */
181 while (fgets(mapline, S_LEN, map)) {
182 unsigned int this = 0;
183
184 if (sscanf(mapline, "%llx %s %s", &next_add, mode, next_name) != 3)
185 bb_error_msg_and_die("%s(%i): wrong map line",
186 mapFile, maplineno);
187
188 header_printed = 0;
189
190 /* ignore any LEADING (before a '[tT]' symbol is found)
191 Absolute symbols */
192 if ((*mode == 'A' || *mode == '?') && total == 0) continue;
193 if (*mode != 'T' && *mode != 't'
194 && *mode != 'W' && *mode != 'w'
195 ) {
196 break; /* only text is profiled */
197 }
198
199 if (indx >= len / sizeof(*buf))
200 bb_error_msg_and_die("profile address out of range. "
201 "Wrong map file?");
202
203 while (indx < (next_add-add0)/step) {
204 if (optBins && (buf[indx] || optAll)) {
205 if (!header_printed) {
206 printf("%s:\n", fn_name);
207 header_printed = 1;
208 }
209 printf("\t%"PRIx64"\t%u\n", (indx - 1)*step + add0, buf[indx]);
210 }
211 this += buf[indx++];
212 }
213 total += this;
214
215 if (optBins) {
216 if (optVerbose || this > 0)
217 printf(" total\t\t\t\t%u\n", this);
218 } else if ((this || optAll)
219 && (fn_len = next_add-fn_add) != 0
220 ) {
221 if (optVerbose)
222 printf("%016llx %-40s %6u %8.4f\n", fn_add,
223 fn_name, this, this/(double)fn_len);
224 else
225 printf("%6u %-40s %8.4f\n",
226 this, fn_name, this/(double)fn_len);
227 if (optSub) {
228 unsigned long long scan;
229
230 for (scan = (fn_add-add0)/step + 1;
231 scan < (next_add-add0)/step; scan++) {
232 unsigned long long addr;
233
234 addr = (scan - 1)*step + add0;
235 printf("\t%#llx\t%s+%#llx\t%u\n",
236 addr, fn_name, addr - fn_add,
237 buf[scan]);
238 }
239 }
240 }
241
242 fn_add = next_add;
243 strcpy(fn_name, next_name);
244
245 maplineno++;
246 }
247
248 /* clock ticks, out of kernel text - probably modules */
249 printf("%6u %s\n", buf[len/sizeof(*buf)-1], "*unknown*");
250
251 /* trailer */
252 if (optVerbose)
253 printf("%016x %-40s %6u %8.4f\n",
254 0, "total", total, total/(double)(fn_add-add0));
255 else
256 printf("%6u %-40s %8.4f\n",
257 total, "total", total/(double)(fn_add-add0));
258
259 fclose(map);
260 free(buf);
261
262 return EXIT_SUCCESS;
263}
Note: See TracBrowser for help on using the repository browser.