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