77

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?

lukas
  • 2,300
  • 6
  • 28
  • 41
Proud Member
  • 40,078
  • 47
  • 146
  • 231
  • There is an example [in lldb-for-gdb-users.txt](http://opensource.apple.com/source/lldb/lldb-69/docs/lldb-for-gdb-users.txt) for C: `expr (int) printf ("...")`. May be you should prefix your method invocation with `expr (type)`? – osgx Oct 10 '12 at 23:31

2 Answers2

127

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.)

Jason Molenda
  • 14,835
  • 1
  • 59
  • 61
  • expr -- [self setAlpha:0.5f] or expr -- [self setAlpha:1] both make the view in question completely disappear from screen. Seems like something is happening, but definitely not the right thing. I can only type these commands when I set a breakpoint. Or is there a way to do things like this while the code is still running / unpaused? – Proud Member Oct 11 '12 at 02:39
  • No, you need the process to be stopped when you call this method. If this selector takes a float type, there is a shortcoming you may be hitting with Xcode 4.5's lldb--if the function argument takes a float type and you don't have debug information, lldb doesn't give you any way to pass the value as a float. It will pass it as a double unconditionally, following the old C language no-prototype argument promotion rules. If lldb has debug information for this class, it should be able to do the right thing. Many instances of this problem in ObjC programming will be fixed in a future release. – Jason Molenda Oct 11 '12 at 05:12
  • NB: If you're hitting the problem I meant with float v. double, the value you are passing in to your setAlpha will not be what you expect, it will be some random looking crazy number that may be very close to 0, for instance. – Jason Molenda Oct 11 '12 at 05:13
  • "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". Thanks! That saved me. – kakyo Aug 20 '14 at 22:05
10

If you need multiline, use expression:

expression

do {
  try thing.save()
} catch {
  print(error)
}

// code will execute now

Blank line to finish and execute the code.

João Souza
  • 4,032
  • 3
  • 25
  • 38