blob: 1508c64684d28ce2feab14f2a6bb97c3ed5534c6 [file] [log] [blame] [raw]
# This gdb script provides several useful routines for debugging ngx_lua or
# standalone Lua/LuaJIT.
#
# You need gdb >= v7.3 to make this script working correctly.
#
# Installation: place it at $HOME/.gdbinit
#
# -- chaoslawful <at> gmail <dot> com
#### Lua type defines ####
set $__LUA_TNONE = -1
set $__LUA_TNIL = 0
set $__LUA_TBOOLEAN = 1
set $__LUA_TLIGHTUSERDATA = 2
set $__LUA_TNUMBER = 3
set $__LUA_TSTRING = 4
set $__LUA_TTABLE = 5
set $__LUA_TFUNCTION = 6
set $__LUA_TUSERDATA = 7
set $__LUA_TTHREAD = 8
#### Lua constants ####
set $__LUA_GLOBALSINDEX = -10002
set $__LUA_ENVIRONINDEX = -10001
set $__LUA_REGISTRYINDEX = -10000
#### Auxiliary methods ####
define __lua_debug_instance
if !$__lua_debug_instance
set $__lua_debug_instance = (lua_Debug*)malloc(sizeof(lua_Debug))
end
end
define __free_lua_debug_instance
if $__lua_debug_instance
set $rc = free($__lua_debug_instance)
set $__lua_debug_instance = 0
end
end
set $__BUCKET_SIZE = 16
define __set_instance
if !$__set_instance
set $__set_instance = (void*(*(*))[2])malloc($__BUCKET_SIZE*sizeof(void*(*)[2]))
set $rc = memset($__set_instance, 0, $__BUCKET_SIZE*sizeof(void*(*)[2]))
end
end
define __free_set_instance
if $__set_instance
__set_clean
set $rc = free($__set_instance)
set $__set_instance = 0
end
end
define __set_add
set $p = (void*)$arg0
set $__bkt_idx = (int)$p%$__BUCKET_SIZE
__set_instance
set $__elem = (void*(*)[2])$__set_instance[$__bkt_idx]
set $__found = 0
while $__elem
if (*$__elem)[0] == $p
set $__found = 1
loop_break
end
set $__elem = (void*(*)[2])(*$__elem)[1]
end
if $__found
set $existed_in_set = 1
else
set $existed_in_set = 0
set $rc = (void*(*)[2])calloc(1, sizeof(void*)*2)
set (*$rc)[0] = $p
set (*$rc)[1] = $__set_instance[$__bkt_idx]
set $__set_instance[$__bkt_idx] = $rc
end
end
define __set_is_exist
set $p = (void*)$arg0
set $__bkt_idx = (int)$p%$__BUCKET_SIZE
__set_instance
set $__elem = (void*(*)[2])$__set_instance[$__bkt_idx]
set $__found = 0
while $__elem
if (*$__elem)[0] == $p
set $__found = 1
loop_break
end
set $__elem = (void*(*)[2])(*$__elem)[1]
end
if $__found
set $existed_in_set = 1
else
set $existed_in_set = 0
end
end
define __set_clean
__set_instance
set $__bkt_idx = 0
while $__bkt_idx < $__BUCKET_SIZE
set $__elem = (void*(*)[2])$__set_instance[$__bkt_idx]
while $__elem
set $__next = (void*(*)[2])(*$__elem)[1]
set $rc = free($__elem)
set $__elem = $__next
end
set $__set_instance[$__bkt_idx] = 0
set $__bkt_idx = $__bkt_idx+1
end
end
define hook-quit
__free_lua_debug_instance
__free_set_instance
end
define hook-detach
__free_lua_debug_instance
__free_set_instance
end
define hook-disconnect
__free_lua_debug_instance
__free_set_instance
end
define _lua_pop
set $l = (lua_State*)$arg0
set $_n = (int)$arg1
set $_rc = lua_settop($l, -$_n-1)
end
define _lua_dump_locals
set $l = (lua_State*)$arg0
set $dbg = (lua_Debug*)$arg1
set $idx = 1
set $rc = lua_getlocal($l, $dbg, $idx)
if $rc
printf "\t----[[ Locals ]]----\n"
while $rc
printf "\t%d:\t'%s' = ", $idx, $rc
__lua_dump_stack $l -1
printf "\n"
_lua_pop $l 1
set $idx = $idx + 1
set $rc = lua_getlocal($l, $dbg, $idx)
end
else
printf "\tNo locals!\n"
end
printf "\n"
end
define _lua_dump_upvalues
set $l = (lua_State*)$arg0
set $dbg = (lua_Debug*)$arg1
set $idx = 1
set $rc = lua_getinfo($l, "f", $dbg)
if $rc
set $rc = lua_getupvalue($l, -1, $idx)
if $rc
printf "\t----[[ Upvalues ]]----\n"
while $rc
printf "\t%d:\t'%s' = ", $idx, $rc
__lua_dump_stack $l -1
printf "\n"
_lua_pop $l 1
set $idx = $idx + 1
set $rc = lua_getupvalue($l, -1, $idx)
end
else
printf "\tNo upvalues!\n"
end
_lua_pop $l 1
else
printf "\tFailed to get function closure!\n"
end
printf "\n"
end
define __lua_dump_stack
__set_clean
__lua_dump_stack_aux $arg0 $arg1 0
end
define __lua_dump_stack_aux
set $l = (lua_State*)$arg0
set $nidx_$arg2 = (int)$arg1
set $cidx_$arg2 = (int)$arg2+1
# relative stack index to absolute index
if $nidx_$arg2 < 0 && $nidx_$arg2 > $__LUA_REGISTRYINDEX
set $nidx_$arg2 = $nidx_$arg2 + (int)lua_gettop($l) + 1
end
set $vt_$arg2 = (int)lua_type($l, $nidx_$arg2)
if $vt_$arg2 == $__LUA_TNONE
echo <invalid index>
end
if $vt_$arg2 == $__LUA_TNIL
echo (nil)
end
if $vt_$arg2 == $__LUA_TBOOLEAN
printf "(bool) %d", lua_toboolean($l, $nidx_$arg2)
end
if $vt_$arg2 == $__LUA_TLIGHTUSERDATA
printf "(ludata) %p", lua_touserdata($l, $nidx_$arg2)
end
if $vt_$arg2 == $__LUA_TNUMBER
printf "%g", lua_tonumber($l, $nidx_$arg2)
end
if $vt_$arg2 == $__LUA_TSTRING
set $tmplen = (size_t*)malloc(sizeof(size_t))
set $tmp = lua_pushvalue($l, $nidx_$arg2)
set $tmp = lua_tolstring($l, -1, $tmplen)
#printf "(string:%d) ", *$tmplen
eval "output/r *(const char (*)[%d])$tmp", *$tmplen
_lua_pop $l 1
set $tmp = free($tmplen)
end
if $vt_$arg2 == $__LUA_TTABLE
set $rc = lua_topointer($l, $nidx_$arg2)
#printf "(table) %p { ", $rc
printf "{ "
__set_add $rc
if $existed_in_set
printf "... "
else
set $rc = lua_pushnil($l)
set $rc = lua_next($l, $nidx_$arg2)
while $rc != 0
printf "["
__lua_dump_stack_aux $l -2 $cidx_$arg2
printf "]"
printf " = "
__lua_dump_stack_aux $l -1 $cidx_$arg2
printf ", "
_lua_pop $l 1
set $rc = lua_next($l, $nidx_$arg2)
end
end
printf "}"
end
if $vt_$arg2 == $__LUA_TFUNCTION
printf "(func) %p", lua_topointer($l, $nidx_$arg2)
end
if $vt_$arg2 == $__LUA_TUSERDATA
printf "(udata) %p", lua_topointer($l, $nidx_$arg2)
end
if $vt_$arg2 == $__LUA_TTHREAD
printf "(thread) %p", lua_topointer($l, $nidx_$arg2)
else
if $vt_$arg2 > $__LUA_TTHREAD || $vt_$arg2 < 0
echo <unknown type>
end
end
end
#### Command methods ####
define lbt
if $argc < 1
echo Please specify Lua state and/or dump flag!\n
else
set $l = (lua_State*)$arg0
if $argc > 1
set $dump_local = ($arg1&1)==1
set $dump_upvalue = ($arg1&2)==2
else
set $dump_local = 0
set $dump_upvalue = 0
end
__lua_debug_instance
set $dbg = $__lua_debug_instance
set $level = 0
set $rc = lua_getstack($l, $level, $dbg)
while $rc > 0
set $rc = lua_getinfo($l, "Sln", $dbg)
set $name = $dbg->name
if !$name
set $name = "???"
end
printf "#%d\t%s\t[%s]\tat %s:%d\n", $level, $name, $dbg->what, $dbg->source, $dbg->currentline
if $dump_local
_lua_dump_locals $l $dbg
end
if $dump_upvalue
_lua_dump_upvalues $l $dbg
end
set $level = $level+1
set $rc = lua_getstack($l, $level, $dbg)
end
end
end
document lbt
lbt <lua state> [<dump>]: Dump the backtrace of the specified Lua state. <dump> is a mask value, whose bit 1/2 controls the dump of locals/upvalues at each stack frame correspondingly. So set <dump> to 1 dumps only locals; set to 2 dumps only upvalues; and set to 3 dumps both locals and upvalues.
end
define ll
if $argc != 2
echo Please specify Lua state and stack frame number (0-based)!\n
else
set $l = (lua_State*)$arg0
set $level = (int)$arg1
__lua_debug_instance
set $dbg = $__lua_debug_instance
set $rc = lua_getstack($l, $level, $dbg)
if $rc > 0
_lua_dump_locals $l $dbg
else
echo Failed to get Lua stack frame!\n
end
end
end
document ll
ll <lua state> <frameno>: Dump all local vars in the specified Lua stack frame (0-based).
end
define lu
if $argc != 2
echo Please specify Lua state and stack frame number (0-based)!\n
else
set $l = (lua_State*)$arg0
set $level = (int)$arg1
__lua_debug_instance
set $dbg = $__lua_debug_instance
set $rc = lua_getstack($l, $level, $dbg)
if $rc > 0
_lua_dump_upvalues $l $dbg
else
echo Failed to get Lua stack frame!\n
end
end
end
document lu
lu <lua state> <frameno>: Dump all upvalues in the specified Lua stack frame (0-based).
end
define lg
if $argc != 1
echo Please specify Lua state!\n
else
set $l = (lua_State*)$arg0
__lua_dump_stack $l $__LUA_GLOBALSINDEX
printf "\n"
end
end
document lg
lg <lua state>: Dump all entries in Lua global table.
end
define lr
if $argc != 1
echo Please specify Lua state!\n
else
set $l = (lua_State*)$arg0
__lua_dump_stack $l $__LUA_REGISTRYINDEX
printf "\n"
end
end
document lr
lr <lua state>: Dump all entries in Lua registry table.
end
define ls
if $argc != 1
echo Please specify Lua state!\n
else
set $l = (lua_State*)$arg0
set $idx = lua_gettop($l)
while $idx >= 1
printf "#%d ", $idx
__lua_dump_stack $l $idx
printf "\n"
set $idx = $idx - 1
end
end
end
document ls
ls <lua state>: Dump all entries in call stack.
end
# vi:ft=gdb ts=4 sw=4