Skip to content
This repository has been archived by the owner on Jan 12, 2019. It is now read-only.

关于源码编译的基础知识 via LinuxSir (上篇) #6

Open
JackieMium opened this issue Mar 8, 2018 · 0 comments
Open

关于源码编译的基础知识 via LinuxSir (上篇) #6

JackieMium opened this issue Mar 8, 2018 · 0 comments
Labels
Code Talk is chip, show me the code Linux Linux related 基础 很基础的东西
Milestone

Comments

@JackieMium
Copy link
Owner

JackieMium commented Mar 8, 2018

2017-05-18 

这一篇博文很长,我分成下上下两篇。

内容来自已经不存在的 LinuxSir 社区(RIP)的 LFS 板块,当时很多东西我并不懂,只是觉得很有趣所以复制粘贴到我的笔记软件里了。
几年之后我对 Linux 熟悉一些,也用过 Gentoo 很久并一直认为这是我最喜欢的 Linux 发行版。虽然我对源码编译很感兴趣,但是知之甚少。偶然再看到这篇博客很多东西有种豁然开朗的感觉。再想回去 LinuxSir 社区,发现它早已不复存在。

我现在仍然觉得这两篇博文很有趣,并且打算还保留它们。如果原作者看到的话,有什么问题请和我联系。

以下时原文,有少量改动。


如果不出意外的话,会出现say.so => not found. 这时的./test是不能运行的. 但至少说明程序运行时是需要这个库的. 那为什么找不到这个库呢? 那就让我们看看系统是怎样寻找这些库的吧.

首先是ld-linux.so.2这个不能不说,它太重要了,以至于也决定了后面的搜索方式.

先是程序内部决定的.

strings test 

还好我们这个test程序不大,不用过滤输出,好,你看见什么, /lib/ld-linux.so.2, say.so, libc.so.6, 对, 用到的库!

但我们发现不同,有的有路径,有的没有,先不管没有路径的怎么寻找,有路径的肯定是能找到了,那好,我们让say.so也有了路径.

gcc test.c ./say.so -o test2 
strings test2 

我们发现原来的输出中原来的say.so已经变成了./say.so. 运行一下./test2, 可以运行了! 好,找到库了,这里用的相对路径,无疑,我们将say.so移动到非当前文件夹.那test就又不能运行了.这样无疑是把我们用到的库硬编码进了程序里.我不喜欢硬编码,太死板.那不硬编码系统怎么找到我们需要的文件呢.

在程序没有把库地址硬编码经进去的前提下,系统会寻找LD_LIBRARY_PATH环境变量中的地址.
如果系统在这一步也没发现我们需要的库呢.
/etc/ld.so.cache这个由ldconfig生成的文件,记载着在/etc/ld.so.conf文件中指明的所有库路径加上/lib, /usr/lib里的所有库的信息.
其实以上这句话只是在大多数情况下是正确的, 是否是这个文件由ld-linux.so.2决定. 如过你的LFS中的第一遍工具链/tools还在的话,

strings /tools/lib/ld-linux.so.2 |grep etc 

输出很可能是/tools/etc/ld.so.cache. 那么它用的哪个文件我们就清楚了吧.
可这个路径前面的/tools到底和什么有关呢?首先我们可能会想到与ld-linux所在的位置有关. 还好我们有3套glib, 感谢LFS, 现在我们拿第二遍的工具链下手. 假设我们的LFS在/lfsroot

strings /lfsroot/lib/ld-linux.so.2 

很奇怪的是输出竟然是/etc/ld.so.cache! 那这到底和什么有关呢,没错就是我们编译时候的--prefix有关.
现在再看这个/etc/ld.so.conf, 和/lib, /usr/lib这些默认ldconfig路径. 也都要加上个这个prefix了.

strings /tools/sbin/ldconfig |grep etc 
strings /tools/sbin/ldconfig |grep /lib 

验证一下吧.
那要是ld.so.cache里也没有记载这个库的地址怎么办呢.
最后在默认路径里找.这个路径一般是/lib, /usr/lib, 但也不全是.

strings /tools/lib/ld-linux.so.2 |grep /lib 

还是要加个prefix.
现在我们反过来思考,不用程序中硬编码的/lib/ld-linux.so.2做动态加载器了.这也可以?!是的!虽然不一定成功.

LD_TRACE_LOADED_OBJECTS=y /tools/lib/ld-linux.so.2 /bin/test 
LD_TRACE_LOADED_OBJECTS=y /lib/ld-linux.so.2 /bin/test 
LD_TRACE_LOADED_OBJECTS=y /lfsroot/lib/ld-linux.so.2 /bin/test 

为了说明顺序,我们做如下很危险的实验:

ldconfig /lfsroot/lib; 
ldconfig -p 

会出现很多内容,但不要试着过滤,因为这时的系统应该很多程序不能运行了.先踏下心来观察.你会发现很多库出现两次/lfsroot/lib, 和/lib而且/lfsroot/lib在前, 说明ldconfig先处理参数给出的地址,最后是默认地址.但顺序也不一定,应该还和编译glibc时我们的参数--enable-kernel有关(我根据种种表现猜测).
加上export LD_LIBRARY_PATH=/lib 环境变量在前面,不能运行的程序又能运行了,说明LD_LIBRARY_PATH变量的优先级优于ld.so.cache

unset LD_LIBRARY_PATH 
echo >/etc/ld.so.cache 
ldconfig -p 

应该什么都不出现,可大部分程序能运行.说明ld-linux.so.2决定的默认路径起了作用(注意,这里的ldconfig的默认路径没有作用)

ldconfig 

恢复系统正常.

@JackieMium JackieMium added Linux Linux related 基础 很基础的东西 Code Talk is chip, show me the code labels Mar 8, 2018
@JackieMium JackieMium changed the title 关于源码编译的基础知识via LinuxSir (上篇) 关于源码编译的基础知识 via LinuxSir (上篇) Mar 8, 2018
@JackieMium JackieMium added this to the Migration milestone Mar 9, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Code Talk is chip, show me the code Linux Linux related 基础 很基础的东西
Projects
None yet
Development

No branches or pull requests

1 participant