__udivdi3 undefined - 如何找到使用它的代码?

dme*_*ter 18 c linux kernel linux-kernel

在32位Linux内核上编译内核模块会导致

"__udivdi3" [mymodule.ko] undefined!
"__umoddi3" [mymodule.ko] undefined!
Run Code Online (Sandbox Code Playgroud)

在64位系统上一切都很好.据我所知,原因是32位Linux内核不支持64位整数除法和模数.

如何找到发出64位操作的代码.它们很难手动找到,因为我无法轻易检查"/"是32位宽还是64位宽.如果"正常"函数未定义,我可以grep它们,但这不可能在这里.还有另一种搜索引用的好方法吗?某种"机器代码grep"?

该模块由几千行代码组成.我真的不能手动检查每一行.

Has*_*kun 21

首先,您可以使用do_div宏进行64位除法.(注意原型是uint32_t do_div(uint64_t dividend, uint32_t divisor)和" dividend"可以多次评估.

{
    unsigned long long int x = 6;
    unsigned long int y = 4;
    unsigned long int rem;

    rem = do_div(x, y);
    /* x now contains the result of x/y */
}
Run Code Online (Sandbox Code Playgroud)

此外,您应该能够在代码中找到long long int(或uint64_t)类型的用法,或者,您可以-g使用标志构建模块并使用objdump -S来获取源注释的反汇编.

注意:这适用于2.6内核,我没有检查任何更低的用法

  • 要添加一小部分信息,do_div()在<asm/div64.h>标头中定义. (10认同)
  • @Jordan:我无法确认这个 atm,但 IIRC `objdump -Sr` 将为您提供带有重定向的带注释的反汇编,您应该能够在那里找到对 `__udivdi3` 的调用。 (2认同)

Ces*_*arB 5

实际上, 32 位 Linux 内核支持64位整数除法和取模;但是,您必须使用正确的宏来执行此操作(哪些宏取决于您的内核版本,因为最近创建了新的更好的 IIRC)。无论您针对哪种架构进行编译,宏都会以最有效的方式执行正确的操作。

找到它们的使用位置的最简单方法是(如 @shodanex 的答案中所述)生成汇编代码;IIRC,这样做的方法类似于make directory/module.s(以及您已经必须传递给的任何参数make)。下一个最简单的方法是反汇编.o文件(使用类似的方法objdump --disassemble)。这两种方式都会为您提供生成调用的函数(并且,如果您知道如何阅读汇编,则可以了解函数内发生除法的位置)。