Important: The information in this document is obsolete and should not be used for new development.
The static linker (ld)
supports the removal of unused code and data blocks from executable
files. This process (known as dead-code stripping) helps reduce
the overall size of executables, which in turn improves performance
by reducing the memory footprint of the executable. It also allows
programs to link successfully in the situation where unused code
refers to an undefined symbol, something that would normally result
in a link error.
Dead-code stripping is not limited to removing only unused functions and executable code from a binary. The linker also removes any unused symbols and data that reside in data blocks. Such symbols might include global variables, static variables, and string data among others.
When dead-code stripping is enabled, the static linker searches for code that is unreachable from an initial set of live symbols and blocks. The initial list of live symbols and blocks may include the following:
Symbols listed in an exports file; alternatively, the symbols absent from a list of items marked as not to be exported. For dynamic libraries or bundles without an exports file, all global symbols are part of the initial live list. See “Preventing the Stripping of Unused Symbols” for more information.
The block representing the default entry point or the symbol
listed after the -e linker option,
either of which identifies the specific entry point for an executable.
See the ld man page for
more information on the -e option.
The symbol listed after the -init linker
option, which identifies the initialization routine for a shared
library. See the ld man
page for more information.
Symbols whose declaration includes the used attribute.
See “Preventing the Stripping of Unused Symbols” for more information.
Objective-C runtime data.
Symbols marked as being referenced dynamically (via the REFERENCED_DYNAMICALLY bit
in /usr/include/mach-o/nlist.h).
Enabling Dead-Code Stripping in Your Project
Identifying Stripped Symbols
Preventing the Stripping of Unused Symbols
Assembly Language Support
To enable dead-code stripping in your project, you must pass the appropriate command-line options to the linker. From Xcode, you add these options in the Build pane of the target inspector; otherwise, you must add these options to your makefile or build scripts. Table 28-2 lists the Xcode build settings that control dead-code stripping. Enabling either of these build settings causes Xcode to build with the corresponding linker option.
Linker option |
Build setting |
|---|---|
|
Dead Code Stripping (DEAD_CODE_STRIPPING) |
|
Don’t Dead-Strip Inits and Terms (PRESERVE_DEAD_CODE_INITS_AND_TERMS) |
Table 28-1 lists the basic dead-code stripping options.
Linker option |
Description |
|---|---|
|
Enables basic dead-code stripping by the linker. |
|
Prevents all constructors and destructors from being
stripped when the |
You must recompile all object files using the compiler included
with Xcode 1.5 or later before dead-code stripping can be performed
by the linker. You must also compile the object files with the -gfull option
to ensure that the resulting binaries can be properly debugged.
In Xcode, change the value of the Level of Debug Symbols (GCC_DEBUGGING_SYMBOLS)
build setting to All Symbols (-gfull).
Note: The
GCC compiler’s -g option
normally defaults to -gused,
which reduces the size of .o files
at the expense of symbol information. Although the -gfull option does
create larger .o files,
it often leads to smaller executable files, even without dead-code
stripping enabled.
If you want to know what symbols were stripped by the static
linker, you can find out by examining the linker-generated load
map. This map lists all of the segments and sections in the linked
executable and also lists the dead-stripped symbols. To have the
linker generate a load map, add the -M option
to your linker command-line options. In Xcode, you can add this
option to the Other Linker Flags build setting.
Note: If
you are passing this option through the cc compiler
driver, make sure to pass this flag as -Wl,-M so
that it is sent to the linker and not the compiler.
If your executable contains symbols that you know should not be stripped, you need to notify the linker that the symbol is actually used. You must prevent the stripping of symbols in situations where external code (such as plug-ins) use those symbols but local code does not.
There are two ways to tell the linker not to dead strip a
symbol. You can include it in an exports file or mark the symbol
declaration explicitly. To mark the declaration of a symbol, you
include the used attribute
as part of its definition. For example, you would mark a function
as used by declaring it as follows:
void MyFunction(int param1) __attribute__((used)); |
Alternatively, you can provide an exports list for your executable
that lists any symbols you expect to be used by plug-ins or other
external code modules. To specify an exports file from Xcode, use
the Exported Symbols File (EXPORTED_SYMBOLS_FILE) build setting;
enter the path, relative to the project directory, to the exports
file. To specify an exports file from the linker command line use
the -exported_symbols_list.
option. (You can also specify a list of symbols not to
export using the -unexported_symbols_list option.)
If you are using an exports list and building either a shared
library, or an executable that will be used with ld's -bundle_loader flag,
you need to include the symbols for exception frame information
in the exports list for your exported C++ symbols. Otherwise, they
may be stripped. These symbols end with .eh;
you can view them with the nm tool.
If you are writing assembly language code, the assembler now recognizes some additional directives to preserve or enhance the dead-stripping of code and data. You can use these directives to flag individual symbols or entire sections of assembly code.
To prevent the dead stripping of an individual symbol, use
the .no_dead_strip directive.
For example, the following code prevents the specified string from
being dead stripped:
.no_dead_strip _my_version_string |
.cstring |
_my_version_string: |
.ascii "Version 1.1" |
To prevent an entire section from being dead stripped, add
the no_dead_strip attribute
to the section declaration. The following example demonstrates the
use of this attribute:
.section __OBJC, __image_info, regular, no_dead_strip |
You can also add the live_support attribute
to a section to prevent it from being dead stripped if it references
other code that is live. This attribute prevents the dead stripping
of some code that might actually be needed but not referenced in
a detectable way. For example, the compiler adds this attribute
to C++ exception frame information. In your code, you might use
the attribute as follows:
.section __TEXT, __eh_frame, coalesced, no_toc+strip_static_syms+live_support |
The .subsections_via_symbols directive
notifies the assembler that the contents of sections may be safely
divided into individual blocks prior to dead-code stripping. This
directive makes it possible for individual symbols to be stripped
out of a given section if they are not used. This directive applies
to all section declarations in your assembly file and should be
placed outside of any section declarations, as shown below:
.subsections_via_symbols |
; Section declarations... |
If you use this directive, make sure that each symbol in the
section marks the beginning of a separate block of code. Implicit
dependencies between blocks of code might result in the removal
of needed code from the executable. For example, the following section contains
three individual symbols, but execution of the code at _plus_three ends
at the blr statement
at the bottom of the code block.
.text |
.globl _plus_three |
_plus_three: |
addi r3, r3, 1 |
.globl _plus_two |
_plus_two: |
addi r3, r3, 1 |
.global _plus_one |
_plus_one: |
addi r3, r3, 1 |
blr |
If you were to use the .subsections_via_symbols directive
on this code, the assembler would permit the stripping of the symbols _plus_two and _plus_one if
they were not called by any other code. If this occurred, _plus_three would
no longer return the correct value because part of its code would
be missing. In addition, if _plus_one were
dead stripped, the code might crash as it continued executing into
the next block.
Last updated: 2006-11-07