gdb Plugin for Debugging¶
LuaVela provides gdb plugin for better visualization of LuaVela’s data structures to simplify debugging.
Installation and usage¶
Just run the following script in gdb:
(gdb) source /path/to/ujit/gdb/ujit-gdb.py
Note that this should be done on each run of gdb. If you don’t want to do this every time, add the line above to ~/.gdbinit
.
Available commands¶
Note
Information about command usage can be obtained in gdb by calling help func
i.e. help uj-stack
.
uj-stack[-vm] L¶
Dumps Lua stack of the given coroutine L
.
(gdb) uj-stack 0x7ffff7fd8378
[WARNING] Bad VM state: INTERP, must be CFUNC or LFUNC
0x7ffff7fe8e70:0x7ffff7fe8e30 [ ] 5 slots: Red zone
0x7ffff7fe8e20 [ M]
0x7ffff7fe8e10:0x7ffff7fe8b80 [ ] 42 slots: Free stack slots
0x7ffff7fe8b70 [ T ]
0x7ffff7fe8b60 [ ] VALUE: fast function 19
0x7ffff7fe8b50 [ B ] VALUE: nil
0x7ffff7fe8b40 [ ] FRAME: [L] delta=5, fast function 2
0x7ffff7fe8b30 [ ] VALUE: string: 0x7ffff7fda590 "Hello, here is my string"
0x7ffff7fe8b20 [ ] VALUE: table 0x7ffff7feb8e8
0x7ffff7fe8b10 [ ] VALUE: thread 0x7ffff7fd9cf8
0x7ffff7fe8b00 [ ] VALUE: table 0x7ffff7fd9ca8
0x7ffff7fe8af0 [ ] FRAME: [L] delta=3, Lua function 0x7ffff7fe58f0, upvalues 1, 0x7ffff7fda4d8 "@/home/ibondarev/calls.lua":1
0x7ffff7fe8ae0 [ ] VALUE: number: 141
Output is similar to uj_dump_stack
function from LuaVela.
If execution is stopped inside the VM (e.g. break point was set on lj_BC_CALL), call uj-stack-vm
instead (since v0.21).
uj-bc (since v0.22)¶
Dumps byte codes and corresponding source code of a currently executing frame. Highlights the byte code which is about to execute with “->”.
Looks up L
in current frame and uses it as a lua_State*
if stopped in non-VM frame. If there’s no L
in current frame, specify it explicitly as in uj-stack command.
Breakpoint 1, 0x000055555563f996 in lj_BC_CALL ()
(gdb) uj-bc
<...>
-- BYTECODE -- /home/jsmith/script.lua:0-15
9 end
0001 FNEW 0 0 ; /home/jsmith/script.lua:1
11 local str = string.reverse("hello")
0002 GGET 1 1 ; "string"
0003 TGETS 1 1 2 ; "reverse"
0004 KSTR 2 3 ; "hello"
-> 0005 CALL 1 2 2
12 local x = ujit.table.size({ 1, 2, nil, 3})
0006 GGET 2 4 ; "ujit"
0007 TGETS 2 2 5 ; "table"
0008 TGETS 2 2 6 ; "size"
0009 TDUP 3 7
0010 CALL 2 2 2
13 print(test(x))
<...>
Note that in contrast to uj-stack
, there’s no separate command if you want to dump byte codes when execution stopped inside the VM.
uj-tv addr¶
(gdb) uj-tv L->base - 2
string: 0x7ffff7fda590 "Hello, here is my string"
uj-tab addr¶
Dumps the contents of the GCtab
at addr.
(gdb) uj-tab 0x7ffff7fd9ca8
Array part:
[0] nil
[1] number: 11
[2] string: 0x7ffff7fda590 "Hello, here is my string"
[3] false
[4] true
[5] Lua function 0x7ffff7fec458, upvalues 0, 0x7ffff7fda4d8 "@/home/johnsmith/calls.lua":17
[6] userdata 0x7ffff7fdf6f0
[7] thread 0x7ffff7fd9cf8
[8] table 0x7ffff7fec400
[9] true
[10] nil
[11] cdata 0x7ffff7fe7bc8
[12] nil
[13] nil
[14] nil
[15] nil
[16] nil
Hash part:
{ false } => { Lua function 0x7ffff7fec648, upvalues 0, 0x7ffff7fda4d8 "@/home/jsmith/calls.lua":28 } next = 0x0
{ table 0x7ffff7fec5f8 } => { number: 11 } next = 0x7ffff7fecac8
{ nil } => { nil } next = 0x0
{ nil } => { nil } next = 0x0
{ nil } => { nil } next = 0x0
{ nil } => { nil } next = 0x0
{ Lua function 0x7ffff7fec6a0, upvalues 0, 0x7ffff7fda4d8 "@/home/jsmith/calls.lua":25 } => { string: 0x7ffff7fe5818 "str" } next = 0x0
{ string: 0x7ffff7fe5d40 "3" } => { false } next = 0x0
{ nil } => { nil } next = 0x0
{ nil } => { nil } next = 0x0
{ string: 0x7ffff7fe6458 "key1" } => { table 0x7ffff7fec6d0 } next = 0x0
{ thread 0x7ffff7fd9cf8 } => { true } next = 0x0
{ string: 0x7ffff7fe6480 "9" } => { true } next = 0x0
{ true } => { userdata 0x7ffff7fdf6f0 } next = 0x7ffff7feca50
{ userdata 0x7ffff7fdf6f0 } => { thread 0x7ffff7fd9cf8 } next = 0x7ffff7fecaa0
{ string: 0x7ffff7fe64a8 "11" } => { number: 15 } next = 0x0
{ nil } => { nil } next = 0x0
lines indicate unused slots in a hash part of a table and should be ignored.
uj-str addr¶
(gdb) uj-str ((TValue *)0x7ffff7fe8b30)->gcr
string: 0x7ffff7fda590 "Hello, here is my string"
uj-tab-collisions addr¶
Dumps all collided keys followed by list of node indexes of the GCtab
at addr
. The last line contains the number of colliding keys.
load-trace-dwarf addr¶
Tries to demangle a code pointed to by addr
into a symbol corresponding to a trace. Relies on the __jit_debug_descriptor
symbol and other GDB APIs for registering symbols for dynamically emitted machine code.
If addr
is omitted, %rip
is used.