阅读笔记:链接器 - 源代码漫游
原作者: Rod Evans
原文来自: http://blogs.sun.com/roller/page/rie
译注者: Badcoffee
Email: blog.oliver@gmail.com
Blog: http://blog.csdn.net/yayong
2005年6月
这篇文章涉及的很多概念在The Linker and Libraries Guide这本书上有详细介绍。这也是讲解链接器和ELF文件最全和最贴近实际实现的一本书,更重要的是,是免费的电子版:)
The Link-editors - a source tour Welcome to OpenSolaris. I've been working with the link-editors(链接器) for many years, and I thought that with the general availability of the source, now would be an opportune time to cover some history, and give a brief overview of the link-editors source hierarchy.
The link-editor components reside under the usr/src/cmd/sgs directory. This Software Generation Subsystem hierarchy originated from the AT&T and Sun collaboration that produced Solaris 2.0. Under this directory exist the link-editors, and various tools that manipulate or display ELF file information. There are also some ancillary(辅助的) components that I've never modified. I believe at some point it may also have contained compilers, however these have long since moved to their own separate source base.
注解:1.链接器这部分的源代码源自AT&T和SUN共同协作开发的Solaris 2.0。这一点并不感到意外,熟悉Solaris历史的人都知道,Solaris是从BSD逐渐过渡到System V的。
The Link-EditorWhen you mention the link-editor, most folks think of ld(1). You'll find this under sgs/ld. However, this binary is only a stub(桩) that provides argument processing and then dynamically loads the heart of the link-editor, libld.so. This library provides two flavors(种), a 32-bit version, and a 64-bit version, both capable of producing a 32-bit or 64-bit output file. The class of library that is loaded, is chosen from the class of the first input relocatable object read from the command line. This model stems(来自) from a compiler requirement that the link-editor class remain consistent with various compiler subcomponents.
注解: 2. ld只是link-Editor的一部分。而且实际上libld.so才是ld的核心部分,ld只是个stub。
3. libld.so有32和64位两个版本,用来产生32和64位的二进制对象。
4. 具体产生32还是64位的二进制对象是由ld的输入的对象来决定的。
5. 而ld的输入又是来自编译器的需求,链接器要与各种编译器保持一致性。
The Runtime Linker(运行时链接器)
However, there's another link-editor that is required to execute every application on Solaris. This editor takes over where the standard link-editor left off, and is referred to as the runtime-linker, ld.so.1(1). You can find this under sgs/rtld. The runtime linker takes an application from exec(2), loads any required dependencies, and binds the associated objects together with the information left from ld(1). The runtime linker can also be called upon by the application to load additional dependencies and locate symbols.
注解:6. 另外一种链接器就是运行时链接器ld.so.1。它负责ld留下的部分工作,即完成动态库中函数和符号的动态链接。
7. 动态链接器实际上是在应用程序装载的时候被exec系统调用来调用的,负责装载该应用所依赖的动态库。
8. 应用程序所依赖的动态库的信息实际上是ld在生成二进制对象的时候生成并存放在该文件的。
9. 当应用程序需调用自己依赖的动态库的函数时,就会再次调用ld.so.1来定位和解析符号为实际地址。
This very close association of ld(1) and ld.so.1(1), is one reason the link-editors are considered part of the core OS rather than a component of the compilers. This separation(隔离) has also insured the link-editors are compiler neutral(中立的).
注解:10. 链接器一般被认为是操作系统的核心而不是编译器的组成部件。这种隔离也确保了链接器是编译器中立的。
One historic area of the runtime linker is its AOUT support. Objects from our SunOS4.x release were in AOUT format, and to aid customer transition(转移) from this release to Solaris, support for executing AOUT applications was provided by ld.so.1(1). We keep thinking that we're long past this transition need, and that this support could be purged(清除) from the system. However, we continue to come across(偶遇) customers that are still running an AOUT binary on Solaris. Sometimes the customer is Sun!
注解:11. Solaris的运行时链接器支持a.out格式。这是Sun OS 4.x遗留下来的格式,为保持向后兼容,所以至今支持。作者在这里说明了为什么这么久还没有去除这个支持--至今还有客户在Solaris运行a.out格式的二进制。
12. come across 是偶遇的意思
Also, if you poke around (闲逛) the relocation(重定位) files for ld(1) and ld.so.1(1), you'll find a mechanism for sorting and counting relative(相对的) relocations. This allows a faster processing loop for these relocations at runtime. Bryan did this before going on to bigger and better projects. It took him a couple of deltas to get things right, but he was a young lad back then.
注解:13. ld和ld.so.1排序和计算的机制,保证了运行时重定位的处理循环速度速度很快。这部分是Bryan实现的,那时他还很年轻,如果访问Bryan的Blog就会发现,他就是发明dtrace的3个人之一。在我的近距离接触OpenSolaris(2) 中有他的几篇Blog的链接。
Support LibrariesThere are various support libraries employed(使用) by the link-editors. A debugging library, liblddbg.so, is employed by ld(1), ld.so.1(1) and elfdump(1) to provide tracing diagnostics. A common library is used to insure the debugging information looks consistent between the various tools. ld(1) uses libldmake.so to provide .make.state support, and libldstab.so for generic .stabs processing. ld.so.1(1) uses librtld.so for extending the runtime dynamic linking support, and librtld_db.so for mdb(1) and various proc tool support. ld.so.1(1) also used libld.so to process relocatable objects.
注解:13. elfdump是非常不错的察看ELF文件格式的工具。在我的X86汇编语言学习手记(3)中,就使用了这个工具察看ELF文件格式。
14. mdb是Solaris内核的调试工具,在我的X86汇编语言学习手记(1,2,3)中,都用mdb对例子程序进行了调试。
15. 这里的其他名词,我目前不是很了解,只有到The Linker and Libraries Guide这本书里找答案了。
As you can see, there is a lot of interrelationships(相互关系) between the various components of the link-editors. The interfaces between these components are private and often change. When providing updates to the link-editors in patches and updates, this family of components is maintained and supplied as a whole unit.
Proto BuildAs part of building the link-editor components, you might notice that we first build a version of ld(1) under sgs/proto, then use this version of ld(1) to build the other link-editor components, including the final ld(1). This two-stage build has developed as we frequently use new link-editor capabilities and flags to build our own components. A case of eating your own dog food. Without this two-stage build we would first have to integrate a version of ld(1) that provides the new capabilities, wait a week or two for this version of ld(1) to propagate into developers build environments, and then integrated the updates that require to use the new capabilities. Our two-stage build makes for a much faster turn-around. And, should we break something, we're usually the first to find out as we develop our changes.
注解:16. Build链接器的过程。这里谈到了链接器两阶段编译的过程,先Build最新的ld,再用新编译的最新的ld来build其他部分,包括最终版本的ld。这是因为链接器的build中使用了最新版本的ld的功能和符号标志。这样也会使链接器的开发者在第一时间发现新版ld的问题。
Package BuildUnder sgs/packages you'll see we have the capability of building our own package. This isn't the official package(s) that the link-editors are distributed under, but a sparse(几个) package, containing all our components. This package is how we install new link-editors quickly on a variety of test machines, or provide to other developers to test new capabilities or bug fixes, before we integrate into an official build. Note, there's no co-ordination between this package and the official package database, it's really no different than tar(1)'ing the bits onto your system, except you can back the changes out!
注解:17. 这里谈了Solaris package的build。
PatchesWe make a lot of patches. Sure, there are bugs and escalations(向上报告) that need resolving, but we frequently have to make new capabilities available on older releases. The compilers are released asynchronously(异步的) from the core OS, and new capabilities required by these compilers must be made available on every release the compilers are targeted to.
注解:18. 由于编译器和Solaris核心的发布不是同步的,链接器的patche需要随编译器的发布来提供。
We have a unique way of generating patches. When asked to generate a patch we typically backport(向后移植) all the latest and greatest components. As I described earlier, there's a lot of interaction between the various components, and thus trying to evaluate whether an individual component can be delivered isn't always easy. So, we've cut this question out of the puzzle from the start, and always deliver all the link-editor components as a family.
注解:18. 由于链接器内部的联系比较紧密,不同组件间互操作性比较强,所以单独为某一组件提供patche,所以经常是提供全部链接器的组件的patche。
Trying to isolate a particular bug fix can also be challenging. It may look like a two line code fix addresses(解决) a customer escalation, but these two lines are often dependent on some other fixes, in other files, that occurred many months before. Trying to remember, and test for all these possible interactions can be a nightmare(梦魇), so we've removed this question from the puzzle too.
When we address a bug, we address it in the latest source base. If the bug can't be duplicated, then it may have been fixed by some previous change, in which case we'll point to the associated patch. Otherwise, we'll use all the resources available on the latest systems to track down and fix the issue. Yep, that means we get to use the latest mdb(1) features, dtrace(1M), etc. There's nothing more frustrating(灰心) that having to evaluate a bug on an old release where none of your favorite tools exist. Sometime we have to fall back to an older release, but we try and avoid it if we can.
注解:19. 因为组件间内部的相互作用,隔离特定的bug修改也是挑战,因此当解决bug是,通常都是在最新的代码上来作。Bug重现也是在最新的系统上跟踪和修改。因此他们可以使用最新的mdb和dtrace的特性。
20. 在旧版的Solaris,没有dtace和mdb这样的工具是很痛苦的事情。dtrace和mdb都是Solaris提供的非常强大的调试工具。
Having a fix for the issue, we'll integrate the changes in the latest Solaris release. And, after some soak time(等待时间), in which the fix has gone through various test cycles and been deployed on our desktops and building servers, we'll integrate the same changes in all the patch gates. Effectively, we're only maintaining one set of bits across all releases. This greatly reduces the maintenance of the various patch environments, and frees up more time for future development.
注解:21. bug修补后先放到最新的Solaris发行版本,经过一段soak time的验证,会集成同样的代码改变到Solaris的patche gate.
22. 因为前面讲到的只维护一套代码在所有的Solaris发行版本,这使得开发者有更多时间做未来的开发做工作。
This model hasn't been without some vocal(噪声) opponents(反对) - "I want a fix for xyz, and you're giving me WHAT!". But most have come around to the simplicity and efficiency of the whole process. Is it flawless(缺点)? No. Occasionally, regressions(指因为代码改动新引入的bug) have occurred, although these are always in some area that has been outside of the scenarios(特定情况) we're aware of, or test for. Customers always do interesting things. But it will be a customer who finds such as issue, either in a major release, update or patch. Our answer is to respond immediately to any such issues. Our package build comes in very handy(容易取得的) here.
You can always find the bugs we've fixed and patches generated from our SUNWonld-README file.
注解:23.只维护单一code base的问题不是很多,但是有时候会引入客户原本没有的问题。
Other StuffSome other support tools are elfdump(1), ldd(1), and pvs(1). And, there's crle(1), moe(1), and lari(1). I quite enjoyed coming up with these latter names, but you might need some familiarity with old American culture to appreciate this. Which is rather odd in itself, as I'm British.
注解:24. 这里面给出了几个相关的命令:
elfdump 用来分析EFL文件
ldd 察看二进制对象的依赖关系
pvs 打印二进制对象的内部版本信息
crle 配置运行时链接环境
moe 包含运行时链接器的保留字的二进制对象路径的展开工具
lari 运行时链接信息的分析工具
Anyway, hopefully this blog has enlightened you on navigating the OpenSolaris hierarchy in regard the link-editors.
Have fun, and in respect for a popular, current media event - may the source be with you.
Technorati Tag: OpenSolaris
Technorati Tag: Solaris