试用内核gcov
对于2.6.31及以上的内核,gcov已经默认支持:http://kernelnewbies.org/Linux_2_6_31#head-1c98f5fae2cb7f0fa65bb6de08d7c5c6475180a8
也就是不用再打补丁,执行make menuconfig,选中如下选项:
General setup —>
GCOV-based kernel profiling —>
[*] Enable gcov-based kernel profiling
[*] Profile entire Kernel
[root@localhost linux-2.6.38.8]# cat .config | grep GCOV # GCOV-based kernel profiling CONFIG_GCOV_KERNEL=y CONFIG_GCOV_PROFILE_ALL=y [root@localhost linux-2.6.38.8]#
编译安装这个内核:
[root@localhost linux-2.6.38.8]# make; make modules;make modules_install;make install;
重启机器后,mount加载debugfs文件系统,并调用gcov对相应文件做覆盖测量:
[root@localhost ~]# mount -t debugfs none /sys/kernel/debug [root@localhost ~]# cd /usr/src/linux-2.6.38.8 [root@localhost linux-2.6.38.8]# gcov kernel/gcov/base.c -o /sys/kernel/debug/gcov/usr/src/linux-2.6.38.8/kernel/gcov/ File 'kernel/gcov/base.c' Lines executed:80.00% of 45 kernel/gcov/base.c:creating 'base.c.gcov' [root@localhost linux-2.6.38.8]#
查看结果:
[root@localhost linux-2.6.38.8]# cat base.c.gcov
-: 0:Source:kernel/gcov/base.c
-: 0:Graph:/sys/kernel/debug/gcov/usr/src/linux-2.6.38.8/kernel/gcov/base.gcno
-: 0:Data:/sys/kernel/debug/gcov/usr/src/linux-2.6.38.8/kernel/gcov/base.gcda
-: 0:Runs:0
-: 0:Programs:0
-: 1:/*
-: 2: * This code maintains a list of active profiling data structures.
-: 3: *
-: 4: * Copyright IBM Corp. 2009
-: 5: * 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 Larson
-: 14: */
-: 15:
-: 16:#define pr_fmt(fmt) "gcov: " fmt
-: 17:
-: 18:#include <linux/init.h>
-: 19:#include <linux/module.h>
-: 20:#include <linux/mutex.h>
-: 21:#include "gcov.h"
-: 22:
-: 23:static struct gcov_info *gcov_info_head;
-: 24:static int gcov_events_enabled;
-: 25:static DEFINE_MUTEX(gcov_lock);
-: 26:
-: 27:/*
-: 28: * __gcov_init is called by gcc-generated constructor code for each object
-: 29: * file compiled with -fprofile-arcs.
-: 30: */
1617: 31:void __gcov_init(struct gcov_info *info)
-: 32:{
-: 33: static unsigned int gcov_version;
-: 34:
1617: 35: mutex_lock(&gcov_lock);
1617: 36: if (gcov_version == 0) {
1: 37: gcov_version = info->version;
-: 38: /*
-: 39: * Printing gcc's version magic may prove useful for debugging
-: 40: * incompatibility reports.
-: 41: */
1: 42: pr_info("version magic: 0x%x\n", gcov_version);
-: 43: }
-: 44: /*
-: 45: * Add new profiling data structure to list and inform event
-: 46: * listener.
-: 47: */
1617: 48: info->next = gcov_info_head;
1617: 49: gcov_info_head = info;
1617: 50: if (gcov_events_enabled)
257: 51: gcov_event(GCOV_ADD, info);
1617: 52: mutex_unlock(&gcov_lock);
1617: 53:}
-: 54:EXPORT_SYMBOL(__gcov_init);
-: 55:
-: 56:/*
-: 57: * These functions may be referenced by gcc-generated profiling code but serve
-: 58: * no function for kernel profiling.
-: 59: */
#####: 60:void __gcov_flush(void)
-: 61:{
-: 62: /* Unused. */
#####: 63:}
-: 64:EXPORT_SYMBOL(__gcov_flush);
-: 65:
#####: 66:void __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
-: 67:{
-: 68: /* Unused. */
#####: 69:}
-: 70:EXPORT_SYMBOL(__gcov_merge_add);
-: 71:
#####: 72:void __gcov_merge_single(gcov_type *counters, unsigned int n_counters)
-: 73:{
-: 74: /* Unused. */
#####: 75:}
-: 76:EXPORT_SYMBOL(__gcov_merge_single);
-: 77:
#####: 78:void __gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
-: 79:{
-: 80: /* Unused. */
#####: 81:}
-: 82:EXPORT_SYMBOL(__gcov_merge_delta);
-: 83:
-: 84:/**
-: 85: * gcov_enable_events - enable event reporting through gcov_event()
-: 86: *
-: 87: * Turn on reporting of profiling data load/unload-events through the
-: 88: * gcov_event() callback. Also replay all previous events once. This function
-: 89: * is needed because some events are potentially generated too early for the
-: 90: * callback implementation to handle them initially.
-: 91: */
1: 92:void gcov_enable_events(void)
-: 93:{
-: 94: struct gcov_info *info;
-: 95:
1: 96: mutex_lock(&gcov_lock);
1: 97: gcov_events_enabled = 1;
-: 98: /* Perform event callback for previously registered entries. */
1361: 99: for (info = gcov_info_head; info; info = info->next)
1360: 100: gcov_event(GCOV_ADD, info);
1: 101: mutex_unlock(&gcov_lock);
1: 102:}
-: 103:
-: 104:#ifdef CONFIG_MODULES
-: 105:static inline int within(void *addr, void *start, unsigned long size)
-: 106:{
13666: 107: return ((addr >= start) && (addr < start + size));
-: 108:}
-: 109:
-: 110:/* Update list and generate events when modules are unloaded. */
158: 111:static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,
-: 112: void *data)
-: 113:{
158: 114: struct module *mod = data;
-: 115: struct gcov_info *info;
-: 116: struct gcov_info *prev;
-: 117:
158: 118: if (event != MODULE_STATE_GOING)
149: 119: return NOTIFY_OK;
9: 120: mutex_lock(&gcov_lock);
9: 121: prev = NULL;
-: 122: /* Remove entries located in module from linked list. */
13675: 123: for (info = gcov_info_head; info; info = info->next) {
27332: 124: if (within(info, mod->module_core, mod->core_size)) {
9: 125: if (prev)
#####: 126: prev->next = info->next;
-: 127: else
9: 128: gcov_info_head = info->next;
9: 129: if (gcov_events_enabled)
9: 130: gcov_event(GCOV_REMOVE, info);
-: 131: } else
13657: 132: prev = info;
-: 133: }
9: 134: mutex_unlock(&gcov_lock);
-: 135:
9: 136: return NOTIFY_OK;
-: 137:}
-: 138:
-: 139:static struct notifier_block gcov_nb = {
-: 140: .notifier_call = gcov_module_notifier,
-: 141:};
-: 142:
1: 143:static int __init gcov_init(void)
-: 144:{
1: 145: return register_module_notifier(&gcov_nb);
-: 146:}
-: 147:device_initcall(gcov_init);
-: 148:#endif /* CONFIG_MODULES */
[root@localhost linux-2.6.38.8]#
试试其他文件:
[root@localhost linux-2.6.38.8]# gcov /usr/src/linux-2.6.38.8/drivers/net/e1000/e1000_main.c -o /sys/kernel/debug/gcov/usr/src/linux-2.6.38.8/drivers/net/e1000/
[root@localhost linux-2.6.38.8]# ls *.gcov
atomic.h.gcov getorder.h.gcov irqflags.h.gcov skbuff.h.gcov
bitops.h.gcov gfp.h.gcov kobject.h.gcov slab.h.gcov
checksum_64.h.gcov highmem.h.gcov list.h.gcov slub_def.h.gcov
device.h.gcov if_vlan.h.gcov mii.h.gcov spinlock.h.gcov
dma-mapping-common.h.gcov interrupt.h.gcov mm.h.gcov tcp.h.gcov
dma-mapping.h.gcov io.h.gcov netdevice.h.gcov thread_info.h.gcov
e1000_main.c.gcov ip.h.gcov paravirt.h.gcov uaccess.h.gcov
etherdevice.h.gcov ipv6.h.gcov pci.h.gcov
[root@localhost linux-2.6.38.8]# head e1000_main.c.gcov
-: 0:Source:drivers/net/e1000/e1000_main.c
-: 0:Graph:/sys/kernel/debug/gcov/usr/src/linux-2.6.38.8/drivers/net/e1000/e1000_main.gcno
-: 0:Data:/sys/kernel/debug/gcov/usr/src/linux-2.6.38.8/drivers/net/e1000/e1000_main.gcda
-: 0:Runs:0
-: 0:Programs:0
-: 1:/*******************************************************************************
-: 2:
-: 3: Intel PRO/1000 Linux driver
-: 4: Copyright(c) 1999 - 2006 Intel Corporation.
-: 5:
[root@localhost linux-2.6.38.8]#
的确OK。值得注意的是,不能切换当前目录,否则得到的e1000_main.c.gcov没有源代码,全是EOF(一开始,我看把我的内核源码目录 /usr/src/linux-2.6.38.8/搞得很混乱,所以切换当前目录到/tmp目录,结果发现生成的文件没有对应的源代码):
[root@localhost tmp]# head e1000_main.c.gcov
-: 0:Source:drivers/net/e1000/e1000_main.c
-: 0:Graph:/sys/kernel/debug/gcov/usr/src/linux-2.6.38.8/drivers/net/e1000/e1000_main.gcno
-: 0:Data:/sys/kernel/debug/gcov/usr/src/linux-2.6.38.8/drivers/net/e1000/e1000_main.gcda
-: 0:Runs:0
-: 0:Programs:0
-: 1:/*EOF*/
-: 2:/*EOF*/
-: 3:/*EOF*/
-: 4:/*EOF*/
-: 5:/*EOF*/
试试自定义模块:
[root@localhost module_test]# cat module_test.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#define OOPSTIMEOUT 100
static unsigned long start_time;
static unsigned int fun_hook(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
printk(KERN_DEBUG "skb data len: %u\n", skb->len);
return NF_ACCEPT;
}
static struct nf_hook_ops nf_ops = {
.hook = fun_hook,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_NAT_DST,
};
static int __init module_test_init(void)
{
int ret = 0;
start_time = jiffies;
ret = nf_register_hook(&nf_ops);
if (ret < 0) {
printk("error register hook %d.\n", ret);
return ret;
}
printk("insmod ok, start_time: %lu.\n", start_time);
return 0;
}
static void __exit module_test_exit(void)
{
nf_unregister_hook(&nf_ops);
return;
}
module_init(module_test_init);
module_exit(module_test_exit);
MODULE_LICENSE("GPL");
[root@localhost module_test]# cat Makefile
# Makefile
MDIR = $(shell pwd)
ifeq (, $(KSRC))
KSRC := /usr/src/linux-`uname -r`
endif
ifeq (, $(PROJECT_DIR))
PROJECT_DIR := $(PWD)/../
endif
module := module_test
obj-m := $(module).o
srcs = $(wildcard, *.c)
$(module)-objs := $(addsuffix .o, $(basename $(srcs)))
EXTRA_CFLAGS += -g $(FLAG) -I$(PROJECT_DIR)/inc -I${SHAREDHDR} -I$(KERNELHDR) -O2 -D__KERNEL__ -DMODULE $(INCLUDE) -DEXPORT_SYMTAB
TARGET = $(module).ko
all:
make -C $(KSRC) M=$(MDIR) modules
debug:
make EXTRA_FLAGS="${EXTRA_CFLAGS} -DDEBUG" -C $(KSRC) M=$(MDIR) modules
clean:
make -C $(KSRC) M=$(MDIR) clean
install: all
cp -f $(TARGET) $(INSTALL_DIR)
[root@localhost module_test]# make
make -C /usr/src/linux-`uname -r` M=/home/gcov/module_test modules
make[1]: Entering directory `/usr/src/linux-2.6.38.8'
CC [M] /home/gcov/module_test/module_test.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/gcov/module_test/module_test.mod.o
LD [M] /home/gcov/module_test/module_test.ko
make[1]: Leaving directory `/usr/src/linux-2.6.38.8'
[root@localhost module_test]# insmod module_test.ko
看结果:
[root@localhost module_test]# gcov /home/gcov/module_test/module_test.c -o /sys/kernel/debug/gcov/home/gcov/module_test/
File '/home/gcov/module_test/module_test.c'
Lines executed:71.43% of 14
/home/gcov/module_test/module_test.c:creating 'module_test.c.gcov'
[root@localhost module_test]# cat module_test.c.gcov
-: 0:Source:/home/gcov/module_test/module_test.c
-: 0:Graph:/sys/kernel/debug/gcov/home/gcov/module_test/module_test.gcno
-: 0:Data:/sys/kernel/debug/gcov/home/gcov/module_test/module_test.gcda
-: 0:Runs:0
-: 0:Programs:0
-: 1:
-: 2:#include <linux/kernel.h>
-: 3:#include <linux/module.h>
-: 4:#include <linux/netfilter.h>
-: 5:#include <linux/netfilter_ipv4.h>
-: 6:
-: 7:#define OOPSTIMEOUT 100
-: 8:static unsigned long start_time;
-: 9:
37: 10:static unsigned int fun_hook(unsigned int hooknum,
-: 11: struct sk_buff *skb,
-: 12: const struct net_device *in,
-: 13: const struct net_device *out,
-: 14: int (*okfn)(struct sk_buff *))
-: 15:{
37: 16: printk(KERN_DEBUG "skb data len: %u\n", skb->len);
-: 17:
37: 18: return NF_ACCEPT;
-: 19:}
-: 20:
-: 21:static struct nf_hook_ops nf_ops = {
-: 22: .hook = fun_hook,
-: 23: .owner = THIS_MODULE,
-: 24: .pf = NFPROTO_IPV4,
-: 25: .hooknum = NF_INET_PRE_ROUTING,
-: 26: .priority = NF_IP_PRI_NAT_DST,
-: 27:};
-: 28:
1: 29:static int __init module_test_init(void)
-: 30:{
1: 31: int ret = 0;
1: 32: start_time = jiffies;
-: 33:
1: 34: ret = nf_register_hook(&nf_ops);
1: 35: if (ret < 0) {
#####: 36: printk("error register hook %d.\n", ret);
#####: 37: return ret;
-: 38: }
1: 39: printk("insmod ok, start_time: %lu.\n", start_time);
-: 40:
1: 41: return 0;
-: 42:}
-: 43:
#####: 44:static void __exit module_test_exit(void)
-: 45:{
#####: 46: nf_unregister_hook(&nf_ops);
-: 47: return;
-: 48:}
-: 49:
-: 50:module_init(module_test_init);
-: 51:module_exit(module_test_exit);
-: 52:
-: 53:MODULE_LICENSE("GPL");
-: 54:
[root@localhost module_test]#
完全参考:http://ltp.sourceforge.net/coverage/gcov.php
转载请保留地址:http://lenky.info/archives/2012/08/24/1888 或 http://lenky.info/?p=1888
备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。
法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以或书面等方式告知,本站将及时删除相关内容或链接。
创作共享协议. Copyright ©2011-2013
@lenky
嗯 我试下 谢了
by the way:
博客不错哦 特别是回复评论这么及时 赞
@lenky
嗯 我试下 谢了
by the way:
博客不错哦 特别是回复评论这么及时 赞
@lenky
我用ubuntu 12.10 自带的gcc 版本为gcc-4.7.3 编译内核版本为 3.4.57 /sys/kernel/debug/gcov目录下也是只有reset文件,
我换成ubuntu 10.04 自带的gcc 版本为 gcc-4.4.3 编译内核版本一样 /sys/kernel/debug/gcov目录下 就出现源文件目录
其他操作都一样,这是为什么了? 按道理向后兼容撒
呵 不清楚 如果怀疑是gcc问题 那你在ubantu上试试4.4.3
@lenky
请问 你用的gcc版本是多少?
这个不记得了, 但应该是CENTOS 6.0发行版上的gcc包。
@robin
确定前面几个步骤都做对了么?
为什么我的内核/sys/kernel/debug/gcov 下面只有reset, 没有内核目录
为什么我的内核/sys/kernel/debug/gcov 下面只有debug, 没有内核目录