Greg Clayton | e8ec5ac | 2012-11-16 23:50:32 +0000 | [diff] [blame^] | 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
| 2 | <html xmlns="http://www.w3.org/1999/xhtml">
|
| 3 | <head>
|
| 4 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
| 5 | <link href="style.css" rel="stylesheet" type="text/css" />
|
| 6 | <title>Debug Sybmols on Mac OS X</title>
|
| 7 | </head>
|
| 8 |
|
| 9 | <body>
|
| 10 | <div class="www_title">
|
| 11 | The <strong>LLDB</strong> Debugger
|
| 12 | </div>
|
| 13 |
|
| 14 | <div id="container">
|
| 15 | <div id="content">
|
| 16 |
|
| 17 | <!--#include virtual="sidebar.incl"-->
|
| 18 |
|
| 19 | <div id="middle">
|
| 20 | <div class="post">
|
| 21 | <h1 class="postheader">Debug Symbols on MacOSX</h1>
|
| 22 | <div class="postcontent">
|
| 23 | <p>On MacOSX, debug symbols are often in stand alone bundles called <b>dSYM</b> files.
|
| 24 | These are bundles that contain DWARF debug information and other resources related to
|
| 25 | builds and debug info.</p>
|
| 26 | <p>The DebugSymbols.framework framework helps locate dSYM files when given a UUID. It can
|
| 27 | locate the symbols using a variety of methods:</p>
|
| 28 | <ul>
|
| 29 | <li>Spotlight</li>
|
| 30 | <li>Explicit search paths</li>
|
| 31 | <li>Implicit search paths</li>
|
| 32 | <li>File mapped UUID paths</li>
|
| 33 | <li>Running one or more shell scripts</li>
|
| 34 | </ul>
|
| 35 | <p>DebugSymbols.framework also has global defaults that can be modified to allow
|
| 36 | all of the debug tools (lldb, gdb, sample, CoreSymbolication.framework) to easily
|
| 37 | find important debug symbols. The domain for the DebugSymbols.framework defaults
|
| 38 | is <b>com.apple.DebugSymbols</b>, and the defaults can be read, written or modified
|
| 39 | using the <b>defaults</b> shell command:
|
| 40 | <code><pre><tt><b>% defaults read com.apple.DebugSymbols
|
| 41 | % defaults write com.apple.DebugSymbols KEY ...
|
| 42 | % defaults delete com.apple.DebugSymbols KEY</b>
|
| 43 | </tt></pre></code>
|
| 44 |
|
| 45 | <p>The following is a list of the defaults key value
|
| 46 | setting pairs that can be used to enhance symbol location:</p>
|
| 47 | <table class="stats" width="620" cellspacing="0">
|
| 48 | <tr>
|
| 49 | <td class="hed" width="20%">Defaults Key</td>
|
| 50 | <td class="hed" width="70%">Description</td>
|
| 51 | </tr>
|
| 52 |
|
| 53 | <tr>
|
| 54 | <td class="content">
|
| 55 | <b>DBGFileMappedPaths</b>
|
| 56 | </td>
|
| 57 | <td class="content">
|
| 58 | This default can be specified as a single string, or an array of strings.
|
| 59 | Each string represents a directory that contains file mapped UUID values
|
| 60 | that point to dSYM files. See the "File Mapped UUID Directories" section
|
| 61 | below for more details. Whenever DebugSymbols.framework is asked to lookup
|
| 62 | a dSYM file, it will first look in any file mapped UUID directories
|
| 63 | for a quick match.
|
| 64 | </td>
|
| 65 | </tr>
|
| 66 | <td class="content" colspan="2">
|
| 67 | <code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths -string /path/to/uuidmap1</b>
|
| 68 | <b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths -array /path/to/uuidmap1
|
| 69 | /path/to/uuidmap2</b>
|
| 70 | </tt></pre></code>
|
| 71 | </tr>
|
| 72 | <tr>
|
| 73 | <td class="content">
|
| 74 | <b>DBGShellCommands</b>
|
| 75 | </td>
|
| 76 | <td class="content">
|
| 77 | This default can be specified as a single string, or an array of strings.
|
| 78 | Specifies a shell script that will get run in order to find the dSYM.
|
| 79 | The shell script will be run given a single UUID value as the shell
|
| 80 | command arguments and the shell command is expected to return a property
|
| 81 | list. See the property list format defined below.
|
| 82 | </td>
|
| 83 | </tr>
|
| 84 | <td class="content" colspan="2">
|
| 85 | <code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGShellCommands -string /path/to/script1</b>
|
| 86 | <b>% defaults write com.apple.DebugSymbols DBGShellCommands -array /path/to/script1
|
| 87 | /path/to/script2</b>
|
| 88 | </tt></pre></code>
|
| 89 | </td>
|
| 90 | </tr>
|
| 91 | <tr>
|
| 92 | <td class="content">
|
| 93 | <b>DBGSpotlightPaths</b>
|
| 94 | </td>
|
| 95 | <td class="content">
|
| 96 | Specifies the directories to limit spotlight searches to as a string or array of strings. When any
|
| 97 | other defaults are supplied to <b>com.apple.DebugSymbols</b>, spotlight
|
| 98 | searches will be disabled unless this default is set to an empty array:
|
| 99 | </td>
|
| 100 | </tr>
|
| 101 | <td class="content" colspan="2">
|
| 102 | <code><pre><tt><font color="green"># Specify an empty array to keep Spotlight searches enabled in all locations</font>
|
| 103 | <b>% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array</b>
|
| 104 |
|
| 105 | <font color="green"># Specify an array of paths to limit spotlight searches to certain directories</font>
|
| 106 | <b>% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array /path/dir1 /path/dir2</b>
|
| 107 | </tt></pre></code>
|
| 108 | </td>
|
| 109 | </tr>
|
| 110 | </table>
|
| 111 | </div>
|
| 112 | <div class="postfooter"></div>
|
| 113 | </div>
|
| 114 | <div class="post">
|
| 115 | <h1 class="postheader">Shell Script Property List Format</h1>
|
| 116 | <div class="postcontent">
|
| 117 | <p>Shell scripts that are specified with the <b>DBGShellCommands</b> defaults key
|
| 118 | will be run in the order in which they are specified until a match is found.
|
| 119 | The shell script will be invoked with a single UUID string value like
|
| 120 | "23516BE4-29BE-350C-91C9-F36E7999F0F1". The shell script must respond with a
|
| 121 | property list being written to STDOUT. The property list must contain UUID
|
| 122 | string values as the root key values, with a dictionary for each UUID. The dictionaries
|
| 123 | can contain one or more of the following keys:
|
| 124 |
|
| 125 | <table class="stats" width="620" cellspacing="0">
|
| 126 | <tr>
|
| 127 | <td class="hed" width="20%">Key</td>
|
| 128 | <td class="hed" width="70%">Description</td>
|
| 129 | </tr>
|
| 130 | <tr>
|
| 131 | <td class="content">
|
| 132 | <b>DBGArchitecture</b>
|
| 133 | </td>
|
| 134 | <td class="content">A textual architecture or target triple like "x86_64", "i386", or "x86_64-apple-macosx".
|
| 135 | </td>
|
| 136 | </tr>
|
| 137 | <tr>
|
| 138 | <td class="content">
|
| 139 | <b>DBGBuildSourcePath</b>
|
| 140 | </td>
|
| 141 | <td class="content">A path prefix that was used when building the dSYM file. The debug information will
|
| 142 | contain paths with this prefix.
|
| 143 | </td>
|
| 144 | </tr>
|
| 145 | <tr>
|
| 146 | <td class="content">
|
| 147 | <b>DBGSourcePath</b>
|
| 148 | </td>
|
| 149 | <td class="content">A path prefix for where the sources exist after the build has completed. Often when
|
| 150 | building projects, build machines will host the sources in a temporary directory while building, then
|
| 151 | move the sources to another location for archiving. If the paths in the debug info don't match where
|
| 152 | the sources are currently hosted, then specifying this path along with the <b>DBGBuildSourcePath</b>
|
| 153 | will help the developer tools always show you sources when debugging or symbolicating.
|
| 154 | </td>
|
| 155 | </tr>
|
| 156 | <tr>
|
| 157 | <td class="content">
|
| 158 | <b>DBGDSYMPath</b>
|
| 159 | </td>
|
| 160 | <td class="content">A path to the dSYM mach-o file inside the dSYM bundle.
|
| 161 | </td>
|
| 162 | </tr>
|
| 163 | <tr>
|
| 164 | <td class="content">
|
| 165 | <b>DBGSymbolRichExecutable</b>
|
| 166 | </td>
|
| 167 | <td class="content">A path to the symbol rich executable. Binaries are often stripped after
|
| 168 | being built and packaged into a release. If your build systems saves an unstripped executable
|
| 169 | a path to this executable can be provided.
|
| 170 | </td>
|
| 171 | </tr>
|
| 172 | <tr>
|
| 173 | <td class="content">
|
| 174 | <b>DBGError</b>
|
| 175 | </td>
|
| 176 | <td class="content">If a binary can not be located for the supplied UUID, a user readable error
|
| 177 | can be returned.
|
| 178 | </td>
|
| 179 | </tr>
|
| 180 | </table>
|
| 181 |
|
| 182 | <p>Below is a sample shell script output for a binary that contains two architectures:
|
| 183 | <code><pre><tt>
|
| 184 | <?xml version="1.0" encoding="UTF-8"?>
|
| 185 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
| 186 | <plist version="1.0">
|
| 187 | <dict>
|
| 188 | <key>23516BE4-29BE-350C-91C9-F36E7999F0F1</key>
|
| 189 | <dict>
|
| 190 | <key>DBGArchitecture</key>
|
| 191 | <string>i386</string>
|
| 192 | <key>DBGBuildSourcePath</key>
|
| 193 | <string>/path/to/build/sources</string>
|
| 194 | <key>DBGSourcePath</key>
|
| 195 | <string>/path/to/actual/sources</string>
|
| 196 | <key>DBGDSYMPath</key>
|
| 197 | <string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string>
|
| 198 | <key>DBGSymbolRichExecutable</key>
|
| 199 | <string>/path/to/unstripped/exectuable</string>
|
| 200 | </dict>
|
| 201 | <key>A40597AA-5529-3337-8C09-D8A014EB1578</key>
|
| 202 | <dict>
|
| 203 | <key>DBGArchitecture</key>
|
| 204 | <string>x86_64</string>
|
| 205 | <key>DBGBuildSourcePath</key>
|
| 206 | <string>/path/to/build/sources</string>
|
| 207 | <key>DBGSourcePath</key>
|
| 208 | <string>/path/to/actual/sources</string>
|
| 209 | <key>DBGDSYMPath</key>
|
| 210 | <string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string>
|
| 211 | <key>DBGSymbolRichExecutable</key>
|
| 212 | <string>/path/to/unstripped/exectuable</string>
|
| 213 | </dict>
|
| 214 | </dict>
|
| 215 | </plist>
|
| 216 | </tt></pre></code>
|
| 217 |
|
| 218 | </div>
|
| 219 | <div class="postfooter"></div>
|
| 220 | </div>
|
| 221 | <div class="post">
|
| 222 | <h1 class="postheader">Embedding UUID property lists inside the dSYM bundles</h1>
|
| 223 | <div class="postcontent">
|
| 224 | <p>Since dSYM files are bundles, you can also place UUID info plists files inside
|
| 225 | your dSYM bundles in the <b>Contents/Resources</b> directory. One of the main
|
| 226 | reasons to create the UUID plists inside the dSYM bundles
|
| 227 | is that it will help LLDB and other developer tools show you source. LLDB currently
|
| 228 | knows how to check for these plist files so it can automatically remap the source
|
| 229 | location information in the debug info.
|
| 230 |
|
| 231 | <p>If we take the two UUID values from the returns plist above, we can split
|
| 232 | them out and save then in the dSYM bundle:
|
| 233 |
|
| 234 | <code><pre><tt><b>% ls /path/to/foo.dSYM/Contents/Resources</b>
|
| 235 | 23516BE4-29BE-350C-91C9-F36E7999F0F1.plist
|
| 236 | A40597AA-5529-3337-8C09-D8A014EB1578.plist
|
| 237 |
|
| 238 | <b>% cat /path/to/foo.dSYM/Contents/Resources/23516BE4-29BE-350C-91C9-F36E7999F0F1.plist</b>
|
| 239 | <?xml version="1.0" encoding="UTF-8"?>
|
| 240 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
| 241 | <plist version="1.0">
|
| 242 | <dict>
|
| 243 | <key>DBGArchitecture</key>
|
| 244 | <string>i386</string>
|
| 245 | <key>DBGBuildSourcePath</key>
|
| 246 | <string>/path/to/build/sources</string>
|
| 247 | <key>DBGSourcePath</key>
|
| 248 | <string>/path/to/actual/sources</string>
|
| 249 | <key>DBGDSYMPath</key>
|
| 250 | <string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string>
|
| 251 | <key>DBGSymbolRichExecutable</key>
|
| 252 | <string>/path/to/unstripped/exectuable</string>
|
| 253 | </dict>
|
| 254 | </plist>
|
| 255 | </tt></pre></code>
|
| 256 |
|
| 257 | <p>Note that the output is very close to what is needed by shell script output,
|
| 258 | so making the results of your shell script will be very easy to create by
|
| 259 | combining two plists into a single one where you take the UUID and use it a
|
| 260 | string key, and the value is the contents of the plist.
|
| 261 |
|
| 262 |
|
| 263 | </div>
|
| 264 | <div class="postfooter"></div>
|
| 265 | </div>
|
| 266 | <div class="post">
|
| 267 | <h1 class="postheader">File Mapped UUID Directories</h1>
|
| 268 | <div class="postcontent">
|
| 269 | <p>File Mapped directories can be used for efficient dSYM file lookups for
|
| 270 | local or remote dSYM files. The UUID is broken up by splitting the first
|
| 271 | 20 hex digits into 4 character chunks, and a directory is created for each
|
| 272 | chunk, and each subsequent directory is created inside the previous one.
|
| 273 | A symlink is then created whose name is the last 12 hex digits in the deepest
|
| 274 | directory. The symlinks value is a full path to the mach-o files inside the
|
| 275 | dSYM bundle which contains the DWARF. Whenever DebugSymbols.framework is asked
|
| 276 | to lookup a dSYM file, it will first look in any file mapped UUID directories
|
| 277 | for a quick match if the defaults are appropriately set.
|
| 278 |
|
| 279 | <p>For example, if we take the sample UUID plist inforamtion from above, we
|
| 280 | can create a File Mapped UUID directory cache in <b>~/Library/SymbolCache/dsyms/uuids</b>.
|
| 281 | We can easily see how things are laid out:
|
| 282 |
|
| 283 | <code><pre><tt><b>% find ~/Library/SymbolCache/dsyms/uuids -type l</b>
|
| 284 | ~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1
|
| 285 | ~/Library/SymbolCache/dsyms/uuids/A405/97AA/5529/3337/8C09/D8A014EB1578
|
| 286 | </tt></pre></code>
|
| 287 |
|
| 288 | <p>The last entries in these file mapped directories are symlinks to the actual dsym mach file in the dsym bundle:
|
| 289 |
|
| 290 | <code><pre><tt><b>% ls -lAF ~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1</b>
|
| 291 | ~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1@ -> ../../../../../../dsyms/foo.dSYM/Contents/Resources/DWARF/foo
|
| 292 | </tt></pre></code>
|
| 293 | <p>Then you can also tell DebugSymbols to check this UUID file map cache using:
|
| 294 |
|
| 295 | <code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths ~/Library/SymbolCache/dsyms/uuids</b>
|
| 296 | </tt></pre></code>
|
| 297 |
|
| 298 |
|
| 299 | </div>
|
| 300 | <div class="postfooter"></div>
|
| 301 | </div>
|
| 302 | <div class="post">
|
| 303 | <h1 class="postheader">dSYM Locating Shell Script Tips</h1>
|
| 304 | <div class="postcontent">
|
| 305 |
|
| 306 | <p>One possible implementation of a dSYM finding shell script is to have the script
|
| 307 | download and cache files locally in a known location. Then create a UUID map
|
| 308 | for each UUID value that was found in a local UUID File Map cache so the next query for the dSYM
|
| 309 | file will be able to use the cached version. So the shell script is used to
|
| 310 | initially download and cache the file, and subsequent accesses will use the
|
| 311 | cache and avoid calling the shell script.
|
| 312 |
|
| 313 | <p>Then the defaults for DebugSymbols.framework will entail enabling your shell script,
|
| 314 | enabling the file mapped path setting so that already downloaded dSYMS fill quickly
|
| 315 | be found without needing to run the shell script every time, and also leaving spotlight enabled
|
| 316 | so that other normal dSYM files are still found:
|
| 317 |
|
| 318 | <code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGShellCommands /path/to/shellscript
|
| 319 | % defaults write com.apple.DebugSymbols DBGFileMappedPaths ~/Library/SymbolCache/dsyms/uuids
|
| 320 | % defaults write com.apple.DebugSymbols DBGSpotlightPaths -array</b>
|
| 321 | </tt></pre></code>
|
| 322 |
|
| 323 | Hopefully this helps explain how DebugSymbols.framework can help any company
|
| 324 | implement a smart symbol finding and caching with minimal overhead.
|
| 325 | </p>
|
| 326 | </div>
|
| 327 | <div class="postfooter"></div>
|
| 328 | </div>
|
| 329 | </div>
|
| 330 | </div>
|
| 331 | </div>
|
| 332 | </body>
|
| 333 | </html> |