6.10. 调整工具链
现在已经安装了最终的 C 库,是时候调整工具链,以便它将任何新编译的程序与这些新库链接起来。
/工具/bin/{ld,ld-old}
/tools/$(uname -m)-pc-linux-gnu/bin/{ld,ld-old}
/工具/bin/{ld-new,ld}
/工具/bin/{ld,ld-old}
/tools/$(uname -m)-pc-linux-gnu/bin/{ld,ld-old}
/工具/bin/{ld-new,ld}
首先,备份 /工具 链接器,并将其替换为我们在第 5 章中所做的调整后的链接器。我们还将在 /工具/$(uname -m)-pc-linux-gnu/bin:
MV MV MV
ln
-v
-v
-v
MV MV MV
ln
-sv /tools/bin/ld /tools/$(uname -m)-pc-linux-gnu/bin/ld
-sv /tools/bin/ld /tools/$(uname -m)-pc-linux-gnu/bin/ld
接下来,修改 GCC 规范文件,使其指向新的动态链接器。 简单地删除“/tools”的所有实例应该会给我们留下正确的动态链接器路径。 还要调整规范文件,以便 GCC 知道在哪里可以找到正确的头文件和 Glibc 启动文件。 一种 口渴 命令完成此操作:
gcc -dumpspecs | sed -e 's@/tools@@g' \
-e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
-e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
`目录名 $(gcc --print-libgcc-file-name)`/specs
gcc -dumpspecs | sed -e 's@/tools@@g' \
-e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
-e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
`目录名 $(gcc --print-libgcc-file-name)`/specs
目视检查规格文件以验证实际进行了预期更改是一个好主意。
此时必须确保调整后的工具链的基本功能(编译和链接)按预期工作。 为此,请执行以下健全性检查:
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log readelf -l a.out | grep ':/lib'
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log readelf -l a.out | grep ':/lib'
应该没有错误,最后一个命令的输出将是(允许动态链接器名称中特定于平台的差异):
[请求程序解释器:/lib64/ld-linux-x86-64.so.2]
[请求程序解释器:/lib64/ld-linux-x86-64.so.2]
请注意,在 64 位系统上 / lib目录 是我们的动态链接器的位置,但可以通过 /lib64 中的符号链接访问。
备注
在 32 位系统上,解释器应该是 /lib/ld-linux.so.2。
备注
在 32 位系统上,解释器应该是 /lib/ld-linux.so.2。
现在确保我们设置为使用正确的启动文件:
grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
最后一条命令的输出应该是:
/usr/lib/../lib/crt1.o 成功
/usr/lib/../lib/crti.o 成功
/usr/lib/../lib/crtn.o 成功
/usr/lib/../lib/crt1.o 成功
/usr/lib/../lib/crti.o 成功
/usr/lib/../lib/crtn.o 成功
验证编译器是否正在搜索正确的头文件:
grep -B1 '^ /usr/include' dummy.log
grep -B1 '^ /usr/include' dummy.log
此命令应返回以下输出:
#include <...> 搜索从这里开始:
/ usr / include
#include <...> 搜索从这里开始:
/ usr / include
接下来,验证新链接器是否与正确的搜索路径一起使用:
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
对包含带有“-linux-gnu”组件的路径的引用应该被忽略,否则最后一个命令的输出应该是:
SEARCH_DIR("/usr/lib") SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib") SEARCH_DIR("/lib")
接下来确保我们使用了正确的 libc:
grep "/lib.*/libc.so.6 " dummy.log
grep "/lib.*/libc.so.6 " dummy.log
最后一条命令的输出应该是:
尝试打开 /lib/libc.so.6 成功
尝试打开 /lib/libc.so.6 成功
最后,确保 GCC 使用正确的动态链接器:
grep 发现 dummy.log
grep 发现 dummy.log
最后一个命令的输出应该是(允许动态链接器名称中特定于平台的差异):
在 /lib/ld-linux-x86-64.so.2 找到 ld-linux-x86-64.so.2
在 /lib/ld-linux-x86-64.so.2 找到 ld-linux-x86-64.so.2
如果输出未如上所示出现或根本没有收到,则说明出现了严重错误。 调查并追溯这些步骤以找出问题所在并进行纠正。 最可能的原因是规格文件调整出现问题。 在继续该过程之前,需要解决任何问题。
一切正常后,清理测试文件:
rm -v dummy.c a.out dummy.log
rm -v dummy.c a.out dummy.log