http://bugzilla.kernel.org/show_bug.cgi?id=12446

 

在Linux2.6.26下用EXPORT_SYMBOL时出现Unknown symbol?

如何解决!!

这是linux kernel 2.6.26 之后版本的bug (详细描述, 请看http://bugzilla.kernel.org/show_bug.cgi?id=12446)
并且这个bug不会被fix

解决办法是把mod_a的Module.symvers放到mod_b的当前路径,从而编译mod_b,符号信息会自动连接进去.
或者在mod_b的makefile中使用KBUILD_EXTRA_SYMBOLS指定mod_a的Module.symvers, 如:
KBUILD_EXTRA_SYMBOLS=/mod_a/Module.symvers

编译mod_b时,搜索Module.symvers的路径是:
1, kernel source path, e.g. /usr/src/kernels/linux-2.6.28.10
2, makefile中M=所指定的路径, 它等效于变量KBUILD_EXTMOD的值
3, 变量KBUILD_EXTRA_SYMBOLS的值

 

 

Bug 12446 - Unable to insmod module. Unknwon symbol found
 
Summary:Unable to insmod module. Unknwon symbol found

Status:REJECTED WILL_NOT_FIX
 
Product:Drivers
Component: Other
Version:2.5
Platform:All Linux
 
Importance:P1 low
Assigned To:
 
URL: 
 
Depends on: 
Blocks: 
 Show dependency treegraph
 
Reported:2009-01-14 05:53 by
Modified:2009-06-04 06:54 (History)
 
Kernel Version:2.6.28
Tree:Mainline
Regression:No
 


Attachments



Description From 2009-01-14 05:53:57
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 From 2009-01-17 02:44:19 -------
what about using modprobe instead ? (as this looks in modules.dep to find the
dependend modules and load them before) 
------- Comment #2 From 2009-01-18 21:40:43 -------
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 From 2009-01-19 00:20:32 -------
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 From 2009-01-28 21:04:34 -------
Any updates ?
------- Comment #5 From 2009-03-19 10:19:16 -------
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 From 2009-03-19 21:04:12 -------
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 From 2009-03-19 21:48:40 -------
cc'ing Rusty Russell.
------- Comment #8 From 2009-03-20 12:11:23 -------
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 From 2009-03-22 23:00:51 -------
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 From 2009-06-04 05:28:02 -------
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 From 2009-06-04 05:31:40 -------
A typo, it should be
""modprobe --force-modversion" does NOT work for me, it will report "invalid
module
format""
------- Comment #12 From 2009-06-04 06:54:15 -------
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.