Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 |
Jim Ingham | 0136f47 | 2010-09-10 23:12:45 +0000 | [diff] [blame] | 10 | the lldb command syntax fairly structured. The commands are all of the |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 11 | form |
| 12 | |
| 13 | <noun> <verb> [-options [option-value]] [argument [argument...]] |
| 14 | |
Jim Ingham | 0136f47 | 2010-09-10 23:12:45 +0000 | [diff] [blame] | 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 | |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 | |
Jim Ingham | 3f09c63 | 2010-09-11 00:03:03 +0000 | [diff] [blame] | 38 | (gdb) break foo.c:12 |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 39 | |
| 40 | or |
| 41 | |
Jim Ingham | 3f09c63 | 2010-09-11 00:03:03 +0000 | [diff] [blame] | 42 | (gdb) break foo |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 53 | to set a file & line breakpoint. To set a breakpoint on a function |
| 54 | by name, you do: |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 62 | to break on all C++ methods named foo, or: |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 | |
Jim Ingham | 0136f47 | 2010-09-10 23:12:45 +0000 | [diff] [blame] | 74 | So for instance: |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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>. |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 86 | Individual options in a command can have different completers, so for |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 87 | instance the -f option in "breakpoint" completes to source files, the |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 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... |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 91 | |
| 92 | The individual commands are pretty extensively documented, using |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 93 | the "help" command. And there is an "apropos" command that will |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 162 | 1.1: where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405, address = 0x0000000100010d5b, resolved, hit count = 0 |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 163 | |
Jim Ingham | 0136f47 | 2010-09-10 23:12:45 +0000 | [diff] [blame] | 164 | Note that each "logical" breakpoint can have multiple "locations". |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 165 | The logical breakpoint has an integer id, and it's locations have an |
Jim Ingham | 0136f47 | 2010-09-10 23:12:45 +0000 | [diff] [blame] | 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 |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 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). |
Jim Ingham | 0136f47 | 2010-09-10 23:12:45 +0000 | [diff] [blame] | 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 |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 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". |
Jim Ingham | 0136f47 | 2010-09-10 23:12:45 +0000 | [diff] [blame] | 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 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 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: |
Jim Ingham | 0136f47 | 2010-09-10 23:12:45 +0000 | [diff] [blame] | 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) |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 195 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 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: |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 200 | |
| 201 | (lldb) b command add -c 1.1 |
| 202 | Enter your debugger command(s). Type 'DONE' to end. |
| 203 | > bt |
| 204 | > DONE |
| 205 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 206 | The "-c" option specifies that the breakpoint command is a set of lldb |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 207 | commmand interpreter commands. Use "-s" if you want to implement your |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 208 | breakpoint command using the Python interface instead. |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 246 | After launching, we can continue until we hit our breakpoint. The primitive |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 256 | Thread 1, and step into the function in Thread 2, and continue Thread |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 257 | 3" etc. When we eventually support keeping some threads running while |
| 258 | others are stopped this will be particularly important. For |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 259 | convenience, however, all the stepping commands have easy aliases. |
| 260 | So "thread continue" is just "c", etc. |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 261 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 262 | The other program stepping commands are pretty much the same as in gdb. |
| 263 | You've got: |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 264 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 265 | 1. (lldb) thread step-in |
| 266 | The same as gdb's "step" -- there is also the alias "s" in lldb |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 267 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 268 | 2. (lldb) thread step-over |
| 269 | The same as gdb's "next" -- there is also the alias "n" in lldb |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 270 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 271 | 3. (lldb) thread step-out |
| 272 | The same as gdb's "finish" -- there is also the alias "f" in lldb |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 285 | close equivalent to gdb's "until" command. |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 286 | |
| 287 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 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. |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 350 | (lldb) thread backtrace all |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 369 | The frame variable command is not a full expression parser but it |
| 370 | does support some common operations like defererencing: |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 371 | |
| 372 | (lldb) fr v *self |
| 373 | (SKTGraphicView *) self = 0x0000000100208b40 |
| 374 | (NSView) NSView = { |
| 375 | (NSResponder) NSResponder = { |
| 376 | ... |
| 377 | |
| 378 | and structure element references: |
| 379 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 380 | (lldb) frame variable self.isa |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 381 | (struct objc_class *) self.isa = 0x0000000100023730 |
| 382 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 383 | The frame variable command will also perform "object printing" operations on |
| 384 | variables (currently we only support NSPrintForDebugger) with: |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 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 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 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... |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 428 | |
Jason Molenda | 19525a4 | 2010-09-11 00:37:21 +0000 | [diff] [blame] | 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: |
Jim Ingham | 93230a3 | 2010-09-04 00:49:36 +0000 | [diff] [blame] | 431 | |
| 432 | (lldb) expr self = $0 |
| 433 | $4 = (SKTGraphicView *) 0x0000000100135430 |