试用内核gcov

http://www.lenky.info/archives/2012/08/1888


对于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

1
2
3
4
5
[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]#

编译安装这个内核:

1
[root@localhost linux-2.6.38.8]# make; make modules;make modules_install;make install;

重启机器后,mount加载debugfs文件系统,并调用gcov对相应文件做覆盖测量:

1
2
3
4
5
6
7
8
[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]#

查看结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
[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 <oberpar@linux.vnet.ibm.com>
         -:    6: *
         -:    7: *    Uses gcc-internal data definitions.
         -:    8: *    Based on the gcov-kernel patch by:
         -:    9: *       Hubertus Franke <frankeh@us.ibm.com>
         -:   10: *       Nigel Hinds <nhinds@us.ibm.com>
         -:   11: *       Rajan Ravindran <rajancr@us.ibm.com>
         -:   12: *       Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
         -:   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]#

试试其他文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[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目录,结果发现生成的文件没有对应的源代码):

1
2
3
4
5
6
7
8
9
10
11
[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*/

试试自定义模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
[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

看结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
[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://www.lenky.info/archives/2012/08/1888 或 http://lenky.info/?p=1888


备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。

法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以Email或书面等方式告知,本站将及时删除相关内容或链接。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值