天天看点

符号、链接与调试

Symbols have always presented a conundrum for developers:

  • You want to remove all symbols from your program because this makes the code smaller, and potentially faster.
  • However, if you remove all symbols, your crash log backtraces will contain just hex values, which makes it significantly harder to interpret them.

Modern versions of Xcode make it easy to have your cake and eat it to. You can remove all symbols from your program before shipping it to end users, and still have easy access to symbolic debugger information when interpreting crash logs. This section explains how to do this.

Symbols Divided

When you build a program with Xcode, you must deal with two very different types of symbols:

  • Mach-O Symbols — These symbols may be interpreted by the linker (either static, ld, or dynamic, dyld).
  • Debugger Symbols — These symbols are interpreted by the debugger.

Mach-O symbols are subdivided into two groups:

  • local symbols — These symbols are ignored by the linker, and are solely present for the benefit of tools like CrashReporter. When you declare a function as ​

    ​static​

    ​ in C, it gets recorded as a local symbol.
  • global symbols — These symbols are interpreted by both the static and dynamic linker. When you declare a function as ​

    ​extern​

    ​ in C, it gets recorded as a global symbol.

Xcode supports two forms of debugger symbols:

  • DWARF — This is the modern debugger symbols format, supported by Xcode 2.3 and later. DWARF symbols have numerous advantages, not the least being the nice integration with CrashReporter, as described below.
  • STABS — This older debugger symbols format is now deprecated.

Note: STABS debugger symbols are actually stored in the Mach-O symbol table. This made the process of managing symbols more confusing because it conflated two very different concepts (that is, Mach-O symbols and debugger symbols).

​​Back to Top​​​ ​​

符号、链接与调试

​​

Stripping Debugger Symbols

Xcode's DWARF implementation makes it very easy to strip debugger symbols from your released program. All you need to do is set the "Debug Information Format" build setting for your release build to "DWARF with dSYM File" (​

​DEBUG_INFORMATION_FORMAT = dwarf-with-dsym​

​​). When you build your program Xcode will extract all of the debugging information and place it in a ​

​.dSYM​

​document, which it places right next to your program in the build folder. You can then:

  • package up your program and ship it to your users
  • archive the ​

    ​.dSYM​

    ​ file

If, at any time in the future, you need to debug your released program, you can just put it and the ​

​.dSYM​

​ file in the same directory and GDB will automatically find and use the debugger symbols.

符号、链接与调试

Stripping Mach-O Symbols

Stripping Mach-O symbols is a more complicated issue. The problem is that some Mach-O symbols are interpreted at runtime by the dynamic linker, and you must ensure that those symbols are not stripped. There's one overall approach, but you have modify it depending on the type of program you are building.

The first step is to enable the "Deployment Postprocessing" build setting (​

​DEPLOYMENT_POSTPROCESSING = YES​

​) for your release build. This will cause Xcode to automatically remove some symbols from your program. The exact behavior depends on the "Strip Style" build setting. You have three choices for this setting:

  • All Symbols (​

    ​STRIP_STYLE = all​

    ​) — Xcode will strip all symbols that are not specifically marked as being needed at runtime. This is equivalent to running strip tool with the "-u" and "-r" flags.
  • Non-Global Symbols (​

    ​STRIP_STYLE = non-global​

    ​) — Xcode will strip all local symbols. This is equivalent to running strip tool with the "-x" flags.
  • Debugging Symbols (​

    ​STRIP_STYLE = debugging​

    ​) — Xcode will strip no symbols! Actually, it runs the strip tool with the "-S" flag, which causes it to remove all debugger symbols. This is relevant if you're using STABS debugger symbols. However, if you're sensible and are using DWARF, your debugger symbols will not be affected by this; ​

    ​strip​

    ​ will remove some information from your program (notably the debug map used by dsymutil) but this will not affect the ​

    ​.dSYM​

    ​ file that Xcode has already created.

Critically, the default value for the "Strip Style" build setting depends on your target type.  ​​Table 2​​ shows this relationship.

Table 2: Default strip style by target type

Target Type Mach-O Type Default Strip Style
Application, Command-Line Tool

​MH_EXECUTE​

All Symbols
Bundle

​MH_BUNDLE​

Non-Global Symbols
Framework, Dynamic Library

​MH_DYLIB​

Debugging Symbols
Static Library

​MH_OBJECT​

IMPORTANT: If you do not set the "Strip Style" build setting at the project layer, Xcode will display a value of All Symbols. This is misleading. The actual value you get depends on the target type, as shown above. If you open the target build settings, you will set the actual value that will be used.

On the other hand, if you do set a value for the "Strip Style" build setting at the project layer, this will apply to all targets (unless you override it at the target layer). If your project has multiple targets of different types, this is unlikely to be useful. In this case you will probably want to set the "Strip Style" build setting at the target layer for all targets.

For more information about how Xcode's build settings are layered, see the Build Setting Evaluation section section of the ​​Xcode User Guide​​.

There are two common approaches to stripping Mach-O symbols:

  • typical — In most cases it's reasonable to leave all Mach-O global and local symbols in your release program. They don't bloat the program too much, and their presence can be useful. For example:
  • your CrashReporter logs will include basic symbols in the backtrace
  • you can set DTrace probe points on these symbols
  • restricted — In some cases it's necessary to remove all non-essential symbols from a program. For example:
  • when you want to reduce the program's size as much as possible
  • when you don't want users seeing your symbol names

Implementing the typical approach is trivial. Set the "Strip Style" build setting to Debugging Symbols, and Xcode will leave all of your global and local Mach-O symbols in the program. This approach works for all target types.

Implementing the restricted approach is a bit trickier. You have to do different things depending on your target type. For an application or command-line tool, you can simply set the "Strip Style" build setting to "All Symbols".

------------------越是喧嚣的世界,越需要宁静的思考------------------

合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。

积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里;不积小流,无以成江海。骐骥一跃,不能十步;驽马十驾,功在不舍。锲而舍之,朽木不折;锲而不舍,金石可镂。蚓无爪牙之利,筋骨之强,上食埃土,下饮黄泉,用心一也。蟹六跪而二螯,非蛇鳝之穴无可寄托者,用心躁也。