insmod fails with “Unknown symbol in module” for a symbol defined in another module

后端 未结 2 1155
温柔的废话
温柔的废话 2021-02-04 04:49

I am working in Ubuntu. I am trying to make two kernel modules which uses each other functions. My problem is that I got modules properly compiled, but the symbol is not resolve

2条回答
  •  不思量自难忘°
    2021-02-04 05:41

    Here are some issues I found with your code:

    (a). Your initialization and termination functions should be declared static and properly identified. For example, in m1.c -

    static int __init hello_start(void)
    {
         printk(KERN_INFO "Loading m1 module ...\n");
    
        func_m2();
    
        return 0;
    }
    
    static void __exit hello_end(void)
    {
        printk(KERN_INFO "Unloading m1 ...\n");
    }
    

    Repeat this for m2.c

    (b). Build both of your modules together, using the same Makefile. I bet if you look closely at the output from your existing Makefile for m1.c, you will see a warning indicating that func_m2() is undefined. Anyhow, the consolidated Makefile should look like -

    SRCS   = m1.c m2.c
    OBJS   = $(SRCS:.c=.o)
    
    obj-m += $(OBJS)
    
    EXTRA_CFLAGS = -O2
    
    
    all:
        $(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
    
    clean:
        $(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
        $(RM) Module.markers modules.order
    

    After both modules are built, run insmod on 'm2.ko' before issuing the insmod for 'm1.ko'. Check results via dmesg.

    Also, over here I am assuming that both m1.c and m2.c are in the same directory. Even if they are in different directories, this technique will work, but it will be messy. If they are in different directories, do the following.

    I did little research and found a way to build modules in separate directories. The example I used is much simpler than what you have, but perhaps it is adaptable.

    I have following manifest of files in a directory called ExportSymbol...

    $ ls -CFR
    .:
    include/  Makefile  mod1/  mod2/
    
    ./include:
    m2_func.h
    
    ./mod1:
    Makefile  module1.c
    
    ./mod2:
    Makefile  module2.c
    

    The m2_func.h appears as:

    #ifndef M2_FUNC_H
    #define M2_FUNC_H
    
    void m2_func(void);
    
    #endif
    

    The top-level Makefile appears as:

    obj-y := mod1/ mod2/
    
    all:
        $(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
    
    clean:
        $(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
        $(RM) Module.markers modules.order
    

    The Makefile and module1.c, which are in mod1/, appear as:

    SRCS   = module1.c
    OBJS   = $(SRCS:.c=.o)
    
    obj-m += $(OBJS)
    
    EXTRA_CFLAGS += -I${PWD}/include
    
    all:
        $(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
    
    clean:
        $(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
        $(RM) Module.markers modules.order
    

    #include 
    #include 
    
    static int __init hello_start(void)
    {
     printk(KERN_INFO "Loading m1 module ...\n");
    
     m2_func();
    
     return 0;
    }
    
    static void __exit hello_end(void)
    {
     printk(KERN_INFO "Unloading m1 ...\n");
    }
    
    module_init(hello_start);
    module_exit(hello_end);
    
    MODULE_LICENSE("GPL");
    

    The Makefile and module2.c, which are in mod2/, appear as:

    SRCS   = module2.c
    OBJS   = $(SRCS:.c=.o)
    
    obj-m += $(OBJS)
    
    EXTRA_CFLAGS += -I${PWD}/include
    
    all:
        $(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
    
    clean:
        $(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
        $(RM) Module.markers modules.order
    

    #include "m2_func.h"
    #include 
    #include 
    
    static int __init hello_start(void)
    {
     printk(KERN_INFO "Loading m2 module ...\n");
    
     return 0;
    }
    
    static void __exit hello_end(void)
    {
     printk(KERN_INFO "Unloading m2 ...\n");
    }
    
    void m2_func(void)
    {
     printk(KERN_INFO "This a function in m2\n");
    } 
    
    module_init(hello_start);
    module_exit(hello_end);
    
    MODULE_LICENSE("GPL");
    EXPORT_SYMBOL(m2_func);
    

    NOTE: I can't use your makefile as it generates *.ko per each c file. The Makefile is doing its job. A 'ko' file is a kernel object file; you will have one for each .c source file. There's no way around this. If you do not want multiple ko-files, then put all of your code in one source file.

提交回复
热议问题