Search code examples
xcodellvmlldb

How to call methods or execute code in LLDB debugger?


I know I can type print someFloatVariable when I set a breakpoint or po [self someIvarHoldingAnObject], but I can't do useful things like:

[self setAlpha:1];

Then it spits out:

error: '[self' is not a valid command.

Weird thing is that I can call po [self someIvarHoldingAnObject] and it will print it's description.

I believe I've seen a video a year ago where someone demonstrated how to execute code through the console at runtime, and if I am not mistaken this guy also provided arguments and assigned objects to pointers. How to do that?


Solution

  • The canonical reference for gdb v. lldb commands is http://lldb.llvm.org/lldb-gdb.html

    You want to use the expr command which evaluates an expression. It's one of the lldb commands that takes "raw input" in addition to arguments so you often need a "--" to indicate where the arguments (to expr) end and the command(s) begin. e.g.

    (lldb) expr -- [self setAlpha:1]
    

    There is a shortcut, "p", which does the -- for you (but doesn't allow any arguments), e.g.

    (lldb) p [self setAlpha:1]
    

    If the function(s) you're calling are not part of your program, you'll often need to explicitly declare their return type so lldb knows how to call them. e.g.

    (lldb) p printf("hi\n")
    error: 'printf' has unknown return type; cast the call to its declared return type
    error: 1 errors parsing expression
    (lldb) p (int)printf("hi\n")
    (int) $0 = 3
    hi
    (lldb)
    

    There is a neat way to work around the floating point argument problem, BTW. You create an "expression prefix" file which is added to every expression you enter in lldb, with a prototype of your class methods. For instance, I have a class MyClass which inherits from NSObject, it has two methods of interest, "setArg:" and "getArg" which set and get a float ivar. This is a silly little example, but it shows how to use it. Here's a prefix file I wrote for lldb:

    @interface NSObject
    @end
    @interface MyClass : NSObject
    - init;
    - setArg: (float)arg;
    - (float) getArg;
    @end
    
    extern "C" {
      int strcmp (const char *, const char *);
      int printf(const char * __restrict, ...);
      void puts (const char *);
    }
    

    in my ~/.lldbinit file I add

    settings set target.expr-prefix /Users/jason/lldb-prefix.h
    

    and now I can do

    (lldb)    p [var getArg]
    (float) $0 = 0.5
    (lldb)    p [var setArg:0.7]
    (id) $1 = 0x0000000100104740
    (lldb)    p [var getArg]
    (float) $2 = 0.7
    

    You'll notice I included a couple of standard C library functions in here too. After doing this, I don't need to cast the return types of these any more, e.g.

    (lldb) p printf("HI\n")
    <no result>
    HI
    (lldb) p strcmp ("HI", "THERE")
    (int) $3 = -12
    

    (a fix for that "<no result>" thing has been committed to the lldb TOT sources already.)