首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux内核跟踪点:将探测函数连接到跟踪点时未定义的符号

Linux内核跟踪点:将探测函数连接到跟踪点时未定义的符号
EN

Stack Overflow用户
提问于 2019-01-16 09:12:40
回答 1查看 658关注 0票数 2

我现在正在练习Linux跟踪点。基本上,我试图创建一个内核模块,其中定义了一个探测函数,并将其连接到Linux内核中的一个跟踪点(内核源文件dev.c中的“trace_netif_receive_skb”)。当我在SLES11上编译和运行内核模块时,它工作得很好。但是当我在SLES12上做同样的事情时,它抱怨这个符号是没有定义的。内核模块源代码是:

代码语言:javascript
复制
  1 #include <linux/module.h>
  2 #include <linux/kernel.h>
  3 #include <linux/init.h>
  4 #include <linux/skbuff.h>
  5 #include <trace/events/net.h>
  6 
  7 static void probe(void *ignore, struct sk_buff *skb)
  8 {
  9     printk(KERN_INFO "probe, protocol[0X%04X]\n", ntohs(skb->protocol));
 10 }
 11 
 12 static int __init init_tracepoint(void)
 13 {
 14     if (0 != register_trace_netif_receive_skb(probe, NULL))
 15     {
 16         printk(KERN_INFO "tracepoint init fails\n");
 17     }
 18 
 19     printk(KERN_INFO "tracepoint init succeeds\n");
 20     return 0;
 21 }
 22 
 23 static void __exit cleanup_tracepoint(void)
 24 {
 25     unregister_trace_netif_receive_skb(probe, NULL);
 26     tracepoint_synchronize_unregister();
 27 
 28     printk(KERN_INFO "tracepoint exit\n");
 29 }
 30 
 31 module_init(init_tracepoint);
 32 module_exit(cleanup_tracepoint);
 33 
 34 MODULE_LICENSE("GPL");

这是SLES11上的输出,没有错误报告。

代码语言:javascript
复制
suse11-1:~/works/tracepoint # make
make -C /lib/modules/3.0.76-0.11-default/build M=/root/works/tracepoint modules
make[1]: Entering directory `/usr/src/linux-3.0.76-0.11-obj/x86_64/default'
make -C ../../../linux-3.0.76-0.11 O=/usr/src/linux-3.0.76-0.11-obj/x86_64/default/. modules
  CC [M]  /root/works/tracepoint/tracepoint.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /root/works/tracepoint/tracepoint.mod.o
  LD [M]  /root/works/tracepoint/tracepoint.ko
make[1]: Leaving directory `/usr/src/linux-3.0.76-0.11-obj/x86_64/default'
suse11-1:~/works/tracepoint # insmod tracepoint.ko

这是SLES12上的输出,它说:警告:"__tracepoint_netif_receive_skb“/root/works/code/tracepoint/tracepoint.ko未定义!我可以在/var/log/messages中找到“未知符号__tracepoint_netif_receive_skb (err 0)”。

代码语言:javascript
复制
suse12-1:~/works/codes/tracepoint # make
make -C /lib/modules/4.4.21-69-default/build M=/root/works/codes/tracepoint modules
make[1]: Entering directory '/usr/src/linux-4.4.21-69-obj/x86_64/default'
  CC [M]  /root/works/codes/tracepoint/tracepoint.o
  Building modules, stage 2.
  MODPOST 1 modules
WARNING: "__tracepoint_netif_receive_skb" [/root/works/codes/tracepoint/tracepoint.ko] undefined!
  CC      /root/works/codes/tracepoint/tracepoint.mod.o
  LD [M]  /root/works/codes/tracepoint/tracepoint.ko
make[1]: Leaving directory '/usr/src/linux-4.4.21-69-obj/x86_64/default'
suse12-1:~/works/codes/tracepoint # 
suse12-1:~/works/codes/tracepoint # insmod tracepoint.ko 
insmod: ERROR: could not insert module tracepoint.ko: Unknown symbol in module

我检查了SLES11和SLES12的跟踪点框架的内核源代码,除非调用EXPORT_TRACEPOINT_SYMBOL()或EXPORT_TRACEPOINT_SYMBOL_GPL(),否则不导出"__tracepoint_##name“定义的”__tracepoint_##name/ linux /tracepoint.h“,但在linux内核代码中没有找到调用EXPORT_TRACEPOINT_SYMBOL(netif_receive_skb)或EXPORT_TRACEPOINT_SYMBOL_GPL来导出符号__tracepoint_netif_receive_skb的位置。那么为什么我没有在SLES11上遇到这个问题呢?我如何让它在SLES12上工作呢?

EN

回答 1

Stack Overflow用户

发布于 2022-04-12 07:46:49

使用for_each_kernel_tracepoint查找目标跟踪点和注册探针,为我工作,祝你好运。

代码语言:javascript
复制
struct tp_reg {
    const char *name;
    struct tracepoint *tp;
    void *fn;
};

static void each_tracepoint(struct tracepoint *tp, void *priv)
{
    struct tp_reg *regs = (struct tp_reg *)priv;
    int i;
    
    for (i = 0; regs[i].name; ++i) {
        if (strcmp(tp->name, regs[i].name) == 0) {
            if (tracepoint_probe_register(tp, regs[i].fn, NULL) == 0) {
                regs[i].tp = tp;
            }
        }
    }
}

static void unregister_tp(struct tp_reg *regs)
{
    int i;

    for (i = 0; regs[i].name; ++i) {
        if (regs[i].tp) {
            tracepoint_probe_unregister(regs[i].tp, regs[i].fn, NULL);
            regs[i].tp = NULL;
        }
    }
    
    tracepoint_synchronize_unregister();
}

static int register_tp(struct tp_reg *regs)
{
    int i;
    
    for_each_kernel_tracepoint(each_tracepoint, regs);

    for (i = 0; regs[i].name; ++i) {
        if (regs[i].tp == NULL) {
            printk(KERN_ALERT "trace point %s not found.\n", regs[i].name);
            unregister_tp(regs);
            return 1;
        }
    }
    
    return 0;
}

样本代码:

代码语言:javascript
复制
static void probe_callback(void *ignore, struct pt_regs *regs, long id)
{
    if (id == __NR_execve) {
        char file[100];

        if (strncpy_from_user(file, (void *)PT_REGS_PARM1(regs), sizeof(file)) < 0)
            return;

        printk(KERN_INFO "execve %s", file);
    }
}

static struct tp_reg myreg[] = {
    { .name = "sys_enter", .fn = (void *)probe_callback },
    { .name = NULL }
};

static int __init init_tracepoint(void)
{
    return register_tp(myreg);
}

static void __exit cleanup_tracepoint(void)
{
    unregister_tp(myreg);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54213660

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档