Annotation of src/usr.bin/gprof/tahoe.c, Revision 1.6
1.6 ! espie 1: /* $OpenBSD: tahoe.c,v 1.5 2003/06/03 02:56:08 millert Exp $ */
1.1 deraadt 2: /* $NetBSD: tahoe.c,v 1.5 1995/04/19 07:16:27 cgd Exp $ */
3:
4: /*
5: * Copyright (c) 1983, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.5 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: #if 0
35: static char sccsid[] = "@(#)tahoe.c 8.1 (Berkeley) 6/6/93";
36: #else
1.6 ! espie 37: static char rcsid[] = "$OpenBSD: tahoe.c,v 1.5 2003/06/03 02:56:08 millert Exp $";
1.1 deraadt 38: #endif
39: #endif /* not lint */
40:
41: #include "gprof.h"
42:
43: /*
44: * a namelist entry to be the child of indirect callf
45: */
46: nltype indirectchild = {
47: "(*)" , /* the name */
48: (unsigned long) 0 , /* the pc entry point */
49: (unsigned long) 0 , /* entry point aligned to histogram */
50: (double) 0.0 , /* ticks in this routine */
51: (double) 0.0 , /* cumulative ticks in children */
52: (long) 0 , /* how many times called */
53: (long) 0 , /* how many calls to self */
54: (double) 1.0 , /* propagation fraction */
55: (double) 0.0 , /* self propagation time */
56: (double) 0.0 , /* child propagation time */
57: (bool) 0 , /* print flag */
58: (int) 0 , /* index in the graph list */
59: (int) 0 , /* graph call chain top-sort order */
60: (int) 0 , /* internal number of cycle on */
61: (struct nl *) &indirectchild , /* pointer to head of cycle */
62: (struct nl *) 0 , /* pointer to next member of cycle */
63: (arctype *) 0 , /* list of caller arcs */
64: (arctype *) 0 /* list of callee arcs */
65: };
66:
67: operandenum
1.6 ! espie 68: operandmode(unsigned char *modep)
1.1 deraadt 69: {
70: long usesreg = ((long)*modep) & 0xf;
71:
72: switch ( ((long)*modep) >> 4 ) {
73: case 0:
74: case 1:
75: case 2:
76: case 3:
77: return literal;
78: case 4:
79: return indexed;
80: case 5:
81: return reg;
82: case 6:
83: return regdef;
84: case 7:
85: return autodec;
86: case 8:
87: return ( usesreg != 0xe ? autoinc : immediate );
88: case 9:
89: return ( usesreg != PC ? autoincdef : absolute );
90: case 10:
91: return ( usesreg != PC ? bytedisp : byterel );
92: case 11:
93: return ( usesreg != PC ? bytedispdef : bytereldef );
94: case 12:
95: return ( usesreg != PC ? worddisp : wordrel );
96: case 13:
97: return ( usesreg != PC ? worddispdef : wordreldef );
98: case 14:
99: return ( usesreg != PC ? longdisp : longrel );
100: case 15:
101: return ( usesreg != PC ? longdispdef : longreldef );
102: }
103: /* NOTREACHED */
104: }
105:
106: char *
1.6 ! espie 107: operandname(operandenum mode)
1.1 deraadt 108: {
109:
110: switch ( mode ) {
111: case literal:
112: return "literal";
113: case indexed:
114: return "indexed";
115: case reg:
116: return "register";
117: case regdef:
118: return "register deferred";
119: case autodec:
120: return "autodecrement";
121: case autoinc:
122: return "autoincrement";
123: case autoincdef:
124: return "autoincrement deferred";
125: case bytedisp:
126: return "byte displacement";
127: case bytedispdef:
128: return "byte displacement deferred";
129: case byterel:
130: return "byte relative";
131: case bytereldef:
132: return "byte relative deferred";
133: case worddisp:
134: return "word displacement";
135: case worddispdef:
136: return "word displacement deferred";
137: case wordrel:
138: return "word relative";
139: case wordreldef:
140: return "word relative deferred";
141: case immediate:
142: return "immediate";
143: case absolute:
144: return "absolute";
145: case longdisp:
146: return "long displacement";
147: case longdispdef:
148: return "long displacement deferred";
149: case longrel:
150: return "long relative";
151: case longreldef:
152: return "long relative deferred";
153: }
154: /* NOTREACHED */
155: }
156:
157: long
1.6 ! espie 158: operandlength(unsigned char *modep)
1.1 deraadt 159: {
160:
161: switch ( operandmode( modep ) ) {
162: case literal:
163: case reg:
164: case regdef:
165: case autodec:
166: case autoinc:
167: case autoincdef:
168: return 1;
169: case bytedisp:
170: case bytedispdef:
171: case byterel:
172: case bytereldef:
173: return 2;
174: case worddisp:
175: case worddispdef:
176: case wordrel:
177: case wordreldef:
178: return 3;
179: case immediate:
180: case absolute:
181: case longdisp:
182: case longdispdef:
183: case longrel:
184: case longreldef:
185: return 5;
186: case indexed:
187: return 1+operandlength( modep + 1 );
188: }
189: /* NOTREACHED */
190: }
191:
192: unsigned long
1.6 ! espie 193: reladdr(char *modep)
1.1 deraadt 194: {
195: operandenum mode = operandmode( modep );
196: char *cp;
197: short *sp;
198: long *lp;
199: int i;
200: long value = 0;
201:
202: cp = modep;
203: cp += 1; /* skip over the mode */
204: switch ( mode ) {
205: default:
1.3 mickey 206: warnx("[reladdr] not relative address");
1.1 deraadt 207: return (unsigned long) modep;
208: case byterel:
209: return (unsigned long) ( cp + sizeof *cp + *cp );
210: case wordrel:
211: for (i = 0; i < sizeof *sp; i++)
212: value = (value << 8) + (cp[i] & 0xff);
213: return (unsigned long) ( cp + sizeof *sp + value );
214: case longrel:
215: for (i = 0; i < sizeof *lp; i++)
216: value = (value << 8) + (cp[i] & 0xff);
217: return (unsigned long) ( cp + sizeof *lp + value );
218: }
219: }
220:
1.3 mickey 221: void
1.6 ! espie 222: findcall(nltype *parentp, unsigned long p_lowpc, unsigned long p_highpc)
1.1 deraadt 223: {
224: unsigned char *instructp;
225: long length;
226: nltype *childp;
227: operandenum mode;
228: operandenum firstmode;
229: unsigned long destpc;
230:
231: if ( textspace == 0 ) {
232: return;
233: }
234: if ( p_lowpc < s_lowpc ) {
235: p_lowpc = s_lowpc;
236: }
237: if ( p_highpc > s_highpc ) {
238: p_highpc = s_highpc;
239: }
240: # ifdef DEBUG
241: if ( debug & CALLDEBUG ) {
242: printf( "[findcall] %s: 0x%x to 0x%x\n" ,
243: parentp -> name , p_lowpc , p_highpc );
244: }
1.4 danh 245: # endif /* DEBUG */
1.1 deraadt 246: for ( instructp = textspace + p_lowpc ;
247: instructp < textspace + p_highpc ;
248: instructp += length ) {
249: length = 1;
250: if ( *instructp == CALLF ) {
251: /*
252: * maybe a callf, better check it out.
253: * skip the count of the number of arguments.
254: */
255: # ifdef DEBUG
256: if ( debug & CALLDEBUG ) {
257: printf( "[findcall]\t0x%x:callf" , instructp - textspace );
258: }
1.4 danh 259: # endif /* DEBUG */
1.1 deraadt 260: firstmode = operandmode( instructp+length );
261: switch ( firstmode ) {
262: case literal:
263: case immediate:
264: break;
265: default:
266: goto botched;
267: }
268: length += operandlength( instructp+length );
269: mode = operandmode( instructp + length );
270: # ifdef DEBUG
271: if ( debug & CALLDEBUG ) {
272: printf( "\tfirst operand is %s", operandname( firstmode ) );
273: printf( "\tsecond operand is %s\n" , operandname( mode ) );
274: }
1.4 danh 275: # endif /* DEBUG */
1.1 deraadt 276: switch ( mode ) {
277: case regdef:
278: case bytedispdef:
279: case worddispdef:
280: case longdispdef:
281: case bytereldef:
282: case wordreldef:
283: case longreldef:
284: /*
285: * indirect call: call through pointer
286: * either *d(r) as a parameter or local
287: * (r) as a return value
288: * *f as a global pointer
289: * [are there others that we miss?,
290: * e.g. arrays of pointers to functions???]
291: */
292: addarc( parentp , &indirectchild , (long) 0 );
293: length += operandlength( instructp + length );
294: continue;
295: case byterel:
296: case wordrel:
297: case longrel:
298: /*
299: * regular pc relative addressing
300: * check that this is the address of
301: * a function.
302: */
303: destpc = reladdr( instructp+length )
304: - (unsigned long) textspace;
305: if ( destpc >= s_lowpc && destpc <= s_highpc ) {
306: childp = nllookup( destpc );
307: # ifdef DEBUG
308: if ( debug & CALLDEBUG ) {
309: printf( "[findcall]\tdestpc 0x%x" , destpc );
310: printf( " childp->name %s" , childp -> name );
311: printf( " childp->value 0x%x\n" ,
312: childp -> value );
313: }
1.4 danh 314: # endif /* DEBUG */
1.1 deraadt 315: if ( childp -> value == destpc ) {
316: /*
317: * a hit
318: */
319: addarc( parentp , childp , (long) 0 );
320: length += operandlength( instructp + length );
321: continue;
322: }
323: goto botched;
324: }
325: /*
326: * else:
327: * it looked like a callf,
328: * but it wasn't to anywhere.
329: */
330: goto botched;
331: default:
332: botched:
333: /*
334: * something funny going on.
335: */
336: # ifdef DEBUG
337: if ( debug & CALLDEBUG ) {
338: printf( "[findcall]\tbut it's a botch\n" );
339: }
1.4 danh 340: # endif /* DEBUG */
1.1 deraadt 341: length = 1;
342: continue;
343: }
344: }
345: }
346: }