]> git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/README
xnu-2422.1.72.tar.gz
[apple/xnu.git] / tools / lldbmacros / README
1 Table of Contents
2 =================
3 A. How to use lldb for kernel debugging
4 B. Design of lldb kernel debugging platform.
5 C. Kernel debugging commands.
6 i. Using commands.
7 ii. Writing new commands.
8 D. Kernel type summaries.
9 i. Using summaries
10 ii. Writing new summary functions
11 E. FAQ and Generel Coding Guidelines
12 i. Frequently Asked Questions
13 ii. Formatted Output printing guidelines [MUST READ]
14 iii. Coding conventions. [MUST READ]
15 iv. Submitting changes in lldbmacros [MUST READ]
16 F. Development and Debugging on lldb kernel debugging platform.
17 i. Reading a exception backtrace
18 ii. Loading custom or local lldbmacros and operating_system plugin
19 iii. Adding debug related 'printf's
20
21
22 ========================================
23 A. How to use lldb for kernel debugging
24 ========================================
25 lldb can be used for kernel debugging the same way as gdb. The simplest way is to start lldb with kernel symbol file. The lldb environment will ready to connect over kdp-remote '<hostname:port>' or 'gdb-remote <hostname:port>'. In case using a core file please do 'file --core /path/to/corefile'
26
27 Following are detailed steps on how to debug a panic'ed / NMI'ed machine (For the curious souls).
28 lldb debugging in detail:-
29 * start lldb with the right symbols file. If you do not know the version apriori, then enable dsymForUUID to load symbols dynamically.
30 bash$ dsymForUUID --enable
31 bash$ lldb /path/to/mach_kernel.symbols
32 Current executable set to '/Sources/Symbols/xnu/xnu-2253~2/mach_kernel' (x86_64).
33 (lldb)
34 * connect to remote device or load a core file
35 # for kdp
36 (lldb) process connect --plugin kdp-remote udp://17.123.45.67:41139
37 # for gdb (eg with astris)
38 (lldb) process connect --plugin gdb-remote gdb://17.123.45.67:8000
39 # for loading a core file
40 (lldb) file --core /path/to/core/file /path/to/kernel_symbol_file
41 * Once connected you can debug with basic lldb commands like print, bt, expr etc. The xnu debug macros will also be loaded automatically from the dSYM files.
42 In case if you are working with older kernel files you can load kernel specific commands by doing -
43 (lldb) command script import /path/to/xnu/tools/lldbmacros/xnu.py
44 (lldb) showbootargs
45 debug=0x14e ncpus=2
46 * You can do 'kgmhelp' to get a list of commands available through xnu.py
47
48 SPECIAL: The xnu.py script brings in kernel type summary functions. To enable these please do -
49 (lldb) showlldbtypesummaries
50 These could be very handy in printing important information from structures easily.
51 For ex.
52 (lldb) print (thread_t)0x80d6a620
53 (thread_t) $45 = 0x80d6a620
54 thread thread_id processor pri io_policy state wait_queue wait_event wmesg thread_name
55 0x80d6a620 0x317 0x902078c8 61 W 0x910cadd4 0x0 SystemSoundServer
56
57
58 =============================================
59 B. Design of lldb kernel debugging platform.
60 =============================================
61 The lldb debugger provides python scripting bridge for customizing commands and summaries in lldb. Following is the stack of platforms and how commands and summaries interact with it.
62
63 |------- xnu scripts ----------|
64 | |- lldb Command/Scripting-| | <-- provides scriptability for kernel data structures through summary/command invocation.
65 | | |--lldb core--| | | <-- interacts with remote kernel or corefile.
66 | |-------------------------| |
67 |------------------------------|
68
69 The xnu script in xnu/tools/lldbmacros provides the following:
70 * Custom functions to do plumbing of lldb command invocation to python function call. (see doc strings for @lldb_command)
71 The command interface provides some common features (which can be invoked after passing '--' on cmd line) like -
72 i. send the output of command to file on disk
73 ii. search for a string in the output and selectively print the line containing it.
74 iii. -v options to increase verbosity levels in commands.
75 For example: (lldb)showalltasks -- -s kernel_task --o /tmp/kernel_task.output -v
76 will show task summary output with lines matching string 'kernel_task' into a file /tmp/kernel_task.output and with a verbosity level of (default +1)
77
78 * Customization for plugging in summary functions for lldb type summaries. (see doc strings for @lldb_summary)
79 It will automatically register give types with the functions withing the kernel category.
80
81 * Ability to register test cases for macros (see doc strings for @xnudebug_test).
82
83 The file layout is like following
84 xnu/
85 |-tools/
86 |-lldb/
87 |-core/ # Core logic about kernel, lldb value abstraction, configs etc. **DO NOT TOUCH THIS DIR**
88 |-plugins/ # Holds plugins for kernel commands.
89 |-xnu.py # xnu debug framework along with kgmhelp, xnudebug commands.
90 |-xnudefines.py
91 |-utils.py
92 |-process.py # files containing commands/summaries code for each subsystem
93 |-...
94
95 The lldbmacros directory has a Makefile that follows the build process for xnu. This packages lldbmacros scripts into the dSYM of each kernel build. This helps in rev-locking the lldb commands with changes in kernel sources.
96
97 ==============================
98 C. Kernel debugging commands.
99 ==============================
100 i. Using commands.
101 ------------------
102 Using xnu debug commands is very similar to kgmacros in gdb. You can use 'kgmhelp' to get a listing of available commands.
103 If you need detailed help for a command please type 'help <command name>' and the documentation for the command will be displayed.
104 ex.
105 (lldb) help pmap_walk
106 Perform a page-table walk in <pmap> for <virtual_address>.
107 You can pass -- -v for verbose output. To increase the verbosity add more -v args after the '--'.
108 Syntax: pmap_walk <pmap> <virtual_address>
109
110 The basic format for every command provided under kgmhelp is like follows
111 (lldb) command_name [cmd_args..] [-CMDOPTIONS] [-xnuoptions]
112 where:
113 command_name : name of command as registed using the @lldb_command decorator and described in 'kgmhelp'
114 cmd_args : shell like arguments that are passed as is to the registered python function.
115 If there is error in these arguments than the implementor may display according error message.
116 xnuoptions : common options for stream based operations on the output of command_name.
117 Allowed options are
118 -h : show help string of a command
119 -s <regexp> : print only the lines matching <regexp>
120 -o <file> : direct the output of command to <file>. Will not display anything on terminal
121 -v : increase the verbosity of the command. Each '-v' encountered will increase verbosity by 1.
122 -p <plugin> : pass the output of command to <plugin> for processing and followup with command requests by it.
123 CMDOPTIONS : These are command level options (always a CAPITAL letter option) that are defined by the macro developer. Please do
124 help <cmdname> to know how each option operates on that particular command.
125
126 ii. Writing new commands.
127 --------------------------
128 The python modules are designed in such a way that the command from lldb invokes a python function with the arguments passed at lldb prompt.
129 It is recommended that you do a decoupled development for command interface and core utility function so that any function/code can
130 called as a simple util function and get the same output. i.e.
131 (lldb)showtask 0xabcdef000 is same as python >>> GetTaskSummary(0xabcdef000) or equivalent
132
133 Following is a step by step guideline on how to add a new command ( e.g showtaskvme ). [extra tip: Always good idea to wrap your macro code within # Macro: , # EndMacro.]
134 1. register a command to a function. Use the lldb_command decorator to map a 'command_name' to a function. Optionally you can provide getopt compatible option string for customizing your command invocation. Note: Only CAPITAL letter options are allowed. lowercase options are reserved for the framework level features.
135 2. Immediately after the register define the function to handle the command invocation. The signature is always like Abc(cmd_args=None, cmd_options={})
136 3. Add documentation for Abc(). This is very important for lldb to show help for each command. [ Follow the guidelines above with documentation ]
137 4. Use cmd_args array to get args passed on command. For example a command like "showtaskvme 0xabcdef00" will put have cmd_args=['0xabcdef00']
138 - note that we use core.value class as an interface to underlying C structures. Refer [Section B] for more details.
139 - use kern.globals.<variable_name> & kern.GetValueFromAddress for building values from addresses.
140 - remember that the ideal type of object to be passed around is core.value
141 - Anything you 'print' will be relayed to lldb terminal output.
142 5. If the user has passed any custom options they would be in cmd_options dict. the format is {'-<optionflag>':'<value>'}. The <value> will be '' (empty string) for non-option flags.
143 6. If your function finds issue with the passed argument then you can raise ArgumentError('error_message') to notify the user. The framework will automatically catch this and show appropriate help using the function doc string.
144
145 Time for some code example? Try reading the code for function ShowTaskVmeHelper in memory.py.
146
147 SPECIAL Note: Very often you will find yourself making changes to a file for some command/summary and would like to test it out in lldb.
148 To easily reload your changes in lldb please follow the below example.
149 * you fire up lldb and start using zprint. And soon you need to add functionality to zprint.
150 * you happily change a function code in memory.py file to zprint macro.
151 * now to reload that particular changes without killing your debug session do
152 (lldb) xnudebug reload memory
153 memory is reloaded from ./memory.py
154 (lldb)
155
156 It is very important that you do reload using xnudebug command as it does the plumbing of commands and types for your change in the module. Otherwise you could easily get confused
157 why your changes are not reflected in the command.
158
159
160 ==========================
161 D. Kernel type summaries.
162 ==========================
163 i. Using summaries
164 ------------------
165 The lldb debugger provides ways for user to customize how a particular type of object be decsribed when printed. These are very useful in displaying complex and large structures
166 where only certain fields are important based on some flag or value in some field or variable. The way it works is every time lldb wants to print an object it checks
167 for regisetered summaries. We can define python functions and hook it up with lldb as callbacks for type summaries.
168 For example.
169 (lldb) print first_zone
170 (zone_t) $49 = 0xd007c000
171 ZONE TOT_SZ ALLOC_ELTS FREE_ELTS FREE_SZ ELT_SZ ALLOC(ELTS PGS SLK) FLAGS NAME
172 0x00000000d007c000 29808 182 25 3600 144 4096 28 1 64 X$ zones
173 (lldb)
174 Just printing the value of first_zone as (zone_t) 0xd007c000 wouldnt have been much help. But with the registered summary for zone_t we can see all the interesting info easily.
175
176 You do not need to do anything special to use summaries. Once they are registered with lldb they show info automatically when printing objects. However if you wish to
177 see all the registered type summaries run the command 'type summary list -w kernel' on lldb prompt.
178 Also if you wish to quickly disable the summaries for a particular command use the 'showraw' command.
179
180 ii. Writing new summary functions
181 ---------------------------------
182 lldb provides really flexible interface for building summaries for complex objects and data. If you find that a struct or list can be
183 diagnosed better if displayed differently, then feel free to add a type summary for that type. Following is an easy guide on how to do that.
184
185 1. Register a function as a callback for displaying information for a type. Use the @lldb_type_summary() decorator with an array of types you wish to register for callback
186 2. Provide a header for the summary using @header() decorator. This is a strong requirement for summaries. This gets displayed before the output
187 of GetTypeSummary() is displayed. [In case you do not wish to have header then still define it as "" (empty string) ]
188 3. Define the function with signature of GetSomeTypeSummary(valobj). It is highly recommended that the naming be consistent to Get.*?Summary(valobj)
189 The valobj argument holds the core.value object for display.
190 4. Use the utility functions and memory read operations to pull out the required information.
191 [ use kern.globals & kern.GetValueFromAddress for building args to core functions. ]
192 [ remember that the ideal type of object to be passed around is core.value ]
193 5. return a string that would be printed by the caller. When lldb makes a call back it expects a str to be returned. So do not print
194 directly out to console. [ debug info or logs output is okay to be printed anywhere :) ]
195
196 Time for some code example? Try reading the code for GetTaskSummary() in process.py.
197
198
199 ======================================
200 E. FAQs and Generel Coding Guidelines
201 ======================================
202
203 i. Frequently Asked Questions
204 -----------------------------
205
206 Q. How do I avoid printing the summary and see the actual data in a structure?
207 A. There is a command called 'showraw'. This will disable all kernel specific type summaries and execute any command you provide.
208 Ex.
209 (lldb) print (thread_t) 0x80d6a620
210 (thread_t) $45 = 0x80d6a620
211 thread thread_id processor pri io_policy state wait_queue wait_event wmesg thread_name
212 0x80d6a620 0x317 0x902078c8 61 W 0x910cadd4 0x0 SystemSoundServer
213 (lldb) showraw print (thread_t) 0x80d6a620
214 (thread_t) $48 = 0x80d6a620
215
216 Q. I typed 'showallvnodes' and nothing happens for a long time? OR How do I get output of long running command instantly on the terminal?
217 A. The lldb command interface tries to build result object from output of a python function. So in case of functions with very long output or runtime it may
218 seem that the lldb process is hung. But it is not. You can use "-i" option to get immediate output on terminal.
219 ex. (lldb) showallvnodes -- -i
220 Immediate Output
221 ....
222
223 Q. I made a change in a python file for a command or summary, but the output is not reflected in the lldb command?
224 A. The python framework does not allow for removing a loaded module and then reloading it. So sometimes if a command has a cached value from
225 old code that it will still call the old function and hence will not display new changes in file on disk. If you find yourself in such a situation
226 please see [Section C. -> SPECIAL Note]. If the change is to basic class or caching mechanism than it is advised to quit lldb and re-load all modules again.
227
228 Q. I am new to python. I get an error message that I do not understand. what should I do?
229 A. The syntax for python is different from conventional programming languages. If you get any message with SyntaxError or TypeError or ValueError then please
230 review your code and look for common errors like
231 - wrong level of indentation?
232 - missed a ':' at the end of an if, elif, for, while statement?
233 - referencing a key in dictionary that doesnt exist? You might see KeyError in such cases.
234 - mistakenly used python reserved keyword as variable? (check http://docs.python.org/release/3.0.1/reference/lexical_analysis.html#id8)
235 - Trying to modify a string value? You can only create new strings but never modify existing ones.
236 - Trying to add a non string value to a string? This typically happens in print "time is " + gettime(). here gettime() returns int and not str.
237 - using a local variable with same name as global variable?
238 - assigning a value to global variable without declaring first? Its highly recommended to always declare global variable with 'global' keyword
239 If you still have difficulty you can look at the python documentation at http://docs.python.org
240
241 Q. I wish to pass value of variable/expression to xnu lldb macro that accepts only pointers. How can I achieve that?
242 A. Many lldb macros have syntax that accepts pointers (eg showtaskstacks etc). In order to have your expression be evaluated before passing to command use `back ticks`.
243 For example:
244 (lldb) showtaskstacks `(task_t)tasks.next`
245 This way the expressing withing ` ` is evaluated by lldb and the value is passed to the command.
246 Note that if your argument pointer is bad or the memory is corrupted lldb macros will fail with a long backtrace that may not make sense. gdb used to fail silently but lldb does not.
247 Please see Section F(i) for more information on reading backtraces.
248
249
250 ii. Formatted output printing - zen and peace for life
251 ------------------------------------------------------
252
253 To avoid the horrors of printing a tabular data on console and then 2 weeks later again messing with it for a new field, it is recommended to follow these guidelines.
254 * any python string can be invoked to "".format() and hence makes it very easy to play with formats
255 * As a convention, I suggest that for printing pointer values in hex use "{0: <#020x}".format(some_int_value). This will print nice 0x prefixed strings with length padded to 20.
256 * If you need help with format options take a look at http://docs.python.org/library/string.html#format-string-syntax
257 * [ I'd first create a format string for data and then for the header just change the x's and d's to s and pass the header strings to format command. see GetTaskSummary()]
258 * If you need to print a string from a core.value object then use str() to get string representation of value.
259
260
261 iii. Coding conventions
262 -----------------------
263 It is very very HIGHLY RECOMMENDED to follow these guidelines for writing any python code.
264 * Python is very sensitive to tabs and spaces for alignement. So please make sure you INDENT YOUR CODE WITH SPACES at all times.
265 * The standard tab width is 4 spaces. Each increasing indent adds 4 spaces begining of the line.
266 * The format for documentation is -
267 """ A one line summary describing what this function / class does
268 Detailed explanation if necessary along with params and return values.
269 """
270 * All Classes and functions should have a doc string describing what the function does
271 A consistent format is expected. For ex.
272 def SumOfNumbers(a, b, c, d):
273 """ Calculate sum of numbers.
274 params:
275 a - int, value to be added. can be 0
276 b - int/float, value to be added.
277 returns:
278 int/float - Sum of two values
279 raises:
280 TypeError - If any type is not identified in the params
281 """
282 * A Class or Function should always start with CAPITAL letter and be CamelCase. If a function is for internal use only than it starts with '_'.
283 * Function params should always be lower_case and be word separated with '_'
284 * A local variable inside a function should be lower_case and separated with '_'
285 * A variable for internal use in object should start with '_'.
286 * if a class variable is supposed to hold non native type of object, it is good idea to comment what type it holds
287 * A class function with name matching Get(.*?)Summary() is always supposed to return a string which can be printed on stdout or any file.
288 * Functions begining with "Get" (eg. GetVnodePath()) mean they return a value and will not print any output to stdout.
289 * Functions degining with "Show" (eg. ShowZTrace()) mean they will print data on screen and may not return any value.
290
291 iv. Submitting changes in lldbmacros
292 ------------------------------------
293 To contribute new commands or fixes to existing one, it is recommended that you follow the procedure below.
294 * Save the changes requried for new command or fix into lldbmacros directory.
295 * Make sure that the coding conventions are strictly followed.
296 * Run syntax checker on each of the modified files. It will find basic formatting errors in the changed files for you.
297 * If you are adding new file then please update the Makefile and xnu.py imports to ensure they get compiled during kernel build.
298 * Do a clean build of kernel from xnu top level directory.
299 * Verify that your changes are present in the dSYM directory of new build.
300 * Re-run all your test and verification steps with the lldbmacros from the newly packaged dSYM/Contents/Resources/Python/lldbmacros.
301
302 ===============================================================
303 F. Development and Debugging on lldb kernel debugging platform.
304 ===============================================================
305
306 i. Reading a exception backtrace
307 --------------------------------
308 In case of an error the lldbmacros may print out an exception backtrace and halt immediately. The backtrace is very verbose and may be confusing. The important thing is to isolate possible causes of failure, and eventually filing a bug with kernel team. Following are some common ways where you may see an exception instead of your expected result.
309 * The lldbmacros cannot divine the type of memory by inspection. If a wrong pointer is passed from commandline then, the command code will try to read and show some results. It may still be junk or plain erronous. Please make sure your command arguments are correct.
310 For example: a common mistake is to pass task address to showactstack. In such a case lldb command may fail and show you a confusing backtrace.
311 * Kernel debugging is particularly tricky. Many parts of memory may not be readable. There could be failure in network, debugging protocol or just plain bad memory. In such a case please try to see if you can examine memory for the object you are trying to access.
312 * In case of memory corruption, the lldbmacros may have followed wrong pointer dereferencing. This might lead to failure and a exception to be thrown.
313
314 ii. Loading custom or local lldbmacros and operating_system plugin
315 ------------------------------------------------------------------
316 The lldbmacros are packaged right into the dSYM for the kernel executable. This makes debugging very easy since they can get loaded automatically when symbols are loaded.
317 However, this setup makes it difficult for a lldbmacro developer to load custom/local macros. Following is the suggested solution for customizing your debugging setup:
318 * set up environment variable DEBUG_XNU_LLDBMACROS=1 on your shell. This will disable the automatic setup of lldbmacros and the operating_system.py from the symbols.
319 - bash$ export DEBUG_XNU_LLDBMACROS=1
320 * start lldb from the shell
321 - bash$ lldb
322 * [optional] If you are making changes in the operating_system plugin then you need to set the plugin path for lldb to find your custom operating_system plugin file.
323 - (lldb)settings set target.process.python-os-plugin-path /path/to/xnu/tools/lldbmacros/core/operating_system.py
324 If you do not wish to change anything in operating_system plugin then just leave the setting empty. The symbol loading module will set one up for you.
325 * Load the xnu debug macros from your custom location.
326 - (lldb)command script import /path/to/xnu/tools/lldbmacros/xnu.py
327
328 iii. Adding debug related 'printf's
329 -----------------------------------
330 The xnu debug framework provides a utility function (debuglog) in utils.py. Please use this for any of your debugging needs. It will not print any output unless the user turns on debug logging on the command. Please check the documentaiton of debuglog for usage and options.
331
332 * To enable/disable logging
333 - (lldb) xnudebug debug
334 Enabled debug logging.
335
336
337
338