Author: Armin Rigo <[email protected]>
Branch:
Changeset: r1742:84157d77ae80
Date: 2015-03-26 08:02 +0100
http://bitbucket.org/pypy/stmgc/changeset/84157d77ae80/
Log: Forgot "hg add"
diff --git a/c7/gdb/gdb_stm.py b/c7/gdb/gdb_stm.py
new file mode 100644
--- /dev/null
+++ b/c7/gdb/gdb_stm.py
@@ -0,0 +1,114 @@
+"""Adds a few built-in functions for stmgc-c7:
+
+ $gc(p=0, thread='current')
+
+ With an integer argument `p`, returns `(char *)(segment_base + p)`.
+ If `p` is a pointer type, it is assumed to be %gs-relative; the
+ function returns `*p` in the segment.
+
+ The segment is by default the current one, as computed by looking
+ around in the debug information. You can force with the second
+ argment a specific segment number or a specific pthread_self()
+ thread address.
+
+ $psegment(thread='current')
+
+ Return the 'stm_priv_segment_info_t *' of the given thread
+ (given as a segment number or a pthread_self() thread address).
+
+Usage: you can for example add this line in your ~/.gdbinit:
+
+ python exec(open('/path/to/gdb_stm.py').read())
+"""
+import gdb
+
+def gdb_function(func):
+ class Func(gdb.Function):
+ __doc__ = func.__doc__
+ invoke = staticmethod(func)
+ Func(func.__name__)
+
+# -------------------------------------------------------
+
+_nb_segments = None
+_segment_size = None
+_psegment_ofs = None
+
+def get_nb_segments():
+ global _nb_segments
+ if _nb_segments is None:
+ _nb_segments = int(gdb.parse_and_eval('_stm_nb_segments'))
+ assert 1 < _nb_segments <= 240
+ return _nb_segments
+
+def get_segment_size():
+ global _segment_size
+ if _segment_size is None:
+ nb_pages = int(gdb.parse_and_eval('_stm_segment_nb_pages'))
+ _segment_size = nb_pages * 4096
+ return _segment_size
+
+def get_psegment_ofs():
+ global _psegment_ofs
+ if _psegment_ofs is None:
+ _psegment_ofs = int(gdb.parse_and_eval('_stm_psegment_ofs'))
+ return _psegment_ofs
+
+def get_segment_base(segment_id):
+ assert 0 <= segment_id <= get_nb_segments()
+ base = int(gdb.parse_and_eval('stm_object_pages'))
+ return base + get_segment_size() * segment_id
+
+def get_psegment(segment_id, field=''):
+ assert 0 < segment_id <= get_nb_segments()
+ return gdb.parse_and_eval(
+ '((struct stm_priv_segment_info_s *)(stm_object_pages+%d))%s'
+ % (get_segment_size() * segment_id + get_psegment_ofs(), field))
+
+def thread_to_segment_id(thread_id):
+ base = int(gdb.parse_and_eval('stm_object_pages'))
+ for j in range(1, get_nb_segments() + 1):
+ ts = get_psegment(j, '->transaction_state')
+ if int(ts) != 0:
+ ti = get_psegment(j, '->pub.running_thread->creating_pthread[0]')
+ if int(ti) == thread_id:
+ return j
+ raise Exception("thread not found: %r" % (thread_id,))
+
+def interactive_segment_base(thread=None):
+ if thread is None:
+ s = gdb.execute('info threads', False, True)
+ i = s.find('\n* ')
+ assert i >= 0
+ fields = s[i+2:].split()
+ assert fields[1] == 'Thread'
+ assert fields[2].startswith('0x')
+ thread_id = int(fields[2], 16)
+ segment_id = thread_to_segment_id(thread_id)
+ elif thread.type.code == gdb.TYPE_CODE_INT:
+ if 0 <= int(thread) < 256:
+ segment_id = int(thread)
+ else:
+ thread_id = int(thread)
+ segment_id = thread_to_segment_id(thread_id)
+ else:
+ raise TypeError("'thread' argument must be an int or not given")
+ return get_segment_base(segment_id)
+
+@gdb_function
+def gc(p=None, thread=None):
+ sb = interactive_segment_base(thread)
+ if p is not None and p.type.code == gdb.TYPE_CODE_PTR:
+ return gdb.Value(sb + int(p)).cast(p.type).dereference()
+ elif p is None or int(p) == 0:
+ T = gdb.lookup_type('char').pointer()
+ return gdb.Value(sb).cast(T)
+ else:
+ raise TypeError("gc() first argument must be a GC pointer or 0")
+
+@gdb_function
+def psegment(thread=None):
+ sb = interactive_segment_base(thread)
+ return gdb.parse_and_eval(
+ '*((struct stm_priv_segment_info_s *)%d)'
+ % (sb + get_psegment_ofs(),))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit