Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  This code maintains a list of active profiling data structures.
0004  *
0005  *    Copyright IBM Corp. 2009
0006  *    Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
0007  *
0008  *    Uses gcc-internal data definitions.
0009  *    Based on the gcov-kernel patch by:
0010  *       Hubertus Franke <frankeh@us.ibm.com>
0011  *       Nigel Hinds <nhinds@us.ibm.com>
0012  *       Rajan Ravindran <rajancr@us.ibm.com>
0013  *       Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
0014  *       Paul Larson
0015  */
0016 
0017 #define pr_fmt(fmt) "gcov: " fmt
0018 
0019 #include <linux/init.h>
0020 #include <linux/module.h>
0021 #include <linux/mutex.h>
0022 #include <linux/sched.h>
0023 #include "gcov.h"
0024 
0025 int gcov_events_enabled;
0026 DEFINE_MUTEX(gcov_lock);
0027 
0028 /**
0029  * gcov_enable_events - enable event reporting through gcov_event()
0030  *
0031  * Turn on reporting of profiling data load/unload-events through the
0032  * gcov_event() callback. Also replay all previous events once. This function
0033  * is needed because some events are potentially generated too early for the
0034  * callback implementation to handle them initially.
0035  */
0036 void gcov_enable_events(void)
0037 {
0038     struct gcov_info *info = NULL;
0039 
0040     mutex_lock(&gcov_lock);
0041     gcov_events_enabled = 1;
0042 
0043     /* Perform event callback for previously registered entries. */
0044     while ((info = gcov_info_next(info))) {
0045         gcov_event(GCOV_ADD, info);
0046         cond_resched();
0047     }
0048 
0049     mutex_unlock(&gcov_lock);
0050 }
0051 
0052 /**
0053  * store_gcov_u32 - store 32 bit number in gcov format to buffer
0054  * @buffer: target buffer or NULL
0055  * @off: offset into the buffer
0056  * @v: value to be stored
0057  *
0058  * Number format defined by gcc: numbers are recorded in the 32 bit
0059  * unsigned binary form of the endianness of the machine generating the
0060  * file. Returns the number of bytes stored. If @buffer is %NULL, doesn't
0061  * store anything.
0062  */
0063 size_t store_gcov_u32(void *buffer, size_t off, u32 v)
0064 {
0065     u32 *data;
0066 
0067     if (buffer) {
0068         data = buffer + off;
0069         *data = v;
0070     }
0071 
0072     return sizeof(*data);
0073 }
0074 
0075 /**
0076  * store_gcov_u64 - store 64 bit number in gcov format to buffer
0077  * @buffer: target buffer or NULL
0078  * @off: offset into the buffer
0079  * @v: value to be stored
0080  *
0081  * Number format defined by gcc: numbers are recorded in the 32 bit
0082  * unsigned binary form of the endianness of the machine generating the
0083  * file. 64 bit numbers are stored as two 32 bit numbers, the low part
0084  * first. Returns the number of bytes stored. If @buffer is %NULL, doesn't store
0085  * anything.
0086  */
0087 size_t store_gcov_u64(void *buffer, size_t off, u64 v)
0088 {
0089     u32 *data;
0090 
0091     if (buffer) {
0092         data = buffer + off;
0093 
0094         data[0] = (v & 0xffffffffUL);
0095         data[1] = (v >> 32);
0096     }
0097 
0098     return sizeof(*data) * 2;
0099 }
0100 
0101 #ifdef CONFIG_MODULES
0102 /* Update list and generate events when modules are unloaded. */
0103 static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,
0104                 void *data)
0105 {
0106     struct module *mod = data;
0107     struct gcov_info *info = NULL;
0108     struct gcov_info *prev = NULL;
0109 
0110     if (event != MODULE_STATE_GOING)
0111         return NOTIFY_OK;
0112     mutex_lock(&gcov_lock);
0113 
0114     /* Remove entries located in module from linked list. */
0115     while ((info = gcov_info_next(info))) {
0116         if (gcov_info_within_module(info, mod)) {
0117             gcov_info_unlink(prev, info);
0118             if (gcov_events_enabled)
0119                 gcov_event(GCOV_REMOVE, info);
0120         } else
0121             prev = info;
0122     }
0123 
0124     mutex_unlock(&gcov_lock);
0125 
0126     return NOTIFY_OK;
0127 }
0128 
0129 static struct notifier_block gcov_nb = {
0130     .notifier_call  = gcov_module_notifier,
0131 };
0132 
0133 static int __init gcov_init(void)
0134 {
0135     return register_module_notifier(&gcov_nb);
0136 }
0137 device_initcall(gcov_init);
0138 #endif /* CONFIG_MODULES */