Back to index

python3.2  3.2.2
Public Member Functions | Public Attributes | Static Private Attributes
libpython.PyUnicodeObjectPtr Class Reference
Inheritance diagram for libpython.PyUnicodeObjectPtr:
Inheritance graph
[legend]
Collaboration diagram for libpython.PyUnicodeObjectPtr:
Collaboration graph
[legend]

List of all members.

Public Member Functions

def char_width
def proxyval
def write_repr
def field
def pyop_field
def write_field_repr
def get_truncated_repr
def type
def is_null
def is_optimized_out
def safe_tp_name
def subclass_from_type
def from_pyobject_ptr
def get_gdb_type
def as_address

Public Attributes

 tp_name
 address
_PyObject_HEAD_EXTRA Py_ssize_t ob_refcnt
struct _typeobjectob_type

Static Private Attributes

string _typename = 'PyUnicodeObject'

Detailed Description

Definition at line 1114 of file libpython.py.


Member Function Documentation

def libpython.PyObjectPtr.as_address (   self) [inherited]

Definition at line 379 of file libpython.py.

00379 
00380     def as_address(self):
00381         return long(self._gdbval)

Here is the caller graph for this function:

Definition at line 1117 of file libpython.py.

01117 
01118     def char_width(self):
01119         _type_Py_UNICODE = gdb.lookup_type('Py_UNICODE')
01120         return _type_Py_UNICODE.sizeof

Here is the caller graph for this function:

def libpython.PyObjectPtr.field (   self,
  name 
) [inherited]
Get the gdb.Value for the given field within the PyObject, coping with
some python 2 versus python 3 differences.

Various libpython types are defined using the "PyObject_HEAD" and
"PyObject_VAR_HEAD" macros.

In Python 2, this these are defined so that "ob_type" and (for a var
object) "ob_size" are fields of the type in question.

In Python 3, this is defined as an embedded PyVarObject type thus:
   PyVarObject ob_base;
so that the "ob_size" field is located insize the "ob_base" field, and
the "ob_type" is most easily accessed by casting back to a (PyObject*).

Definition at line 157 of file libpython.py.

00157 
00158     def field(self, name):
00159         '''
00160         Get the gdb.Value for the given field within the PyObject, coping with
00161         some python 2 versus python 3 differences.
00162 
00163         Various libpython types are defined using the "PyObject_HEAD" and
00164         "PyObject_VAR_HEAD" macros.
00165 
00166         In Python 2, this these are defined so that "ob_type" and (for a var
00167         object) "ob_size" are fields of the type in question.
00168 
00169         In Python 3, this is defined as an embedded PyVarObject type thus:
00170            PyVarObject ob_base;
00171         so that the "ob_size" field is located insize the "ob_base" field, and
00172         the "ob_type" is most easily accessed by casting back to a (PyObject*).
00173         '''
00174         if self.is_null():
00175             raise NullPyObjectPtr(self)
00176 
00177         if name == 'ob_type':
00178             pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type())
00179             return pyo_ptr.dereference()[name]
00180 
00181         if name == 'ob_size':
00182             pyo_ptr = self._gdbval.cast(PyVarObjectPtr.get_gdb_type())
00183             return pyo_ptr.dereference()[name]
00184 
00185         # General case: look it up inside the object:
00186         return self._gdbval.dereference()[name]

Here is the call graph for this function:

Here is the caller graph for this function:

def libpython.PyObjectPtr.from_pyobject_ptr (   cls,
  gdbval 
) [inherited]
Try to locate the appropriate derived class dynamically, and cast
the pointer accordingly.

Definition at line 360 of file libpython.py.

00360 
00361     def from_pyobject_ptr(cls, gdbval):
00362         '''
00363         Try to locate the appropriate derived class dynamically, and cast
00364         the pointer accordingly.
00365         '''
00366         try:
00367             p = PyObjectPtr(gdbval)
00368             cls = cls.subclass_from_type(p.type())
00369             return cls(gdbval, cast_to=cls.get_gdb_type())
00370         except RuntimeError:
00371             # Handle any kind of error e.g. NULL ptrs by simply using the base
00372             # class
00373             pass
00374         return cls(gdbval)

def libpython.PyObjectPtr.get_gdb_type (   cls) [inherited]

Definition at line 376 of file libpython.py.

00376 
00377     def get_gdb_type(cls):
00378         return gdb.lookup_type(cls._typename).pointer()

def libpython.PyObjectPtr.get_truncated_repr (   self,
  maxlen 
) [inherited]
Get a repr-like string for the data, but truncate it at "maxlen" bytes
(ending the object graph traversal as soon as you do)

Definition at line 202 of file libpython.py.

00202 
00203     def get_truncated_repr(self, maxlen):
00204         '''
00205         Get a repr-like string for the data, but truncate it at "maxlen" bytes
00206         (ending the object graph traversal as soon as you do)
00207         '''
00208         out = TruncatedStringIO(maxlen)
00209         try:
00210             self.write_repr(out, set())
00211         except StringTruncated:
00212             # Truncation occurred:
00213             return out.getvalue() + '...(truncated)'
00214 
00215         # No truncation occurred:
00216         return out.getvalue()

Here is the call graph for this function:

def libpython.PyObjectPtr.is_null (   self) [inherited]

Definition at line 220 of file libpython.py.

00220 
00221     def is_null(self):
00222         return 0 == long(self._gdbval)

Here is the caller graph for this function:

def libpython.PyObjectPtr.is_optimized_out (   self) [inherited]
Is the value of the underlying PyObject* visible to the debugger?

This can vary with the precise version of the compiler used to build
Python, and the precise version of gdb.

See e.g. https://bugzilla.redhat.com/show_bug.cgi?id=556975 with
PyEval_EvalFrameEx's "f"

Definition at line 223 of file libpython.py.

00223 
00224     def is_optimized_out(self):
00225         '''
00226         Is the value of the underlying PyObject* visible to the debugger?
00227 
00228         This can vary with the precise version of the compiler used to build
00229         Python, and the precise version of gdb.
00230 
00231         See e.g. https://bugzilla.redhat.com/show_bug.cgi?id=556975 with
00232         PyEval_EvalFrameEx's "f"
00233         '''
00234         return self._gdbval.is_optimized_out

Here is the caller graph for this function:

def libpython.PyUnicodeObjectPtr.proxyval (   self,
  visited 
)
Scrape a value from the inferior process, and try to represent it
within the gdb process, whilst (hopefully) avoiding crashes when
the remote data is corrupt.

Derived classes will override this.

For example, a PyIntObject* with ob_ival 42 in the inferior process
should result in an int(42) in this process.

visited: a set of all gdb.Value pyobject pointers already visited
whilst generating this value (to guard against infinite recursion when
visiting object graphs with loops).  Analogous to Py_ReprEnter and
Py_ReprLeave

Reimplemented from libpython.PyObjectPtr.

Definition at line 1121 of file libpython.py.

01121 
01122     def proxyval(self, visited):
01123         # From unicodeobject.h:
01124         #     Py_ssize_t length;  /* Length of raw Unicode data in buffer */
01125         #     Py_UNICODE *str;    /* Raw Unicode buffer */
01126         field_length = long(self.field('length'))
01127         field_str = self.field('str')
01128 
01129         # Gather a list of ints from the Py_UNICODE array; these are either
01130         # UCS-2 or UCS-4 code points:
01131         if self.char_width() > 2:
01132             Py_UNICODEs = [int(field_str[i]) for i in safe_range(field_length)]
01133         else:
01134             # A more elaborate routine if sizeof(Py_UNICODE) is 2 in the
01135             # inferior process: we must join surrogate pairs.
01136             Py_UNICODEs = []
01137             i = 0
01138             limit = safety_limit(field_length)
01139             while i < limit:
01140                 ucs = int(field_str[i])
01141                 i += 1
01142                 if ucs < 0xD800 or ucs >= 0xDC00 or i == field_length:
01143                     Py_UNICODEs.append(ucs)
01144                     continue
01145                 # This could be a surrogate pair.
01146                 ucs2 = int(field_str[i])
01147                 if ucs2 < 0xDC00 or ucs2 > 0xDFFF:
01148                     continue
01149                 code = (ucs & 0x03FF) << 10
01150                 code |= ucs2 & 0x03FF
01151                 code += 0x00010000
01152                 Py_UNICODEs.append(code)
01153                 i += 1
01154 
01155         # Convert the int code points to unicode characters, and generate a
01156         # local unicode instance.
01157         # This splits surrogate pairs if sizeof(Py_UNICODE) is 2 here (in gdb).
01158         result = u''.join([_unichr(ucs) for ucs in Py_UNICODEs])
01159         return result

Here is the call graph for this function:

def libpython.PyObjectPtr.pyop_field (   self,
  name 
) [inherited]
Get a PyObjectPtr for the given PyObject* field within this PyObject,
coping with some python 2 versus python 3 differences.

Definition at line 187 of file libpython.py.

00187 
00188     def pyop_field(self, name):
00189         '''
00190         Get a PyObjectPtr for the given PyObject* field within this PyObject,
00191         coping with some python 2 versus python 3 differences.
00192         '''
00193         return PyObjectPtr.from_pyobject_ptr(self.field(name))

Here is the call graph for this function:

Here is the caller graph for this function:

def libpython.PyObjectPtr.safe_tp_name (   self) [inherited]

Definition at line 235 of file libpython.py.

00235 
00236     def safe_tp_name(self):
00237         try:
00238             return self.type().field('tp_name').string()
00239         except NullPyObjectPtr:
00240             # NULL tp_name?
00241             return 'unknown'
00242         except RuntimeError:
00243             # Can't even read the object at all?
00244             return 'unknown'

Here is the call graph for this function:

Here is the caller graph for this function:

def libpython.PyObjectPtr.subclass_from_type (   cls,
  t 
) [inherited]
Given a PyTypeObjectPtr instance wrapping a gdb.Value that's a
(PyTypeObject*), determine the corresponding subclass of PyObjectPtr
to use

Ideally, we would look up the symbols for the global types, but that
isn't working yet:
  (gdb) python print gdb.lookup_symbol('PyList_Type')[0].value
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
  NotImplementedError: Symbol type not yet supported in Python scripts.
  Error while executing Python code.

For now, we use tp_flags, after doing some string comparisons on the
tp_name for some special-cases that don't seem to be visible through
flags

Definition at line 295 of file libpython.py.

00295 
00296     def subclass_from_type(cls, t):
00297         '''
00298         Given a PyTypeObjectPtr instance wrapping a gdb.Value that's a
00299         (PyTypeObject*), determine the corresponding subclass of PyObjectPtr
00300         to use
00301 
00302         Ideally, we would look up the symbols for the global types, but that
00303         isn't working yet:
00304           (gdb) python print gdb.lookup_symbol('PyList_Type')[0].value
00305           Traceback (most recent call last):
00306             File "<string>", line 1, in <module>
00307           NotImplementedError: Symbol type not yet supported in Python scripts.
00308           Error while executing Python code.
00309 
00310         For now, we use tp_flags, after doing some string comparisons on the
00311         tp_name for some special-cases that don't seem to be visible through
00312         flags
00313         '''
00314         try:
00315             tp_name = t.field('tp_name').string()
00316             tp_flags = int(t.field('tp_flags'))
00317         except RuntimeError:
00318             # Handle any kind of error e.g. NULL ptrs by simply using the base
00319             # class
00320             return cls
00321 
00322         #print 'tp_flags = 0x%08x' % tp_flags
00323         #print 'tp_name = %r' % tp_name
00324 
00325         name_map = {'bool': PyBoolObjectPtr,
00326                     'classobj': PyClassObjectPtr,
00327                     'instance': PyInstanceObjectPtr,
00328                     'NoneType': PyNoneStructPtr,
00329                     'frame': PyFrameObjectPtr,
00330                     'set' : PySetObjectPtr,
00331                     'frozenset' : PySetObjectPtr,
00332                     'builtin_function_or_method' : PyCFunctionObjectPtr,
00333                     }
00334         if tp_name in name_map:
00335             return name_map[tp_name]
00336 
00337         if tp_flags & Py_TPFLAGS_HEAPTYPE:
00338             return HeapTypeObjectPtr
00339 
00340         if tp_flags & Py_TPFLAGS_LONG_SUBCLASS:
00341             return PyLongObjectPtr
00342         if tp_flags & Py_TPFLAGS_LIST_SUBCLASS:
00343             return PyListObjectPtr
00344         if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS:
00345             return PyTupleObjectPtr
00346         if tp_flags & Py_TPFLAGS_BYTES_SUBCLASS:
00347             return PyBytesObjectPtr
00348         if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS:
00349             return PyUnicodeObjectPtr
00350         if tp_flags & Py_TPFLAGS_DICT_SUBCLASS:
00351             return PyDictObjectPtr
00352         if tp_flags & Py_TPFLAGS_BASE_EXC_SUBCLASS:
00353             return PyBaseExceptionObjectPtr
00354         #if tp_flags & Py_TPFLAGS_TYPE_SUBCLASS:
00355         #    return PyTypeObjectPtr
00356 
00357         # Use the base class:
00358         return cls

def libpython.PyObjectPtr.type (   self) [inherited]

Definition at line 217 of file libpython.py.

00217 
00218     def type(self):
00219         return PyTypeObjectPtr(self.field('ob_type'))

Here is the call graph for this function:

Here is the caller graph for this function:

def libpython.PyObjectPtr.write_field_repr (   self,
  name,
  out,
  visited 
) [inherited]
Extract the PyObject* field named "name", and write its representation
to file-like object "out"

Definition at line 194 of file libpython.py.

00194 
00195     def write_field_repr(self, name, out, visited):
00196         '''
00197         Extract the PyObject* field named "name", and write its representation
00198         to file-like object "out"
00199         '''
00200         field_obj = self.pyop_field(name)
00201         field_obj.write_repr(out, visited)

Here is the call graph for this function:

Here is the caller graph for this function:

def libpython.PyUnicodeObjectPtr.write_repr (   self,
  out,
  visited 
)
Write a string representation of the value scraped from the inferior
process to "out", a file-like object.

Reimplemented from libpython.PyObjectPtr.

Definition at line 1160 of file libpython.py.

01160 
01161     def write_repr(self, out, visited):
01162         # Write this out as a Python 3 str literal, i.e. without a "u" prefix
01163 
01164         # Get a PyUnicodeObject* within the Python 2 gdb process:
01165         proxy = self.proxyval(visited)
01166 
01167         # Transliteration of Python 3's Object/unicodeobject.c:unicode_repr
01168         # to Python 2:
01169         if "'" in proxy and '"' not in proxy:
01170             quote = '"'
01171         else:
01172             quote = "'"
01173         out.write(quote)
01174 
01175         i = 0
01176         while i < len(proxy):
01177             ch = proxy[i]
01178             i += 1
01179 
01180             # Escape quotes and backslashes
01181             if ch == quote or ch == '\\':
01182                 out.write('\\')
01183                 out.write(ch)
01184 
01185             #  Map special whitespace to '\t', \n', '\r'
01186             elif ch == '\t':
01187                 out.write('\\t')
01188             elif ch == '\n':
01189                 out.write('\\n')
01190             elif ch == '\r':
01191                 out.write('\\r')
01192 
01193             # Map non-printable US ASCII to '\xhh' */
01194             elif ch < ' ' or ch == 0x7F:
01195                 out.write('\\x')
01196                 out.write(hexdigits[(ord(ch) >> 4) & 0x000F])
01197                 out.write(hexdigits[ord(ch) & 0x000F])
01198 
01199             # Copy ASCII characters as-is
01200             elif ord(ch) < 0x7F:
01201                 out.write(ch)
01202 
01203             # Non-ASCII characters
01204             else:
01205                 ucs = ch
01206                 ch2 = None
01207                 if sys.maxunicode < 0x10000:
01208                     # If sizeof(Py_UNICODE) is 2 here (in gdb), join
01209                     # surrogate pairs before calling _unichr_is_printable.
01210                     if (i < len(proxy)
01211                     and 0xD800 <= ord(ch) < 0xDC00 \
01212                     and 0xDC00 <= ord(proxy[i]) <= 0xDFFF):
01213                         ch2 = proxy[i]
01214                         ucs = ch + ch2
01215                         i += 1
01216 
01217                 # Unfortuately, Python 2's unicode type doesn't seem
01218                 # to expose the "isprintable" method
01219                 printable = _unichr_is_printable(ucs)
01220                 if printable:
01221                     try:
01222                         ucs.encode(ENCODING)
01223                     except UnicodeEncodeError:
01224                         printable = False
01225 
01226                 # Map Unicode whitespace and control characters
01227                 # (categories Z* and C* except ASCII space)
01228                 if not printable:
01229                     if ch2 is not None:
01230                         # Match Python 3's representation of non-printable
01231                         # wide characters.
01232                         code = (ord(ch) & 0x03FF) << 10
01233                         code |= ord(ch2) & 0x03FF
01234                         code += 0x00010000
01235                     else:
01236                         code = ord(ucs)
01237 
01238                     # Map 8-bit characters to '\\xhh'
01239                     if code <= 0xff:
01240                         out.write('\\x')
01241                         out.write(hexdigits[(code >> 4) & 0x000F])
01242                         out.write(hexdigits[code & 0x000F])
01243                     # Map 21-bit characters to '\U00xxxxxx'
01244                     elif code >= 0x10000:
01245                         out.write('\\U')
01246                         out.write(hexdigits[(code >> 28) & 0x0000000F])
01247                         out.write(hexdigits[(code >> 24) & 0x0000000F])
01248                         out.write(hexdigits[(code >> 20) & 0x0000000F])
01249                         out.write(hexdigits[(code >> 16) & 0x0000000F])
01250                         out.write(hexdigits[(code >> 12) & 0x0000000F])
01251                         out.write(hexdigits[(code >> 8) & 0x0000000F])
01252                         out.write(hexdigits[(code >> 4) & 0x0000000F])
01253                         out.write(hexdigits[code & 0x0000000F])
01254                     # Map 16-bit characters to '\uxxxx'
01255                     else:
01256                         out.write('\\u')
01257                         out.write(hexdigits[(code >> 12) & 0x000F])
01258                         out.write(hexdigits[(code >> 8) & 0x000F])
01259                         out.write(hexdigits[(code >> 4) & 0x000F])
01260                         out.write(hexdigits[code & 0x000F])
01261                 else:
01262                     # Copy characters as-is
01263                     out.write(ch)
01264                     if ch2 is not None:
01265                         out.write(ch2)
01266 
01267         out.write(quote)
01268 
01269 
01270 

Here is the call graph for this function:


Member Data Documentation

Reimplemented from libpython.PyObjectPtr.

Definition at line 1115 of file libpython.py.

Definition at line 271 of file libpython.py.

Definition at line 107 of file object.h.

struct _typeobject* _object::ob_type [inherited]

Definition at line 108 of file object.h.

Definition at line 270 of file libpython.py.


The documentation for this class was generated from the following file: