8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sgs / gprof / common / calls.c
blob03091864c54c9f466138e3bea0af3e37b403d0ff
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include "gprof.h"
32 * a namelist entry to be the child of indirect calls
34 nltype indirectchild = {
35 "(*)", /* the name */
36 &modules, /* module [-c only for prog txtspace] */
37 (pctype)0, /* the pc entry point */
38 (pctype)0, /* aligned entry point */
39 (unsigned long)0, /* function size */
40 (unsigned char)0, /* symbol information */
41 (size_t)0, /* ticks in this routine */
42 (double)0.0, /* ticks in this routine (as double) */
43 (double)0.0, /* cumulative ticks in children */
44 (long)0, /* how many times called */
45 (long)0, /* how many calls to self */
46 (double)1.0, /* propagation fraction */
47 (double)0.0, /* self propagation time */
48 (double)0.0, /* child propagation time */
49 (bool)0, /* print flag */
50 (int)0, /* index in the graph list */
51 (int)0, /* graph call chain top-sort order */
52 (int)0, /* internal number of cycle on */
53 (struct nl *)&indirectchild, /* pointer to head of cycle */
54 (struct nl *)0, /* pointer to next member of cycle */
55 (arctype *)0, /* list of caller arcs */
56 (arctype *)0, /* list of callee arcs */
57 (unsigned long)0 /* number of callers */
60 void
61 findcalls(nltype *parentp, pctype p_lowpc, pctype p_highpc)
63 unsigned long instructp;
64 sztype length;
65 nltype *childp;
66 pctype destpc;
68 if (textspace == 0) {
69 return;
71 if (p_lowpc > s_highpc)
72 return;
73 if (p_highpc < s_lowpc)
74 return;
75 if (p_lowpc < s_lowpc)
76 p_lowpc = s_lowpc;
77 if (p_highpc > s_highpc)
78 p_highpc = s_highpc;
80 #ifdef DEBUG
81 if (debug & CALLSDEBUG) {
82 printf("[findcalls] %s: 0x%llx to 0x%llx\n",
83 parentp->name, p_lowpc, p_highpc);
85 #endif /* DEBUG */
87 length = 4;
88 for (instructp = (uintptr_t)textspace + p_lowpc - TORIGIN;
89 instructp < (uintptr_t)textspace + p_highpc - TORIGIN;
90 instructp += length) {
92 switch (OP(instructp)) {
93 case CALL:
95 * May be a call, better check it out.
97 #ifdef DEBUG
98 if (debug & CALLSDEBUG) {
99 printf("[findcalls]\t0x%x:call\n",
100 PC_VAL(instructp));
102 #endif /* DEBUG */
103 destpc = (DISP30(instructp) << 2) + PC_VAL(instructp);
104 break;
106 case FMT3_0x10:
107 if (OP3(instructp) != JMPL)
108 continue;
110 #ifdef DEBUG
111 if (debug & CALLSDEBUG)
112 printf("[findcalls]\t0x%x:jmpl",
113 PC_VAL(instructp));
114 #endif /* DEBUG */
115 if (RD(instructp) == R_G0) {
116 #ifdef DEBUG
117 if (debug & CALLSDEBUG) {
118 switch (RS1(instructp)) {
119 case R_O7:
120 printf("\tprobably a RETL\n");
121 break;
122 case R_I7:
123 printf("\tprobably a RET\n");
124 break;
125 default:
126 printf(", but not a call: "
127 "linked to g0\n");
130 #endif /* DEBUG */
131 continue;
133 #ifdef DEBUG
134 if (debug & CALLSDEBUG) {
135 printf("\toperands are DST = R%d,\tSRC = R%d",
136 RD(instructp), RS1(instructp));
138 #endif /* DEBUG */
139 if (IMMED(instructp)) {
140 #ifdef DEBUG
141 if (debug & CALLSDEBUG) {
142 if (SIMM13(instructp) < 0) {
143 printf(" - 0x%x\n",
144 -(SIMM13(instructp)));
145 } else {
146 printf(" + 0x%x\n",
147 SIMM13(instructp));
150 #endif /* DEBUG */
151 switch (RS1(instructp)) {
152 case R_G0:
154 * absolute address, simm 13
156 destpc = SIMM13(instructp);
157 break;
158 default:
160 * indirect call
162 addarc(parentp, &indirectchild, 0);
163 continue;
165 } else {
167 * two register sources, all cases are indirect
169 #ifdef DEBUG
170 if (debug & CALLSDEBUG) {
171 printf(" + R%d\n", RS2(instructp));
173 #endif /* DEBUG */
174 addarc(parentp, &indirectchild, 0);
175 continue;
177 break;
178 default:
179 continue;
183 * Check that the destination is the address of
184 * a function; this allows us to differentiate
185 * real calls from someone trying to get the PC,
186 * e.g. position independent switches.
188 if (destpc >= s_lowpc && destpc <= s_highpc) {
190 childp = nllookup(&modules, destpc, NULL);
191 #ifdef DEBUG
192 if (debug & CALLSDEBUG) {
193 printf("[findcalls]\tdestpc 0x%llx", destpc);
194 printf(" childp->name %s", childp->name);
195 printf(" childp->value 0x%llx\n",
196 childp->value);
198 #endif /* DEBUG */
199 if (childp->value == destpc) {
201 * a hit
203 addarc(parentp, childp, 0);
204 continue;
208 * else:
209 * it looked like a call,
210 * but it wasn't to anywhere.
212 #ifdef DEBUG
213 if (debug & CALLSDEBUG) {
214 printf("[findcalls]\tbut it's a switch or a botch\n");
216 #endif /* DEBUG */
217 continue;