diff --git a/sys/kern/subr_prof.c b/sys/kern/subr_prof.c index 479d95339d02..adb6147f94f4 100644 --- a/sys/kern/subr_prof.c +++ b/sys/kern/subr_prof.c @@ -157,6 +157,7 @@ kmstartup(dummy) uintfptr_t tmp_addr; #endif + tcov_init(); /* * 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. @@ -531,3 +532,49 @@ addupc_task(ke, pc, ticks) } stopprofclock(p); } + +#if defined(__i386__) && __GNUC__ >= 2 +/* + * Support for "--test-coverage --profile-arcs" in GCC. + * + * We need to call all the functions in the .ctor section, in order + * to get all the counter-arrays strung into a list. + * + * XXX: the .ctors call __bb_init_func which is located in over in + * XXX: i386/i386/support.s for historical reasons. There is probably + * XXX: no reason for that to be assembler anymore, but doing it right + * XXX: in MI C code requires one to reverse-engineer the type-selection + * XXX: inside GCC. Have fun. + * + * XXX: Worrisome perspective: Calling the .ctors may make C++ in the + * XXX: kernel feasible. Don't. + */ +typedef void (*ctor_t)(void); +extern ctor_t _start_ctors, _stop_ctors; + +static void +tcov_init(void *foo __unused) +{ + ctor_t *p, q; + + for (p = &_start_ctors; p < &_stop_ctors; p++) { + q = *p; + q(); + } +} + +SYSINIT(kmem, SI_SUB_KPROF, SI_ORDER_SECOND, tcov_init, NULL) + +/* + * GCC contains magic to recognize calls to for instance execve() and + * puts in calls to this function to preserve the profile counters. + * XXX: Put zinging punchline here. + */ +void __bb_fork_func(void); +void +__bb_fork_func(void) +{ +} + +#endif +