如何修复链接器警告:内核 space 中的 "function undefined"?
How to fix linker warning: "function undefined" in kernel space?
我正在为具有一些内核模块的 powerpc 微处理器开发集成 SDK。
Yocto项目提供的内核(3.12.37)和工具链(powerpc gcc 4.9.2)
当我通过提到的工具链和内核源代码在本地机器(x86_64bit Ubuntu 14)中制作 SDK 时,我在编译内核模块期间看到这些警告:
WARNING: "__udivdi3" [modules/foo.ko] undefined!
WARNING: "__umoddi3" [modules/foo.ko] undefined!
当我 insmod
内核模块时出现这些警告。
我意识到这个函数用于 64 位操作,而 libgcc 有这些函数。
这是编译标志:
"-Wall -Werror -gdwarf-3 -Wframe-larger-than=16384 -mcpu=powerpc"
另外,我给了这个标志来静态编译 "-Wl,-static-libgcc"
但没有用。
我的问题是:
为什么链接器要使用 powerpc arch($KERNELDIR/arch/powerpc) 没有的 64 位函数? (链接器知道ARCH是powerpc)
"in the kernel space, compiler does not use libgcc or other userspace functions and libs",这样对吗?如果不是,请向我解释。
- 最后我该如何解决这个问题?
谢谢。
编译器将生成调用 libgcc 中的函数以执行某些操作的代码。在本例中,调用它们对 64 位数量执行常规除法 (/
) 和模 (%
) 运算。
正确,内核不使用 libgcc。需要编写内核代码以防止编译器调用 libgcc 中的函数(在本例中是针对 64 位量的除法和模块操作)。
任何对 64 位数量进行除法或模运算的代码(除了 64 位架构上的本机有符号和无符号 long
类型)需要重写以使用特殊Linux 内核提供的 64 位除法函数和宏,而不是常规的 /
和 %
运算符。
过去,这是通过调用 #include <asm/div64.h>
定义的 do_div(n,base)
宏来完成的,但它有一个不寻常的 non-functionlike 接口,因为它修改了调用者的 [=除了返回余数 n % base
.
之外,17=] 参数也成为被除数 n / base
对于新代码,最好避免使用旧的 do_div(n,base)
宏并使用 #include <linux/math64.h>
声明的函数。那里为有符号和无符号参数以及 32 位和 64 位余数定义了各种函数。您需要选择最合适的函数来满足您的代码要求。
我正在为具有一些内核模块的 powerpc 微处理器开发集成 SDK。
Yocto项目提供的内核(3.12.37)和工具链(powerpc gcc 4.9.2)
当我通过提到的工具链和内核源代码在本地机器(x86_64bit Ubuntu 14)中制作 SDK 时,我在编译内核模块期间看到这些警告:
WARNING: "__udivdi3" [modules/foo.ko] undefined!
WARNING: "__umoddi3" [modules/foo.ko] undefined!
当我 insmod
内核模块时出现这些警告。
我意识到这个函数用于 64 位操作,而 libgcc 有这些函数。
这是编译标志:
"-Wall -Werror -gdwarf-3 -Wframe-larger-than=16384 -mcpu=powerpc"
另外,我给了这个标志来静态编译 "-Wl,-static-libgcc"
但没有用。
我的问题是:
为什么链接器要使用 powerpc arch($KERNELDIR/arch/powerpc) 没有的 64 位函数? (链接器知道ARCH是powerpc)
"in the kernel space, compiler does not use libgcc or other userspace functions and libs",这样对吗?如果不是,请向我解释。
- 最后我该如何解决这个问题?
谢谢。
编译器将生成调用 libgcc 中的函数以执行某些操作的代码。在本例中,调用它们对 64 位数量执行常规除法 (
/
) 和模 (%
) 运算。正确,内核不使用 libgcc。需要编写内核代码以防止编译器调用 libgcc 中的函数(在本例中是针对 64 位量的除法和模块操作)。
任何对 64 位数量进行除法或模运算的代码(除了 64 位架构上的本机有符号和无符号
long
类型)需要重写以使用特殊Linux 内核提供的 64 位除法函数和宏,而不是常规的/
和%
运算符。过去,这是通过调用
之外,17=] 参数也成为被除数#include <asm/div64.h>
定义的do_div(n,base)
宏来完成的,但它有一个不寻常的 non-functionlike 接口,因为它修改了调用者的 [=除了返回余数n % base
.n / base
对于新代码,最好避免使用旧的
do_div(n,base)
宏并使用#include <linux/math64.h>
声明的函数。那里为有符号和无符号参数以及 32 位和 64 位余数定义了各种函数。您需要选择最合适的函数来满足您的代码要求。