Pony LLDB Cheat Sheet
Setup
macOS Setup
% brew install llvm
% sudo /usr/sbin/DevToolsSecurity --enable
Basics
Official LLDB tutorial
http://lldb.llvm.org/tutorial.html
GDB <–> LLDB Rosetta Stone
http://lldb.llvm.org/lldb-gdb.html
Building an Executable You Can Debug
% ponyc --debug
Running an Executable
% lldb EXECUTABLE -- arg1 arg2 arg3 …
% lldb -- EXECUTABLE arg1 arg2 arg3 ...
(lldb) run
Setting Breakpoints
(lldb) breakpoint set --file foo.c --line 12
(lldb) breakpoint set --name foo
(lldb) b foo.c:12
(lldb) b Main_create
(lldb) b map.pony:73
When using a file name/line combination to set the breakpoint, you can specify any file in the program without having to specify a path to that file, as long as the file name is unambiguous.
List Breakpoints
(lldb) breakpoint list
(lldb) b
Backtrace
(lldb) thread backtrace
(lldb) bt
If you would like to limit the size of the backtrace (for example, when you are debugging a case of runaway recursion that blows out the stack and generates a very long backtrace), you can use the --count
or -c
option to specify the number of frames to print, starting with the most recent one.
(lldb) thread backtrace --count 5
(lldb) bt 5
Stepping
(lldb) thread step-in
(lldb) s
(lldb) sif funToStepInto
(lldb) thread step-over
(lldb) n
(lldb) thread step-out
(lldb) finish
(lldb) thread until LINE
Frame
Select a frame:
(lldb) frame select NUMBER
(lldb) f NUMBER
Show the variables in the current frame:
(lldb) frame variable
Show a specific variable from the current frame:
(lldb) frame variable VARIABLE
(lldb) p VARIABLE
Pointer, array, structure, and cast operation from C can be applied to frame variables.
- &variable
- address of a variable
- *variable
- dereference a pointer
- variable.field
- access a field within a structure
- pointer_variable->field
- access a field within a structure pointed to by a pointer
- array_pointer[index]
- access an index within an array
- (type_t *)variable
- cast variable to a pointer to a type_t
Examples
Example: Examining an object
(lldb) frame variable
(OscMessage *const) this = <variable not available>
(Array_U8_val *) parts = 0x0000000108fcf4c0
(OscString *) oscAddress = <variable not available>
(OscString *) types = 0x00007fff5fbff878
(lldb) frame variable *types
(OscString) *types = {
_data = 0x0000000108fcf560
}
(lldb) frame variable *types->_data
(String) *types->_data = (_size = 2, _alloc = 3, _ptr = ",f")
(pony_test_TestHelper *) this = 0x0000000110ff5020
(lldb) p this
(pony_test_TestHelper *) $2 = 0x0000000110ff5020
(lldb) p *$2
(pony_test_TestHelper) $3 = {
_runner = 0x0000000110ff7200
env = 0x0000000108ffec00
}
(lldb) p $3.env
(Env *) $4 = 0x0000000108ffec00
(lldb) p *$4
(Env) $5 = {
root = 0x000000010004f3e0
input = 0x0000000108fd6800
out = 0x0000000108fff500
err = 0x0000000108fff600
args = 0x0000000108fd6400
_envp = 0x00007fff5fbffa98
_vars = 0x000000010004f3b0
}
Using p
lets you work from the resulting lldb temporary variables, which can be very convenient when you want to examine an intermediate result.
Example: Printing A String
Assume you have a Pony String called x
. You can print the string like this:
(lldb) p (char *)(x->_ptr)
(char *) $3 = 0x00000001000106f8 "abc"
(lldb)
Example: Printing The Values In An Array Of Numbers
Assume you have an Array[U64]
called x
with 6 elements. You can print the values of the values of the elements like this:
(lldb) p *(long(*)[6])(x->_ptr)
(long [6]) $3 = ([0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6)
You can adjust the type (long
) to appropriately print the types that correspond to the array values, and adjust the size (6
) to print more or fewer of the elements.
Pony Stuff
Method Name Mangling
Future breakage possible!
While currently necessary for some debugging, you should know that name mangling might change in the future. Do not depend on this remaining static.
Method names get mangled by the compiler. The general format for the mangling is:
<package_>type<_typearg1_typearg2>_rcap_methodname_mangling
In the above:
package
- the name of the package (for methods brought in through use expressions)
type
- the name of the type to which the method belongs
typearg1, typearg2
…- the type parameters of the method (for methods that use type parameters)
rcap
- the reference capability of the method
methodname
- the name of the method
mangling
- a mangling string where each character indicates the type of each method parameter and the method’s return type according to the following conversion:
Type | Mangling |
---|---|
object |
o |
Bool |
b |
I8 |
c |
I16 |
s |
I32 |
i |
I64 |
w |
I128 |
q |
ILong |
l |
ISize |
z |
U8 |
C |
U16 |
S |
U32 |
I |
U64 |
W |
U128 |
Q |
ULong |
L |
USize |
Z |
F32 |
f |
F64 |
d |
These rules can be used to determine the name of function in order to specify that you would like to place a breakpoint on it. You can also type b <characters><tab>
to see a tab-complete list of all the available functions that start with <characters>
. To set a breakpoint on a function:
(lldb) breakpoint set --name Bar_foo
(lldb) b Bar_foo
Calling Methods
As of April 5, 2017, issue #1813 is preventing this from working.
Behaviors and Messages
Each behavior has an associated send method (