You've already forked linux-packaging-mono
							
							
		
			
	
	
		
			346 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
		
		
			
		
	
	
			346 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
|   | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
|  | <html xmlns="http://www.w3.org/1999/xhtml"> | ||
|  | <head> | ||
|  | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> | ||
|  | <link href="style.css" rel="stylesheet" type="text/css" /> | ||
|  | <title>Debug Symbols on Mac OS X</title> | ||
|  | </head> | ||
|  | 
 | ||
|  | <body> | ||
|  |     <div class="www_title"> | ||
|  |       The <strong>LLDB</strong> Debugger | ||
|  |     </div> | ||
|  |      | ||
|  | <div id="container"> | ||
|  | 	<div id="content"> | ||
|  |          | ||
|  |   <!--#include virtual="sidebar.incl"--> | ||
|  |    | ||
|  | 		<div id="middle"> | ||
|  |     		<div class="post"> | ||
|  |     			<h1 class="postheader">Debug Symbols on MacOSX</h1> | ||
|  |     			<div class="postcontent"> | ||
|  |     			    <p>On MacOSX, debug symbols are often in stand alone bundles called <b>dSYM</b> files.  | ||
|  | 								These are bundles that contain DWARF debug information and other resources related to | ||
|  | 								builds and debug info.</p> | ||
|  | 							<p>The DebugSymbols.framework framework helps locate dSYM files when given a UUID. It can | ||
|  | 								locate the symbols using a variety of methods:</p> | ||
|  | 								<ul> | ||
|  | 									<li>Spotlight</li> | ||
|  | 									<li>Explicit search paths</li> | ||
|  | 									<li>Implicit search paths</li> | ||
|  | 									<li>File mapped UUID paths</li> | ||
|  | 									<li>Running one or more shell scripts</li> | ||
|  | 								</ul> | ||
|  | 							<p>DebugSymbols.framework also has global defaults that can be modified to allow | ||
|  | 								all of the debug tools (lldb, gdb, sample, CoreSymbolication.framework) to easily | ||
|  | 								find important debug symbols. The domain for the DebugSymbols.framework defaults | ||
|  | 								is <b>com.apple.DebugSymbols</b>, and the defaults can be read, written or modified | ||
|  | 								using the <b>defaults</b> shell command: | ||
|  | <code><pre><tt><b>% defaults read com.apple.DebugSymbols | ||
|  | % defaults write com.apple.DebugSymbols KEY ... | ||
|  | % defaults delete com.apple.DebugSymbols KEY</b> | ||
|  | </tt></pre></code> | ||
|  | 	 | ||
|  | 								<p>The following is a list of the defaults key value | ||
|  | 								setting pairs that can be	used to enhance symbol location:</p> | ||
|  |                     <table class="stats" width="620" cellspacing="0"> | ||
|  |                     <tr> | ||
|  |                         <td class="hed" width="20%">Defaults Key</td> | ||
|  |                         <td class="hed" width="70%">Description</td> | ||
|  |                     </tr> | ||
|  | 
 | ||
|  |                     <tr> | ||
|  |                         <td class="content"> | ||
|  |                             <b>DBGFileMappedPaths</b> | ||
|  |                         </td> | ||
|  |                         <td class="content"> | ||
|  | 													  This default can be specified as a single string, or an array of strings. | ||
|  |                             Each string represents a directory that contains file mapped UUID values | ||
|  | 														that point to dSYM files. See the "File Mapped UUID Directories" section | ||
|  | 														below for more details. Whenever DebugSymbols.framework is asked to lookup  | ||
|  | 														a dSYM file, it will first look in any file mapped UUID directories | ||
|  | 														for a quick match. | ||
|  |                         </td> | ||
|  | 										</tr> | ||
|  |                         <td class="content" colspan="2"> | ||
|  | <code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths -string /path/to/uuidmap1</b> | ||
|  | <b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths -array /path/to/uuidmap1  | ||
|  |     /path/to/uuidmap2</b> | ||
|  | </tt></pre></code> | ||
|  |                     </tr> | ||
|  |                     <tr> | ||
|  |                         <td class="content"> | ||
|  |                             <b>DBGShellCommands</b> | ||
|  |                         </td> | ||
|  |                         <td class="content"> | ||
|  | 													  This default can be specified as a single string, or an array of strings. | ||
|  |                             Specifies a shell script that will get run in order to find the dSYM. | ||
|  | 														The shell script will be run given a single UUID value as the shell | ||
|  | 														command arguments and the shell command is expected to return a property | ||
|  | 														list. See the property list format defined below. | ||
|  |                         </td> | ||
|  | 										</tr> | ||
|  |                         <td class="content" colspan="2"> | ||
|  | <code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGShellCommands -string /path/to/script1</b> | ||
|  | <b>% defaults write com.apple.DebugSymbols DBGShellCommands -array /path/to/script1 | ||
|  |     /path/to/script2</b> | ||
|  | </tt></pre></code> | ||
|  |                         </td> | ||
|  |                     </tr> | ||
|  |                     <tr> | ||
|  |                         <td class="content"> | ||
|  |                             <b>DBGSpotlightPaths</b> | ||
|  |                         </td> | ||
|  |                         <td class="content"> | ||
|  |                             Specifies the directories to limit spotlight searches to as a string or array of strings. When any  | ||
|  | 														other defaults are supplied to <b>com.apple.DebugSymbols</b>, spotlight | ||
|  | 														searches will be disabled unless this default is set to an empty array: | ||
|  |                         </td> | ||
|  | 										</tr> | ||
|  |                         <td class="content" colspan="2"> | ||
|  | <code><pre><tt><font color="green"># Specify an empty array to keep Spotlight searches enabled in all locations</font> | ||
|  | <b>% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array</b> | ||
|  | 
 | ||
|  | <font color="green"># Specify an array of paths to limit spotlight searches to certain directories</font> | ||
|  | <b>% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array /path/dir1 /path/dir2</b> | ||
|  | </tt></pre></code> | ||
|  |                         </td> | ||
|  |                     </tr> | ||
|  |                     </table> | ||
|  |     			</div> | ||
|  |          	<div class="postfooter"></div> | ||
|  |         </div> | ||
|  |     		<div class="post"> | ||
|  |     			<h1 class="postheader">Shell Script Property List Format</h1> | ||
|  |     			<div class="postcontent"> | ||
|  | <p>Shell scripts that are specified with the <b>DBGShellCommands</b> defaults key | ||
|  | will be run in the order in which they are specified until a match is found. | ||
|  | The shell script will be invoked with a single UUID string value like  | ||
|  | "23516BE4-29BE-350C-91C9-F36E7999F0F1". The shell script must respond with a  | ||
|  | property list being written to STDOUT.  | ||
|  | The property list returned must contain UUID string values as the root key values, with  | ||
|  | a dictionary for each UUID. The dictionaries can contain one or more of the following keys: | ||
|  | 
 | ||
|  | 						<table class="stats" width="620" cellspacing="0"> | ||
|  |              	<tr> | ||
|  |               	<td class="hed" width="20%">Key</td> | ||
|  |                 <td class="hed" width="70%">Description</td> | ||
|  |              	</tr> | ||
|  |               <tr> | ||
|  |                  <td class="content"> | ||
|  |                      <b>DBGArchitecture</b> | ||
|  |                  </td> | ||
|  |                  <td class="content">A textual architecture or target triple like "x86_64", "i386", or "x86_64-apple-macosx". | ||
|  |                  </td> | ||
|  | 							</tr> | ||
|  |               <tr> | ||
|  |                  <td class="content"> | ||
|  |                      <b>DBGBuildSourcePath</b> | ||
|  |                  </td> | ||
|  |                  <td class="content">A path prefix that was used when building the dSYM file. The debug information will | ||
|  | 									contain paths with this prefix. | ||
|  |                  </td> | ||
|  | 							</tr> | ||
|  |               <tr> | ||
|  |                  <td class="content"> | ||
|  |                      <b>DBGSourcePath</b> | ||
|  |                  </td> | ||
|  |                  <td class="content">A path prefix for where the sources exist after the build has completed. Often when | ||
|  | 										building projects, build machines will host the sources in a temporary directory while building, then | ||
|  | 										move the sources to another location for archiving. If the paths in the debug info don't match where | ||
|  | 										the sources are currently hosted, then specifying this path along with the <b>DBGBuildSourcePath</b> | ||
|  | 										will help the developer tools always show you sources when debugging or symbolicating. | ||
|  |                  </td> | ||
|  | 							</tr> | ||
|  |               <tr> | ||
|  |                  <td class="content"> | ||
|  |                      <b>DBGDSYMPath</b> | ||
|  |                  </td> | ||
|  |                  <td class="content">A path to the dSYM mach-o file inside the dSYM bundle. | ||
|  |                  </td> | ||
|  | 							</tr> | ||
|  |               <tr> | ||
|  |                  <td class="content"> | ||
|  |                      <b>DBGSymbolRichExecutable</b> | ||
|  |                  </td> | ||
|  |                  <td class="content">A path to the symbol rich executable. Binaries are often stripped after | ||
|  | 									being built and packaged into a release. If your build systems saves an unstripped executable | ||
|  | 									a path to this executable can be provided. | ||
|  |                  </td> | ||
|  | 							</tr> | ||
|  |               <tr> | ||
|  |                  <td class="content"> | ||
|  |                      <b>DBGError</b> | ||
|  |                  </td> | ||
|  |                  <td class="content">If a binary can not be located for the supplied UUID, a user readable error | ||
|  | 									can be returned. | ||
|  |                  </td> | ||
|  | 							</tr> | ||
|  | 						</table> | ||
|  | 
 | ||
|  | <p>Below is a sample shell script output for a binary that contains two architectures: | ||
|  | <code><pre><tt> | ||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||
|  | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
|  | <plist version="1.0"> | ||
|  | <dict> | ||
|  | 	<key>23516BE4-29BE-350C-91C9-F36E7999F0F1</key> | ||
|  | 	<dict> | ||
|  | 		<key>DBGArchitecture</key> | ||
|  | 		<string>i386</string> | ||
|  | 		<key>DBGBuildSourcePath</key> | ||
|  | 		<string>/path/to/build/sources</string> | ||
|  | 		<key>DBGSourcePath</key> | ||
|  | 		<string>/path/to/actual/sources</string> | ||
|  | 		<key>DBGDSYMPath</key> | ||
|  | 		<string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string> | ||
|  | 		<key>DBGSymbolRichExecutable</key> | ||
|  | 		<string>/path/to/unstripped/executable</string> | ||
|  | 	</dict> | ||
|  | 	<key>A40597AA-5529-3337-8C09-D8A014EB1578</key> | ||
|  | 	<dict> | ||
|  | 		<key>DBGArchitecture</key> | ||
|  | 		<string>x86_64</string> | ||
|  | 		<key>DBGBuildSourcePath</key> | ||
|  | 		<string>/path/to/build/sources</string> | ||
|  | 		<key>DBGSourcePath</key> | ||
|  | 		<string>/path/to/actual/sources</string> | ||
|  | 		<key>DBGDSYMPath</key> | ||
|  | 		<string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string> | ||
|  | 		<key>DBGSymbolRichExecutable</key> | ||
|  | 		<string>/path/to/unstripped/executable</string> | ||
|  | 	</dict> | ||
|  | </dict> | ||
|  | </plist> | ||
|  | </tt></pre></code> | ||
|  | 
 | ||
|  | <p>There is no timeout imposed on a shell script when is it asked to locate a dSYM file, so be careful to not make a shell | ||
|  | script that has high latency or takes a long time to download unless this | ||
|  | is really what you want. This can slow down debug sessions in LLDB and GDB, symbolication | ||
|  | with CoreSymbolication or Report Crash, with no visible feedback to the user. You can | ||
|  | quickly return a plist with a single <b>DBGError</b> key that indicates a timeout | ||
|  | has been reached. You might also want to exec new processes to do the downloads so | ||
|  | that if you return an error that indicates a timeout, your download can still proceed | ||
|  | after your shell script has exited so subsequent debug sessions can use the cached files. | ||
|  | It is also important to track when a current download is in progress in case you get multiple requests for the same UUID so | ||
|  | that you don't end up downloading the same file simultaneously. Also you will want | ||
|  | to verify the download was successful and then and only then place the file into the | ||
|  | cache for tools that will cache files locally. | ||
|  |     			</div> | ||
|  |          	<div class="postfooter"></div> | ||
|  |         </div> | ||
|  |     		<div class="post"> | ||
|  |     			<h1 class="postheader">Embedding UUID property lists inside the dSYM bundles</h1> | ||
|  |     			<div class="postcontent"> | ||
|  | <p>Since dSYM files are bundles, you can also place UUID info plists files inside  | ||
|  | your dSYM bundles in the <b>Contents/Resources</b> directory. One of the main  | ||
|  | reasons to create the UUID plists inside the dSYM bundles | ||
|  | is that it will help LLDB and other developer tools show you source. LLDB currently | ||
|  | knows how to check for these plist files so it can automatically remap the source | ||
|  | location information in the debug info. | ||
|  | 
 | ||
|  | <p>If we take the two UUID values from the returns plist above, we can split  | ||
|  | them out and save then in the dSYM bundle: | ||
|  | 
 | ||
|  | <code><pre><tt><b>% ls /path/to/foo.dSYM/Contents/Resources</b> | ||
|  | 23516BE4-29BE-350C-91C9-F36E7999F0F1.plist | ||
|  | A40597AA-5529-3337-8C09-D8A014EB1578.plist | ||
|  | 
 | ||
|  | <b>% cat /path/to/foo.dSYM/Contents/Resources/23516BE4-29BE-350C-91C9-F36E7999F0F1.plist</b> | ||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||
|  | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
|  | <plist version="1.0"> | ||
|  | <dict> | ||
|  |    <key>DBGArchitecture</key> | ||
|  |    <string>i386</string> | ||
|  |    <key>DBGBuildSourcePath</key> | ||
|  |    <string>/path/to/build/sources</string> | ||
|  |    <key>DBGSourcePath</key> | ||
|  |    <string>/path/to/actual/sources</string> | ||
|  |    <key>DBGDSYMPath</key> | ||
|  |    <string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string> | ||
|  |    <key>DBGSymbolRichExecutable</key> | ||
|  |    <string>/path/to/unstripped/executable</string> | ||
|  | </dict> | ||
|  | </plist> | ||
|  | </tt></pre></code> | ||
|  | 
 | ||
|  | <p>Note that the output is very close to what is needed by shell script output,  | ||
|  | so making the results of your shell script will be very easy to create by  | ||
|  | combining two plists into a single one where you take the UUID and use it a | ||
|  |  string key, and the value is the contents of the plist. | ||
|  | 
 | ||
|  | 
 | ||
|  |     			</div> | ||
|  |          	<div class="postfooter"></div> | ||
|  |         </div> | ||
|  |     		<div class="post"> | ||
|  |     			<h1 class="postheader">File Mapped UUID Directories</h1> | ||
|  |     			<div class="postcontent"> | ||
|  | <p>File Mapped directories can be used for efficient dSYM file lookups for | ||
|  | local or remote dSYM files. The UUID is broken up by splitting the first  | ||
|  | 20 hex digits into 4 character chunks, and a directory is created for each  | ||
|  | chunk, and each subsequent directory is created inside the previous one.  | ||
|  | A symlink is then created whose name is the last 12 hex digits in the deepest | ||
|  | directory. The symlinks value is a full path to the mach-o files inside the | ||
|  | dSYM bundle which contains the DWARF. Whenever DebugSymbols.framework is asked | ||
|  | to lookup a dSYM file, it will first look in any file mapped UUID directories | ||
|  | for a quick match if the defaults are appropriately set. | ||
|  | 
 | ||
|  | <p>For example, if we take the sample UUID plist inforamtion from above, we | ||
|  | can create a File Mapped UUID directory cache in <b>~/Library/SymbolCache/dsyms/uuids</b>. | ||
|  | We can easily see how things are laid out: | ||
|  | 
 | ||
|  | <code><pre><tt><b>% find ~/Library/SymbolCache/dsyms/uuids -type l</b> | ||
|  | ~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1 | ||
|  | ~/Library/SymbolCache/dsyms/uuids/A405/97AA/5529/3337/8C09/D8A014EB1578 | ||
|  | </tt></pre></code> | ||
|  | 
 | ||
|  | <p>The last entries in these file mapped directories are symlinks to the actual dsym mach file in the dsym bundle: | ||
|  | 
 | ||
|  | <code><pre><tt><b>% ls -lAF ~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1</b> | ||
|  | ~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1@ -> ../../../../../../dsyms/foo.dSYM/Contents/Resources/DWARF/foo | ||
|  | </tt></pre></code> | ||
|  | <p>Then you can also tell DebugSymbols to check this UUID file map cache using: | ||
|  | 
 | ||
|  | <code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths ~/Library/SymbolCache/dsyms/uuids</b> | ||
|  | </tt></pre></code> | ||
|  | 
 | ||
|  | 
 | ||
|  |     			</div> | ||
|  |          	<div class="postfooter"></div> | ||
|  |         </div> | ||
|  |     		<div class="post"> | ||
|  |     			<h1 class="postheader">dSYM Locating Shell Script Tips</h1> | ||
|  |     			<div class="postcontent"> | ||
|  | 
 | ||
|  | <p>One possible implementation of a dSYM finding shell script is to have the script | ||
|  | download and cache files locally in a known location. Then create a UUID map | ||
|  | for each UUID value that was found in a local UUID File Map cache so the next query for the dSYM  | ||
|  | file will be able to use the cached version. So the shell script is used to  | ||
|  | initially download and cache the file, and subsequent accesses will use the | ||
|  | cache and avoid calling the shell script. | ||
|  | 
 | ||
|  | <p>Then the defaults for DebugSymbols.framework will entail enabling your shell script,  | ||
|  | enabling the file mapped path setting so that already downloaded dSYMS fill quickly | ||
|  | be found without needing to run the shell script every time, and also leaving spotlight enabled | ||
|  | so that other normal dSYM files are still found: | ||
|  | 
 | ||
|  | <code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGShellCommands /path/to/shellscript | ||
|  | % defaults write com.apple.DebugSymbols DBGFileMappedPaths ~/Library/SymbolCache/dsyms/uuids | ||
|  | % defaults write com.apple.DebugSymbols DBGSpotlightPaths -array</b> | ||
|  | </tt></pre></code> | ||
|  | 
 | ||
|  | Hopefully this helps explain how DebugSymbols.framework can help any company  | ||
|  | implement a smart symbol finding and caching with minimal overhead. | ||
|  | </p> | ||
|  |     			</div> | ||
|  |               	<div class="postfooter"></div> | ||
|  |           	</div> | ||
|  |       	</div> | ||
|  | 	</div> | ||
|  | </div> | ||
|  | </body> | ||
|  | </html> |