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