[转贴]Static Linking Considered Harmful

Static Linking Considered Harmful

There are still too many people out there who think (or even insist) that static linking has benefits. This has never been the case and never will be the case. Here are a few reasons why dynamic linking is superior:

  • fixes (either security or only bug) have to be applied to only one place: the new DSO(s). If various applications are linked statically, all of them would have to be relinked. By the time the problem is discovered the sysadmin usually forgot which apps are built with the problematic library. I consider this alone (together with the next one) to be the killer arguments.

  • Security measures like load address randomization cannot be used. With statically linked applications, only the stack and heap address can be randomized. All text has a fixed address in all invocations. With dynamically linked applications, the kernel has the ability to load all DSOs at arbitrary addresses, independent from each other. In case the application is built as a position independent executable (PIE) even this code can be loaded at random addresses. Fixed addresses (or even only fixed offsets) are the dreams of attackers. And no, it is not possible in general to generate PIEs with static linking. On IA-32 it is possible to use code compiled without -fpic and -fpie in PIEs (although with a cost) but this is not true for other architectures, including x86-64.

  • more efficient use of physical memory. All processes share the same physical pages for the code in the DSOs. With prelinking startup times for dynamically linked code is as good as that of statically linked code.

  • all kinds of features in the libc (locale (through iconv), NSS, IDN, ...) require dynamic linking to load the appropriate external code. We have very limited support for doing this in statically linked code. But it requires that the dynamically loaded modules available at runtime must come from the same glibc version as the code linked into the application. And it is completely unsupported to dynamically load DSOs this way which are not part of glibc. Shipping all the dependencies goes completely against the advantage of static linking people site: that shipping one binary is enough to make it work everywhere.

  • Related, trivial NSS modules can be used from statically linked apps directly. If they require extensive dependencies (like the LDAP NSS module, not part of glibc proper) this will likely not work. And since the selection of the NSS modules is up the the person deploying the code (not the developer), it is not possible to make the assumption that these kind of modules are not used.

  • no accidental violation of the (L)GPL. Should a program which is statically linked be given to a third party, it is necessary to provide the possibility to regenerate the program code.

  • tools and hacks like ltrace, LD_PRELOAD, LD_PROFILE, LD_AUDIT don't work. These can be effective debugging and profiling, especially for remote debugging where the user cannot be trusted with doing complex debugging work.

There are certainly more reasons. The often used argument about statically linked apps being more portable (i.e., can be copied to other systems and simply used since there are no dependencies) is not true since every non-trivial program needs dynamic linking at least for one of the reasons mentioned above. And dynamic linking kills the portability of statically linked apps.

Conclusion: Never use static linking!

Clarification

There is one aspect where people decide to misinterpret these recommendations. I do not say that everything should be stuffed into its own DSO. I would never say this. To the contrary. Code which belongs together because of the development process should be kept in the same object. The reason is that the fewer DSOs are needed the faster everything works (loading, symbol resolution, ...).

One example where this still isn't done right is OpenOffice.org. If you look at the dependencies of the binaries (swriter.bin etc) you'll see lots of files from the OO.org project. Almost all of them are used in all the OO.org programs and none is used outside the project. Especially there is libsoffice.so which itself pulls in a huge number of DSOs. This is done in all OO.org programs!

During deployment there is no reason to do this. All the DSOs pulled in by libsoffice.so and probably some of the others used in the various programs should all be part of one mega-DSO. Yes, this DSO would be big, but it would be smaller than sum of all the loaded dependencies. And more: the export lists can be further restricted making a lot of calls inside the new DSO much faster.

There is a good reason to have all the separate DSOs during development. This makes it possible to rebuild only a small part of the source tree to test out some changes. But this is development. When the binaries are shipped to users (e.g., as part of a distribution) this need falls away and so does the justification.

So, combine all the sources from the same project which are used or at least loaded in all or most situations in one single DSO. It will be smaller and faster. Just don't get overzealous and add 3rd party code as well. E.g., even if you ship a copy of, say, libxml don't add it to your DSO. Only the code which is written as part of the project.

你可能感兴趣的:(application,dependencies,Deployment,profiling,debugging,portability)