[Lldb-commits] [lldb] r113046 - /lldb/trunk/docs/lldb-for-gdb-users.txt

Jim Ingham jingham at apple.com
Fri Sep 3 17:49:36 PDT 2010


Author: jingham
Date: Fri Sep  3 19:49:36 2010
New Revision: 113046

URL: http://llvm.org/viewvc/llvm-project?rev=113046&view=rev
Log:
Adding some docs on how to use lldb.  First cut...

Added:
    lldb/trunk/docs/lldb-for-gdb-users.txt

Added: lldb/trunk/docs/lldb-for-gdb-users.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/docs/lldb-for-gdb-users.txt?rev=113046&view=auto
==============================================================================
--- lldb/trunk/docs/lldb-for-gdb-users.txt (added)
+++ lldb/trunk/docs/lldb-for-gdb-users.txt Fri Sep  3 19:49:36 2010
@@ -0,0 +1,405 @@
+Here's a short precis of how to run lldb if you are familiar with the
+gdb command set:
+
+
+1) LLDB Command Structure:
+
+First some details on lldb command structure to help orient you...
+
+Unlike gdb's command set, which is rather free-form, we tried to make
+the lldb command set fairly structured.  The commands are all of the
+form
+
+<noun> <verb> [-options [option-value]] [argument [argument...]]
+
+We also tried to reduce the number of special purpose argument
+parsers, which sometimes forces the user to be a little more explicit
+about stating their intentions.  The first instance you'll note of
+this is the breakpoint command.  In gdb, to set a breakpoint, you
+would just say:
+
+(gdb) break set foo.c:12
+
+or
+
+(gdb) break set foo
+
+if foo is a function.  As time went on, the parser that tells foo.c:12
+from foo from foo.c::foo (which means the function foo in the file
+foo.c) got more and more complex and bizarre, and especially in C++
+there are times where there's really no way to specify the function
+you want to break on.  The lldb commands are more verbose but also precise.  
+So you say:
+
+(lldb) breakpoint set -f foo.c -l 12
+
+to set a file & line breakpoint.  To set a breakpoint on a function by name, you do:
+
+(lldb) breakpoint set -n foo
+
+This can allow us to be more expressive, so you can say:
+
+(lldb) breakpoint set -M foo
+
+to break on all methods named foo, or:
+
+(lldb) breakpoint set -S alignLeftEdges:
+
+to set a breakpoint on all ObjC selectors called alignLeftEdges:.  It
+also makes it easy to compose specifications, like:
+
+(lldb) breakpoint set -s foo.dylib -n foo
+
+for all functions called foo in the shared library foo.dylib.  Suggestions
+on more interesting primitives of this sort are also very welcome.
+
+The next structural difference between lldb & gdb is that the command
+line is actually parsed by the command interpreter not the commands.
+That means the command syntax is more regular, but it also means you
+may have to quote some arguments in lldb that you wouldn't in gdb.
+But the command syntax is very simple, basically arguments, options
+and option values are all white-space separated.  If you need to put a
+backslash or double-quote character in an argument you back-slash it
+in the argument.  So for instance:
+
+(lldb) breakpoint set -n "-[SKTGraphicView alignLeftEdges:]"
+
+Just like gdb, the lldb command interpreter does a shortest unique
+string match on command names, so the previous command can also be
+typed:
+
+(lldb) b s -n "-[SKTGraphicView alignLeftEdges:]"
+
+lldb also supports command completion for source file names, symbol
+names, file names, etc. Completion is initiated by a hitting a <TAB>.
+Individual options a command can have different completers, so for
+instance the -f option in "breakpoint" completes to source files, the
+-s option to currently loaded dylibs, etc...  We can even do things
+like if you specify -s, and are completing on -f, we will only
+list source files in the dylib specified by -s...
+
+The individual commands are pretty extensively documented, using
+with the "help" command.  And there is an "apropos" command that will
+search the help for a particular word and dump a summary help string
+for each matching command.
+
+Finally, there is a mechanism to construct aliases for commonly used
+commands.  So for instance if you get annoyed typing
+
+(lldb) b s -f foo.c -l 12
+
+you can do:
+
+(lldb) command alias bfl breakpoint set -f %1 -l %2
+(lldb) bfl foo.c 12
+
+We have added a few aliases for commonly used commands (e.g. "step",
+"next" and "continue") but we haven't tried to be exhaustive because
+in our experience it is more convenient to make the basic commands
+unique down to a letter or two, and then learn these sequences than
+fill the namespace with lots of aliases, and then have to type them
+all the way out.
+
+However, users are free to customize lldb's command set however they
+like, and since lldb reads the file ~/.lldbinit at startup, you can
+store all your aliases there and they will be generally available to
+you.  Your aliases are also documented in the help command so you can
+remind yourself of what you've set up.
+
+lldb also has a built-in Python interpreter, which is accessible by
+the "script" command.  All the functionality of the debugger is
+available as classes in the Python interpreter, so the more complex
+commands that in gdb you would introduce with the "define" command can
+be done by writing Python functions using the lldb-Python library,
+then loading the scripts into your running session and accessing them
+with the "script" command.  
+
+
+
+2) A typical session:
+
+
+a) Setting the program to debug:
+
+
+As with gdb, you can start lldb and specify the file you wish to debug
+on the command line:
+
+$ lldb /Projects/Sketch/build/Debug/Sketch.app
+Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
+
+or you can specify it after the fact with the "file" command:
+
+(lldb) file /Projects/Sketch/build/Debug/Sketch.app
+Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
+
+
+b) Setting breakpoints:
+
+
+We've discussed how to set breakpoints above.  You can use "help break set" 
+to see all the options for breakpoint setting.  For instance, we might do:
+
+(lldb) b s -S alignLeftEdges:
+Breakpoint created: 1: name = 'alignLeftEdges:', locations = 1, resolved = 1
+
+You can find out about the breakpoints you've set with:
+
+(lldb) break list
+Current breakpoints:
+1: name = 'alignLeftEdges:', locations = 1, resolved = 1
+  1.1: where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Volumes/ThePlayground/Users/jingham/Projects/Sketch/SKTGraphicView.m:1405, address = 0x0000000100010d5b, resolved, hit count = 0 
+
+Note that each "logical" breakpoint can have multiple resolved
+"locations".  The logical breakpoint has an integer id, and it's
+locations have a an id within their parent breakpoint (the two are
+joined by a ".", e.g. 1.1 in the example above.)  Also the breakpoints
+remain "live" so that if another shared library were to be loaded that
+had another implementation of the "alignLeftEdges:" selector, and new
+location would be added to the breakpoint 1 for it.
+
+You can delete, disable, set conditions and ignore counts either on
+all the locations generated by your logical breakpoint.  So for
+instance if we wanted to add a command to print a backtrace when we
+hit this breakpoint we could do:
+
+(lldb) b command add -c 1.1
+Enter your debugger command(s).  Type 'DONE' to end.
+> bt
+> DONE
+
+The "-c" specifies that the breakpoint command is a set of lldb
+commmand interpreter commands.  Use "-s" if you want to implement your
+breakpoint command using the lldb Python interface instead.
+
+
+c) Running the program:
+
+Then you can either launch the process with the command:
+
+(lldb) process launch
+
+or its alias:
+
+(lldb) r
+
+Or you can attach to a process by name with:
+
+(lldb) process attach -n Sketch
+
+the "attach by name"  also supports the "-w" option which waits for the
+next process of that name to show up, and attaches to that.  You can also
+attach by PID:
+
+(lldb) process attach -p 12345
+Process 46915 Attaching
+(lldb) Process 46915 Stopped
+1 of 3 threads stopped with reasons:
+* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
+
+Note that we tell you that "1 of 3 threads stopped with reasons" and
+then list those threads.  In a multi-threaded environment it is very
+common for more than one thread to hit your breakpoint(s) before the
+kernel actually returns control to the debugger.  In that case, you
+will see all the threads that stopped for some interesting reason
+listed in the stop message.
+
+
+d) Controlling execution:
+
+
+Then we can continue till we hit our breakpoint.  The primitive
+commands for process control all exist under the "thread" command:
+
+(lldb) thread continue
+Resuming thread 0x2c03 in process 46915
+Resuming process 46915
+(lldb)
+
+At present you can only operate on one thread at a time, but the
+design will ultimately support saying "step over the function in
+Thread-1, and step into the function in Thread 2, and continue Thread
+3" etc.  When we eventually support keeping some threads running while
+others are stopped this will be particularly important.  For
+convenience, however, all the stepping type commands have easy
+aliases.  So "thread continue" is just "c", etc.
+
+The other program stepping commands are pretty much the same as in gdb.  You've got:
+
+(lldb) thread step-in
+
+which is the same as gdb's "step" or the alias:
+
+(lldb) s
+
+(lldb) thread step-over
+
+which is the same as gdb's "next" and is aliased to 
+
+(lldb) n
+
+(lldb) thread step-out
+
+which is the same as gdb's "finish" and is aliased to
+
+(lldb) f
+
+And the "by instruction" versions:
+
+(lldb) thread step-inst
+(lldb) thread step-over-inst
+
+Finally, there's:
+
+(lldb) thread until 100
+
+which runs the thread in the current frame till it reaches line 100 in
+this frame or stops if it leaves the current frame.  This is a pretty 
+close equivalent to gdb's until command.
+
+
+One thing here that might be a little disconcerting to gdb users here
+is that when you resume you immediately get a prompt back.  That's
+because the lldb interpreter remains live when you are running the
+target.  This allows you to set a breakpoint, etc without having to
+explicitly interrupt the program you are debugging.  We're still
+working out all the operations that it is safe to do while running.
+But this way of operation will set us up for "no stop" debugging when
+we get to implementing that.  
+
+If you want to interrupt a running program do:
+
+(lldb) process interrupt
+
+To find out the state of the program, use:
+
+(lldb) process status
+Process 47958 is running.
+
+This is very convenient, but it does have the down-side that debugging
+programs that use stdin is no longer as straightforward.  For now, you
+have to specify another tty to use as the program stdout & stdin using
+the appropriate options to "process launch", or start your program in
+another terminal and catch it with "process attach -w".  We will come
+up with some more convenient way to juggle the terminal back & forth
+over time.
+
+
+e) Examining program state:
+
+Once you've stopped, lldb will choose a current thread, usually the
+one that stopped "for a reason", and a current frame in that thread.
+Many the commands for inspecting state work on this current
+thread/frame.
+
+To inspect the current state of your process, you can start with the
+threads:
+
+(lldb) thread list
+Process 46915 state is Stopped
+* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
+  thread #2: tid = 0x2e03, 0x00007fff85cbb08a, where = libSystem.B.dylib`kevent + 10, queue = com.apple.libdispatch-manager
+  thread #3: tid = 0x2f03, 0x00007fff85cbbeaa, where = libSystem.B.dylib`__workq_kernreturn + 10
+
+The * indicates that Thread 1 is the current thread.  To get a
+backtrace for that thread, do:
+
+(lldb) thread backtrace
+thread #1: tid = 0x2c03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
+  frame #0: 0x0000000100010d5b, where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405
+  frame #1: 0x00007fff8602d152, where = AppKit`-[NSApplication sendAction:to:from:] + 95
+  frame #2: 0x00007fff860516be, where = AppKit`-[NSMenuItem _corePerformAction] + 365
+  frame #3: 0x00007fff86051428, where = AppKit`-[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 121
+  frame #4: 0x00007fff860370c1, where = AppKit`-[NSMenu performKeyEquivalent:] + 272
+  frame #5: 0x00007fff86035e69, where = AppKit`-[NSApplication _handleKeyEquivalent:] + 559
+  frame #6: 0x00007fff85f06aa1, where = AppKit`-[NSApplication sendEvent:] + 3630
+  frame #7: 0x00007fff85e9d922, where = AppKit`-[NSApplication run] + 474
+  frame #8: 0x00007fff85e965f8, where = AppKit`NSApplicationMain + 364
+  frame #9: 0x0000000100015ae3, where = Sketch`main + 33 at /Projects/Sketch/SKTMain.m:11
+  frame #10: 0x0000000100000f20, where = Sketch`start + 52
+
+You can also provide a list of threads to backtrace, or the keyword
+"all" to see all threads:
+
+(lldb) thread backtrace all...
+
+Next task is inspecting data:
+
+The most convenient way to inspect a frame's arguments and local variables is:
+
+(lldb) frame variable 
+self = (SKTGraphicView *) 0x0000000100208b40
+_cmd = (struct objc_selector *) 0x000000010001bae1
+sender = (id) 0x00000001001264e0
+selection = (NSArray *) 0x00000001001264e0
+i = (NSUInteger) 0x00000001001264e0
+c = (NSUInteger) 0x00000001001253b0
+
+You can also choose particular variables to view:
+
+(lldb) frame variable self
+(SKTGraphicView *) self = 0x0000000100208b40
+
+The frame variable command is not a full expression parser but it does support some common operations like defererencing:
+
+(lldb) fr v *self
+(SKTGraphicView *) self = 0x0000000100208b40
+  (NSView) NSView = {
+    (NSResponder) NSResponder = {
+...
+
+and structure element references:
+
+(lldb) frame variable self.NS(lldb) frame variable self.isa
+(struct objc_class *) self.isa = 0x0000000100023730
+
+The frame variable command will also perform "object printing" operations on variables (currently we
+only support NSPrintForDebugger) with:
+
+(lldb) fr v -o self
+(SKTGraphicView *) self = 0x0000000100208b40
+<SKTGraphicView: 0x100208b40>
+
+You can select another frame to view with:
+
+(lldb) frame select 9
+frame #9: 0x0000000100015ae3, where = Sketch`main + 33 at /Projects/Sketch/SKTMain.m:11
+   8      
+   9      
+  10      int main(int argc, const char *argv[]) {
+  11 ->       return NSApplicationMain(argc, argv);
+  12          }
+  13          
+  14          
+
+Another neat trick that the variable list does is array references, so:
+
+(lldb) fr v argv[0]
+(char const *) argv[0] = 0x00007fff5fbffaf8 "/Projects/Sketch/build/Debug/Sketch.app/Contents/MacOS/Sketch"
+
+If you need to view more complex data or change program data, you can
+use the general "expression" command.  It takes an expression and
+evaluates it in the scope of the currently selected frame.  For instance:
+
+(lldb) expr self
+$0 = (SKTGraphicView *) 0x0000000100135430
+(lldb) expr self = 0x00
+$1 = (SKTGraphicView *) 0x0000000000000000
+(lldb) frame var self
+(SKTGraphicView *) self = 0x0000000000000000
+
+You can also call functions:
+
+(lldb) expr (int) printf ("I have a pointer 0x%llx.\n", self)
+$2 = (int) 22
+I have a pointer 0x0.
+
+One thing to note from this example is that lldb commands can be
+defined to take "raw" input.  "expression" is one of these.  So in the expression command,
+you don't have to quote your whole expression, nor backslash protect quotes, etc...
+
+Finally, the results of the expressions are stored in persistent
+variables (of the form \$([0-9])+) that you can use in further expressions, like:
+
+(lldb) expr self = $0
+$4 = (SKTGraphicView *) 0x0000000100135430





More information about the lldb-commits mailing list