123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- /*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2019, Matthew Macy <mmacy@freebsd.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
- #include <sys/cdefs.h>
- __FBSDID("$FreeBSD$");
- #include <sys/types.h>
- #include <sys/systm.h>
- #include <sys/param.h>
- #include <sys/sbuf.h>
- #include <sys/queue.h>
- #include <sys/linker.h>
- #include <sys/module.h>
- #include <sys/eventhandler.h>
- #include <sys/kernel.h>
- #include <sys/malloc.h>
- #include <sys/syslog.h>
- #include <sys/proc.h>
- #include <sys/sched.h>
- #include <sys/syslog.h>
- #include <sys/sysctl.h>
- #include <gnu/gcov/gcov.h>
- #include <sys/queue.h>
- #include "linker_if.h"
- static void gcov_invoke_ctors(void);
- static int gcov_ctors_done;
- int gcov_events_enabled;
- static int
- gcov_stats_reset_sysctl(SYSCTL_HANDLER_ARGS)
- {
- int error, v;
- v = 0;
- error = sysctl_handle_int(oidp, &v, 0, req);
- if (error)
- return (error);
- if (req->newptr == NULL)
- return (error);
- if (v == 0)
- return (0);
- gcov_stats_reset();
- return (0);
- }
- static int
- gcov_stats_enable_sysctl(SYSCTL_HANDLER_ARGS)
- {
- int error, v;
- v = gcov_events_enabled;
- error = sysctl_handle_int(oidp, &v, v, req);
- if (error)
- return (error);
- if (req->newptr == NULL)
- return (error);
- if (v == gcov_events_enabled)
- return (0);
- //gcov_events_reset();
- gcov_events_enabled = !!v;
- if (!gcov_ctors_done)
- gcov_invoke_ctors();
- if (gcov_events_enabled)
- gcov_enable_events();
- return (0);
- }
- int
- within_module(vm_offset_t addr, module_t mod)
- {
- linker_file_t link_info;
- vm_offset_t mod_addr;
- size_t mod_size;
- link_info = module_file(mod);
- mod_addr = (vm_offset_t)link_info->address;
- mod_size = link_info->size;
- if (addr >= mod_addr && addr < mod_addr + mod_size)
- return (1);
- return (0);
- }
- #define GCOV_PREFIX "_GLOBAL__sub_I_65535_0_"
- static int
- gcov_invoke_ctor(const char *name, void *arg)
- {
- void (*ctor)(void);
- c_linker_sym_t sym;
- linker_symval_t symval;
- linker_file_t lf;
- if (strstr(name, GCOV_PREFIX) == NULL)
- return (0);
- lf = arg;
- LINKER_LOOKUP_SYMBOL(lf, name, &sym);
- LINKER_SYMBOL_VALUES(lf, sym, &symval);
- ctor = (void *)symval.value;
- ctor();
- return (0);
- }
- static int
- gcov_invoke_lf_ctors(linker_file_t lf, void *arg __unused)
- {
- printf("%s processing file: %s\n", __func__, lf->filename);
- LINKER_EACH_FUNCTION_NAME(lf, gcov_invoke_ctor, lf);
- return (0);
- }
- static void
- gcov_invoke_ctors(void)
- {
- gcov_fs_init();
- linker_file_foreach(gcov_invoke_lf_ctors, NULL);
- gcov_ctors_done = 1;
- }
- static int
- gcov_init(void *arg __unused)
- {
- EVENTHANDLER_REGISTER(module_unload, gcov_module_unload, NULL, 0);
- gcov_enable_events();
- return (0);
- }
- SYSINIT(gcov_init, SI_SUB_EVENTHANDLER, SI_ORDER_ANY, gcov_init, NULL);
- static SYSCTL_NODE(_debug, OID_AUTO, gcov, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
- "gcov code coverage");
- SYSCTL_PROC(_debug_gcov, OID_AUTO, reset,
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, NULL, 0,
- gcov_stats_reset_sysctl, "I",
- "Reset all profiling counts");
- SYSCTL_PROC(_debug_gcov, OID_AUTO, enable,
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, NULL, 0,
- gcov_stats_enable_sysctl, "I",
- "Enable code coverage");
|