diff options
Diffstat (limited to 'Tools/gdb/libpython.py')
-rwxr-xr-x | Tools/gdb/libpython.py | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index 75f1ccb..e4d2c1e 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -44,7 +44,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 # compatible (2.6+ and 3.0+). See #19308. -from __future__ import print_function, with_statement +from __future__ import print_function import gdb import os import locale @@ -666,8 +666,9 @@ class PyDictObjectPtr(PyObjectPtr): ''' keys = self.field('ma_keys') values = self.field('ma_values') - for i in safe_range(keys['dk_size']): - ep = keys['dk_entries'].address + i + entries, nentries = self._get_entries(keys) + for i in safe_range(nentries): + ep = entries[i] if long(values): pyop_value = PyObjectPtr.from_pyobject_ptr(values[i]) else: @@ -707,6 +708,33 @@ class PyDictObjectPtr(PyObjectPtr): pyop_value.write_repr(out, visited) out.write('}') + def _get_entries(self, keys): + dk_nentries = int(keys['dk_nentries']) + dk_size = int(keys['dk_size']) + try: + # <= Python 3.5 + return keys['dk_entries'], dk_size + except gdb.error: + # >= Python 3.6 + pass + + if dk_size <= 0xFF: + offset = dk_size + elif dk_size <= 0xFFFF: + offset = 2 * dk_size + elif dk_size <= 0xFFFFFFFF: + offset = 4 * dk_size + else: + offset = 8 * dk_size + + ent_addr = keys['dk_indices']['as_1'].address + ent_addr = ent_addr.cast(_type_unsigned_char_ptr()) + offset + ent_ptr_t = gdb.lookup_type('PyDictKeyEntry').pointer() + ent_addr = ent_addr.cast(ent_ptr_t) + + return ent_addr, dk_nentries + + class PyListObjectPtr(PyObjectPtr): _typename = 'PyListObject' |