Bug 12446 - Unable to insmod module. Unknwon symbol found
Summary: Unable to insmod module. Unknwon symbol found
Status: REJECTED WILL_NOT_FIX
Alias: None
Product: Drivers
Classification: Unclassified
Component: Other (show other bugs)
Hardware: All Linux
: P1 low
Assignee: drivers_other
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-01-14 05:53 UTC by amit jain
Modified: 2009-06-04 06:54 UTC (History)
5 users (show)

See Also:
Kernel Version: 2.6.28
Subsystem:
Regression: No
Bisected commit-id:


Attachments

Description amit jain 2009-01-14 05:53:57 UTC
Latest working kernel version:2.6.28
Earliest failing kernel version:2.6.26
Distribution:
Hardware Environment:
Software Environment:
Problem Description:
When you use driver dependent on other driver. It should load cleanely, if other is loaded. But in kernel 2.6.26 onwards its give error, unknown symbol found.
Actually find_symbol able to find symbol but check_version unable to match crc.
Because crc is not know to other driver. 

Steps to reproduce:
1) create two device drivers in two separate directories. let say hello and bye 
2) Export Symbol from hello module and try to use that in bye module.
3) Compile both the driver separately.
4) insmod hello.ko
3) While insmod(ing) bye.ko, gives error "Unknown Symbol found"
Comment 1 Roland Kletzing 2009-01-17 02:44:19 UTC
what about using modprobe instead ? (as this looks in modules.dep to find the dependend modules and load them before) 
Comment 2 sucheta 2009-01-18 21:40:43 UTC
Hi Roland, using modprobe doesn't work. The entries in modules.dep are added. Still it ends up showing the same prints - "no symbol version for " and "Unknown symbol ". And modprobe fails.
Comment 3 amit jain 2009-01-19 00:20:32 UTC
Hi Roland,
   Thanks a lot for replying. Below I have written details of experiments we did and our understanding.

Problem: insmod failure for externally compiled module :-

Experiments:
(1) Compiling 2 modules a.ko and b.ko ( dependent on a.ko ) together :- Works

(2) Copying Module.symvers from module "a" dir to the module "b" dir, before compiling b.ko :- Works.

(3) Modprobe after appending following lines in /lib/modules/modules.dep 
    /lib/modules/2.6.27.7-smp/kernel/drivers/net/a.ko
    /lib/modules/2.6.27.7-smp/kernel/drivers/net/b.ko: /lib/modules/2.6.27.7-smp/kernel/drivers/net/a.ko
   :- Fails

(4) After compiling b.ko, just modifying b.mod.c file to include the undefined symbol in its version table doesn't work (didn't expect to work ).

(5) export_objs (doesn't work):
    In Makefile of a.ko:
       export_objs := a.ko / export-objs := a.ko / exportobjs := a.ko.

(6) Adding "#define EXPORT_SYMTAB" in a.c file (doesn't work).

From above experiments, we found that In .mod.c file it maintains __versions array, which contains export symbol name and its crc.
We see symbols of modules which are compiled with kernel. No symbols of externally compiled modules.

The call trace is load_module -> simplify_symbols -> resolve_symbol -> 
find_symbol and check_version ( if find_symbol succeeds ).

check_version behavior comparison in 2.6.26 and earlier version kernels :-

In earlier versions of kernel also, symbol couldn't be found in its version table. Still, check_version used to 
return 1 (success) and the dependent module could be insmod(ed) successfully.

However, in kernel 2.6.26 onwards, behavior has changed.  check_version on not finding the reqd. symbol in its version table returns 0 (fail) and  the dependent external module can't be inserted anymore.

Waiting eagerly for your reply. Thanks in advance.
Comment 4 amit jain 2009-01-28 21:04:34 UTC
Any updates ?
Comment 5 Alan 2009-03-19 10:19:16 UTC
No but this is not a support facility, just a bug tracker and as a problem only you've reported and nobody else has duplicated its a very very low priority, especially as its only out of tree code seeing it
Comment 6 amit jain 2009-03-19 21:04:12 UTC
It should not be very very low priotity, Its easy to reproduce. 
Its should be blocker bug, because anybody how will try to compile module dependent on other module, will fail.

Strange, Why didn't nobody reply on it.
I am really stuck, because of this problem.
Comment 7 Tejun Heo 2009-03-19 21:48:40 UTC
cc'ing Rusty Russell.
Comment 8 Roland Kletzing 2009-03-20 12:11:23 UTC
hello amit, 
i think alan is right. this seems a very specific, personal problem. 

anyway, if you think it`s a general kernel problem, please post an as simple as possible repro-case (i.e. some sourcecode) for your problem, so chances will raise that someone will look at your problem. 

i`d recommend bringing this up on kernel related mailing lists
Comment 9 Rusty Russell 2009-03-22 23:00:51 UTC
This is true; a5dd69707424a35d2d2cc094e870f595ad61e916 changed this.

The argument is that modversions is supposed to version symbols used in a module, and this
doesn't really work for out-of-tree modules (unless you copy Module.symvers across, as done
above).   Otherwise module B doesn't know the version of symbol A; we changed such a missing
version to fail; the user *did* want us to check versions.

Currently you have to modprobe --force-modversion to load such a module.

I think the new behavior is correct.
Comment 10 Qihua Dai 2009-06-04 05:28:02 UTC
I also met the same problem on kernel 2.6.28.10.
"modprobe --force-modversion" does work for me, it will report "invalid module format"

Besides the solution of copy Module.symvers across, below solution can workaround it:
In the makefile of "b", define KBUILD_EXTRA_SYMBOLS which points to Module.symvers in "a" Dir so that "b" will find Module.symvers of "a"
e.g.
KBUILD_EXTRA_SYMBOLS=/mod_a/Module.symvers

During building "b", the search path of Module.symvers will be. Please correct me if my understanding is incorrect.
1, kernel source path, e.g. /usr/src/kernels/linux-2.6.28.10 
2, the value of $(M) defined in makefile, which is the same as the value of KBUILD_EXTMOD
3, the value of KBUILD_EXTRA_SYMBOLS

I think it's a generic kernel problem. It's better to fix it. Below attached a simple case which is from below link:
http://topic.csdn.net/u/20081009/11/6fb7295c-0d30-4d4f-b390-af4413aa7f7e.html?seed=1582387931

=============C/C++ code
// Module A (mod_a.c)
#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>

static int func1(void)
{
       printk("In Func: %s...\n",__func__);
       return 0;
}

// Export symbol func1
EXPORT_SYMBOL(func1);

static int __init hello_init(void)
{
       printk("Module 1,Init!\n");
       return 0;
}

static void __exit hello_exit(void)
{
       printk("Module 1,Exit!\n");
}

module_init(hello_init);
module_exit(hello_exit);


=============C/C++ code
// Module B (mod_b.c)
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/module.h>

static int func2(void)
{
       extern int func1(void);
       func1();
       printk("In Func: %s...\n",__func__);
       return 0;
}

static int __init hello_init(void)
{
       printk("Module 2,Init!\n");
       func2();
       return 0;
}

static void __exit hello_exit(void)
{
       printk("Module 2,Exit!\n");
}

module_init(hello_init);
module_exit(hello_exit);


=============Makefile for Module A 

BatchFile code
obj-m += mod1.o
mod1-y := mod_a.o

KVERSION = $(shell uname -r)

all: 
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
    
clean:
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
    rm -f *.o *.ko *.cmd


=============Makefile for Module B 

BatchFile code
obj-m += mod2.o
mod2-y := mod_b.o

KVERSION = $(shell uname -r)

all: 
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
    
clean:
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
    rm -f *.o *.ko *.cmd
Comment 11 Qihua Dai 2009-06-04 05:31:40 UTC
A typo, it should be
""modprobe --force-modversion" does NOT work for me, it will report "invalid module
format""
Comment 12 Rusty Russell 2009-06-04 06:54:15 UTC
You can't modprobe --force if  CONFIG_MODULE_FORCE_LOAD isn't set.  That was added in 2.6.26, and is off by default.

Hope that clarifies,
Rusty.

Note You need to log in before you can comment on or make changes to this bug.