How to call methods or execute code in LLDB debugger?

XcodeLlvmLldb

Xcode Problem Overview


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?

Xcode Solutions


Solution 1 - Xcode

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

Solution 2 - Xcode

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionProud MemberView Question on Stackoverflow
Solution 1 - XcodeJason MolendaView Answer on Stackoverflow
Solution 2 - XcodeJoão SouzaView Answer on Stackoverflow