Export_Symbol in Kernel Module | Undefined Symbol During Insmod

EXPORT_SYMBOL in kernel module | undefined symbol during insmod

There are two ways to solve this, 1) Compile both the kernel modules in the same Makefile i.e. objs-m := a.o b.o. 2) Include **KBUILD_EXTRA_SYMBOLS=<"absolute path to the Module.symvers of the kernel module which is exporting function or variable"> in the Makefile of the kernel module which will use exported function or variable.

Unknown symbol in module on module insertion despite EXPORT_SYMBOL

As Vadim Stupakov said in the comment, Putting the Module.symvers file in the module source directory fixed my issue. From this documentation

Module versioning is enabled by the CONFIG_MODVERSIONS tag, and is used
as a simple ABI consistency check. A CRC value of the full prototype
for an exported symbol is created. When a module is loaded/used, the
CRC values contained in the kernel are compared with similar values in
the module. if they are not equal, the kernel refuses to load the
module.
Module.symvers contains a list of all exported symbols from a kernel
build.

As per my understanding, Module.symvers is created on make modules. I missed out that file. When I put the appropriate Module.symvers in the module build directory, the module works as I expected without any errors.

insmod Unknown symbol in module

There may be couple of reason for this error. One of them might be symbol named "function" is exported as GPL only. Or may be kernel against which you are loading your module does not have that "function" symbol, but it is in some other kernel version.

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

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 <linux/module.h>
#include <linux/kernel.h>

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 <linux/module.h>
#include <linux/kernel.h>

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.

How to export a symbol from an external module?

Add this line at the very top of your Makefile for your hello module:

KBUILD_EXTRA_SYMBOLS := /home/your-user/path/to/printt/Module.symvers

(be sure to put in the correct path to your printt module).

Now rebuild your hello module and it will be loaded just fine.

For details see Documentation/kbuild/modules.txt, "6.3 Symbols From Another External Module".

Unknown symbol from kernel module (dm9601 driver), does this require a rebuild of the kernel?

First check, if the symbols are part of kernel symbols list,

for ex: cat /proc/kallsyms | grep mii_link_ok

If symbols are not present, then those symbols need to be exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL().

If symbols are present try one of the below,

  1. Include **KBUILD_EXTRA_SYMBOLS=<"absolute path to the Module.symvers of the kernel module which is exporting function or variable"> in the Makefile of the kernel module which will use exported function or variable, in your case dm9601 Makefile.

for ex: KBUILD_EXTRA_SYMBOLS := absolute_path_to_Module.symvers_of_mii

EXPORT_SYMBOL in kernel module | undefined symbol during insmod


  1. List item

Unknown symbol in while loading a kernel module

Hope this will solve the issue!.



Related Topics



Leave a reply



Submit