[Tarantool-patches] [PATCH v2 luajit 3/3] gdb: enhance the extension loading

Igor Munkin imun at tarantool.org
Wed Feb 5 19:22:29 MSK 2020


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 <imun at tarantool.org>
---
 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 <path-to-repo>/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 <TValue *>
 
@@ -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 <GCstr *>
 
@@ -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 <GCtab *>
 
@@ -561,10 +547,6 @@ The command recieves a GCtab adress and dumps the table contents:
   <hnode ptr>: { <tv> } => { <tv> }; next = <next hnode ptr>
     '''
 
-    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 [<lua_State *>]
 
@@ -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: <IDLE|ACTIVE|RECORD|START|END|ASM|ERR>
     '''
 
-    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: <number of weak tables (to be cleared)>
     '''
 
-    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



More information about the Tarantool-patches mailing list