| 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 | int |
| 51 | iscall (unsigned char *ip) { |
| 52 | if (*ip == 0xeb || *ip == 0x9a) |
| 53 | return 1; |
| 54 | return 0; |
| 55 | } |
| 56 | |
| 57 | findcall( parentp , p_lowpc , p_highpc ) |
| 58 | nltype *parentp; |
| 59 | unsigned long p_lowpc; |
| 60 | unsigned long p_highpc; |
| 61 | { |
| 62 | unsigned char *instructp; |
| 63 | long length; |
| 64 | nltype *childp; |
| 65 | unsigned long destpc; |
| 66 | |
| 67 | if ( textspace == 0 ) { |
| 68 | return; |
| 69 | } |
| 70 | if ( p_lowpc < s_lowpc ) { |
| 71 | p_lowpc = s_lowpc; |
| 72 | } |
| 73 | if ( p_highpc > s_highpc ) { |
| 74 | p_highpc = s_highpc; |
| 75 | } |
| 76 | # ifdef DEBUG |
| 77 | if ( debug & CALLDEBUG ) { |
| 78 | printf( "[findcall] %s: 0x%x to 0x%x\n" , |
| 79 | parentp -> name , p_lowpc , p_highpc ); |
| 80 | } |
| 81 | # endif DEBUG |
| 82 | for ( instructp = textspace + p_lowpc ; |
| 83 | instructp < textspace + p_highpc ; |
| 84 | instructp += length ) { |
| 85 | length = 1; |
| 86 | if ( iscall (instructp) ) { |
| 87 | # ifdef DEBUG |
| 88 | if ( debug & CALLDEBUG ) { |
| 89 | printf( "[findcall]\t0x%x:callf" , instructp - textspace ); |
| 90 | } |
| 91 | # endif DEBUG |
| 92 | length = 4; |
| 93 | /* |
| 94 | * regular pc relative addressing |
| 95 | * check that this is the address of |
| 96 | * a function. |
| 97 | */ |
| 98 | destpc = ( (unsigned long)instructp + 5 - (unsigned long) textspace); |
| 99 | if ( destpc >= s_lowpc && destpc <= s_highpc ) { |
| 100 | childp = nllookup( destpc ); |
| 101 | # ifdef DEBUG |
| 102 | if ( debug & CALLDEBUG ) { |
| 103 | printf( "[findcall]\tdestpc 0x%x" , destpc ); |
| 104 | printf( " childp->name %s" , childp -> name ); |
| 105 | printf( " childp->value 0x%x\n" , |
| 106 | childp -> value ); |
| 107 | } |
| 108 | # endif DEBUG |
| 109 | if ( childp -> value == destpc ) { |
| 110 | /* |
| 111 | * a hit |
| 112 | */ |
| 113 | addarc( parentp , childp , (long) 0 ); |
| 114 | length += 4; /* constant lengths */ |
| 115 | continue; |
| 116 | } |
| 117 | goto botched; |
| 118 | } |
| 119 | /* |
| 120 | * else: |
| 121 | * it looked like a callf, |
| 122 | * but it wasn't to anywhere. |
| 123 | */ |
| 124 | botched: |
| 125 | /* |
| 126 | * something funny going on. |
| 127 | */ |
| 128 | # ifdef DEBUG |
| 129 | if ( debug & CALLDEBUG ) { |
| 130 | printf( "[findcall]\tbut it's a botch\n" ); |
| 131 | } |
| 132 | # endif DEBUG |
| 133 | length = 1; |
| 134 | continue; |
| 135 | } |
| 136 | } |
| 137 | } |