* Copyright (c) 1982, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)subr_prof.c 7.4 (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;
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
));
* Profiling is what mcount checks to see if
* all the data structures are ready!!!
profiling
= 0; /* patch by hand when you're ready */
* 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.
asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */
asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */
; /* avoid label botch */
asm(" movl -8(fp),r12"); /* selfpc = callf frame */
asm(" movl -8(r11),r11"); /* frompcindex = 1 callf frame back */
* Insure that we cannot be recursively invoked.
* this requires that splhigh() and splx() below
* 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
;
printf("mcount: tos overflow\n");
asm("#the end of mcount()");