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