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