// SPDX-License-Identifier: GPL-2.01/*2* This code maintains a list of active profiling data structures.3*4* Copyright IBM Corp. 20095* Author(s): Peter Oberparleiter <[email protected]>6*7* Uses gcc-internal data definitions.8* Based on the gcov-kernel patch by:9* Hubertus Franke <[email protected]>10* Nigel Hinds <[email protected]>11* Rajan Ravindran <[email protected]>12* Peter Oberparleiter <[email protected]>13* Paul Larson14*/1516#define pr_fmt(fmt) "gcov: " fmt1718#include <linux/init.h>19#include <linux/module.h>20#include <linux/mutex.h>21#include <linux/sched.h>22#include "gcov.h"2324int gcov_events_enabled;25DEFINE_MUTEX(gcov_lock);2627/**28* gcov_enable_events - enable event reporting through gcov_event()29*30* Turn on reporting of profiling data load/unload-events through the31* gcov_event() callback. Also replay all previous events once. This function32* is needed because some events are potentially generated too early for the33* callback implementation to handle them initially.34*/35void gcov_enable_events(void)36{37struct gcov_info *info = NULL;3839mutex_lock(&gcov_lock);40gcov_events_enabled = 1;4142/* Perform event callback for previously registered entries. */43while ((info = gcov_info_next(info))) {44gcov_event(GCOV_ADD, info);45cond_resched();46}4748mutex_unlock(&gcov_lock);49}5051/**52* store_gcov_u32 - store 32 bit number in gcov format to buffer53* @buffer: target buffer or NULL54* @off: offset into the buffer55* @v: value to be stored56*57* Number format defined by gcc: numbers are recorded in the 32 bit58* unsigned binary form of the endianness of the machine generating the59* file. Returns the number of bytes stored. If @buffer is %NULL, doesn't60* store anything.61*/62size_t store_gcov_u32(void *buffer, size_t off, u32 v)63{64u32 *data;6566if (buffer) {67data = buffer + off;68*data = v;69}7071return sizeof(*data);72}7374/**75* store_gcov_u64 - store 64 bit number in gcov format to buffer76* @buffer: target buffer or NULL77* @off: offset into the buffer78* @v: value to be stored79*80* Number format defined by gcc: numbers are recorded in the 32 bit81* unsigned binary form of the endianness of the machine generating the82* file. 64 bit numbers are stored as two 32 bit numbers, the low part83* first. Returns the number of bytes stored. If @buffer is %NULL, doesn't store84* anything.85*/86size_t store_gcov_u64(void *buffer, size_t off, u64 v)87{88u32 *data;8990if (buffer) {91data = buffer + off;9293data[0] = (v & 0xffffffffUL);94data[1] = (v >> 32);95}9697return sizeof(*data) * 2;98}99100#ifdef CONFIG_MODULES101/* Update list and generate events when modules are unloaded. */102static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,103void *data)104{105struct module *mod = data;106struct gcov_info *info = NULL;107struct gcov_info *prev = NULL;108109if (event != MODULE_STATE_GOING)110return NOTIFY_OK;111mutex_lock(&gcov_lock);112113/* Remove entries located in module from linked list. */114while ((info = gcov_info_next(info))) {115if (gcov_info_within_module(info, mod)) {116gcov_info_unlink(prev, info);117if (gcov_events_enabled)118gcov_event(GCOV_REMOVE, info);119} else120prev = info;121}122123mutex_unlock(&gcov_lock);124125return NOTIFY_OK;126}127128static struct notifier_block gcov_nb = {129.notifier_call = gcov_module_notifier,130};131132static int __init gcov_init(void)133{134return register_module_notifier(&gcov_nb);135}136device_initcall(gcov_init);137#endif /* CONFIG_MODULES */138139140