1

在 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:
4

1 回答 1

1

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

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

于 2014-05-25T04:19:02.017 回答