Apple publishes no separate specification for dSYM bundles. This page describes them
as dsymutil (part of LLVM) writes them. The file
inside is an ordinary Mach-O file, so its header,
load commands and symbol table are documented on the Mach-O pages and only what is
particular to dSYM files is given here. The debug data itself is
DWARF.
Folder layout
MyApp.app.dSYM/
Contents/
Info.plist
Resources/
DWARF/
MyApp
MyApp.app.| Path | Meaning |
|---|---|
name.dSYM/ | The bundle. Unless an output name is given, dsymutil names it after the input with .dSYM added. |
Contents/Info.plist | A property list identifying the bundle (keys below). |
Contents/Resources/DWARF/file | The debug symbols file, with the same file name as the input binary. |
Contents/Resources/… | dsymutil --embed-resource can add further files, which must stay inside Resources. |
With dsymutil --flat no bundle is made: the same Mach-O file is written
alone as name.dwarf.
Info.plist
An XML property list holding one dictionary:
| Key | Value | Meaning |
|---|---|---|
CFBundleDevelopmentRegion | English | Always this value. |
CFBundleIdentifier | com.apple.xcode.dsym.id | id is the program’s own bundle identifier when dsymutil finds its Info.plist (e.g. com.apple.xcode.dsym.com.example.myapp), otherwise the bundle folder’s name without .dSYM. |
CFBundleInfoDictionaryVersion | 6.0 | Always this value. |
CFBundlePackageType | dSYM | Marks the bundle as a debug symbol bundle. |
CFBundleSignature | ???? | Always this value. |
CFBundleShortVersionString | string | The program’s marketing version, from its Info.plist; may be left out. |
CFBundleVersion | string | The program’s build version, from its Info.plist. |
Toolchain | string | Written only when a toolchain string is set. |
The DWARF file
The file in Resources/DWARF is a Mach-O file (for a universal program,
one per architecture slice). dsymutil writes it like this:
| Part | Value in a dSYM |
|---|---|
Header filetype | 10, MH_DSYM. |
LC_UUID | Copied from the program slice (a program with more than one UUID is refused), so a debugger can pair the two; dwarfdump --uuid shows it. |
LC_BUILD_VERSION | Copied with its platform, minimum OS and SDK, but with the tool list replaced by one entry for dsymutil. |
LC_TARGET_TRIPLE | Copied when present. |
LC_SEGMENT / LC_SEGMENT_64 | Every segment of the program except __DWARF is copied with its section headers, but with file offset and file size 0 and section offsets 0, so it has no contents. The exception is __TEXT,__eh_frame, whose data is copied. |
__LINKEDIT segment | Re-pointed at the new symbol and string tables. |
LC_SYMTAB | Written only when the program is an executable. Undefined symbols, N_AST entries and everything between an N_SO with a name and the closing N_SO (the debug notes) are left out; other symbols are copied. |
__DWARF segment | The debug sections (below), with real contents. |
__DWARF sections
Mach-O section names hold at most 16 characters, so DWARF section
.debug_x is written __debug_x, cut to 16
characters where needed. LLVM defines these sections in the __DWARF
segment; the DWARF meaning of each is on the
DWO sections and units page and in the DWARF
standard:
| Mach-O section | DWARF section | Mach-O section | DWARF section |
|---|---|---|---|
__debug_info | .debug_info | __debug_aranges | .debug_aranges |
__debug_abbrev | .debug_abbrev | __debug_ranges | .debug_ranges |
__debug_line | .debug_line | __debug_rnglists | .debug_rnglists |
__debug_line_str | .debug_line_str | __debug_macinfo | .debug_macinfo |
__debug_frame | .debug_frame | __debug_macro | .debug_macro |
__debug_pubnames | .debug_pubnames | __debug_inlined | .debug_inlined |
__debug_pubtypes | .debug_pubtypes | __debug_cu_index | .debug_cu_index |
__debug_gnu_pubn | .debug_gnu_pubnames | __debug_tu_index | .debug_tu_index |
__debug_gnu_pubt | .debug_gnu_pubtypes | __debug_names | .debug_names |
__debug_str | .debug_str | __apple_names | Apple accelerator table of names |
__debug_str_offs | .debug_str_offsets | __apple_types | accelerator table of types |
__debug_addr | .debug_addr | __apple_namespac | accelerator table of namespaces |
__debug_loc | .debug_loc | __apple_objc | accelerator table of Objective-C classes |
__debug_loclists | .debug_loclists | __swift_ast | Swift module data, copied from the files named by N_AST entries |
dsymutil --accelerator chooses the name index written:
Apple, Dwarf, Pub, Default or
None.
The debug map
dsymutil builds the dSYM from a debug map: stab entries in the
program’s symbol table that name the object
files holding the DWARF and the functions and variables taken from each. The entries
its parser acts on (values from the Mach-O symbols page):
| Type | Name | Use in the debug map |
|---|---|---|
0x66 | N_OSO | Starts a new object file: the name is its path, n_value its timestamp, used to tell apart same-named members of a static library. |
0x68 | N_LIB | Starts a library whose own dSYM is looked for; its N_OSO entries are read only if none is found. |
0x24 | N_FUN | A function: a named entry gives its name and address; a following entry with an empty name gives its size. |
0x26 | N_STSYM | A static variable and its address. |
0x20 | N_GSYM | A global variable; its address is looked up in the program’s own symbol table. |
0x32 | N_AST | A Swift module file whose contents are copied into __swift_ast. |
Other stabs (such as N_BNSYM, N_ENSYM and
N_SO) are ignored by the parser.
Sources
LLVM source: tools/dsymutil/dsymutil.cpp (bundle folders, file names,
--flat, --embed-resource, --accelerator and the
Info.plist keys), MachOUtils.cpp (load commands, segments, symbol table
and MH_DSYM), MachODebugMapParser.cpp (debug map entries) and
lib/MC/MCObjectFileInfo.cpp (the __DWARF section names).
Stab values are those on this site’s Mach-O
symbols page. Apple publishes no dSYM specification; files made by Apple’s own
copy of the tools may differ in details not covered by these sources, such as the
default version strings.