Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C __udivdi3未定义—;如何找到使用它的代码?_C_Linux_Linux Kernel_Kernel - Fatal编程技术网

C __udivdi3未定义—;如何找到使用它的代码?

C __udivdi3未定义—;如何找到使用它的代码?,c,linux,linux-kernel,kernel,C,Linux,Linux Kernel,Kernel,在32位Linux内核上编译内核模块会导致 "__udivdi3" [mymodule.ko] undefined! "__umoddi3" [mymodule.ko] undefined! 在64位系统上一切正常。据我所知,这是因为在32位Linux内核中不支持64位整数除法和模运算 如何找到发出64位操作的代码。它们很难手动查找,因为我无法轻松检查“/”是32位宽还是64位宽。如果“正常”函数未定义,我可以grep它们,但这在这里是不可能的。有没有另一种搜索参考资料的好方法?某种“机器代码

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

"__udivdi3" [mymodule.ko] undefined!
"__umoddi3" [mymodule.ko] undefined!
在64位系统上一切正常。据我所知,这是因为在32位Linux内核中不支持64位整数除法和模运算

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


该模块由数千行代码组成。我真的无法手动检查每一行。

在编译阶段之后,您应该能够获得一些有文档记录的程序集,并查看这些函数是否被调用。尝试使用CFLAGS并添加-S标志。
编译应在汇编阶段停止。然后,您可以在汇编文件中查找有问题的函数调用。

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


找到它们的使用位置的最简单方法是(如@shodanex的回答中所述)生成汇编代码;IIRC,这样做的方法类似于
make directory/module.s
(以及必须传递给
make
)的任何参数)。下一个最简单的方法是反汇编
.o
文件(使用类似于
objdump的东西——反汇编
)。这两种方法都将为您提供生成调用的函数(如果您知道如何读取汇编,则可以大致了解在函数中进行除法的位置)。

首先,您可以使用
do\u div
宏进行64位除法。(注意原型是
uint32\u t do\u div(uint64\u t divident,uint32\u t divisor)
,并且“
divident
”可以多次计算

{
    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 */
}
此外,您应该能够在代码中找到
long-long-int
(或
uint64\u t
)类型的用法,或者,您也可以使用
-g
标志构建模块,并使用
objdump-S
获取源代码注释反汇编


注意:这适用于2.6内核,我没有检查任何更低版本的使用情况

添加一点信息,do_div()是在标题中定义的。Linux坚持让您使用一个丑陋的函数来划分,而不仅仅是实现
\uudivdi3
等,这似乎很可笑。它们很容易实现,如果您在asm中实现,它们将比libgcc的版本更高效(可能快2-3倍)@WilliBallenthin即使在使用之后,也要面对这个问题。那么有人建议我需要做些什么来解决这个问题吗?@Jordan:
-g
标志是用于GCC的(因此对象包含调试信息)并且属于
CFLAGS\u模块
,objdump将在生成的对象文件上运行。@Jordan:我无法确认这个atm,但是IIRC
objdump-Sr
将为您提供带重定向的带注释的反汇编,您应该能够在那里找到对
udivdi3
的调用。