* Copyright (c) 1983 The Regents of the University of California.
* This module is believed to contain source code proprietary to AT&T.
* Use and redistribution is subject to the Berkeley Software License
* Agreement and your Software Agreement with AT&T (Western Electric).
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid
[] = "@(#)gmon.c 5.5 (Berkeley) 4/12/91";
#endif /* LIBC_SCCS and not lint */
* froms is actually a bunch of unsigned shorts indexing tos
static int profiling
= 3;
static unsigned short *froms
;
static struct tostruct
*tos
= 0;
static char *s_lowpc
= 0;
static char *s_highpc
= 0;
static unsigned long s_textsize
= 0;
/* see profil(2) where this is describe (incorrectly) */
#define SCALE_1_TO_1 0x10000L
#define MSG "No space for monitor buffer(s)\n"
monstartup(lowpc
, highpc
)
* round lowpc and highpc to multiples of the density we're using
* so the rest of the scaling (here and in gprof) stays in ints.
ROUNDDOWN((unsigned)lowpc
, HISTFRACTION
*sizeof(HISTCOUNTER
));
ROUNDUP((unsigned)highpc
, HISTFRACTION
*sizeof(HISTCOUNTER
));
s_textsize
= highpc
- lowpc
;
monsize
= (s_textsize
/ HISTFRACTION
) + sizeof(struct phdr
);
buffer
= sbrk( monsize
);
if ( buffer
== (char *) -1 ) {
write( 2 , MSG
, sizeof(MSG
) - 1 );
froms
= (unsigned short *) sbrk( s_textsize
/ HASHFRACTION
);
if ( froms
== (unsigned short *) -1 ) {
write( 2 , MSG
, sizeof(MSG
) - 1 );
tolimit
= s_textsize
* ARCDENSITY
/ 100;
if ( tolimit
< MINARCS
) {
} else if ( tolimit
> 65534 ) {
tos
= (struct tostruct
*) sbrk( tolimit
* sizeof( struct tostruct
) );
if ( tos
== (struct tostruct
*) -1 ) {
write( 2 , MSG
, sizeof(MSG
) - 1 );
monitor( lowpc
, highpc
, buffer
, monsize
, tolimit
);
fd
= creat( "gmon.out" , 0666 );
perror( "mcount: gmon.out" );
fprintf( stderr
, "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf
, ssiz
);
write( fd
, sbuf
, ssiz
);
endfrom
= s_textsize
/ (HASHFRACTION
* sizeof(*froms
));
for ( fromindex
= 0 ; fromindex
< endfrom
; fromindex
++ ) {
if ( froms
[fromindex
] == 0 ) {
frompc
= s_lowpc
+ (fromindex
* HASHFRACTION
* sizeof(*froms
));
for (toindex
=froms
[fromindex
]; toindex
!=0; toindex
=tos
[toindex
].link
) {
"[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
frompc
, tos
[toindex
].selfpc
, tos
[toindex
].count
);
rawarc
.raw_frompc
= (unsigned long) frompc
;
rawarc
.raw_selfpc
= (unsigned long) tos
[toindex
].selfpc
;
rawarc
.raw_count
= tos
[toindex
].count
;
write( fd
, &rawarc
, sizeof rawarc
);
asm("#the beginning of mcount()");
register char *selfpc
; /* r11 => r5 */
register unsigned short *frompcindex
; /* r10 => r4 */
register struct tostruct
*top
; /* r9 => r3 */
register struct tostruct
*prevtop
; /* r8 => r2 */
register long toindex
; /* r7 => r1 */
* find the return address for mcount,
* and the return address for mcount's caller.
asm(" .text"); /* make sure we're in text space */
asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */
asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */
* check that we are profiling
* and that we aren't recursively invoked.
* check that frompcindex is a reasonable pc value.
* for example: signal catchers get called from the stack,
* not from text space. too bad.
frompcindex
= (unsigned short *)((long)frompcindex
- (long)s_lowpc
);
if ((unsigned long)frompcindex
> s_textsize
) {
&froms
[((long)frompcindex
) / (HASHFRACTION
* sizeof(*froms
))];
* first time traversing this arc
if (toindex
>= tolimit
) {
if (top
->selfpc
== selfpc
) {
* arc at front of chain; usual case.
* have to go looking down chain for it.
* top points to what we are looking at,
* prevtop points to previous top.
* we know it is not at the head of the chain.
for (; /* goto done */; ) {
* top is end of the chain and none of the chain
* had top->selfpc == selfpc.
* so we allocate a new tostruct
* and link it to the head of the chain.
if (toindex
>= tolimit
) {
top
->link
= *frompcindex
;
* otherwise, check the next arc on the chain.
if (top
->selfpc
== selfpc
) {
* move it to the head of the chain.
prevtop
->link
= top
->link
;
top
->link
= *frompcindex
;
profiling
++; /* halt further profiling */
# define TOLIMIT "mcount: tos overflow\n"
write(2, TOLIMIT
, sizeof(TOLIMIT
) - 1);
asm("#the end of mcount()");
monitor( lowpc
, highpc
, buf
, bufsiz
, nfunc
)
char *buf
; /* declared ``short buffer[]'' in monitor(3) */
int nfunc
; /* not used, available for compatability only */
( (struct phdr
*) buf
) -> lpc
= lowpc
;
( (struct phdr
*) buf
) -> hpc
= highpc
;
( (struct phdr
*) buf
) -> ncnt
= ssiz
;
bufsiz
-= sizeof(struct phdr
);
s_scale
= ( (float) bufsiz
/ o
) * SCALE_1_TO_1
;
* profiling is what mcount checks to see if
* all the data structures are ready.
profil(sbuf
+ sizeof(struct phdr
), ssiz
- sizeof(struct phdr
),
profil((char *)0, 0, 0, 0);