Annotation of 43BSD/ucb/gprof/calls.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.