* Copyright (c) 1982, 1986 Regents of the University of California.
* %sccs.include.redist.c%
* @(#)subr_prof.c 7.8 (Berkeley) %G%
* Froms is actually a bunch of unsigned shorts indexing tos
struct tostruct
*tos
= 0;
char *s_lowpc
= (char *)0x80000000;
char *s_lowpc
= (char *)0xc0000000;
char *s_lowpc
= (char *)0x00000000;
u_long fromssize
, tossize
;
* 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)s_lowpc
, HISTFRACTION
*sizeof (HISTCOUNTER
));
ROUNDUP((unsigned)s_highpc
, HISTFRACTION
*sizeof (HISTCOUNTER
));
s_textsize
= s_highpc
- s_lowpc
;
printf("Profiling kernel, s_textsize=%d [%x..%x]\n",
s_textsize
, s_lowpc
, s_highpc
);
ssiz
= (s_textsize
/ HISTFRACTION
) + sizeof (struct phdr
);
sbuf
= (u_short
*)malloc(ssiz
, M_GPROF
, M_WAITOK
);
printf("No space for monitor buffer(s)\n");
fromssize
= s_textsize
/ HASHFRACTION
;
froms
= (u_short
*)malloc(fromssize
, M_GPROF
, M_WAITOK
);
printf("No space for monitor buffer(s)\n");
tolimit
= s_textsize
* ARCDENSITY
/ 100;
else if (tolimit
> (0xffff - 1))
tossize
= tolimit
* sizeof (struct tostruct
);
tos
= (struct tostruct
*)malloc(tossize
, M_GPROF
, M_WAITOK
);
printf("No space for monitor buffer(s)\n");
free(sbuf
, M_GPROF
), sbuf
= 0;
free(froms
, M_GPROF
), froms
= 0;
((struct phdr
*)sbuf
)->lpc
= s_lowpc
;
((struct phdr
*)sbuf
)->hpc
= s_highpc
;
((struct phdr
*)sbuf
)->ncnt
= ssiz
;
kcount
= (u_short
*)(((int)sbuf
) + sizeof (struct phdr
));
* Special, non-profiled versions
#if defined(hp300) && !defined(__GNUC__)
* This routine is massaged so that it may be jsb'ed to on vax.
asm("#the beginning of mcount()");
register char *selfpc
; /* r11 => r5 */
register u_short
*frompcindex
; /* r10 => r4 */
register struct tostruct
*top
; /* r9 => r3 */
register struct tostruct
*prevtop
; /* r8 => r2 */
register long toindex
; /* r7 => r1 */
asm(" .text"); /* make sure we're in text space */
* Check that we are profiling.
* Find the return address for mcount,
* and the return address for mcount's caller.
; /* avoid label botch */
* selfpc = pc pushed by mcount jsr,
* frompcindex = pc pushed by jsr into self.
* In GCC the caller's stack frame has already been built so we
* have to chase a6 to find caller's raddr. This assumes that all
* routines we are profiling were built with GCC and that all
* profiled routines use link/unlk.
asm("movl a6@(4),%0" : "=r" (selfpc
));
asm("movl a6@(0)@(4),%0" : "=r" (frompcindex
));
asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */
asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */
asm(" movl -8(fp),r12"); /* selfpc = callf frame */
asm(" movl -8(r11),r11"); /* frompcindex = 1 callf frame back */
asm(" .text"); /* make sure we're in text space */
asm(" movl a6@(4),a5"); /* selfpc = pc pushed by mcount jsr */
asm(" movl a6@(8),a4"); /* frompcindex = pc pushed by jsr into
self, stack frame not yet built */
#endif /* not __GNUC__ */
* Insure that we cannot be recursively invoked.
* this requires that splhigh() and splx() below
#if defined(hp300) && defined(__GNUC__)
asm("movw sr,%0" : "=g" (s
));
* Check that frompcindex is a reasonable pc value.
* For example: signal catchers get called from the stack,
* not from text space. too bad.
frompcindex
= (u_short
*)((long)frompcindex
- (long)s_lowpc
);
if ((u_long
)frompcindex
> s_textsize
)
&froms
[((long)frompcindex
) / (HASHFRACTION
* sizeof (*froms
))];
* First time traversing this arc
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.
top
->link
= *frompcindex
;
* Otherwise, check the next arc on the chain.
if (top
->selfpc
== selfpc
) {
* There it is, increment its count and
* move it to the head of the chain.
prevtop
->link
= top
->link
;
top
->link
= *frompcindex
;
#if defined(hp300) && defined(__GNUC__)
asm("movw %0,sr" : : "g" (s
));
printf("mcount: tos overflow\n");
asm("#the end of mcount()");