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