180544aebSJohn Birrell /*- 280544aebSJohn Birrell * Copyright (c) 2007-2008 John Birrell <jb@FreeBSD.org> 380544aebSJohn Birrell * All rights reserved. 480544aebSJohn Birrell * 580544aebSJohn Birrell * Redistribution and use in source and binary forms, with or without 680544aebSJohn Birrell * modification, are permitted provided that the following conditions 780544aebSJohn Birrell * are met: 880544aebSJohn Birrell * 1. Redistributions of source code must retain the above copyright 980544aebSJohn Birrell * notice, this list of conditions and the following disclaimer. 1080544aebSJohn Birrell * 2. Redistributions in binary form must reproduce the above copyright 1180544aebSJohn Birrell * notice, this list of conditions and the following disclaimer in the 1280544aebSJohn Birrell * documentation and/or other materials provided with the distribution. 1380544aebSJohn Birrell * 1480544aebSJohn Birrell * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1580544aebSJohn Birrell * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1680544aebSJohn Birrell * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1780544aebSJohn Birrell * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1880544aebSJohn Birrell * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1980544aebSJohn Birrell * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2080544aebSJohn Birrell * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2180544aebSJohn Birrell * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2280544aebSJohn Birrell * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2380544aebSJohn Birrell * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2480544aebSJohn Birrell * SUCH DAMAGE. 2580544aebSJohn Birrell */ 2680544aebSJohn Birrell 2780544aebSJohn Birrell #include <sys/cdefs.h> 2880544aebSJohn Birrell __FBSDID("$FreeBSD$"); 2980544aebSJohn Birrell 3080544aebSJohn Birrell #include "opt_kdb.h" 3180544aebSJohn Birrell 3280544aebSJohn Birrell #include <sys/param.h> 3380544aebSJohn Birrell #include <sys/systm.h> 3480544aebSJohn Birrell #include <sys/eventhandler.h> 3580544aebSJohn Birrell #include <sys/kdb.h> 3680544aebSJohn Birrell #include <sys/kernel.h> 3780544aebSJohn Birrell #include <sys/malloc.h> 3880544aebSJohn Birrell #include <sys/proc.h> 3980544aebSJohn Birrell #include <sys/dtrace_bsd.h> 40de5b1952SAlexander Leidinger #include <sys/sysctl.h> 41*f2789bd5SMark Johnston #include <sys/sysent.h> 4280544aebSJohn Birrell 4380544aebSJohn Birrell #define KDTRACE_PROC_SIZE 64 4480544aebSJohn Birrell #define KDTRACE_THREAD_SIZE 256 4580544aebSJohn Birrell 46de5b1952SAlexander Leidinger FEATURE(kdtrace_hooks, 47de5b1952SAlexander Leidinger "Kernel DTrace hooks which are required to load DTrace kernel modules"); 48de5b1952SAlexander Leidinger 49d745c852SEd Schouten static MALLOC_DEFINE(M_KDTRACE, "kdtrace", "DTrace hooks"); 5080544aebSJohn Birrell 51*f2789bd5SMark Johnston /* Hooks used in the machine-dependent trap handlers. */ 52*f2789bd5SMark Johnston dtrace_trap_func_t dtrace_trap_func; 53*f2789bd5SMark Johnston dtrace_doubletrap_func_t dtrace_doubletrap_func; 54*f2789bd5SMark Johnston dtrace_pid_probe_ptr_t dtrace_pid_probe_ptr; 55*f2789bd5SMark Johnston dtrace_return_probe_ptr_t dtrace_return_probe_ptr; 56*f2789bd5SMark Johnston 57*f2789bd5SMark Johnston systrace_probe_func_t systrace_probe_func; 58*f2789bd5SMark Johnston 5980544aebSJohn Birrell /* Return the DTrace process data size compiled in the kernel hooks. */ 6080544aebSJohn Birrell size_t 6180544aebSJohn Birrell kdtrace_proc_size() 6280544aebSJohn Birrell { 639f3a1843SRui Paulo 6480544aebSJohn Birrell return (KDTRACE_PROC_SIZE); 6580544aebSJohn Birrell } 6680544aebSJohn Birrell 6780544aebSJohn Birrell static void 6880544aebSJohn Birrell kdtrace_proc_ctor(void *arg __unused, struct proc *p) 6980544aebSJohn Birrell { 7080544aebSJohn Birrell 71258f5a25SRui Paulo p->p_dtrace = malloc(KDTRACE_PROC_SIZE, M_KDTRACE, M_WAITOK|M_ZERO); 7280544aebSJohn Birrell } 7380544aebSJohn Birrell 7480544aebSJohn Birrell static void 7580544aebSJohn Birrell kdtrace_proc_dtor(void *arg __unused, struct proc *p) 7680544aebSJohn Birrell { 779f3a1843SRui Paulo 7880544aebSJohn Birrell if (p->p_dtrace != NULL) { 7980544aebSJohn Birrell free(p->p_dtrace, M_KDTRACE); 8080544aebSJohn Birrell p->p_dtrace = NULL; 8180544aebSJohn Birrell } 8280544aebSJohn Birrell } 8380544aebSJohn Birrell 8480544aebSJohn Birrell /* Return the DTrace thread data size compiled in the kernel hooks. */ 8580544aebSJohn Birrell size_t 8680544aebSJohn Birrell kdtrace_thread_size() 8780544aebSJohn Birrell { 88258f5a25SRui Paulo 8980544aebSJohn Birrell return (KDTRACE_THREAD_SIZE); 9080544aebSJohn Birrell } 9180544aebSJohn Birrell 9280544aebSJohn Birrell static void 9380544aebSJohn Birrell kdtrace_thread_ctor(void *arg __unused, struct thread *td) 9480544aebSJohn Birrell { 9580544aebSJohn Birrell 96258f5a25SRui Paulo td->td_dtrace = malloc(KDTRACE_THREAD_SIZE, M_KDTRACE, M_WAITOK|M_ZERO); 9780544aebSJohn Birrell } 9880544aebSJohn Birrell 9980544aebSJohn Birrell static void 10080544aebSJohn Birrell kdtrace_thread_dtor(void *arg __unused, struct thread *td) 10180544aebSJohn Birrell { 1029f3a1843SRui Paulo 10380544aebSJohn Birrell if (td->td_dtrace != NULL) { 10480544aebSJohn Birrell free(td->td_dtrace, M_KDTRACE); 10580544aebSJohn Birrell td->td_dtrace = NULL; 10680544aebSJohn Birrell } 10780544aebSJohn Birrell } 10880544aebSJohn Birrell 10980544aebSJohn Birrell /* 11080544aebSJohn Birrell * Initialise the kernel DTrace hooks. 11180544aebSJohn Birrell */ 11280544aebSJohn Birrell static void 11380544aebSJohn Birrell init_dtrace(void *dummy __unused) 11480544aebSJohn Birrell { 1159f3a1843SRui Paulo 1169f3a1843SRui Paulo EVENTHANDLER_REGISTER(process_ctor, kdtrace_proc_ctor, NULL, 1179f3a1843SRui Paulo EVENTHANDLER_PRI_ANY); 1189f3a1843SRui Paulo EVENTHANDLER_REGISTER(process_dtor, kdtrace_proc_dtor, NULL, 1199f3a1843SRui Paulo EVENTHANDLER_PRI_ANY); 1209f3a1843SRui Paulo EVENTHANDLER_REGISTER(thread_ctor, kdtrace_thread_ctor, NULL, 1219f3a1843SRui Paulo EVENTHANDLER_PRI_ANY); 1229f3a1843SRui Paulo EVENTHANDLER_REGISTER(thread_dtor, kdtrace_thread_dtor, NULL, 1239f3a1843SRui Paulo EVENTHANDLER_PRI_ANY); 12480544aebSJohn Birrell } 12580544aebSJohn Birrell 12680544aebSJohn Birrell SYSINIT(kdtrace, SI_SUB_KDTRACE, SI_ORDER_FIRST, init_dtrace, NULL); 127