1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59#include "libbb.h"
60#include <sys/utsname.h>
61
62#define S_LEN 128
63
64int readprofile_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
65int readprofile_main(int argc UNUSED_PARAM, char **argv)
66{
67 FILE *map;
68 const char *mapFile, *proFile;
69 unsigned long indx;
70 size_t len;
71 uint64_t add0;
72 unsigned int step;
73 unsigned int *buf, total, fn_len;
74 unsigned long long fn_add, next_add;
75 char fn_name[S_LEN], next_name[S_LEN];
76 char mapline[S_LEN];
77 char mode[8];
78 int maplineno;
79 int multiplier;
80 unsigned opt;
81 enum {
82 OPT_M = (1 << 0),
83 OPT_m = (1 << 1),
84 OPT_p = (1 << 2),
85 OPT_n = (1 << 3),
86 OPT_a = (1 << 4),
87 OPT_b = (1 << 5),
88 OPT_s = (1 << 6),
89 OPT_i = (1 << 7),
90 OPT_r = (1 << 8),
91 OPT_v = (1 << 9),
92 };
93#define optMult (opt & OPT_M)
94#define optNative (opt & OPT_n)
95#define optAll (opt & OPT_a)
96#define optBins (opt & OPT_b)
97#define optSub (opt & OPT_s)
98#define optInfo (opt & OPT_i)
99#define optReset (opt & OPT_r)
100#define optVerbose (opt & OPT_v)
101
102#define next (current^1)
103
104 proFile = "/proc/profile";
105 mapFile = "/boot/System.map";
106 multiplier = 0;
107
108 opt = getopt32(argv, "M:+m:p:nabsirv", &multiplier, &mapFile, &proFile);
109
110 if (opt & (OPT_M|OPT_r)) {
111 int fd, to_write;
112
113
114
115
116
117 to_write = sizeof(int);
118 if (!optMult)
119 to_write = 1;
120
121 fd = xopen("/proc/profile", O_WRONLY);
122 xwrite(fd, &multiplier, to_write);
123 close(fd);
124 return EXIT_SUCCESS;
125 }
126
127
128
129
130 len = MAXINT(ssize_t);
131 buf = xmalloc_xopen_read_close(proFile, &len);
132 len /= sizeof(*buf);
133
134 if (!optNative) {
135 int big = 0, small = 0;
136 unsigned *p;
137
138 for (p = buf+1; p < buf+len; p++) {
139 if (*p & ~0U << (sizeof(*buf)*4))
140 big++;
141 if (*p & ((1 << (sizeof(*buf)*4))-1))
142 small++;
143 }
144 if (big > small) {
145 bb_error_msg("assuming reversed byte order, "
146 "use -n to force native byte order");
147 BUILD_BUG_ON(sizeof(*p) > 8);
148 for (p = buf; p < buf+len; p++) {
149 if (sizeof(*p) == 2)
150 *p = bswap_16(*p);
151 if (sizeof(*p) == 4)
152 *p = bswap_32(*p);
153 if (sizeof(*p) == 8)
154 *p = bb_bswap_64(*p);
155 }
156 }
157 }
158
159 step = buf[0];
160 if (optInfo) {
161 printf("Sampling_step: %u\n", step);
162 return EXIT_SUCCESS;
163 }
164
165 map = xfopen_for_read(mapFile);
166 add0 = 0;
167 maplineno = 1;
168 while (fgets(mapline, S_LEN, map)) {
169 if (sscanf(mapline, "%llx %s %s", &fn_add, mode, fn_name) != 3)
170 bb_error_msg_and_die("%s(%i): wrong map line",
171 mapFile, maplineno);
172
173 if (strcmp(fn_name, "_stext") == 0) {
174 add0 = fn_add;
175 break;
176 }
177 maplineno++;
178 }
179
180 if (!add0)
181 bb_error_msg_and_die("can't find \"_stext\" in %s", mapFile);
182
183
184
185
186 total = 0;
187 indx = 1;
188 while (fgets(mapline, S_LEN, map)) {
189 bool header_printed;
190 unsigned int this;
191
192 if (sscanf(mapline, "%llx %s %s", &next_add, mode, next_name) != 3)
193 bb_error_msg_and_die("%s(%i): wrong map line",
194 mapFile, maplineno);
195
196 header_printed = 0;
197
198
199
200 if ((mode[0] == 'A' || mode[0] == '?') && total == 0)
201 continue;
202 if ((mode[0]|0x20) != 't' && (mode[0]|0x20) != 'w') {
203 break;
204 }
205
206 if (indx >= len)
207 bb_error_msg_and_die("profile address out of range. "
208 "Wrong map file?");
209
210 this = 0;
211 while (indx < (next_add-add0)/step) {
212 if (optBins && (buf[indx] || optAll)) {
213 if (!header_printed) {
214 printf("%s:\n", fn_name);
215 header_printed = 1;
216 }
217 printf("\t%"PRIx64"\t%u\n", (indx - 1)*step + add0, buf[indx]);
218 }
219 this += buf[indx++];
220 }
221 total += this;
222
223 if (optBins) {
224 if (optVerbose || this > 0)
225 printf(" total\t\t\t\t%u\n", this);
226 } else
227 if ((this || optAll)
228 && (fn_len = next_add-fn_add) != 0
229 ) {
230 if (optVerbose)
231 printf("%016llx %-40s %6u %8.4f\n", fn_add,
232 fn_name, this, this/(double)fn_len);
233 else
234 printf("%6u %-40s %8.4f\n",
235 this, fn_name, this/(double)fn_len);
236 if (optSub) {
237 unsigned long long scan;
238
239 for (scan = (fn_add-add0)/step + 1;
240 scan < (next_add-add0)/step; scan++) {
241 unsigned long long addr;
242
243 addr = (scan - 1)*step + add0;
244 printf("\t%#llx\t%s+%#llx\t%u\n",
245 addr, fn_name, addr - fn_add,
246 buf[scan]);
247 }
248 }
249 }
250
251 fn_add = next_add;
252 strcpy(fn_name, next_name);
253
254 maplineno++;
255 }
256
257
258 printf("%6u *unknown*\n", buf[len-1]);
259
260
261 if (optVerbose)
262 printf("%016x %-40s %6u %8.4f\n",
263 0, "total", total, total/(double)(fn_add-add0));
264 else
265 printf("%6u %-40s %8.4f\n",
266 total, "total", total/(double)(fn_add-add0));
267
268 if (ENABLE_FEATURE_CLEAN_UP) {
269 fclose(map);
270 free(buf);
271 }
272
273 return EXIT_SUCCESS;
274}
275