如何修复链接器警告:内核 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" 但没有用。

我的问题是:

  1. 为什么链接器要使用 powerpc arch($KERNELDIR/arch/powerpc) 没有的 64 位函数? (链接器知道ARCH是powerpc)

  2. "in the kernel space, compiler does not use libgcc or other userspace functions and libs",这样对吗?如果不是,请向我解释。

  3. 最后我该如何解决这个问题?

谢谢。

  1. 编译器将生成调用 libgcc 中的函数以执行某些操作的代码。在本例中,调用它们对 64 位数量执行常规除法 (/) 和模 (%) 运算。

  2. 正确,内核不使用 libgcc。需要编写内核代码以防止编译器调用 libgcc 中的函数(在本例中是针对 64 位量的除法和模块操作)。

  3. 任何对 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 位余数定义了各种函数。您需要选择最合适的函数来满足您的代码要求。