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
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
32 * a namelist entry to be the child of indirect calls
34 nltype indirectchild
= {
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 */
61 findcalls(nltype
*parentp
, pctype p_lowpc
, pctype p_highpc
)
63 unsigned long instructp
;
71 if (p_lowpc
> s_highpc
)
73 if (p_highpc
< s_lowpc
)
75 if (p_lowpc
< s_lowpc
)
77 if (p_highpc
> s_highpc
)
81 if (debug
& CALLSDEBUG
) {
82 printf("[findcalls] %s: 0x%llx to 0x%llx\n",
83 parentp
->name
, p_lowpc
, p_highpc
);
88 for (instructp
= (uintptr_t)textspace
+ p_lowpc
- TORIGIN
;
89 instructp
< (uintptr_t)textspace
+ p_highpc
- TORIGIN
;
90 instructp
+= length
) {
92 switch (OP(instructp
)) {
95 * May be a call, better check it out.
98 if (debug
& CALLSDEBUG
) {
99 printf("[findcalls]\t0x%x:call\n",
103 destpc
= (DISP30(instructp
) << 2) + PC_VAL(instructp
);
107 if (OP3(instructp
) != JMPL
)
111 if (debug
& CALLSDEBUG
)
112 printf("[findcalls]\t0x%x:jmpl",
115 if (RD(instructp
) == R_G0
) {
117 if (debug
& CALLSDEBUG
) {
118 switch (RS1(instructp
)) {
120 printf("\tprobably a RETL\n");
123 printf("\tprobably a RET\n");
126 printf(", but not a call: "
134 if (debug
& CALLSDEBUG
) {
135 printf("\toperands are DST = R%d,\tSRC = R%d",
136 RD(instructp
), RS1(instructp
));
139 if (IMMED(instructp
)) {
141 if (debug
& CALLSDEBUG
) {
142 if (SIMM13(instructp
) < 0) {
144 -(SIMM13(instructp
)));
151 switch (RS1(instructp
)) {
154 * absolute address, simm 13
156 destpc
= SIMM13(instructp
);
162 addarc(parentp
, &indirectchild
, 0);
167 * two register sources, all cases are indirect
170 if (debug
& CALLSDEBUG
) {
171 printf(" + R%d\n", RS2(instructp
));
174 addarc(parentp
, &indirectchild
, 0);
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
);
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",
199 if (childp
->value
== destpc
) {
203 addarc(parentp
, childp
, 0);
209 * it looked like a call,
210 * but it wasn't to anywhere.
213 if (debug
& CALLSDEBUG
) {
214 printf("[findcalls]\tbut it's a switch or a botch\n");