1 /*- 2 * Copyright (c) 1983, 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)mcount.c 8.1 (Berkeley) 6/4/93 30 * $FreeBSD: src/lib/libc/gmon/mcount.c,v 1.20 2004/10/16 06:32:43 obrien Exp $ 31 */ 32 33 #include <sys/param.h> 34 #include <sys/gmon.h> 35 36 /* 37 * mcount is called on entry to each function compiled with the profiling 38 * switch set. _mcount(), which is declared in a machine-dependent way 39 * with _MCOUNT_DECL, does the actual work and is either inlined into a 40 * C routine or called by an assembly stub. In any case, this magic is 41 * taken care of by the MCOUNT definition in <machine/profile.h>. 42 * 43 * _mcount updates data structures that represent traversals of the 44 * program's call graph edges. frompc and selfpc are the return 45 * address and function address that represents the given call graph edge. 46 * 47 * Note: the original BSD code used the same variable (frompcindex) for 48 * both frompcindex and frompc. Any reasonable, modern compiler will 49 * perform this optimization. 50 */ 51 /* _mcount; may be static, inline, etc */ 52 _MCOUNT_DECL(u_long frompc, u_long selfpc) 53 { 54 u_long frompci; 55 u_short *frompcindex; 56 struct tostruct *top, *prevtop; 57 struct gmonparam *p; 58 long toindex; 59 60 p = &_gmonparam; 61 /* 62 * check that we are profiling 63 * and that we aren't recursively invoked. 64 */ 65 if (p->state != GMON_PROF_ON) 66 return; 67 p->state = GMON_PROF_BUSY; /* XXX */ 68 frompci = frompc - p->lowpc; 69 70 /* 71 * check that frompc is a reasonable pc value. 72 * for example: signal catchers get called from the stack, 73 * not from text space. too bad. 74 */ 75 if (frompci >= p->textsize) 76 goto done; 77 78 frompcindex = &p->froms[frompci / (p->hashfraction * sizeof(*p->froms))]; 79 toindex = *frompcindex; 80 if (toindex == 0) { 81 /* 82 * first time traversing this arc 83 */ 84 toindex = ++p->tos[0].link; 85 if (toindex >= p->tolimit) 86 /* halt further profiling */ 87 goto overflow; 88 89 *frompcindex = toindex; 90 top = &p->tos[toindex]; 91 top->selfpc = selfpc; 92 top->count = 1; 93 top->link = 0; 94 goto done; 95 } 96 top = &p->tos[toindex]; 97 if (top->selfpc == selfpc) { 98 /* 99 * arc at front of chain; usual case. 100 */ 101 top->count++; 102 goto done; 103 } 104 /* 105 * have to go looking down chain for it. 106 * top points to what we are looking at, 107 * prevtop points to previous top. 108 * we know it is not at the head of the chain. 109 */ 110 for (; /* goto done */; ) { 111 if (top->link == 0) { 112 /* 113 * top is end of the chain and none of the chain 114 * had top->selfpc == selfpc. 115 * so we allocate a new tostruct 116 * and link it to the head of the chain. 117 */ 118 toindex = ++p->tos[0].link; 119 if (toindex >= p->tolimit) 120 goto overflow; 121 122 top = &p->tos[toindex]; 123 top->selfpc = selfpc; 124 top->count = 1; 125 top->link = *frompcindex; 126 *frompcindex = toindex; 127 goto done; 128 } 129 /* 130 * otherwise, check the next arc on the chain. 131 */ 132 prevtop = top; 133 top = &p->tos[top->link]; 134 if (top->selfpc == selfpc) { 135 /* 136 * there it is. 137 * increment its count 138 * move it to the head of the chain. 139 */ 140 top->count++; 141 toindex = prevtop->link; 142 prevtop->link = top->link; 143 top->link = *frompcindex; 144 *frompcindex = toindex; 145 goto done; 146 } 147 148 } 149 done: 150 p->state = GMON_PROF_ON; /* XXX */ 151 return; 152 overflow: 153 p->state = GMON_PROF_ERROR; /* XXX */ 154 return; 155 } 156 157 /* 158 * Actual definition of mcount function. Defined in <machine/profile.h>, 159 * which is included by <sys/gmon.h>. 160 */ 161 MCOUNT 162