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