From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtpng1.m.smailru.net (smtpng1.m.smailru.net [94.100.181.251]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 00B1D4696C4 for ; Wed, 5 Feb 2020 19:24:47 +0300 (MSK) From: Igor Munkin Date: Wed, 5 Feb 2020 19:22:29 +0300 Message-Id: <3bfab5cce3e3816bc1c8c969e33204c2a00c929a.1580917791.git.imun@tarantool.org> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH v2 luajit 3/3] gdb: enhance the extension loading List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: tarantool-patches@dev.tarantool.org Definition of LJ_64, LJ_GC64 and LJ_FR2 constants in script requires LuaJIT internal enum values to be presented in the executable. Otherwise the extension loading fails. The changes handles exception for the following scenarios: * luajit-gdb.py is loaded for an arbitrary executable, e.g. /bin/echo * luajit-gdb.py is loaded for a luajit executable (or the one linked against libluajit) but debug info is not found Signed-off-by: Igor Munkin --- src/luajit-gdb.py | 102 ++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 57 deletions(-) diff --git a/src/luajit-gdb.py b/src/luajit-gdb.py index 90df101..bc37674 100644 --- a/src/luajit-gdb.py +++ b/src/luajit-gdb.py @@ -1,3 +1,6 @@ +# GDB extension for LuaJIT post-mortem analysis. +# To use, just put 'source /src/luajit-gdb.py' in gdb. + import re import gdb import sys @@ -151,11 +154,9 @@ def frame_prev(framelink): # Const {{{ -LJ_64 = str(gdb.parse_and_eval('IRT_PTR')) == 'IRT_P64' - -LJ_GC64 = str(gdb.parse_and_eval('IRT_PGC')) == 'IRT_P64' - -LJ_FR2 = LJ_GC64 +LJ_64 = None +LJ_GC64 = None +LJ_FR2 = None LJ_GCVMASK = ((1 << 47) - 1) @@ -460,7 +461,14 @@ def dump_gc(g): return '\n'.join(map(lambda s: '\t' + s, stats)) -class LJDumpArch(gdb.Command): + +class LJBase(gdb.Command): + + def __init__(self, name): + super(__class__, self).__init__(name, gdb.COMMAND_DATA) + gdb.write('{} command initialized\n'.format(name)) + +class LJDumpArch(LJBase): ''' lj-arch @@ -469,20 +477,13 @@ compile-time flags. These values define the sizes of host and GC pointers respectively. ''' - def __init__(self): - super(LJDumpArch, self).__init__( - 'lj-arch', gdb.COMMAND_DATA - ) - def invoke(self, arg, from_tty): gdb.write('LJ_64: {LJ_64}, LJ_GC64: {LJ_GC64}\n'.format( LJ_64 = LJ_64, LJ_GC64 = LJ_GC64 )) -LJDumpArch() - -class LJDumpTValue(gdb.Command): +class LJDumpTValue(LJBase): ''' lj-tv @@ -511,18 +512,11 @@ Whether the type of the given address differs from the listed above, then error message occurs. ''' - def __init__(self): - super(LJDumpTValue, self).__init__( - 'lj-tv', gdb.COMMAND_DATA - ) - def invoke(self, arg, from_tty): tv = cast('TValue *', parse_arg(arg)) gdb.write('{}\n'.format(dump_tvalue(tv))) -LJDumpTValue() - -class LJDumpString(gdb.Command): +class LJDumpString(LJBase): ''' lj-str @@ -533,11 +527,6 @@ the payload, size in bytes and hash. is replaced with the corresponding error when decoding fails. ''' - def __init__(self): - super(LJDumpString, self).__init__( - 'lj-str', gdb.COMMAND_DATA - ) - def invoke(self, arg, from_tty): string = cast('GCstr *', parse_arg(arg)) gdb.write("String: {body} [{len} bytes] with hash {hash}\n".format( @@ -546,10 +535,7 @@ is replaced with the corresponding error when decoding fails. len = string['len'], )) - -LJDumpString() - -class LJDumpTable(gdb.Command): +class LJDumpTable(LJBase): ''' lj-tab @@ -561,10 +547,6 @@ The command recieves a GCtab adress and dumps the table contents: : { } => { }; next = ''' - def __init__(self): - super(LJDumpTable, self).__init__( - 'lj-tab', gdb.COMMAND_DATA) - def invoke(self, arg, from_tty): t = cast('GCtab *', parse_arg(arg)) array = mref('TValue *', t['array']) @@ -598,9 +580,7 @@ The command recieves a GCtab adress and dumps the table contents: n = mref('struct Node *', node['next']) )) -LJDumpTable() - -class LJDumpStack(gdb.Command): +class LJDumpStack(LJBase): ''' lj-stack [] @@ -633,16 +613,10 @@ coroutine guest stack: If L is ommited the main coroutine is used. ''' - def __init__(self): - super(LJDumpStack, self).__init__( - 'lj-stack', gdb.COMMAND_DATA) - def invoke(self, arg, from_tty): gdb.write('{}\n'.format(dump_stack(L(parse_arg(arg))))) -LJDumpStack() - -class LJState(gdb.Command): +class LJState(LJBase): ''' lj-state The command requires no args and dumps current VM and GC states @@ -651,10 +625,6 @@ The command requires no args and dumps current VM and GC states * JIT state: ''' - def __init__(self): - super(LJState, self).__init__( - 'lj-state', gdb.COMMAND_DATA) - def invoke(self, arg, from_tty): g = G(L(None)) gdb.write('{}\n'.format('\n'.join( @@ -665,9 +635,7 @@ The command requires no args and dumps current VM and GC states }.items()) ))) -LJState() - -class LJGC(gdb.Command): +class LJGC(LJBase): ''' lj-gc @@ -685,10 +653,6 @@ The command requires no args and dumps current GC stats: * weak: ''' - def __init__(self): - super(LJGC, self).__init__( - 'lj-gc', gdb.COMMAND_DATA) - def invoke(self, arg, from_tty): g = G(L(None)) gdb.write('GC stats: {state}\n{stats}\n'.format( @@ -696,4 +660,28 @@ The command requires no args and dumps current GC stats: stats = dump_gc(g) )) -LJGC() +def load(commands): + global LJ_64, LJ_GC64, LJ_FR2 + + try: + LJ_64 = str(gdb.parse_and_eval('IRT_PTR')) == 'IRT_P64' + LJ_FR2 = LJ_GC64 = str(gdb.parse_and_eval('IRT_PGC')) == 'IRT_P64' + except: + gdb.write('luajit-gdb.py failed to load: ' + 'no debugging symbols found for libluajit\n') + return + + for name, command in commands.items(): + command(name) + + gdb.write('luajit-gdb.py is successfully loaded\n') + +load({ + 'lj-arch': LJDumpArch, + 'lj-tv': LJDumpTValue, + 'lj-str': LJDumpString, + 'lj-tab': LJDumpTable, + 'lj-stack': LJDumpStack, + 'lj-state': LJState, + 'lj-gc': LJGC, +}) -- 2.24.0