/* * Entry point from instrumented code. * This is called once per basic-block/edge. */ void notrace __sanitizer_cov_trace_pc(void) { struct task_struct *t; enum kcov_mode mode; t = current; /* * We are interested in code coverage as a function of a syscall inputs, * so we ignore code executed in interrupts. * The checks for whether we are in an interrupt are open-coded, because * 1. We can't use in_interrupt() here, since it also returns true * when we are inside local_bh_disable() section. * 2. We don't want to use (in_irq() | in_serving_softirq() | in_nmi()), * since that leads to slower generated code (three separate tests, * one for each of the flags). */ if (!t || (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_OFFSET | NMI_MASK))) return; mode = READ_ONCE(t->kcov_mode); if (mode == KCOV_MODE_TRACE) { unsigned long *area; unsigned long pos; unsigned long ip = _RET_IP_; #ifdef CONFIG_RANDOMIZE_BASE ip -= kaslr_offset(); #endif /* * There is some code that runs in interrupts but for which * in_interrupt() returns false (e.g. preempt_schedule_irq()). * READ_ONCE()/barrier() effectively provides load-acquire wrt * interrupts, there are paired barrier()/WRITE_ONCE() in * kcov_ioctl_locked(). */ barrier(); area = t->kcov_area; /* The first word is number of subsequent PCs. */ pos = READ_ONCE(area[0]) + 1; if (likely(pos < t->kcov_size)) { area[pos] = ip; WRITE_ONCE(area[0], pos); } } }
/* * Entry point from instrumented code. * This is called once per basic-block/edge. */ void notrace __sanitizer_cov_trace_pc(void) { struct task_struct *t; enum kcov_mode mode; t = current; /* * We are interested in code coverage as a function of a syscall inputs, * so we ignore code executed in interrupts. */ if (!t || !in_task()) return; mode = READ_ONCE(t->kcov_mode); if (mode == KCOV_MODE_TRACE) { unsigned long *area; unsigned long pos; unsigned long ip = _RET_IP_; #ifdef CONFIG_RANDOMIZE_BASE ip -= kaslr_offset(); #endif /* * There is some code that runs in interrupts but for which * in_interrupt() returns false (e.g. preempt_schedule_irq()). * READ_ONCE()/barrier() effectively provides load-acquire wrt * interrupts, there are paired barrier()/WRITE_ONCE() in * kcov_ioctl_locked(). */ barrier(); area = t->kcov_area; /* The first word is number of subsequent PCs. */ pos = READ_ONCE(area[0]) + 1; if (likely(pos < t->kcov_size)) { area[pos] = ip; WRITE_ONCE(area[0], pos); } } }