2 * Copyright (c) 1983, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (C) 2007-2015 Free Software Foundation, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 4. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/param.h>
35 #include <sys/gmon_out.h>
48 #include <libc-internal.h>
49 #include <not-cancel.h>
55 #define internal_function
56 #define weak_alias(fun,aliasid) extern __typeof(fun) aliasid __attribute__ ((weak, alias (#fun)));
57 #define __libc_enable_secure 0
59 /* Head of basic-block list or NULL. */
60 struct __bb *__bb_head attribute_hidden;
62 struct gmonparam _gmonparam attribute_hidden = { GMON_PROF_OFF };
65 * See profil(2) where this is described:
68 #define SCALE_1_TO_1 0x10000L
70 #define ERR(s) write (STDERR_FILENO, s, sizeof (s) - 1)
72 void moncontrol (int mode);
73 void __moncontrol (int mode);
74 static void write_hist (int fd) internal_function;
75 static void write_call_graph (int fd) internal_function;
76 static void write_bb_counts (int fd) internal_function;
80 * profiling is what mcount checks to see if
81 * all the data structures are ready.
84 __moncontrol (int mode)
86 struct gmonparam *p = &_gmonparam;
88 /* Don't change the state if we ran into an error. */
89 if (p->state == GMON_PROF_ERROR)
95 __profil((void *) p->kcount, p->kcountsize, p->lowpc, s_scale);
96 p->state = GMON_PROF_ON;
101 __profil(NULL, 0, 0, 0);
102 p->state = GMON_PROF_OFF;
105 weak_alias (__moncontrol, moncontrol)
109 __monstartup (u_long lowpc, u_long highpc)
113 struct gmonparam *p = &_gmonparam;
117 * round lowpc and highpc to multiples of the density we're using
118 * so the rest of the scaling (here and in gprof) stays in ints.
120 p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
121 if (sizeof *p->froms % sizeof(HISTCOUNTER) != 0)
123 p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
124 p->textsize = p->highpc - p->lowpc;
125 p->kcountsize = ROUNDUP((p->textsize + HISTFRACTION - 1) / HISTFRACTION,
130 /* Avoid odd scales by rounding up highpc to get kcountsize rounded. */
131 p->textsize = ROUNDUP (highpc - p->lowpc,
132 HISTFRACTION * sizeof (*p->froms));
133 p->highpc = p->lowpc + p->textsize;
134 p->kcountsize = p->textsize / HISTFRACTION;
136 p->hashfraction = HASHFRACTION;
137 p->log_hashfraction = -1;
138 /* The following test must be kept in sync with the corresponding
140 if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) {
141 /* if HASHFRACTION is a power of two, mcount can use shifting
142 instead of integer division. Precompute shift amount. */
143 p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1;
145 p->tolimit = p->textsize * ARCDENSITY / 100;
146 if (p->tolimit < MINARCS)
147 p->tolimit = MINARCS;
148 else if (p->tolimit > MAXARCS)
149 p->tolimit = MAXARCS;
150 p->tossize = p->tolimit * sizeof(struct tostruct);
152 /* p->kcount must not share cache lines with the adjacent data, because
153 we use uncached accesses while profiling. */
154 linesz = __dcache_linesz ();
155 cp = calloc (ROUNDUP (p->kcountsize, linesz) + p->tossize
159 ERR("monstartup: out of memory\n");
161 p->state = GMON_PROF_ERROR;
162 /* In case we loose the error state due to a race,
163 prevent invalid writes also by clearing tolimit. */
167 p->tos = (struct tostruct *)cp;
169 cp = (char *) ROUNDUP ((ptrdiff_t) cp, linesz);
170 p->kcount = (HISTCOUNTER *)cp;
171 cp += ROUNDUP (p->kcountsize, linesz);
175 o = p->highpc - p->lowpc;
176 if (p->kcountsize < (u_long) o)
179 s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1;
181 /* avoid floating point operations */
182 int quot = o / p->kcountsize;
186 else if (quot >= 0x100)
187 s_scale = 0x10000 / quot;
188 else if (o >= 0x800000)
189 s_scale = 0x1000000 / (o / (p->kcountsize >> 8));
191 s_scale = 0x1000000 / ((o << 8) / p->kcountsize);
194 s_scale = SCALE_1_TO_1;
198 weak_alias (__monstartup, monstartup)
205 u_char tag = GMON_TAG_TIME_HIST;
206 struct arc_gmon_hist_hdr thdr __attribute__ ((aligned (__alignof__ (char *))));
209 if (_gmonparam.kcountsize > 0)
211 *(char **) thdr.low_pc = (char *) _gmonparam.lowpc;
212 *(char **) thdr.high_pc = (char *) _gmonparam.highpc;
213 *(int32_t *) thdr.hist_size = (_gmonparam.kcountsize
214 / sizeof (HISTCOUNTER));
215 *(int32_t *) thdr.prof_rate = __profile_frequency ();
216 strncpy (thdr.dimen, "seconds", sizeof (thdr.dimen));
217 thdr.dimen_abbrev = 's';
219 r = write (fd, &tag, sizeof tag);
222 r = write (fd, &thdr, sizeof thdr);
223 if (r != sizeof thdr)
225 r = write (fd,_gmonparam.kcount, _gmonparam.kcountsize);
226 if ((unsigned) r != _gmonparam.kcountsize)
234 write_call_graph (int fd)
236 #define NARCS_PER_WRITE 64
237 #define BYTES_PER_ARC (1 + sizeof (struct gmon_cg_arc_record))
238 #define BYTES_PER_WRITE (BYTES_PER_ARC * NARCS_PER_WRITE)
240 u_long frompc, selfpc, count;
241 char buffer[BYTES_PER_WRITE], *p;
242 u_long *prof_desc = __arc_profile_desc_secstart;
243 u_long *prof_count = __arc_profile_counters_secstart;
244 u_long *prof_desc_end = __arc_profile_desc_secend;
245 u_long *prof_forward = __arc_profile_forward_secstart;
247 for (p = buffer; p < buffer + BYTES_PER_WRITE; p += BYTES_PER_ARC)
248 *p = GMON_TAG_CG_ARC;
250 frompc = *prof_desc++ & -2;
251 while (prof_desc < prof_desc_end)
253 selfpc = *prof_desc++;
256 frompc = selfpc & -2;
257 selfpc = *prof_desc++;
259 count = *prof_count++;
272 arc.frompc = (char *) frompc;
273 arc.selfpc = (char *) selfpc;
275 memcpy (p + 1, &arc, sizeof arc);
278 if (p == buffer + BYTES_PER_WRITE)
280 write (fd, buffer, BYTES_PER_WRITE);
286 for (to_index = count;
288 to_index = _gmonparam.tos[to_index].link)
298 arc.frompc = (char *) frompc;
299 arc.selfpc = (char *) _gmonparam.tos[to_index].selfpc;
300 arc.count = _gmonparam.tos[to_index].count;
301 memcpy (p + 1, &arc, sizeof arc);
304 if (p == buffer + BYTES_PER_WRITE)
306 write (fd, buffer, BYTES_PER_WRITE);
312 while (prof_forward < __arc_profile_forward_secend)
314 /* ??? The 'call count' is actually supposed to be a fixed point
315 factor, with 16 bits each before and after the point.
316 It would be much nicer if we figured out the actual number
317 of calls to the caller, and multiplied that with the fixed point
318 factor to arrive at the estimated calls for the callee. */
319 memcpy (p + 1, prof_forward, 3 * sizeof *prof_forward);
321 p += 1 + 3 * sizeof *prof_forward;
322 if (p == buffer + BYTES_PER_WRITE)
324 write (fd, buffer, BYTES_PER_WRITE);
329 write (fd, buffer, p - buffer);
335 write_bb_counts (int fd)
338 u_char tag = GMON_TAG_BB_COUNT;
342 struct { unsigned long address; long count; } bbbody[8];
345 /* Write each group of basic-block info (all basic-blocks in a
346 compilation unit form a single group). */
348 for (grp = __bb_head; grp; grp = grp->next)
350 ncounts = grp->ncounts;
352 write (fd, &ncounts, sizeof ncounts);
353 for (nfilled = i = 0; i < ncounts; ++i)
355 if (nfilled == sizeof (bbbody) / sizeof (bbbody[0]))
357 write (fd, bbbody, sizeof bbbody);
361 bbbody[nfilled].address = grp->addresses[i];
362 bbbody[nfilled++].count = grp->counts[i];
365 write (fd, bbbody, nfilled * sizeof bbbody[0]);
373 struct gmon_hdr ghdr __attribute__ ((aligned (__alignof__ (int))));
378 # define O_NOFOLLOW 0
381 env = getenv ("GMON_OUT_PREFIX");
382 if (env != NULL && !__libc_enable_secure)
384 size_t len = strlen (env);
386 snprintf (buf, sizeof (buf), "%s.%u", env, getpid ());
387 fd = open (buf, O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW, 0666);
392 fd = open ("gmon.out", O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW,
396 perror ("_mcleanup: gmon.out");
401 /* write gmon.out header: */
402 memset (&ghdr, '\0', sizeof (struct gmon_hdr));
403 memcpy (&ghdr.cookie[0], GMON_MAGIC, sizeof (ghdr.cookie));
404 *(int32_t *) ghdr.version = GMON_VERSION;
405 write (fd, &ghdr, sizeof (struct gmon_hdr));
407 /* write PC histogram: */
410 /* write call-graph: */
411 write_call_graph (fd);
413 /* write basic-block execution counts: */
414 write_bb_counts (fd);
421 __write_profiling (void)
423 int save = _gmonparam.state;
424 _gmonparam.state = GMON_PROF_OFF;
425 if (save == GMON_PROF_ON)
427 _gmonparam.state = save;
430 /* This symbol isn't used anywhere in the DSO and it is not exported.
431 This would normally mean it should be removed to get the same API
432 in static libraries. But since profiling is special in static libs
433 anyway we keep it. But not when building the DSO since some
434 quality assurance tests will otherwise trigger. */
435 weak_alias (__write_profiling, write_profiling)
444 if (_gmonparam.state != GMON_PROF_ERROR)
447 /* free the memory. */
448 if (_gmonparam.tos != NULL)
449 free (_gmonparam.tos);