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”
That's an easy one. Near the top are these:
WARNING: "STUB_stop_elevator" [/home/lukas/Desktop/COP4610-Operating-Systems-Project-2-master/elevator/elevator.ko] undefined!
WARNING: "STUB_issue_request" [/home/lukas/Desktop/COP4610-Operating-Systems-Project-2-master/elevator/elevator.ko] undefined!
WARNING: "STUB_start_elevator" [/home/lukas/Desktop/COP4610-Operating-Systems-Project-2-master/elevator/elevator.ko] undefined!
Your module will not load due to the undefined symbols. Once those are resolved when building, module loading should work better. It looks like your link is using only 1 object file. Though I don't have access to confirm, try adjusting your Makefile to list all object files; it could be that obj-m is incomplete and should list the same files as those with obj-y.
If you run into other undefined symbols while loading the module and they're external to your module, there's probably a dependency issue. For that case, copy your module to /lib/modules/......
and try loading with modprobe
insmod error unknown symbol in module
parport_register_device
is exported in drivers/parport/share.c. So you have to load parport driver first (modprobe parport
) and then your driver.
What's meaning of EXPORT_SYMBOL in Linux kernel code?
It makes a symbol accessible to dynamically loaded modules (provided that said modules add an extern
declaration).
Not long ago, someone asked how to use it.
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.
Related Topics
Store Passwords Required by a Linux Daemon
Is There Compatible Odbc Driver with Mariadb 10 on Linux
When to Use Linux Kernel Add_Timer Vs Queue_Delayed_Work
Removing Parts of a String That Contain Digit with Sed/Perl
Get Canonical Path from Pathname
How to Configure Multiple Ssh Access to an Ec2 Instance
Inspect Network Traffic from Simple Linux Cli App
How to Solve Ssh: /Usr/Lib64/Libcrypto.So.10: No Version Information Available
Communication Between Linked Docker Containers
Ubuntu Linux: Netbeans Cannot Detect Git or Cordova Installed
Linux Bash Commands to Remove Duplicates from a CSV File
Bash Ip If Then Else Statement
How to Access Google Drive from Cli Cyberduck
Run a .Net Mvc5 Application on Mono
Shared Library Mysteriously Doesn't Get Linked to Application
"Relocation R_X86_64_32S Against '.Bss' Can Not Be Used When Making a Shared Object"