|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)callf.c 1.1 (Tahoe) 3/21/85";
3: #endif not lint
4:
5: #include "gprof.h"
6:
7: /*
8: * a namelist entry to be the child of indirect callf
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: unsigned char *modep;
34: {
35: long usesreg = ((long)*modep) & 0xf;
36:
37: switch ( ((long)*modep) >> 4 ) {
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 != 0xe ? 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: unsigned char *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( modep + 1 );
155: }
156: /* NOTREACHED */
157: }
158:
159: unsigned long
160: reladdr( modep )
161: char *modep;
162: {
163: operandenum mode = operandmode( modep );
164: char *cp;
165: short *sp;
166: long *lp;
167: int i;
168: long value = 0;
169:
170: cp = modep;
171: cp += 1; /* skip over the mode */
172: switch ( mode ) {
173: default:
174: fprintf( stderr , "[reladdr] not relative address\n" );
175: return (unsigned long) modep;
176: case byterel:
177: return (unsigned long) ( cp + sizeof *cp + *cp );
178: case wordrel:
179: for (i = 0; i < sizeof *sp; i++)
180: value = (value << 8) + (cp[i] & 0xff);
181: return (unsigned long) ( cp + sizeof *sp + value );
182: case longrel:
183: for (i = 0; i < sizeof *lp; i++)
184: value = (value << 8) + (cp[i] & 0xff);
185: return (unsigned long) ( cp + sizeof *lp + value );
186: }
187: }
188:
189: findcallf( parentp , p_lowpc , p_highpc )
190: nltype *parentp;
191: unsigned long p_lowpc;
192: unsigned long p_highpc;
193: {
194: unsigned char *instructp;
195: long length;
196: nltype *childp;
197: operandenum mode;
198: operandenum firstmode;
199: unsigned long destpc;
200:
201: if ( textspace == 0 ) {
202: return;
203: }
204: if ( p_lowpc < s_lowpc ) {
205: p_lowpc = s_lowpc;
206: }
207: if ( p_highpc > s_highpc ) {
208: p_highpc = s_highpc;
209: }
210: # ifdef DEBUG
211: if ( debug & CALLFDEBUG ) {
212: printf( "[findcallf] %s: 0x%x to 0x%x\n" ,
213: parentp -> name , p_lowpc , p_highpc );
214: }
215: # endif DEBUG
216: for ( instructp = textspace + p_lowpc ;
217: instructp < textspace + p_highpc ;
218: instructp += length ) {
219: length = 1;
220: if ( *instructp == CALLF ) {
221: /*
222: * maybe a callf, better check it out.
223: * skip the count of the number of arguments.
224: */
225: # ifdef DEBUG
226: if ( debug & CALLFDEBUG ) {
227: printf( "[findcallf]\t0x%x:callf" , instructp - textspace );
228: }
229: # endif DEBUG
230: firstmode = operandmode( instructp+length );
231: switch ( firstmode ) {
232: case literal:
233: case immediate:
234: break;
235: default:
236: goto botched;
237: }
238: length += operandlength( instructp+length );
239: mode = operandmode( instructp + length );
240: # ifdef DEBUG
241: if ( debug & CALLFDEBUG ) {
242: printf( "\tfirst operand is %s", operandname( firstmode ) );
243: printf( "\tsecond operand is %s\n" , operandname( mode ) );
244: }
245: # endif DEBUG
246: switch ( mode ) {
247: case regdef:
248: case bytedispdef:
249: case worddispdef:
250: case longdispdef:
251: case bytereldef:
252: case wordreldef:
253: case longreldef:
254: /*
255: * indirect call: call through pointer
256: * either *d(r) as a parameter or local
257: * (r) as a return value
258: * *f as a global pointer
259: * [are there others that we miss?,
260: * e.g. arrays of pointers to functions???]
261: */
262: addarc( parentp , &indirectchild , (long) 0 );
263: length += operandlength( instructp + length );
264: continue;
265: case byterel:
266: case wordrel:
267: case longrel:
268: /*
269: * regular pc relative addressing
270: * check that this is the address of
271: * a function.
272: */
273: destpc = reladdr( instructp+length )
274: - (unsigned long) textspace;
275: if ( destpc >= s_lowpc && destpc <= s_highpc ) {
276: childp = nllookup( destpc );
277: # ifdef DEBUG
278: if ( debug & CALLFDEBUG ) {
279: printf( "[findcallf]\tdestpc 0x%x" , destpc );
280: printf( " childp->name %s" , childp -> name );
281: printf( " childp->value 0x%x\n" ,
282: childp -> value );
283: }
284: # endif DEBUG
285: if ( childp -> value == destpc ) {
286: /*
287: * a hit
288: */
289: addarc( parentp , childp , (long) 0 );
290: length += operandlength( instructp + length );
291: continue;
292: }
293: goto botched;
294: }
295: /*
296: * else:
297: * it looked like a callf,
298: * but it wasn't to anywhere.
299: */
300: goto botched;
301: default:
302: botched:
303: /*
304: * something funny going on.
305: */
306: # ifdef DEBUG
307: if ( debug & CALLFDEBUG ) {
308: printf( "[findcallf]\tbut it's a botch\n" );
309: }
310: # endif DEBUG
311: length = 1;
312: continue;
313: }
314: }
315: }
316: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.