|
|
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.