- exclude test_http_cookies when running selftests, due to hang seen on

http://koji.fedoraproject.org/koji/taskinfo?taskID=2088463 (cancelled
    after
11 hours)
- update python-gdb.py from v5 to py3k version submitted upstream
This commit is contained in:
dmalcolm 2010-04-13 17:36:08 +00:00
parent 80325d9c24
commit bbd09cc947
2 changed files with 64 additions and 67 deletions

View File

@ -19,9 +19,10 @@ giving file/line information and the state of local variables
In particular, given a gdb.Value corresponding to a PyObject* in the inferior In particular, given a gdb.Value corresponding to a PyObject* in the inferior
process, we can generate a "proxy value" within the gdb process. For example, process, we can generate a "proxy value" within the gdb process. For example,
given a PyObject* in the inferior process that is in fact a PyListObject* given a PyObject* in the inferior process that is in fact a PyListObject*
holding three PyObject* that turn out to be PyStringObject* instances, we can holding three PyObject* that turn out to be PyBytesObject* instances, we can
generate a proxy value within the gdb process that is a list of strings: generate a proxy value within the gdb process that is a list of bytes
["foo", "bar", "baz"] instances:
[b"foo", b"bar", b"baz"]
Doing so can be expensive for complicated graphs of objects, and could take Doing so can be expensive for complicated graphs of objects, and could take
some time, so we also have a "write_repr" method that writes a representation some time, so we also have a "write_repr" method that writes a representation
@ -39,7 +40,7 @@ the type names are known to the debugger
The module also extends gdb with some python-specific commands. The module also extends gdb with some python-specific commands.
''' '''
from __future__ import with_statement
import gdb import gdb
# Look up the gdb.Type for some standard types: # Look up the gdb.Type for some standard types:
@ -57,7 +58,7 @@ Py_TPFLAGS_INT_SUBCLASS = (1L << 23)
Py_TPFLAGS_LONG_SUBCLASS = (1L << 24) Py_TPFLAGS_LONG_SUBCLASS = (1L << 24)
Py_TPFLAGS_LIST_SUBCLASS = (1L << 25) Py_TPFLAGS_LIST_SUBCLASS = (1L << 25)
Py_TPFLAGS_TUPLE_SUBCLASS = (1L << 26) Py_TPFLAGS_TUPLE_SUBCLASS = (1L << 26)
Py_TPFLAGS_STRING_SUBCLASS = (1L << 27) Py_TPFLAGS_BYTES_SUBCLASS = (1L << 27)
Py_TPFLAGS_UNICODE_SUBCLASS = (1L << 28) Py_TPFLAGS_UNICODE_SUBCLASS = (1L << 28)
Py_TPFLAGS_DICT_SUBCLASS = (1L << 29) Py_TPFLAGS_DICT_SUBCLASS = (1L << 29)
Py_TPFLAGS_BASE_EXC_SUBCLASS = (1L << 30) Py_TPFLAGS_BASE_EXC_SUBCLASS = (1L << 30)
@ -99,7 +100,7 @@ class TruncatedStringIO(object):
# Truncation: # Truncation:
self._val += data[0:self.maxlen - len(self._val)] self._val += data[0:self.maxlen - len(self._val)]
raise StringTruncated() raise StringTruncated()
self._val += data self._val += data
def getvalue(self): def getvalue(self):
@ -108,7 +109,7 @@ class TruncatedStringIO(object):
class PyObjectPtr(object): class PyObjectPtr(object):
""" """
Class wrapping a gdb.Value that's a either a (PyObject*) within the Class wrapping a gdb.Value that's a either a (PyObject*) within the
inferior process, or some subclass pointer e.g. (PyStringObject*) inferior process, or some subclass pointer e.g. (PyBytesObject*)
There will be a subclass for every refined PyObject type that we care There will be a subclass for every refined PyObject type that we care
about. about.
@ -120,7 +121,7 @@ class PyObjectPtr(object):
def __init__(self, gdbval, cast_to=None): def __init__(self, gdbval, cast_to=None):
if cast_to: if cast_to:
self._gdbval = gdbval.cast(cast_to) self._gdbval = gdbval.cast(cast_to)
else: else:
self._gdbval = gdbval self._gdbval = gdbval
@ -148,12 +149,8 @@ class PyObjectPtr(object):
return pyo_ptr.dereference()[name] return pyo_ptr.dereference()[name]
if name == 'ob_size': if name == 'ob_size':
try: pyo_ptr = self._gdbval.cast(PyVarObjectPtr.get_gdb_type())
# Python 2: return pyo_ptr.dereference()[name]
return self._gdbval.dereference()[name]
except RuntimeError:
# Python 3:
return self._gdbval.dereference()['ob_base'][name]
# General case: look it up inside the object: # General case: look it up inside the object:
return self._gdbval.dereference()[name] return self._gdbval.dereference()[name]
@ -318,8 +315,8 @@ class PyObjectPtr(object):
return PyListObjectPtr return PyListObjectPtr
if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS: if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS:
return PyTupleObjectPtr return PyTupleObjectPtr
if tp_flags & Py_TPFLAGS_STRING_SUBCLASS: if tp_flags & Py_TPFLAGS_BYTES_SUBCLASS:
return PyStringObjectPtr return PyBytesObjectPtr
if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS: if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS:
return PyUnicodeObjectPtr return PyUnicodeObjectPtr
if tp_flags & Py_TPFLAGS_DICT_SUBCLASS: if tp_flags & Py_TPFLAGS_DICT_SUBCLASS:
@ -355,6 +352,8 @@ class PyObjectPtr(object):
def as_address(self): def as_address(self):
return long(self._gdbval) return long(self._gdbval)
class PyVarObjectPtr(PyObjectPtr):
_typename = 'PyVarObject'
class ProxyAlreadyVisited(object): class ProxyAlreadyVisited(object):
''' '''
@ -365,7 +364,7 @@ class ProxyAlreadyVisited(object):
''' '''
def __init__(self, rep): def __init__(self, rep):
self._rep = rep self._rep = rep
def __repr__(self): def __repr__(self):
return self._rep return self._rep
@ -407,7 +406,7 @@ class InstanceProxy(object):
else: else:
return '<%s at remote 0x%x>' % (self.cl_name, return '<%s at remote 0x%x>' % (self.cl_name,
self.address) self.address)
def _PyObject_VAR_SIZE(typeobj, nitems): def _PyObject_VAR_SIZE(typeobj, nitems):
return ( ( typeobj.field('tp_basicsize') + return ( ( typeobj.field('tp_basicsize') +
nitems * typeobj.field('tp_itemsize') + nitems * typeobj.field('tp_itemsize') +
@ -446,7 +445,7 @@ class HeapTypeObjectPtr(PyObjectPtr):
pass pass
# Not found, or some kind of error: # Not found, or some kind of error:
return None return None
def proxyval(self, visited): def proxyval(self, visited):
''' '''
@ -515,20 +514,6 @@ class PyBaseExceptionObjectPtr(PyObjectPtr):
out.write(self.safe_tp_name()) out.write(self.safe_tp_name())
self.write_field_repr('args', out, visited) self.write_field_repr('args', out, visited)
class PyBoolObjectPtr(PyObjectPtr):
"""
Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
<bool> instances (Py_True/Py_False) within the process being debugged.
"""
_typename = 'PyBoolObject'
def proxyval(self, visited):
if int_from_int(self.field('ob_ival')):
return True
else:
return False
class PyClassObjectPtr(PyObjectPtr): class PyClassObjectPtr(PyObjectPtr):
""" """
Class wrapping a gdb.Value that's a PyClassObject* i.e. a <classobj> Class wrapping a gdb.Value that's a PyClassObject* i.e. a <classobj>
@ -548,7 +533,7 @@ class BuiltInMethodProxy(object):
def __init__(self, ml_name, pyop_m_self): def __init__(self, ml_name, pyop_m_self):
self.ml_name = ml_name self.ml_name = ml_name
self.pyop_m_self = pyop_m_self self.pyop_m_self = pyop_m_self
def __repr__(self): def __repr__(self):
return ('<built-in method %s of %s object at remote 0x%x>' return ('<built-in method %s of %s object at remote 0x%x>'
% (self.ml_name, % (self.ml_name,
@ -592,7 +577,7 @@ class PyCodeObjectPtr(PyObjectPtr):
# Initialize lineno to co_firstlineno as per PyCode_Addr2Line # Initialize lineno to co_firstlineno as per PyCode_Addr2Line
# not 0, as lnotab_notes.txt has it: # not 0, as lnotab_notes.txt has it:
lineno = int_from_int(self.field('co_firstlineno')) lineno = int_from_int(self.field('co_firstlineno'))
addr = 0 addr = 0
for addr_incr, line_incr in zip(co_lnotab[::2], co_lnotab[1::2]): for addr_incr, line_incr in zip(co_lnotab[::2], co_lnotab[1::2]):
@ -630,9 +615,9 @@ class PyDictObjectPtr(PyObjectPtr):
result = {} result = {}
for pyop_key, pyop_value in self.iteritems(): for pyop_key, pyop_value in self.iteritems():
proxy_key = pyop_key.proxyval(visited) proxy_key = pyop_key.proxyval(visited)
proxy_value = pyop_value.proxyval(visited) proxy_value = pyop_value.proxyval(visited)
result[proxy_key] = proxy_value result[proxy_key] = proxy_value
return result return result
def write_repr(self, out, visited): def write_repr(self, out, visited):
@ -690,13 +675,6 @@ class PyInstanceObjectPtr(PyObjectPtr):
_write_instance_repr(out, visited, _write_instance_repr(out, visited,
cl_name, pyop_in_dict, self.as_address()) cl_name, pyop_in_dict, self.as_address())
class PyIntObjectPtr(PyObjectPtr):
_typename = 'PyIntObject'
def proxyval(self, visited):
result = int_from_int(self.field('ob_ival'))
return result
class PyListObjectPtr(PyObjectPtr): class PyListObjectPtr(PyObjectPtr):
_typename = 'PyListObject' _typename = 'PyListObject'
@ -711,7 +689,7 @@ class PyListObjectPtr(PyObjectPtr):
if self.as_address() in visited: if self.as_address() in visited:
return ProxyAlreadyVisited('[...]') return ProxyAlreadyVisited('[...]')
visited.add(self.as_address()) visited.add(self.as_address())
result = [PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited) result = [PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
for i in safe_range(int_from_int(self.field('ob_size')))] for i in safe_range(int_from_int(self.field('ob_size')))]
return result return result
@ -770,6 +748,16 @@ class PyLongObjectPtr(PyObjectPtr):
result = -result result = -result
return result return result
class PyBoolObjectPtr(PyLongObjectPtr):
"""
Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
<bool> instances (Py_True/Py_False) within the process being debugged.
"""
def proxyval(self, visited):
if PyLongObjectPtr.proxyval(self, visited):
return True
else:
return False
class PyNoneStructPtr(PyObjectPtr): class PyNoneStructPtr(PyObjectPtr):
""" """
@ -839,7 +827,7 @@ class PyFrameObjectPtr(PyObjectPtr):
''' '''
Look for the named local variable, returning a (PyObjectPtr, scope) pair Look for the named local variable, returning a (PyObjectPtr, scope) pair
where scope is a string 'local', 'global', 'builtin' where scope is a string 'local', 'global', 'builtin'
If not found, return (None, None) If not found, return (None, None)
''' '''
for pyop_name, pyop_value in self.iter_locals(): for pyop_name, pyop_value in self.iter_locals():
@ -861,9 +849,9 @@ class PyFrameObjectPtr(PyObjectPtr):
def current_line_num(self): def current_line_num(self):
'''Get current line number as an integer (1-based) '''Get current line number as an integer (1-based)
Translated from PyFrame_GetLineNumber and PyCode_Addr2Line Translated from PyFrame_GetLineNumber and PyCode_Addr2Line
See Objects/lnotab_notes.txt See Objects/lnotab_notes.txt
''' '''
if self.is_optimized_out(): if self.is_optimized_out():
@ -894,9 +882,9 @@ class PyFrameObjectPtr(PyObjectPtr):
return return
out.write('Frame 0x%x, for file %s, line %i, in %s (' out.write('Frame 0x%x, for file %s, line %i, in %s ('
% (self.as_address(), % (self.as_address(),
self.co_filename, self.co_filename.proxyval(visited),
self.current_line_num(), self.current_line_num(),
self.co_name)) self.co_name.proxyval(visited)))
first = True first = True
for pyop_name, pyop_value in self.iter_locals(): for pyop_name, pyop_value in self.iter_locals():
if not first: if not first:
@ -906,7 +894,7 @@ class PyFrameObjectPtr(PyObjectPtr):
out.write(pyop_name.proxyval(visited)) out.write(pyop_name.proxyval(visited))
out.write('=') out.write('=')
pyop_value.write_repr(out, visited) pyop_value.write_repr(out, visited)
out.write(')') out.write(')')
class PySetObjectPtr(PyObjectPtr): class PySetObjectPtr(PyObjectPtr):
@ -958,8 +946,8 @@ class PySetObjectPtr(PyObjectPtr):
out.write('])') out.write('])')
class PyStringObjectPtr(PyObjectPtr): class PyBytesObjectPtr(PyObjectPtr):
_typename = 'PyStringObject' _typename = 'PyBytesObject'
def __str__(self): def __str__(self):
field_ob_size = self.field('ob_size') field_ob_size = self.field('ob_size')
@ -1038,7 +1026,7 @@ def stringify(val):
# TODO: repr() puts everything on one line; pformat can be nicer, but # TODO: repr() puts everything on one line; pformat can be nicer, but
# can lead to v.long results; this function isolates the choice # can lead to v.long results; this function isolates the choice
if True: if True:
return repr(val) return repr(val)
else: else:
from pprint import pformat from pprint import pformat
return pformat(val) return pformat(val)
@ -1065,7 +1053,7 @@ def pretty_printer_lookup(gdbval):
if type.code == gdb.TYPE_CODE_PTR: if type.code == gdb.TYPE_CODE_PTR:
type = type.target().unqualified() type = type.target().unqualified()
t = str(type) t = str(type)
if t in ("PyObject", "PyFrameObject"): if t in ("PyObject", "PyFrameObject", "PyUnicodeObject"):
return PyObjectPtrPrinter(gdbval) return PyObjectPtrPrinter(gdbval)
""" """
@ -1099,7 +1087,7 @@ register (gdb.current_objfile ())
class Frame(object): class Frame(object):
''' '''
Wrapper for gdb.Frame, adding various methods Wrapper for gdb.Frame, adding various methods
''' '''
def __init__(self, gdbframe): def __init__(self, gdbframe):
self._gdbframe = gdbframe self._gdbframe = gdbframe
@ -1193,7 +1181,7 @@ class PyList(gdb.Command):
Use Use
py-list START py-list START
to list at a different line number within the python source. to list at a different line number within the python source.
Use Use
py-list START, END py-list START, END
to list a specific range of lines within the python source. to list a specific range of lines within the python source.
@ -1252,8 +1240,8 @@ class PyList(gdb.Command):
if i + start == lineno: if i + start == lineno:
linestr = '>' + linestr linestr = '>' + linestr
sys.stdout.write('%4s %s' % (linestr, line)) sys.stdout.write('%4s %s' % (linestr, line))
# ...and register the command: # ...and register the command:
PyList() PyList()

View File

@ -39,7 +39,7 @@
Summary: Version 3 of the Python programming language aka Python 3000 Summary: Version 3 of the Python programming language aka Python 3000
Name: python3 Name: python3
Version: %{pybasever}.2 Version: %{pybasever}.2
Release: 4%{?dist} Release: 5%{?dist}
License: Python License: Python
Group: Development/Languages Group: Development/Languages
Source: http://python.org/ftp/python/%{version}/Python-%{version}.tar.bz2 Source: http://python.org/ftp/python/%{version}/Python-%{version}.tar.bz2
@ -72,9 +72,12 @@ Source3: macros.pybytecompile
# See https://fedoraproject.org/wiki/Features/EasierPythonDebugging for more # See https://fedoraproject.org/wiki/Features/EasierPythonDebugging for more
# information # information
# #
# Downloaded from: # This is the version from
# http://bugs.python.org/issue8032 # http://bugs.python.org/issue8380
# This is Tools/gdb/libpython.py from v5 of the patch #
# This is Tools/gdb/libpython.py from:
# http://bugs.python.org/file16902/port-gdb7-hooks-to-py3k.patch
# when applied to r80008 of the py3k branch
Source4: python-gdb.py Source4: python-gdb.py
# Systemtap tapset to make it easier to use the systemtap static probes # Systemtap tapset to make it easier to use the systemtap static probes
@ -446,9 +449,9 @@ sed \
%check %check
# Run the upstream test suite, using the "runtests.sh" harness from the upstream # Run the upstream test suite, using the "runtests.sh" harness from the upstream
# tarball. # tarball.
# I'm seeing occasional hangs in "test_httplib" when running the test suite inside # I'm seeing occasional hangs in some http tests when running the test suite
# Koji. For that reason I exclude that one. # inside Koji. For that reason I exclude them
LD_LIBRARY_PATH=$(pwd) ./runtests.sh -x test_httplib LD_LIBRARY_PATH=$(pwd) ./runtests.sh -x test_httplib test_http_cookies
# Note that we're running the tests using the version of the code in the builddir, # Note that we're running the tests using the version of the code in the builddir,
# not in the buildroot. # not in the buildroot.
@ -695,6 +698,12 @@ rm -fr %{buildroot}
%changelog %changelog
* Tue Apr 13 2010 David Malcolm <dmalcolm@redhat.com> - 3.1.2-5
- exclude test_http_cookies when running selftests, due to hang seen on
http://koji.fedoraproject.org/koji/taskinfo?taskID=2088463 (cancelled after
11 hours)
- update python-gdb.py from v5 to py3k version submitted upstream
* Wed Mar 31 2010 David Malcolm <dmalcolm@redhat.com> - 3.1.2-4 * Wed Mar 31 2010 David Malcolm <dmalcolm@redhat.com> - 3.1.2-4
- update python-gdb.py from v4 to v5 (improving performance and stability, - update python-gdb.py from v4 to v5 (improving performance and stability,
adding commands) adding commands)