|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)calls.c 5.1 (Berkeley) 6/4/85"; ! 9: #endif not lint ! 10: ! 11: #include "gprof.h" ! 12: ! 13: /* ! 14: * a namelist entry to be the child of indirect calls ! 15: */ ! 16: nltype indirectchild = { ! 17: "(*)" , /* the name */ ! 18: (unsigned long) 0 , /* the pc entry point */ ! 19: (unsigned long) 0 , /* entry point aligned to histogram */ ! 20: (double) 0.0 , /* ticks in this routine */ ! 21: (double) 0.0 , /* cumulative ticks in children */ ! 22: (long) 0 , /* how many times called */ ! 23: (long) 0 , /* how many calls to self */ ! 24: (double) 1.0 , /* propagation fraction */ ! 25: (double) 0.0 , /* self propagation time */ ! 26: (double) 0.0 , /* child propagation time */ ! 27: (bool) 0 , /* print flag */ ! 28: (int) 0 , /* index in the graph list */ ! 29: (int) 0 , /* graph call chain top-sort order */ ! 30: (int) 0 , /* internal number of cycle on */ ! 31: (struct nl *) &indirectchild , /* pointer to head of cycle */ ! 32: (struct nl *) 0 , /* pointer to next member of cycle */ ! 33: (arctype *) 0 , /* list of caller arcs */ ! 34: (arctype *) 0 /* list of callee arcs */ ! 35: }; ! 36: ! 37: operandenum ! 38: operandmode( modep ) ! 39: struct modebyte *modep; ! 40: { ! 41: long usesreg = modep -> regfield; ! 42: ! 43: switch ( modep -> modefield ) { ! 44: case 0: ! 45: case 1: ! 46: case 2: ! 47: case 3: ! 48: return literal; ! 49: case 4: ! 50: return indexed; ! 51: case 5: ! 52: return reg; ! 53: case 6: ! 54: return regdef; ! 55: case 7: ! 56: return autodec; ! 57: case 8: ! 58: return ( usesreg != PC ? autoinc : immediate ); ! 59: case 9: ! 60: return ( usesreg != PC ? autoincdef : absolute ); ! 61: case 10: ! 62: return ( usesreg != PC ? bytedisp : byterel ); ! 63: case 11: ! 64: return ( usesreg != PC ? bytedispdef : bytereldef ); ! 65: case 12: ! 66: return ( usesreg != PC ? worddisp : wordrel ); ! 67: case 13: ! 68: return ( usesreg != PC ? worddispdef : wordreldef ); ! 69: case 14: ! 70: return ( usesreg != PC ? longdisp : longrel ); ! 71: case 15: ! 72: return ( usesreg != PC ? longdispdef : longreldef ); ! 73: } ! 74: /* NOTREACHED */ ! 75: } ! 76: ! 77: char * ! 78: operandname( mode ) ! 79: operandenum mode; ! 80: { ! 81: ! 82: switch ( mode ) { ! 83: case literal: ! 84: return "literal"; ! 85: case indexed: ! 86: return "indexed"; ! 87: case reg: ! 88: return "register"; ! 89: case regdef: ! 90: return "register deferred"; ! 91: case autodec: ! 92: return "autodecrement"; ! 93: case autoinc: ! 94: return "autoincrement"; ! 95: case autoincdef: ! 96: return "autoincrement deferred"; ! 97: case bytedisp: ! 98: return "byte displacement"; ! 99: case bytedispdef: ! 100: return "byte displacement deferred"; ! 101: case byterel: ! 102: return "byte relative"; ! 103: case bytereldef: ! 104: return "byte relative deferred"; ! 105: case worddisp: ! 106: return "word displacement"; ! 107: case worddispdef: ! 108: return "word displacement deferred"; ! 109: case wordrel: ! 110: return "word relative"; ! 111: case wordreldef: ! 112: return "word relative deferred"; ! 113: case immediate: ! 114: return "immediate"; ! 115: case absolute: ! 116: return "absolute"; ! 117: case longdisp: ! 118: return "long displacement"; ! 119: case longdispdef: ! 120: return "long displacement deferred"; ! 121: case longrel: ! 122: return "long relative"; ! 123: case longreldef: ! 124: return "long relative deferred"; ! 125: } ! 126: /* NOTREACHED */ ! 127: } ! 128: ! 129: long ! 130: operandlength( modep ) ! 131: struct modebyte *modep; ! 132: { ! 133: ! 134: switch ( operandmode( modep ) ) { ! 135: case literal: ! 136: case reg: ! 137: case regdef: ! 138: case autodec: ! 139: case autoinc: ! 140: case autoincdef: ! 141: return 1; ! 142: case bytedisp: ! 143: case bytedispdef: ! 144: case byterel: ! 145: case bytereldef: ! 146: return 2; ! 147: case worddisp: ! 148: case worddispdef: ! 149: case wordrel: ! 150: case wordreldef: ! 151: return 3; ! 152: case immediate: ! 153: case absolute: ! 154: case longdisp: ! 155: case longdispdef: ! 156: case longrel: ! 157: case longreldef: ! 158: return 5; ! 159: case indexed: ! 160: return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 ); ! 161: } ! 162: /* NOTREACHED */ ! 163: } ! 164: ! 165: unsigned long ! 166: reladdr( modep ) ! 167: struct modebyte *modep; ! 168: { ! 169: operandenum mode = operandmode( modep ); ! 170: char *cp; ! 171: short *sp; ! 172: long *lp; ! 173: ! 174: cp = (char *) modep; ! 175: cp += 1; /* skip over the mode */ ! 176: switch ( mode ) { ! 177: default: ! 178: fprintf( stderr , "[reladdr] not relative address\n" ); ! 179: return (unsigned long) modep; ! 180: case byterel: ! 181: return (unsigned long) ( cp + sizeof *cp + *cp ); ! 182: case wordrel: ! 183: sp = (short *) cp; ! 184: return (unsigned long) ( cp + sizeof *sp + *sp ); ! 185: case longrel: ! 186: lp = (long *) cp; ! 187: return (unsigned long) ( cp + sizeof *lp + *lp ); ! 188: } ! 189: } ! 190: ! 191: findcalls( parentp , p_lowpc , p_highpc ) ! 192: nltype *parentp; ! 193: unsigned long p_lowpc; ! 194: unsigned long p_highpc; ! 195: { ! 196: unsigned char *instructp; ! 197: long length; ! 198: nltype *childp; ! 199: operandenum mode; ! 200: operandenum firstmode; ! 201: unsigned long destpc; ! 202: ! 203: if ( textspace == 0 ) { ! 204: return; ! 205: } ! 206: if ( p_lowpc < s_lowpc ) { ! 207: p_lowpc = s_lowpc; ! 208: } ! 209: if ( p_highpc > s_highpc ) { ! 210: p_highpc = s_highpc; ! 211: } ! 212: # ifdef DEBUG ! 213: if ( debug & CALLSDEBUG ) { ! 214: printf( "[findcalls] %s: 0x%x to 0x%x\n" , ! 215: parentp -> name , p_lowpc , p_highpc ); ! 216: } ! 217: # endif DEBUG ! 218: for ( instructp = textspace + p_lowpc ; ! 219: instructp < textspace + p_highpc ; ! 220: instructp += length ) { ! 221: length = 1; ! 222: if ( *instructp == CALLS ) { ! 223: /* ! 224: * maybe a calls, better check it out. ! 225: * skip the count of the number of arguments. ! 226: */ ! 227: # ifdef DEBUG ! 228: if ( debug & CALLSDEBUG ) { ! 229: printf( "[findcalls]\t0x%x:calls" , instructp - textspace ); ! 230: } ! 231: # endif DEBUG ! 232: firstmode = operandmode( (struct modebyte *) (instructp+length) ); ! 233: switch ( firstmode ) { ! 234: case literal: ! 235: case immediate: ! 236: break; ! 237: default: ! 238: goto botched; ! 239: } ! 240: length += operandlength( (struct modebyte *) (instructp+length) ); ! 241: mode = operandmode( (struct modebyte *) ( instructp + length ) ); ! 242: # ifdef DEBUG ! 243: if ( debug & CALLSDEBUG ) { ! 244: printf( "\tfirst operand is %s", operandname( firstmode ) ); ! 245: printf( "\tsecond operand is %s\n" , operandname( mode ) ); ! 246: } ! 247: # endif DEBUG ! 248: switch ( mode ) { ! 249: case regdef: ! 250: case bytedispdef: ! 251: case worddispdef: ! 252: case longdispdef: ! 253: case bytereldef: ! 254: case wordreldef: ! 255: case longreldef: ! 256: /* ! 257: * indirect call: call through pointer ! 258: * either *d(r) as a parameter or local ! 259: * (r) as a return value ! 260: * *f as a global pointer ! 261: * [are there others that we miss?, ! 262: * e.g. arrays of pointers to functions???] ! 263: */ ! 264: addarc( parentp , &indirectchild , (long) 0 ); ! 265: length += operandlength( ! 266: (struct modebyte *) ( instructp + length ) ); ! 267: continue; ! 268: case byterel: ! 269: case wordrel: ! 270: case longrel: ! 271: /* ! 272: * regular pc relative addressing ! 273: * check that this is the address of ! 274: * a function. ! 275: */ ! 276: destpc = reladdr( (struct modebyte *) (instructp+length) ) ! 277: - (unsigned long) textspace; ! 278: if ( destpc >= s_lowpc && destpc <= s_highpc ) { ! 279: childp = nllookup( destpc ); ! 280: # ifdef DEBUG ! 281: if ( debug & CALLSDEBUG ) { ! 282: printf( "[findcalls]\tdestpc 0x%x" , destpc ); ! 283: printf( " childp->name %s" , childp -> name ); ! 284: printf( " childp->value 0x%x\n" , ! 285: childp -> value ); ! 286: } ! 287: # endif DEBUG ! 288: if ( childp -> value == destpc ) { ! 289: /* ! 290: * a hit ! 291: */ ! 292: addarc( parentp , childp , (long) 0 ); ! 293: length += operandlength( (struct modebyte *) ! 294: ( instructp + length ) ); ! 295: continue; ! 296: } ! 297: goto botched; ! 298: } ! 299: /* ! 300: * else: ! 301: * it looked like a calls, ! 302: * but it wasn't to anywhere. ! 303: */ ! 304: goto botched; ! 305: default: ! 306: botched: ! 307: /* ! 308: * something funny going on. ! 309: */ ! 310: # ifdef DEBUG ! 311: if ( debug & CALLSDEBUG ) { ! 312: printf( "[findcalls]\tbut it's a botch\n" ); ! 313: } ! 314: # endif DEBUG ! 315: length = 1; ! 316: continue; ! 317: } ! 318: } ! 319: } ! 320: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.