150
|
1 Here's a short precis of how to run lldb if you are familiar with the
|
|
2 gdb command set:
|
|
3
|
|
4
|
|
5 1) LLDB Command Structure:
|
|
6
|
|
7 First some details on lldb command structure to help orient you...
|
|
8
|
|
9 Unlike gdb's command set, which is rather free-form, we tried to make
|
|
10 the lldb command syntax fairly structured. The commands are all of the
|
|
11 form
|
|
12
|
|
13 <noun> <verb> [-options [option-value]] [argument [argument...]]
|
|
14
|
|
15 The command line parsing is done before command execution, so it is
|
|
16 uniform across all the commands. The command syntax is very simple,
|
|
17 basically arguments, options and option values are all white-space
|
|
18 separated. If you need to put a backslash or double-quote character
|
|
19 in an argument you back-slash it in the argument. That makes the
|
|
20 command syntax more regular, but it also means you may have to
|
|
21 quote some arguments in lldb that you wouldn't in gdb.
|
|
22
|
|
23 Options can be placed anywhere on the command line, but if the arguments
|
|
24 begin with a "-" then you have to tell lldb that you're done with options
|
|
25 using the "--" option. So for instance, the "process launch" command takes
|
|
26 the "-s" option to mean "stop the process at the first instruction". It's
|
|
27 arguments are the arguments you are passing to the program. So if you wanted
|
|
28 to pass an argument that contained a "-" you would have to do:
|
|
29
|
|
30 (lldb) process launch -- -program_arg value
|
|
31
|
|
32 We also tried to reduce the number of special purpose argument
|
|
33 parsers, which sometimes forces the user to be a little more explicit
|
|
34 about stating their intentions. The first instance you'll note of
|
|
35 this is the breakpoint command. In gdb, to set a breakpoint, you
|
|
36 would just say:
|
|
37
|
|
38 (gdb) break foo.c:12
|
|
39
|
|
40 or
|
|
41
|
|
42 (gdb) break foo
|
|
43
|
|
44 if foo is a function. As time went on, the parser that tells foo.c:12
|
|
45 from foo from foo.c::foo (which means the function foo in the file
|
|
46 foo.c) got more and more complex and bizarre, and especially in C++
|
|
47 there are times where there's really no way to specify the function
|
|
48 you want to break on. The lldb commands are more verbose but also precise.
|
|
49 So you say:
|
|
50
|
|
51 (lldb) breakpoint set -f foo.c -l 12
|
|
52
|
|
53 to set a file & line breakpoint. To set a breakpoint on a function
|
|
54 by name, you do:
|
|
55
|
|
56 (lldb) breakpoint set -n foo
|
|
57
|
|
58 This can allow us to be more expressive, so you can say:
|
|
59
|
|
60 (lldb) breakpoint set -M foo
|
|
61
|
|
62 to break on all C++ methods named foo, or:
|
|
63
|
|
64 (lldb) breakpoint set -S alignLeftEdges:
|
|
65
|
|
66 to set a breakpoint on all ObjC selectors called alignLeftEdges:. It
|
|
67 also makes it easy to compose specifications, like:
|
|
68
|
|
69 (lldb) breakpoint set -s foo.dylib -n foo
|
|
70
|
|
71 for all functions called foo in the shared library foo.dylib. Suggestions
|
|
72 on more interesting primitives of this sort are also very welcome.
|
|
73
|
|
74 So for instance:
|
|
75
|
|
76 (lldb) breakpoint set -n "-[SKTGraphicView alignLeftEdges:]"
|
|
77
|
|
78 Just like gdb, the lldb command interpreter does a shortest unique
|
|
79 string match on command names, so the previous command can also be
|
|
80 typed:
|
|
81
|
|
82 (lldb) b s -n "-[SKTGraphicView alignLeftEdges:]"
|
|
83
|
|
84 lldb also supports command completion for source file names, symbol
|
|
85 names, file names, etc. Completion is initiated by a hitting a <TAB>.
|
|
86 Individual options in a command can have different completers, so for
|
|
87 instance the -f option in "breakpoint" completes to source files, the
|
|
88 -s option to currently loaded shared libraries, etc... We can even do
|
|
89 things like if you specify -s, and are completing on -f, we will only
|
|
90 list source files in the shared library specified by -s...
|
|
91
|
|
92 The individual commands are pretty extensively documented, using
|
|
93 the "help" command. And there is an "apropos" command that will
|
|
94 search the help for a particular word and dump a summary help string
|
|
95 for each matching command.
|
|
96
|
|
97 Finally, there is a mechanism to construct aliases for commonly used
|
|
98 commands. So for instance if you get annoyed typing
|
|
99
|
|
100 (lldb) b s -f foo.c -l 12
|
|
101
|
|
102 you can do:
|
|
103
|
|
104 (lldb) command alias bfl breakpoint set -f %1 -l %2
|
|
105 (lldb) bfl foo.c 12
|
|
106
|
|
107 We have added a few aliases for commonly used commands (e.g. "step",
|
|
108 "next" and "continue") but we haven't tried to be exhaustive because
|
|
109 in our experience it is more convenient to make the basic commands
|
|
110 unique down to a letter or two, and then learn these sequences than
|
|
111 fill the namespace with lots of aliases, and then have to type them
|
|
112 all the way out.
|
|
113
|
|
114 However, users are free to customize lldb's command set however they
|
|
115 like, and since lldb reads the file ~/.lldbinit at startup, you can
|
|
116 store all your aliases there and they will be generally available to
|
|
117 you. Your aliases are also documented in the help command so you can
|
|
118 remind yourself of what you've set up.
|
|
119
|
|
120 lldb also has a built-in Python interpreter, which is accessible by
|
|
121 the "script" command. All the functionality of the debugger is
|
|
122 available as classes in the Python interpreter, so the more complex
|
|
123 commands that in gdb you would introduce with the "define" command can
|
|
124 be done by writing Python functions using the lldb-Python library,
|
|
125 then loading the scripts into your running session and accessing them
|
|
126 with the "script" command.
|
|
127
|
|
128
|
|
129
|
|
130 2) A typical session:
|
|
131
|
|
132
|
|
133 a) Setting the program to debug:
|
|
134
|
|
135
|
|
136 As with gdb, you can start lldb and specify the file you wish to debug
|
|
137 on the command line:
|
|
138
|
|
139 $ lldb /Projects/Sketch/build/Debug/Sketch.app
|
|
140 Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
|
|
141
|
|
142 or you can specify it after the fact with the "file" command:
|
|
143
|
|
144 (lldb) file /Projects/Sketch/build/Debug/Sketch.app
|
|
145 Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
|
|
146
|
|
147
|
|
148 b) Setting breakpoints:
|
|
149
|
|
150
|
|
151 We've discussed how to set breakpoints above. You can use "help break set"
|
|
152 to see all the options for breakpoint setting. For instance, we might do:
|
|
153
|
|
154 (lldb) b s -S alignLeftEdges:
|
|
155 Breakpoint created: 1: name = 'alignLeftEdges:', locations = 1, resolved = 1
|
|
156
|
|
157 You can find out about the breakpoints you've set with:
|
|
158
|
|
159 (lldb) break list
|
|
160 Current breakpoints:
|
|
161 1: name = 'alignLeftEdges:', locations = 1, resolved = 1
|
|
162 1.1: where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405, address = 0x0000000100010d5b, resolved, hit count = 0
|
|
163
|
|
164 Note that each "logical" breakpoint can have multiple "locations".
|
|
165 The logical breakpoint has an integer id, and it's locations have an
|
|
166 id within their parent breakpoint (the two are joined by a ".",
|
|
167 e.g. 1.1 in the example above.)
|
|
168
|
|
169 Also the breakpoints remain "live" so that if another shared library
|
|
170 were to be loaded that had another implementation of the
|
|
171 "alignLeftEdges:" selector, the new location would be added to
|
|
172 breakpoint 1 (e.g. a "1.2" breakpoint would be set on the newly loaded
|
|
173 selector).
|
|
174
|
|
175 The other piece of information in the breakpoint listing is whether the
|
|
176 breakpoint location was "resolved" or not. A location gets resolved when
|
|
177 the file address it corresponds to gets loaded into the program you are
|
|
178 debugging. For instance if you set a breakpoint in a shared library that
|
|
179 then gets unloaded, that breakpoint location will remain, but it will no
|
|
180 longer be "resolved".
|
|
181
|
|
182 One other thing to note for gdb users is that lldb acts like gdb with:
|
|
183
|
|
184 (gdb) set breakpoint pending on
|
|
185
|
|
186 That is, lldb should always make a breakpoint from your specification, even
|
|
187 if it couldn't find any locations that match the specification. You can tell
|
|
188 whether the expression was resolved or not by checking the locations field
|
|
189 in "breakpoint list", and we report the breakpoint as "pending" when you
|
|
190 set it so you can tell you've made a typo more easily, if that was indeed
|
|
191 the reason no locations were found:
|
|
192
|
|
193 (lldb) b s -f no_such_file.c -l 10000000
|
|
194 Breakpoint created: 1: file ='no_such_file.c', line = 10000000, locations = 0 (pending)
|
|
195
|
|
196 You can delete, disable, set conditions and ignore counts either on all the
|
|
197 locations generated by your logical breakpoint, or on particular locations
|
|
198 your specification resolved to. For instance if we wanted to add a command
|
|
199 to print a backtrace when we hit this breakpoint we could do:
|
|
200
|
|
201 (lldb) b command add -c 1.1
|
|
202 Enter your debugger command(s). Type 'DONE' to end.
|
|
203 > bt
|
|
204 > DONE
|
|
205
|
|
206 The "-c" option specifies that the breakpoint command is a set of lldb
|
|
207 command interpreter commands. Use "-s" if you want to implement your
|
|
208 breakpoint command using the Python interface instead.
|
|
209
|
|
210
|
|
211 c) Running the program:
|
|
212
|
|
213 Then you can either launch the process with the command:
|
|
214
|
|
215 (lldb) process launch
|
|
216
|
|
217 or its alias:
|
|
218
|
|
219 (lldb) r
|
|
220
|
|
221 Or you can attach to a process by name with:
|
|
222
|
|
223 (lldb) process attach -n Sketch
|
|
224
|
|
225 The "attach by name" also supports the "-w" option which waits for the
|
|
226 next process of that name to show up, and attaches to that. You can also
|
|
227 attach by PID:
|
|
228
|
|
229 (lldb) process attach -p 12345
|
|
230 Process 46915 Attaching
|
|
231 (lldb) Process 46915 Stopped
|
|
232 1 of 3 threads stopped with reasons:
|
|
233 * thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
|
|
234
|
|
235 Note that we tell you that "1 of 3 threads stopped with reasons" and
|
|
236 then list those threads. In a multi-threaded environment it is very
|
|
237 common for more than one thread to hit your breakpoint(s) before the
|
|
238 kernel actually returns control to the debugger. In that case, you
|
|
239 will see all the threads that stopped for some interesting reason
|
|
240 listed in the stop message.
|
|
241
|
|
242
|
|
243 d) Controlling execution:
|
|
244
|
|
245
|
|
246 After launching, we can continue until we hit our breakpoint. The primitive
|
|
247 commands for process control all exist under the "thread" command:
|
|
248
|
|
249 (lldb) thread continue
|
|
250 Resuming thread 0x2c03 in process 46915
|
|
251 Resuming process 46915
|
|
252 (lldb)
|
|
253
|
|
254 At present you can only operate on one thread at a time, but the
|
|
255 design will ultimately support saying "step over the function in
|
|
256 Thread 1, and step into the function in Thread 2, and continue Thread
|
|
257 3" etc. When we eventually support keeping some threads running while
|
|
258 others are stopped this will be particularly important. For
|
|
259 convenience, however, all the stepping commands have easy aliases.
|
|
260 So "thread continue" is just "c", etc.
|
|
261
|
|
262 The other program stepping commands are pretty much the same as in gdb.
|
|
263 You've got:
|
|
264
|
|
265 1. (lldb) thread step-in
|
|
266 The same as gdb's "step" -- there is also the alias "s" in lldb
|
|
267
|
|
268 2. (lldb) thread step-over
|
|
269 The same as gdb's "next" -- there is also the alias "n" in lldb
|
|
270
|
|
271 3. (lldb) thread step-out
|
|
272 The same as gdb's "finish" -- there is also the alias "f" in lldb
|
|
273
|
|
274 And the "by instruction" versions:
|
|
275
|
|
276 (lldb) thread step-inst
|
|
277 (lldb) thread step-over-inst
|
|
278
|
|
279 Finally, there's:
|
|
280
|
|
281 (lldb) thread until 100
|
|
282
|
|
283 Which runs the thread in the current frame till it reaches line 100 in
|
|
284 this frame or stops if it leaves the current frame. This is a pretty
|
|
285 close equivalent to gdb's "until" command.
|
|
286
|
|
287
|
|
288 One thing here that might be a little disconcerting to gdb users here is that
|
|
289 when you resume process execution, you immediately get a prompt back. That's
|
|
290 because the lldb interpreter remains live when you are running the target.
|
|
291 This allows you to set a breakpoint, etc without having to explicitly interrupt
|
|
292 the program you are debugging. We're still working out all the operations
|
|
293 that it is safe to do while running. But this way of operation will set us
|
|
294 up for "no stop" debugging when we get to implementing that.
|
|
295
|
|
296 If you want to interrupt a running program do:
|
|
297
|
|
298 (lldb) process interrupt
|
|
299
|
|
300 To find out the state of the program, use:
|
|
301
|
|
302 (lldb) process status
|
|
303 Process 47958 is running.
|
|
304
|
|
305 This is very convenient, but it does have the down-side that debugging
|
|
306 programs that use stdin is no longer as straightforward. For now, you
|
|
307 have to specify another tty to use as the program stdout & stdin using
|
|
308 the appropriate options to "process launch", or start your program in
|
|
309 another terminal and catch it with "process attach -w". We will come
|
|
310 up with some more convenient way to juggle the terminal back & forth
|
|
311 over time.
|
|
312
|
|
313
|
|
314 e) Examining program state:
|
|
315
|
|
316 Once you've stopped, lldb will choose a current thread, usually the
|
|
317 one that stopped "for a reason", and a current frame in that thread.
|
|
318 Many the commands for inspecting state work on this current
|
|
319 thread/frame.
|
|
320
|
|
321 To inspect the current state of your process, you can start with the
|
|
322 threads:
|
|
323
|
|
324 (lldb) thread list
|
|
325 Process 46915 state is Stopped
|
|
326 * thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
|
|
327 thread #2: tid = 0x2e03, 0x00007fff85cbb08a, where = libSystem.B.dylib`kevent + 10, queue = com.apple.libdispatch-manager
|
|
328 thread #3: tid = 0x2f03, 0x00007fff85cbbeaa, where = libSystem.B.dylib`__workq_kernreturn + 10
|
|
329
|
|
330 The * indicates that Thread 1 is the current thread. To get a
|
|
331 backtrace for that thread, do:
|
|
332
|
|
333 (lldb) thread backtrace
|
|
334 thread #1: tid = 0x2c03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
|
|
335 frame #0: 0x0000000100010d5b, where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405
|
|
336 frame #1: 0x00007fff8602d152, where = AppKit`-[NSApplication sendAction:to:from:] + 95
|
|
337 frame #2: 0x00007fff860516be, where = AppKit`-[NSMenuItem _corePerformAction] + 365
|
|
338 frame #3: 0x00007fff86051428, where = AppKit`-[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 121
|
|
339 frame #4: 0x00007fff860370c1, where = AppKit`-[NSMenu performKeyEquivalent:] + 272
|
|
340 frame #5: 0x00007fff86035e69, where = AppKit`-[NSApplication _handleKeyEquivalent:] + 559
|
|
341 frame #6: 0x00007fff85f06aa1, where = AppKit`-[NSApplication sendEvent:] + 3630
|
|
342 frame #7: 0x00007fff85e9d922, where = AppKit`-[NSApplication run] + 474
|
|
343 frame #8: 0x00007fff85e965f8, where = AppKit`NSApplicationMain + 364
|
|
344 frame #9: 0x0000000100015ae3, where = Sketch`main + 33 at /Projects/Sketch/SKTMain.m:11
|
|
345 frame #10: 0x0000000100000f20, where = Sketch`start + 52
|
|
346
|
|
347 You can also provide a list of threads to backtrace, or the keyword
|
|
348 "all" to see all threads:
|
|
349
|
|
350 (lldb) thread backtrace all
|
|
351
|
|
352 Next task is inspecting data:
|
|
353
|
|
354 The most convenient way to inspect a frame's arguments and local variables is:
|
|
355
|
|
356 (lldb) frame variable
|
|
357 self = (SKTGraphicView *) 0x0000000100208b40
|
|
358 _cmd = (struct objc_selector *) 0x000000010001bae1
|
|
359 sender = (id) 0x00000001001264e0
|
|
360 selection = (NSArray *) 0x00000001001264e0
|
|
361 i = (NSUInteger) 0x00000001001264e0
|
|
362 c = (NSUInteger) 0x00000001001253b0
|
|
363
|
|
364 You can also choose particular variables to view:
|
|
365
|
|
366 (lldb) frame variable self
|
|
367 (SKTGraphicView *) self = 0x0000000100208b40
|
|
368
|
|
369 The frame variable command is not a full expression parser but it
|
|
370 does support some common operations like dereferencing:
|
|
371
|
|
372 (lldb) fr v *self
|
|
373 (SKTGraphicView *) self = 0x0000000100208b40
|
|
374 (NSView) NSView = {
|
|
375 (NSResponder) NSResponder = {
|
|
376 ...
|
|
377
|
|
378 and structure element references:
|
|
379
|
|
380 (lldb) frame variable self.isa
|
|
381 (struct objc_class *) self.isa = 0x0000000100023730
|
|
382
|
|
383 The frame variable command will also perform "object printing" operations on
|
|
384 variables (currently we only support NSPrintForDebugger) with:
|
|
385
|
|
386 (lldb) fr v -o self
|
|
387 (SKTGraphicView *) self = 0x0000000100208b40
|
|
388 <SKTGraphicView: 0x100208b40>
|
|
389
|
|
390 You can select another frame to view with:
|
|
391
|
|
392 (lldb) frame select 9
|
|
393 frame #9: 0x0000000100015ae3, where = Sketch`main + 33 at /Projects/Sketch/SKTMain.m:11
|
|
394 8
|
|
395 9
|
|
396 10 int main(int argc, const char *argv[]) {
|
|
397 11 -> return NSApplicationMain(argc, argv);
|
|
398 12 }
|
|
399 13
|
|
400 14
|
|
401
|
|
402 Another neat trick that the variable list does is array references, so:
|
|
403
|
|
404 (lldb) fr v argv[0]
|
|
405 (char const *) argv[0] = 0x00007fff5fbffaf8 "/Projects/Sketch/build/Debug/Sketch.app/Contents/MacOS/Sketch"
|
|
406
|
|
407 If you need to view more complex data or change program data, you can
|
|
408 use the general "expression" command. It takes an expression and
|
|
409 evaluates it in the scope of the currently selected frame. For instance:
|
|
410
|
|
411 (lldb) expr self
|
|
412 $0 = (SKTGraphicView *) 0x0000000100135430
|
|
413 (lldb) expr self = 0x00
|
|
414 $1 = (SKTGraphicView *) 0x0000000000000000
|
|
415 (lldb) frame var self
|
|
416 (SKTGraphicView *) self = 0x0000000000000000
|
|
417
|
|
418 You can also call functions:
|
|
419
|
|
420 (lldb) expr (int) printf ("I have a pointer 0x%llx.\n", self)
|
|
421 $2 = (int) 22
|
|
422 I have a pointer 0x0.
|
|
423
|
|
424 One thing to note from this example is that lldb commands can be defined to
|
|
425 take "raw" input. "expression" is one of these. So in the expression command,
|
|
426 you don't have to quote your whole expression, nor backslash protect quotes,
|
|
427 etc...
|
|
428
|
|
429 Finally, the results of the expressions are stored in persistent variables
|
|
430 (of the form $[0-9]+) that you can use in further expressions, like:
|
|
431
|
|
432 (lldb) expr self = $0
|
|
433 $4 = (SKTGraphicView *) 0x0000000100135430
|
|
434
|
|
435 f) Customization:
|
|
436
|
|
437 You can use the embedded Python interpreter to add the following 'pwd' and 'cd' commands
|
|
438 for your lldb session:
|
|
439
|
|
440 (lldb) script import os
|
|
441 (lldb) command alias pwd script print os.getcwd()
|
|
442 (lldb) command regex cd "s/^(.*)$/script os.chdir(os.path.expanduser('%1'))/"
|
|
443
|
|
444 ...
|
|
445
|
|
446 (lldb) cd /tmp
|
|
447 script os.chdir(os.path.expanduser('/tmp'))
|
|
448 (lldb) pwd
|
|
449 /private/tmp
|
|
450 (lldb)
|
|
451
|
|
452 Or for a more capable 'cd' command, create ~/utils.py like this:
|
|
453
|
|
454 import os
|
|
455
|
|
456 def chdir(debugger, args, result, dict):
|
|
457 """Change the working directory, or cd to ${HOME}."""
|
|
458 dir = args.strip()
|
|
459 if dir:
|
|
460 os.chdir(args)
|
|
461 else:
|
|
462 os.chdir(os.path.expanduser('~'))
|
|
463 print "Current working directory: %s" % os.getcwd()
|
|
464
|
|
465 and, have the following in your ~/.lldbinit file:
|
|
466
|
|
467 script import os, sys
|
|
468 script sys.path.append(os.path.expanduser('~'))
|
|
469 script import utils
|
|
470 command alias pwd script print os.getcwd()
|
|
471 command script add -f utils.chdir cd
|
|
472
|
|
473 and, then in your lldb session, you can have:
|
|
474
|
|
475 (lldb) help cd
|
|
476
|
|
477 Change the working directory, or cd to ${HOME}.
|
|
478 Syntax: cd
|
|
479 (lldb) cd
|
|
480 Current working directory: /Volumes/data/Users/johnny
|
|
481 (lldb) cd /tmp
|
|
482 Current working directory: /private/tmp
|
|
483 (lldb) pwd
|
|
484 /private/tmp
|
|
485 (lldb)
|
|
486
|
|
487 For more examples of customization, look under the ToT/examples/customization
|
|
488 directory.
|