对“__divdi3”的未定义引用
Undefined reference to '__divdi3'
在 link 对 long long
类型的整数执行除法和模运算的一些代码时,我收到以下两个错误:
util.c:(.text+0x1af): undefined reference to '__divdi3'
util.c:(.text+0x1ef): undefined reference to '__moddi3'
我也尝试过使用 unsigned long long
,但是会导致以下错误:
util.c:(.text+0x1af): undefined reference to '__udivdi3'
util.c:(.text+0x1ef): undefined reference to '__umoddi3'
将 long long
替换为 int
或 long
可以解决问题,但我需要使用 unsigned long long
.
我正在使用以下命令行编译和 link 程序:
gcc -ffreestanding -c kernel/util.c -o kernel/util.o
ld -o kernel32.bin -Ttext 0x500 kernel/util.o kernel/kernel.o --oformat binary
这是函数:
char* itoa(unsigned long long i, char b[]){
if (i == 0){
b[0] = '0';
b[1] = '[=14=]';
return b;
}
char const digit[] = "0123456789";
char* p = b;
if (i < 0){
*p++ = '-';
i *= -1;
}
unsigned long long shifter = i;
while (shifter){
++p;
shifter = shifter / 10;
}
*p = '[=14=]';
while (i){
*--p = digit[i % 10];
i = i / 10;
}
return b;
}
显然,编译器正在引用 __udivdi3
来除以整数,但 linker 找不到它..
顺便说一下,二进制文件是作为32位操作系统使用的,因此缺少很多标准库
编辑:我正在使用 gcc 4.8.4 和 ld 2.24
据此link:https://gcc.gnu.org/onlinedocs/gcc-3.3/gccint/Library-Calls.html
感兴趣的函数在 libgcc.a
库中定义。 (不在 libgcc.so
图书馆中。)
如果您的 link 步骤包含 -static
参数,我认为您的代码将使用 libgcc.a 库
然而,这个link:https://sourceware.org/ml/crossgcc/2006-04/msg00000.html
有以下要说的:
通常您 link 使用 gcc 而不是 ld 来避免这些类型的问题。
我会使用 gcc 将其更改为 link,或者添加适当的 -L 和 -l 选项以使其使用适当的 libgcc
看来你用错了功能:
— 运行时函数:long __divdi3 (long a, long b)
我猜正确的函数是:
— 运行时函数:long long __divti3 (long long a, long long b)
(https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines)
很遗憾,我不确定是否在您的 gcc 版本中实现了。
当为不为 GCC 用作 [unsigned
] long long
的数据类型提供硬件支持的体系结构构建代码时,GCC 生成代码以对该类型的值进行算术运算,其中涉及调用其自己的支持库 libgcc
提供的函数。 __divdi3()
等就在其中。这不是 GCC 可以做到的唯一方式,但它非常适合 GCC 支持多种体系结构的目标。
当被指示充当独立编译器时,GCC 不会自动 link libgcc,因此不会自动提供这些功能的实现。这一直是之前投诉的主题,例如this one and this later one。 GCC 维护者的立场是这不是 GCC 缺陷,它不会渲染 GCC non-conforming。我发现他们的推理有问题,但不太可能改变。至少,这是实施质量问题。
我确实知道 GCC 维护者来自哪里,但是:一个独立的环境提供了标准库的 none,除了根据提供给它的代码外,不能解释大多数函数调用。那么,如果该代码包含对与 libgcc 中某些函数同名的函数的显式调用怎么办?除非用户明确表示他需要 libgcc,否则编译器不应该假定它是需要的函数的那些版本。但问题是,如果 编译器 插入这样的调用,那么它不仅知道预期的实现是什么,而且如果不兼容的实现是 link,结果也是错误的代替编辑。因此,这是GCC自己造成的问题。
最重要的是,您可以明确请求 linked libgcc。您需要指定它是静态 linked,因为您不能在上下文中依赖动态 linker。这些额外的 link 选项应该可以做到:
-static-libgcc -lgcc
或者,您可以自己编写这些函数的实现,或者抄袭 GCC 的源代码,但我不明白您为什么更喜欢这些选项中的任何一个。
在 link 对 long long
类型的整数执行除法和模运算的一些代码时,我收到以下两个错误:
util.c:(.text+0x1af): undefined reference to '__divdi3'
util.c:(.text+0x1ef): undefined reference to '__moddi3'
我也尝试过使用 unsigned long long
,但是会导致以下错误:
util.c:(.text+0x1af): undefined reference to '__udivdi3'
util.c:(.text+0x1ef): undefined reference to '__umoddi3'
将 long long
替换为 int
或 long
可以解决问题,但我需要使用 unsigned long long
.
我正在使用以下命令行编译和 link 程序:
gcc -ffreestanding -c kernel/util.c -o kernel/util.o
ld -o kernel32.bin -Ttext 0x500 kernel/util.o kernel/kernel.o --oformat binary
这是函数:
char* itoa(unsigned long long i, char b[]){
if (i == 0){
b[0] = '0';
b[1] = '[=14=]';
return b;
}
char const digit[] = "0123456789";
char* p = b;
if (i < 0){
*p++ = '-';
i *= -1;
}
unsigned long long shifter = i;
while (shifter){
++p;
shifter = shifter / 10;
}
*p = '[=14=]';
while (i){
*--p = digit[i % 10];
i = i / 10;
}
return b;
}
显然,编译器正在引用 __udivdi3
来除以整数,但 linker 找不到它..
顺便说一下,二进制文件是作为32位操作系统使用的,因此缺少很多标准库
编辑:我正在使用 gcc 4.8.4 和 ld 2.24
据此link:https://gcc.gnu.org/onlinedocs/gcc-3.3/gccint/Library-Calls.html
感兴趣的函数在 libgcc.a
库中定义。 (不在 libgcc.so
图书馆中。)
如果您的 link 步骤包含 -static
参数,我认为您的代码将使用 libgcc.a 库
然而,这个link:https://sourceware.org/ml/crossgcc/2006-04/msg00000.html
有以下要说的:
通常您 link 使用 gcc 而不是 ld 来避免这些类型的问题。
我会使用 gcc 将其更改为 link,或者添加适当的 -L 和 -l 选项以使其使用适当的 libgcc
看来你用错了功能:
— 运行时函数:long __divdi3 (long a, long b)
我猜正确的函数是:
— 运行时函数:long long __divti3 (long long a, long long b)
(https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines)
很遗憾,我不确定是否在您的 gcc 版本中实现了。
当为不为 GCC 用作 [unsigned
] long long
的数据类型提供硬件支持的体系结构构建代码时,GCC 生成代码以对该类型的值进行算术运算,其中涉及调用其自己的支持库 libgcc
提供的函数。 __divdi3()
等就在其中。这不是 GCC 可以做到的唯一方式,但它非常适合 GCC 支持多种体系结构的目标。
当被指示充当独立编译器时,GCC 不会自动 link libgcc,因此不会自动提供这些功能的实现。这一直是之前投诉的主题,例如this one and this later one。 GCC 维护者的立场是这不是 GCC 缺陷,它不会渲染 GCC non-conforming。我发现他们的推理有问题,但不太可能改变。至少,这是实施质量问题。
我确实知道 GCC 维护者来自哪里,但是:一个独立的环境提供了标准库的 none,除了根据提供给它的代码外,不能解释大多数函数调用。那么,如果该代码包含对与 libgcc 中某些函数同名的函数的显式调用怎么办?除非用户明确表示他需要 libgcc,否则编译器不应该假定它是需要的函数的那些版本。但问题是,如果 编译器 插入这样的调用,那么它不仅知道预期的实现是什么,而且如果不兼容的实现是 link,结果也是错误的代替编辑。因此,这是GCC自己造成的问题。
最重要的是,您可以明确请求 linked libgcc。您需要指定它是静态 linked,因为您不能在上下文中依赖动态 linker。这些额外的 link 选项应该可以做到:
-static-libgcc -lgcc
或者,您可以自己编写这些函数的实现,或者抄袭 GCC 的源代码,但我不明白您为什么更喜欢这些选项中的任何一个。