home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / gcc-2.3.3-src.lha / GNU / src / amiga / gcc-2.3.3 / config / gmon-sol2.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  11KB  |  400 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. /* Mangled into a form that works on Sparc Solaris 2 by Mark Eichin
  35.  * for Cygnus Support, July 1992.
  36.  */
  37.  
  38. #ifndef lint
  39. static char sccsid[] = "@(#)gmon.c    5.3 (Berkeley) 5/22/91";
  40. #endif /* not lint */
  41.  
  42. #include <unistd.h>
  43.  
  44. #ifdef DEBUG
  45. #include <stdio.h>
  46. #endif
  47.  
  48. #if 0
  49. #include "gmon.h"
  50. #else
  51. struct phdr {
  52.   char *lpc;
  53.   char *hpc;
  54.   int ncnt;
  55. };
  56. #define HISTFRACTION 2
  57. #define HISTCOUNTER unsigned short
  58. #define HASHFRACTION 1
  59. #define ARCDENSITY 2
  60. #define MINARCS 50
  61. struct tostruct {
  62.   char *selfpc;
  63.   long count;
  64.   unsigned short link;
  65. };
  66. struct rawarc {
  67.     unsigned long       raw_frompc;
  68.     unsigned long       raw_selfpc;
  69.     long                raw_count;
  70. };
  71. #define ROUNDDOWN(x,y)  (((x)/(y))*(y))
  72. #define ROUNDUP(x,y)    ((((x)+(y)-1)/(y))*(y))
  73.  
  74. #endif
  75.  
  76. /* extern mcount() asm ("mcount"); */
  77. /*extern*/ char *minbrk /* asm ("minbrk") */;
  78.  
  79.     /*
  80.      *    froms is actually a bunch of unsigned shorts indexing tos
  81.      */
  82. static int        profiling = 3;
  83. static unsigned short    *froms;
  84. static struct tostruct    *tos = 0;
  85. static long        tolimit = 0;
  86. static char        *s_lowpc = 0;
  87. static char        *s_highpc = 0;
  88. static unsigned long    s_textsize = 0;
  89.  
  90. static int    ssiz;
  91. static char    *sbuf;
  92. static int    s_scale;
  93.     /* see profil(2) where this is describe (incorrectly) */
  94. #define        SCALE_1_TO_1    0x10000L
  95.  
  96. #define    MSG "No space for profiling buffer(s)\n"
  97.  
  98. monstartup(lowpc, highpc)
  99.     char    *lowpc;
  100.     char    *highpc;
  101. {
  102.     int            monsize;
  103.     char        *buffer;
  104.     register int    o;
  105.  
  106.     /*
  107.      *    round lowpc and highpc to multiples of the density we're using
  108.      *    so the rest of the scaling (here and in gprof) stays in ints.
  109.      */
  110.     lowpc = (char *)
  111.         ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
  112.     s_lowpc = lowpc;
  113.     highpc = (char *)
  114.         ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
  115.     s_highpc = highpc;
  116.     s_textsize = highpc - lowpc;
  117.     monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
  118.     buffer = sbrk( monsize );
  119.     if ( buffer == (char *) -1 ) {
  120.     write( 2 , MSG , sizeof(MSG) );
  121.     return;
  122.     }
  123.     froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
  124.     if ( froms == (unsigned short *) -1 ) {
  125.     write( 2 , MSG , sizeof(MSG) );
  126.     froms = 0;
  127.     return;
  128.     }
  129.     tolimit = s_textsize * ARCDENSITY / 100;
  130.     if ( tolimit < MINARCS ) {
  131.     tolimit = MINARCS;
  132.     } else if ( tolimit > 65534 ) {
  133.     tolimit = 65534;
  134.     }
  135.     tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
  136.     if ( tos == (struct tostruct *) -1 ) {
  137.     write( 2 , MSG , sizeof(MSG) );
  138.     froms = 0;
  139.     tos = 0;
  140.     return;
  141.     }
  142.     minbrk = sbrk(0);
  143.     tos[0].link = 0;
  144.     sbuf = buffer;
  145.     ssiz = monsize;
  146.     ( (struct phdr *) buffer ) -> lpc = lowpc;
  147.     ( (struct phdr *) buffer ) -> hpc = highpc;
  148.     ( (struct phdr *) buffer ) -> ncnt = ssiz;
  149.     monsize -= sizeof(struct phdr);
  150.     if ( monsize <= 0 )
  151.     return;
  152.     o = highpc - lowpc;
  153.     if( monsize < o )
  154. #ifndef hp300
  155.     s_scale = ( (float) monsize / o ) * SCALE_1_TO_1;
  156. #else /* avoid floating point */
  157.     {
  158.     int quot = o / monsize;
  159.  
  160.     if (quot >= 0x10000)
  161.         s_scale = 1;
  162.     else if (quot >= 0x100)
  163.         s_scale = 0x10000 / quot;
  164.     else if (o >= 0x800000)
  165.         s_scale = 0x1000000 / (o / (monsize >> 8));
  166.     else
  167.         s_scale = 0x1000000 / ((o << 8) / monsize);
  168.     }
  169. #endif
  170.     else
  171.     s_scale = SCALE_1_TO_1;
  172.     moncontrol(1);
  173. }
  174.  
  175. _mcleanup()
  176. {
  177.     int            fd;
  178.     int            fromindex;
  179.     int            endfrom;
  180.     char        *frompc;
  181.     int            toindex;
  182.     struct rawarc    rawarc;
  183.  
  184.     moncontrol(0);
  185.     fd = creat( "gmon.out" , 0666 );
  186.     if ( fd < 0 ) {
  187.     perror( "mcount: gmon.out" );
  188.     return;
  189.     }
  190. #   ifdef DEBUG
  191.     fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
  192. #   endif DEBUG
  193.     write( fd , sbuf , ssiz );
  194.     endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
  195.     for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
  196.     if ( froms[fromindex] == 0 ) {
  197.         continue;
  198.     }
  199.     frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
  200.     for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
  201. #        ifdef DEBUG
  202.         fprintf( stderr ,
  203.             "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
  204.             frompc , tos[toindex].selfpc , tos[toindex].count );
  205. #        endif DEBUG
  206.         rawarc.raw_frompc = (unsigned long) frompc;
  207.         rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
  208.         rawarc.raw_count = tos[toindex].count;
  209.         write( fd , &rawarc , sizeof rawarc );
  210.     }
  211.     }
  212.     close( fd );
  213. }
  214.  
  215. /*
  216.  * The Sparc stack frame is only held together by the frame pointers
  217.  * in the register windows. According to the SVR4 SPARC ABI
  218.  * Supplement, Low Level System Information/Operating System
  219.  * Interface/Software Trap Types, a type 3 trap will flush all of the
  220.  * register windows to the stack, which will make it possible to walk
  221.  * the frames and find the return addresses.
  222.  *     However, it seems awfully expensive to incur a trap (system
  223.  * call) for every function call. It turns out that "call" simply puts
  224.  * the return address in %o7 expecting the "save" in the procedure to
  225.  * shift it into %i7; this means that before the "save" occurs, %o7
  226.  * contains the address of the call to mcount, and %i7 still contains
  227.  * the caller above that. The asm mcount here simply saves those
  228.  * registers in argument registers and branches to internal_mcount,
  229.  * simulating a call with arguments.
  230.  *     Kludges:
  231.  *     1) the branch to internal_mcount is hard coded; it should be
  232.  * possible to tell asm to use the assembler-name of a symbol.
  233.  *     2) in theory, the function calling mcount could have saved %i7
  234.  * somewhere and reused the register; in practice, I *think* this will
  235.  * break longjmp (and maybe the debugger) but I'm not certain. (I take
  236.  * some comfort in the knowledge that it will break the native mcount
  237.  * as well.)
  238.  *     3) if builtin_return_address worked, this could be portable.
  239.  * However, it would really have to be optimized for arguments of 0
  240.  * and 1 and do something like what we have here in order to avoid the
  241.  * trap per function call performance hit. 
  242.  *     4) the atexit and monsetup calls prevent this from simply
  243.  * being a leaf routine that doesn't do a "save" (and would thus have
  244.  * access to %o7 and %i7 directly) but the call to write() at the end
  245.  * would have also prevented this.
  246.  *
  247.  * -- [eichin:19920702.1107EST]
  248.  */
  249.  
  250. /* i7 == last ret, -> frompcindex */
  251. /* o7 == current ret, -> selfpc */
  252. asm(".global mcount; mcount: mov %i7,%o1; mov %o7,%o0