|
|
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[] = "@(#)vax.c 5.6 (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 calls
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: struct modebyte *modep;
53: {
54: long usesreg = modep -> regfield;
55:
56: switch ( modep -> modefield ) {
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 != PC ? 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: struct modebyte *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( (struct modebyte *) ((char *) modep) + 1 );
174: }
175: /* NOTREACHED */
176: }
177:
178: unsigned long
179: reladdr( modep )
180: struct modebyte *modep;
181: {
182: operandenum mode = operandmode( modep );
183: char *cp;
184: short *sp;
185: long *lp;
186:
187: cp = (char *) 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: sp = (short *) cp;
197: return (unsigned long) ( cp + sizeof *sp + *sp );
198: case longrel:
199: lp = (long *) cp;
200: return (unsigned long) ( cp + sizeof *lp + *lp );
201: }
202: }
203:
204: findcall( parentp , p_lowpc , p_highpc )
205: nltype *parentp;
206: unsigned long p_lowpc;
207: unsigned long p_highpc;
208: {
209: unsigned char *instructp;
210: long length;
211: nltype *childp;
212: operandenum mode;
213: operandenum firstmode;
214: unsigned long destpc;
215:
216: if ( textspace == 0 ) {
217: return;
218: }
219: if ( p_lowpc < s_lowpc ) {
220: p_lowpc = s_lowpc;
221: }
222: if ( p_highpc > s_highpc ) {
223: p_highpc = s_highpc;
224: }
225: # ifdef DEBUG
226: if ( debug & CALLDEBUG ) {
227: printf( "[findcall] %s: 0x%x to 0x%x\n" ,
228: parentp -> name , p_lowpc , p_highpc );
229: }
230: # endif DEBUG
231: for ( instructp = textspace + p_lowpc ;
232: instructp < textspace + p_highpc ;
233: instructp += length ) {
234: length = 1;
235: if ( *instructp == CALLS ) {
236: /*
237: * maybe a calls, better check it out.
238: * skip the count of the number of arguments.
239: */
240: # ifdef DEBUG
241: if ( debug & CALLDEBUG ) {
242: printf( "[findcall]\t0x%x:calls" , instructp - textspace );
243: }
244: # endif DEBUG
245: firstmode = operandmode( (struct modebyte *) (instructp+length) );
246: switch ( firstmode ) {
247: case literal:
248: case immediate:
249: break;
250: default:
251: goto botched;
252: }
253: length += operandlength( (struct modebyte *) (instructp+length) );
254: mode = operandmode( (struct modebyte *) ( instructp + length ) );
255: # ifdef DEBUG
256: if ( debug & CALLDEBUG ) {
257: printf( "\tfirst operand is %s", operandname( firstmode ) );
258: printf( "\tsecond operand is %s\n" , operandname( mode ) );
259: }
260: # endif DEBUG
261: switch ( mode ) {
262: case regdef:
263: case bytedispdef:
264: case worddispdef:
265: case longdispdef:
266: case bytereldef:
267: case wordreldef:
268: case longreldef:
269: /*
270: * indirect call: call through pointer
271: * either *d(r) as a parameter or local
272: * (r) as a return value
273: * *f as a global pointer
274: * [are there others that we miss?,
275: * e.g. arrays of pointers to functions???]
276: */
277: addarc( parentp , &indirectchild , (long) 0 );
278: length += operandlength(
279: (struct modebyte *) ( instructp + length ) );
280: continue;
281: case byterel:
282: case wordrel:
283: case longrel:
284: /*
285: * regular pc relative addressing
286: * check that this is the address of
287: * a function.
288: */
289: destpc = reladdr( (struct modebyte *) (instructp+length) )
290: - (unsigned long) textspace;
291: if ( destpc >= s_lowpc && destpc <= s_highpc ) {
292: childp = nllookup( destpc );
293: # ifdef DEBUG
294: if ( debug & CALLDEBUG ) {
295: printf( "[findcall]\tdestpc 0x%x" , destpc );
296: printf( " childp->name %s" , childp -> name );
297: printf( " childp->value 0x%x\n" ,
298: childp -> value );
299: }
300: # endif DEBUG
301: if ( childp -> value == destpc ) {
302: /*
303: * a hit
304: */
305: addarc( parentp , childp , (long) 0 );
306: length += operandlength( (struct modebyte *)
307: ( instructp + length ) );
308: continue;
309: }
310: goto botched;
311: }
312: /*
313: * else:
314: * it looked like a calls,
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.