Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
c6807afd
Commit
c6807afd
authored
Mar 31, 2019
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update libpython from latest CPython upstream (1ceb3a3d17).
parent
4eef0edd
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
67 additions
and
33 deletions
+67
-33
Cython/Debugger/libpython.py
Cython/Debugger/libpython.py
+67
-33
No files found.
Cython/Debugger/libpython.py
View file @
c6807afd
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
From gdb 7 onwards, gdb's build can be configured --with-python, allowing gdb
From gdb 7 onwards, gdb's build can be configured --with-python, allowing gdb
to be extended with Python code e.g. for library-specific data visualizations,
to be extended with Python code e.g. for library-specific data visualizations,
such as for the C++ STL types. Documentation on this API can be seen at:
such as for the C++ STL types. Documentation on this API can be seen at:
http
s
://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html
http://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html
This python module deals with the case when the process being debugged (the
This python module deals with the case when the process being debugged (the
...
@@ -48,7 +48,7 @@ The module also extends gdb with some python-specific commands.
...
@@ -48,7 +48,7 @@ The module also extends gdb with some python-specific commands.
'''
'''
# NOTE: some gdbs are linked with Python 3, so this file should be dual-syntax
# NOTE: some gdbs are linked with Python 3, so this file should be dual-syntax
# compatible (2.
7+ and 3.3
+). See #19308.
# compatible (2.
6+ and 3.0
+). See #19308.
from
__future__
import
print_function
from
__future__
import
print_function
import
gdb
import
gdb
...
@@ -276,12 +276,13 @@ class PyObjectPtr(object):
...
@@ -276,12 +276,13 @@ class PyObjectPtr(object):
def
safe_tp_name
(
self
):
def
safe_tp_name
(
self
):
try
:
try
:
return
self
.
type
().
field
(
'tp_name'
).
string
()
ob_type
=
self
.
type
()
except
NullPyObjectPtr
:
tp_name
=
ob_type
.
field
(
'tp_name'
)
# NULL tp_name?
return
tp_name
.
string
()
return
'unknown'
# NullPyObjectPtr: NULL tp_name?
except
RuntimeError
:
# RuntimeError: Can't even read the object at all?
# Can't even read the object at all?
# UnicodeDecodeError: Failed to decode tp_name bytestring
except
(
NullPyObjectPtr
,
RuntimeError
,
UnicodeDecodeError
):
return
'unknown'
return
'unknown'
def
proxyval
(
self
,
visited
):
def
proxyval
(
self
,
visited
):
...
@@ -315,7 +316,7 @@ class PyObjectPtr(object):
...
@@ -315,7 +316,7 @@ class PyObjectPtr(object):
def
__repr__
(
self
):
def
__repr__
(
self
):
# For the NULL pointer, we have no way of knowing a type, so
# For the NULL pointer, we have no way of knowing a type, so
# special-case it as per
# special-case it as per
# http
s
://bugs.python.org/issue8032#msg100882
# http://bugs.python.org/issue8032#msg100882
if
self
.
address
==
0
:
if
self
.
address
==
0
:
return
'0x0'
return
'0x0'
return
'<%s at remote 0x%x>'
%
(
self
.
tp_name
,
self
.
address
)
return
'<%s at remote 0x%x>'
%
(
self
.
tp_name
,
self
.
address
)
...
@@ -355,7 +356,9 @@ class PyObjectPtr(object):
...
@@ -355,7 +356,9 @@ class PyObjectPtr(object):
try
:
try
:
tp_name
=
t
.
field
(
'tp_name'
).
string
()
tp_name
=
t
.
field
(
'tp_name'
).
string
()
tp_flags
=
int
(
t
.
field
(
'tp_flags'
))
tp_flags
=
int
(
t
.
field
(
'tp_flags'
))
except
RuntimeError
:
# RuntimeError: NULL pointers
# UnicodeDecodeError: string() fails to decode the bytestring
except
(
RuntimeError
,
UnicodeDecodeError
):
# Handle any kind of error e.g. NULL ptrs by simply using the base
# Handle any kind of error e.g. NULL ptrs by simply using the base
# class
# class
return
cls
return
cls
...
@@ -623,7 +626,10 @@ class PyCFunctionObjectPtr(PyObjectPtr):
...
@@ -623,7 +626,10 @@ class PyCFunctionObjectPtr(PyObjectPtr):
def
proxyval
(
self
,
visited
):
def
proxyval
(
self
,
visited
):
m_ml
=
self
.
field
(
'm_ml'
)
# m_ml is a (PyMethodDef*)
m_ml
=
self
.
field
(
'm_ml'
)
# m_ml is a (PyMethodDef*)
ml_name
=
m_ml
[
'ml_name'
].
string
()
try
:
ml_name
=
m_ml
[
'ml_name'
].
string
()
except
UnicodeDecodeError
:
ml_name
=
'<ml_name:UnicodeDecodeError>'
pyop_m_self
=
self
.
pyop_field
(
'm_self'
)
pyop_m_self
=
self
.
pyop_field
(
'm_self'
)
if
pyop_m_self
.
is_null
():
if
pyop_m_self
.
is_null
():
...
@@ -736,7 +742,7 @@ class PyDictObjectPtr(PyObjectPtr):
...
@@ -736,7 +742,7 @@ class PyDictObjectPtr(PyObjectPtr):
else
:
else
:
offset
=
8
*
dk_size
offset
=
8
*
dk_size
ent_addr
=
keys
[
'dk_indices'
]
[
'as_1'
]
.
address
ent_addr
=
keys
[
'dk_indices'
].
address
ent_addr
=
ent_addr
.
cast
(
_type_unsigned_char_ptr
())
+
offset
ent_addr
=
ent_addr
.
cast
(
_type_unsigned_char_ptr
())
+
offset
ent_ptr_t
=
gdb
.
lookup_type
(
'PyDictKeyEntry'
).
pointer
()
ent_ptr_t
=
gdb
.
lookup_type
(
'PyDictKeyEntry'
).
pointer
()
ent_addr
=
ent_addr
.
cast
(
ent_ptr_t
)
ent_addr
=
ent_addr
.
cast
(
ent_ptr_t
)
...
@@ -934,35 +940,50 @@ class PyFrameObjectPtr(PyObjectPtr):
...
@@ -934,35 +940,50 @@ class PyFrameObjectPtr(PyObjectPtr):
if
long
(
f_trace
)
!=
0
:
if
long
(
f_trace
)
!=
0
:
# we have a non-NULL f_trace:
# we have a non-NULL f_trace:
return
self
.
f_lineno
return
self
.
f_lineno
else
:
#
try:
try
:
return
self
.
co
.
addr2line
(
self
.
f_lasti
)
return
self
.
co
.
addr2line
(
self
.
f_lasti
)
#except ValueError:
except
Exception
:
# return self.f_lineno
# bpo-34989: addr2line() is a complex function, it can fail in many
# ways. For example, it fails with a TypeError on "FakeRepr" if
# gdb fails to load debug symbols. Use a catch-all "except
# Exception" to make the whole function safe. The caller has to
# handle None anyway for optimized Python.
return
None
def
current_line
(
self
):
def
current_line
(
self
):
'''Get the text of the current source line as a string, with a trailing
'''Get the text of the current source line as a string, with a trailing
newline character'''
newline character'''
if
self
.
is_optimized_out
():
if
self
.
is_optimized_out
():
return
'(frame information optimized out)'
return
'(frame information optimized out)'
lineno
=
self
.
current_line_num
()
if
lineno
is
None
:
return
'(failed to get frame line number)'
filename
=
self
.
filename
()
filename
=
self
.
filename
()
try
:
try
:
f
=
open
(
os_fsencode
(
filename
),
'r'
)
with
open
(
os_fsencode
(
filename
),
'r'
)
as
fp
:
lines
=
fp
.
readlines
()
except
IOError
:
except
IOError
:
return
None
return
None
with
f
:
all_lines
=
f
.
readlines
()
try
:
# Convert from 1-based current_line_num to 0-based list offset:
# Convert from 1-based current_line_num to 0-based list offset
return
all_lines
[
self
.
current_line_num
()
-
1
]
return
lines
[
lineno
-
1
]
except
IndexError
:
return
None
def
write_repr
(
self
,
out
,
visited
):
def
write_repr
(
self
,
out
,
visited
):
if
self
.
is_optimized_out
():
if
self
.
is_optimized_out
():
out
.
write
(
'(frame information optimized out)'
)
out
.
write
(
'(frame information optimized out)'
)
return
return
out
.
write
(
'Frame 0x%x, for file %s, line %i, in %s ('
lineno
=
self
.
current_line_num
()
lineno
=
str
(
lineno
)
if
lineno
is
not
None
else
"?"
out
.
write
(
'Frame 0x%x, for file %s, line %s, in %s ('
%
(
self
.
as_address
(),
%
(
self
.
as_address
(),
self
.
co_filename
.
proxyval
(
visited
),
self
.
co_filename
.
proxyval
(
visited
),
self
.
current_line_num
()
,
lineno
,
self
.
co_name
.
proxyval
(
visited
)))
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
():
...
@@ -981,9 +1002,11 @@ class PyFrameObjectPtr(PyObjectPtr):
...
@@ -981,9 +1002,11 @@ class PyFrameObjectPtr(PyObjectPtr):
sys
.
stdout
.
write
(
' (frame information optimized out)
\
n
'
)
sys
.
stdout
.
write
(
' (frame information optimized out)
\
n
'
)
return
return
visited
=
set
()
visited
=
set
()
sys
.
stdout
.
write
(
' File "%s", line %i, in %s
\
n
'
lineno
=
self
.
current_line_num
()
lineno
=
str
(
lineno
)
if
lineno
is
not
None
else
"?"
sys
.
stdout
.
write
(
' File "%s", line %s, in %s
\
n
'
%
(
self
.
co_filename
.
proxyval
(
visited
),
%
(
self
.
co_filename
.
proxyval
(
visited
),
self
.
current_line_num
()
,
lineno
,
self
.
co_name
.
proxyval
(
visited
)))
self
.
co_name
.
proxyval
(
visited
)))
class
PySetObjectPtr
(
PyObjectPtr
):
class
PySetObjectPtr
(
PyObjectPtr
):
...
@@ -1092,6 +1115,7 @@ class PyBytesObjectPtr(PyObjectPtr):
...
@@ -1092,6 +1115,7 @@ class PyBytesObjectPtr(PyObjectPtr):
out
.
write
(
quote
)
out
.
write
(
quote
)
# Added in Cython for Py2 backwards compatibility.
class
PyStringObjectPtr
(
PyBytesObjectPtr
):
class
PyStringObjectPtr
(
PyBytesObjectPtr
):
_typename
=
'PyStringObject'
_typename
=
'PyStringObject'
...
@@ -1166,7 +1190,7 @@ class PyUnicodeObjectPtr(PyObjectPtr):
...
@@ -1166,7 +1190,7 @@ class PyUnicodeObjectPtr(PyObjectPtr):
def
proxyval
(
self
,
visited
):
def
proxyval
(
self
,
visited
):
global
_is_pep393
global
_is_pep393
if
_is_pep393
is
None
:
if
_is_pep393
is
None
:
fields
=
gdb
.
lookup_type
(
'PyUnicodeObject'
).
target
().
fields
()
fields
=
gdb
.
lookup_type
(
'PyUnicodeObject'
).
fields
()
_is_pep393
=
'data'
in
[
f
.
name
for
f
in
fields
]
_is_pep393
=
'data'
in
[
f
.
name
for
f
in
fields
]
if
_is_pep393
:
if
_is_pep393
:
# Python 3.3 and newer
# Python 3.3 and newer
...
@@ -1351,13 +1375,13 @@ class wrapperobject(PyObjectPtr):
...
@@ -1351,13 +1375,13 @@ class wrapperobject(PyObjectPtr):
try
:
try
:
name
=
self
.
field
(
'descr'
)[
'd_base'
][
'name'
].
string
()
name
=
self
.
field
(
'descr'
)[
'd_base'
][
'name'
].
string
()
return
repr
(
name
)
return
repr
(
name
)
except
(
NullPyObjectPtr
,
RuntimeError
):
except
(
NullPyObjectPtr
,
RuntimeError
,
UnicodeDecodeError
):
return
'<unknown name>'
return
'<unknown name>'
def
safe_tp_name
(
self
):
def
safe_tp_name
(
self
):
try
:
try
:
return
self
.
field
(
'self'
)[
'ob_type'
][
'tp_name'
].
string
()
return
self
.
field
(
'self'
)[
'ob_type'
][
'tp_name'
].
string
()
except
(
NullPyObjectPtr
,
RuntimeError
):
except
(
NullPyObjectPtr
,
RuntimeError
,
UnicodeDecodeError
):
return
'<unknown tp_name>'
return
'<unknown tp_name>'
def
safe_self_addresss
(
self
):
def
safe_self_addresss
(
self
):
...
@@ -1435,8 +1459,8 @@ The following code should ensure that the prettyprinter is registered
...
@@ -1435,8 +1459,8 @@ The following code should ensure that the prettyprinter is registered
if the code is autoloaded by gdb when visiting libpython.so, provided
if the code is autoloaded by gdb when visiting libpython.so, provided
that this python file is installed to the same path as the library (or its
that this python file is installed to the same path as the library (or its
.debug file) plus a "-gdb.py" suffix, e.g:
.debug file) plus a "-gdb.py" suffix, e.g:
/usr/lib/libpython
3.7
.so.1.0-gdb.py
/usr/lib/libpython
2.6
.so.1.0-gdb.py
/usr/lib/debug/usr/lib/libpython
3.7
.so.1.0.debug-gdb.py
/usr/lib/debug/usr/lib/libpython
2.6
.so.1.0.debug-gdb.py
"""
"""
def
register
(
obj
):
def
register
(
obj
):
if
obj
is
None
:
if
obj
is
None
:
...
@@ -1451,7 +1475,7 @@ register (gdb.current_objfile ())
...
@@ -1451,7 +1475,7 @@ register (gdb.current_objfile ())
# Unfortunately, the exact API exposed by the gdb module varies somewhat
# Unfortunately, the exact API exposed by the gdb module varies somewhat
# from build to build
# from build to build
# See http
s
://bugs.python.org/issue8279?#msg102276
# See http://bugs.python.org/issue8279?#msg102276
class
Frame
(
object
):
class
Frame
(
object
):
'''
'''
...
@@ -1563,15 +1587,22 @@ class Frame(object):
...
@@ -1563,15 +1587,22 @@ class Frame(object):
# Use the prettyprinter for the func:
# Use the prettyprinter for the func:
func
=
frame
.
read_var
(
arg_name
)
func
=
frame
.
read_var
(
arg_name
)
return
str
(
func
)
return
str
(
func
)
except
ValueError
:
return
(
'PyCFunction invocation (unable to read %s: '
'missing debuginfos?)'
%
arg_name
)
except
RuntimeError
:
except
RuntimeError
:
return
'PyCFunction invocation (unable to read %s)'
%
arg_name
return
'PyCFunction invocation (unable to read %s)'
%
arg_name
if
caller
==
'wrapper_call'
:
if
caller
==
'wrapper_call'
:
arg_name
=
'wp'
try
:
try
:
func
=
frame
.
read_var
(
'wp'
)
func
=
frame
.
read_var
(
arg_name
)
return
str
(
func
)
return
str
(
func
)
except
ValueError
:
return
(
'<wrapper_call invocation (unable to read %s: '
'missing debuginfos?)>'
%
arg_name
)
except
RuntimeError
:
except
RuntimeError
:
return
'<wrapper_call invocation
>'
return
'<wrapper_call invocation
(unable to read %s)>'
%
arg_name
# This frame isn't worth reporting:
# This frame isn't worth reporting:
return
False
return
False
...
@@ -1730,6 +1761,9 @@ class PyList(gdb.Command):
...
@@ -1730,6 +1761,9 @@ class PyList(gdb.Command):
filename = pyop.filename()
filename = pyop.filename()
lineno = pyop.current_line_num()
lineno = pyop.current_line_num()
if lineno is None:
print('
Unable
to
read
python
frame
line
number
')
return
if start is None:
if start is None:
start = lineno - 5
start = lineno - 5
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment