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