我知道目标文件(.o)总是可重定位的,
.a
和文件怎么样.so
?
答案1
文件.a
只是其他文件的存档。通常,这些文件是.o
您已经知道答案的文件。但它们不一定是目标代码 - 事实上,它们根本不一定是目标代码 - 它们实际上可以是任何您喜欢的文件。
文件.so
必须是可重定位才能工作,因为它必须能够根据运行时可用的地址在不同的进程中加载到不同的地址。
答案2
让我们先了解一下可重定位的既定定义。如果一段代码可以放置在内存中的任何位置而无需更改并正确执行,则该代码是可重定位的。因此 .o 和 .a 文件都不是可重定位的,因为它们不是代码片段 (!)。.o 文件包含一段代码及其附带信息,而 .a 文件则是任意文件的集合,可能是 .o。
那么,.o 中包含的代码是否可重定位?不,一般来说不是,因为必须由链接器对其进行增强,才能使用 .o 文件提供的信息填写地址。例如,使用多项式求值器计算正弦,而该求值器位于只有链接器知道的其他库中。因此,多项式求值器的调用地址仍然必须填写;换句话说,代码不能这样执行。
最后,.so 文件中的代码是可重定位的,因为这些代码是共享的,可由多个进程同时执行。如果所有这些进程都必须将代码放在一个正确执行的地址上,那就很不方便了。
答案3
可能有点晚了,但让我试试:
- *.o:对象模块,可能是“pic”或“non-pic”
- *.a: 对象模块的集合
- *.so:共享对象/库,必须从“pic”对象构建
- 'pic' 代码:位置无关代码,可以在任何位置加载并通过重定位运行。
- “非 pic” 代码:必须将其放置在固定地址;或者必须在加载到内存后重新定位;链接共享对象时不能使用“非 pic”对象模块
额外好处:可执行文件不一定是“pic”,但如果是,则可以在运行它时使用 ASLR:https://en.wikipedia.org/wiki/Address_space_layout_randomization