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