【问题标题】:Should gcc builtins always be resolved during the compilation step, or the linker step?gcc builtins 是否应该在编译步骤或链接器步骤中始终被解析?
【发布时间】:2014-05-24 00:42:00
【问题描述】:

在 Solaris 5.11 机器上运行 gcc 3.4.3 时,我看到内置函数在编译期间未定义,但是当 Solaris 链接器链接到 libgcc.a 时,会针对 libgcc.a 解析。

在另一个 Solaris 机器上的 gcc 4.5.2 上,相同的内置函数在 .o 编译期间被解析,并且链接器不关心它们。

在 gcc 3.4.3 上编译的简化示例文件:

# cat ctzll.c
int func(unsigned long long x)
{
        return __builtin_ctzll(x);
}

# cat main.c
int main(void)
{
        return func(0xc0ffee);
}

首先编译ctzll.c,检查符号:

# nm ctzll.o
                 U __ctzdi2
0000000000000000 T func

现在编译 main.c,并链接对象:

# gcc -m64 main.c -c
# gcc -m64 ctzll.o main.o -v
Reading specs from /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/specs
Configured with: /build/i386/components/gcc3/gcc-3.4.3/configure --prefix=/usr/sfw --mandir=/usr/sfw/share/man --infodir=/usr/sfw/share/info --without-gnu-ld --with-ld=/usr/bin/ld --enable-languages=c,c++,f77,objc --enable-shared --with-gnu-as --with-as=/usr/gnu/bin/as
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-20050802)
 /usr/sfw/libexec/gcc/i386-pc-solaris2.11/3.4.3/collect2 -V -Y P,/lib/64:/usr/lib/64:/usr/sfw/lib/64 -R /lib/64:/usr/lib/64:/usr/sfw/lib/64 -Qy /usr/lib/amd64/crt1.o /usr/lib/amd64/crti.o /usr/lib/amd64/values-Xa.o /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtbegin.o -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64 -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/../../../amd64 -L/lib/amd64 -L/usr/lib/amd64 ctzll.o main.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtend.o /usr/lib/amd64/crtn.o
ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.2276
# nm a.out | grep ctz
0000000000400fd0 T __ctzdi2

所以,如果我理解正确的话,Solaris 链接器解析了 __ctzdi2(__builtin_ctzll 的内部表示)。

现在,在另一台 Solaris 机器上使用 gcc 4.5.2 进行编译:

#gcc -m64 ctzll.c -c
# nm ctzll.o
0000000000000000 T func

该符号已在目标文件中正确解析,并已内联到 .o 程序集中:

   8:   48 0f bc 45 f8          bsf    -0x8(%rbp),%rax

3.4.3 编译器的行为是否正确?我希望实际编译通过引用 64 位版本的 libgcc.a 来处理内置函数,如 4.5.2。编译器之间缺乏一致性导致我的项目出现上游问题,因为内置函数仍未定义,并且链接器没有解析符号,因为我没有链接到操作系统特定的 64 位库 (libgcc.a)。我不确定 3.4.3 编译器是否配置错误导致 .o 文件具有通过链接捕获的未定义内置函数,或者新编译器是否更智能,我需要将 64 位库添加到链接器以处理旧的编译器。

3.4.3 似乎显示了一个有效的 libgcc.a,其中包含 _ctzdi2 的定义:

# gcc -m64 -print-libgcc-file-name
/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a
# nm /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a | grep ctzdi2
0000000000000000 T __ctzdi2
_ctzdi2.o:

【问题讨论】:

  • 你是用gcc链接,还是用其他方式链接?
  • 两种行为都很好。根据优化和架构选项,gcc 可能会扩展内置内联或生成对某些函数或其他任何内容的调用。您应该与 libgcc 链接,gcc 默认会这样做。
  • 感谢您的澄清。我正在链接 Solaris 链接器,但它没有链接到 libgcc,因此该符号仍未定义。我想知道是否应该由实际的编译器或链接器负责解析 _builtin 函数

标签: gcc compilation linker solaris gcc3


【解决方案1】:

libgcc.a 的全部意义在于实现 gcc 无法为其生成代码的内置操作(其中不仅包括 __builtin_ 函数,还包括某些 32 位平台上的“long long”数学操作)。

显然,较新的 gcc 在发出代码方面变得更聪明了。

【讨论】:

  • 是的 - 我明白 libgcc 的作用。我不确定是否可以保证实际编译器的工作是解析内置函数,或者有时是否可以将此责任委托给链接器。因为在我的情况下,两者都在推卸责任,符号未解决。
猜你喜欢
  • 2017-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
相关资源
最近更新 更多