8.83. 移除调试符号

本节是可选的。如果系统不是为程序员设计的,也没有调试系统软件的计划,可以通过从二进制程序和库移除调试符号和不必要的符号表项,将系统的体积减小约 2 GB。对于一般的 Linux 用户,这不会造成任何不便。

大多数使用以下命令的用户不会遇到什么困难。但是,如果打错了命令,很容易导致新系统无法使用。因此,在运行 strip 命令前,最好备份 LFS 系统的当前状态。

strip 命令的 --strip-unneeded选项从程序或库中移除所有调试符号。它也会移除所有链接器 (对于静态库) 或动态链接器 (对于动态链接的程序和共享库) 不需要的符号表项。

下面将一些库的调试符号使用 Zlib 压缩并保存在单独的文件中。后续在 BLFS 中,一些软件包的测试套件使用了 valgrind gdb 运行退化测试,它们需要这些调试信息。

需要注意的是,strip 命令会覆盖它正在处理的二进制程序或库文件。这可能导致正在使用该文件中代码或数据的进程崩溃。如果运行 strip 的进程受到影响,则可能导致正在被处理的程序或库完全损坏;这可能导致系统完全不可用。为了避免这种情况,将一些库和程序复制到 /tmp 中,在那里移除调试符号,再使用 install 命令重新安装它们。(第 8.2.1 节 “升级问题” 中的相关条目介绍了使用 install 命令的原因。)

[注意]

注意

ELF 加载器的文件名在 64 位系统是 ld-linux-x86-64.so.2,在 32 位系统是 ld-linux.so.2。下面的命令会为当前架构选择正确的文件名,并排除文件名以 g 结尾的文件。

[重要]

重要

在构建过程中,如果任何一个软件包的版本和本书指定的版本不同 (无论是依照安全公告的要求还是为了满足个人需求),则可能需要更新 save_usrlib 或者 online_usrlib 中的库文件名。否则可能导致系统完全无法使用。

save_usrlib="$(cd /usr/lib; ls ld-linux*[^g])
             libc.so.6
             libthread_db.so.1
             libquadmath.so.0.0.0
             libstdc++.so.6.0.33
             libitm.so.1.0.0
             libatomic.so.1.2.0"

cd /usr/lib

for LIB in $save_usrlib; do
    objcopy --only-keep-debug --compress-debug-sections=zlib $LIB $LIB.dbg
    cp $LIB /tmp/$LIB
    strip --strip-unneeded /tmp/$LIB
    objcopy --add-gnu-debuglink=$LIB.dbg /tmp/$LIB
    install -vm755 /tmp/$LIB /usr/lib
    rm /tmp/$LIB
done

online_usrbin="bash find strip"
online_usrlib="libbfd-2.43.1.so
               libsframe.so.1.0.0
               libhistory.so.8.2
               libncursesw.so.6.5
               libm.so.6
               libreadline.so.8.2
               libz.so.1.3.1
               libzstd.so.1.5.6
               $(cd /usr/lib; find libnss*.so* -type f)"

for BIN in $online_usrbin; do
    cp /usr/bin/$BIN /tmp/$BIN
    strip --strip-unneeded /tmp/$BIN
    install -vm755 /tmp/$BIN /usr/bin
    rm /tmp/$BIN
done

for LIB in $online_usrlib; do
    cp /usr/lib/$LIB /tmp/$LIB
    strip --strip-unneeded /tmp/$LIB
    install -vm755 /tmp/$LIB /usr/lib
    rm /tmp/$LIB
done

for i in $(find /usr/lib -type f -name \*.so* ! -name \*dbg) \
         $(find /usr/lib -type f -name \*.a)                 \
         $(find /usr/{bin,sbin,libexec} -type f); do
    case "$online_usrbin $online_usrlib $save_usrlib" in
        *$(basename $i)* )
            ;;
        * ) strip --strip-unneeded $i
            ;;
    esac
done

unset BIN LIB save_usrlib online_usrbin online_usrlib

这里会产生关于很多文件的错误信息,因为无法识别这些文件的格式。这些警告可以安全地忽略。它们表明那些文件是脚本文件,而不是二进制文件。