Debugger: Retrieve and remember int from native GDB value

When adding expressions for bitfield members in the
debugger's expression view, their corresponding 'gdb.Value'
does not expose the fact that those are actually bitfields,
so e.g. an 'int : 3' is exposed like a "normal" 'int'.

Previously, this would result in wrong values being
retrieved in the 'DumperBase::Value::integer()' function,
when trying to read the value from the corresponding
memory address.

To avoid this, retrieve the actual int representation
for numeric values from the corresponding native 'gdb.Value',
remember them and return that one, similar to how it
is already done for known bitfield members
(s. 'Dumper::memberFromNativeFieldAndValue').

The conversion from the 'gdb.Value' does not work
for integers of a size larger than 64 bits
(like '__int128' used in the "Int128" dumper test).
Therefore, just ignore conversion failures and don't
remember any value explicitly for those cases,
so the same handling as previously used is applied.
(At a quick glance, the reason seems to be that this
is because GDB's corresponding functions use 'int64'
as a return value of the relevant functions [1] [2],
but I did not look closer into what GDB does
internally.)

Corresponding tests will be added in a separate commit.

[1] https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdbsupport/common-types.h;h=f5b2f3d249177acea77231c21c5601f959c18d2f;hb=f3034e25fa98d44b775970f40c9ec85eeae096e6#l33
[2] https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/python/py-value.c;h=6e29284aad11ff344789152a4f601b3474d86bb5;hb=f3034e25fa98d44b775970f40c9ec85eeae096e6#l1706

Fixes: QTCREATORBUG-24693
Change-Id: Idfc3390115e8796f3c778070c23424c3dbdfeddd
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Michael Weghorn
2020-09-24 12:02:06 +02:00
parent 4327ddf6c5
commit d86cf5e235
2 changed files with 9 additions and 1 deletions

View File

@@ -2851,6 +2851,7 @@ class DumperBase():
self.type = None self.type = None
self.ldata = None # Target address in case of references and pointers. self.ldata = None # Target address in case of references and pointers.
self.laddress = None # Own address. self.laddress = None # Own address.
self.lvalue = None
self.lIsInScope = True self.lIsInScope = True
self.ldisplay = None self.ldisplay = None
self.summary = None # Always hexencoded UTF-8. self.summary = None # Always hexencoded UTF-8.
@@ -2924,7 +2925,7 @@ class DumperBase():
def integer(self, bitsize=None): def integer(self, bitsize=None):
if self.type.code == TypeCode.Typedef: if self.type.code == TypeCode.Typedef:
return self.detypedef().integer() return self.detypedef().integer()
elif self.type.code == TypeCode.Bitfield: elif isinstance(self.lvalue, int):
return self.lvalue return self.lvalue
# Could be something like 'short unsigned int' # Could be something like 'short unsigned int'
unsigned = self.type.name == 'unsigned' \ unsigned = self.type.name == 'unsigned' \

View File

@@ -307,6 +307,13 @@ class Dumper(DumperBase):
val.ldisplay += ' (%s)' % intval val.ldisplay += ' (%s)' % intval
elif code == gdb.TYPE_CODE_COMPLEX: elif code == gdb.TYPE_CODE_COMPLEX:
val.ldisplay = str(nativeValue) val.ldisplay = str(nativeValue)
elif code in [gdb.TYPE_CODE_BOOL, gdb.TYPE_CODE_INT]:
try:
# extract int presentation from native value and remember it
val.lvalue = int(nativeValue)
except:
# GDB only support converting integers of max. 64 bits to Python int as of now
pass
#elif code == gdb.TYPE_CODE_ARRAY: #elif code == gdb.TYPE_CODE_ARRAY:
# val.type.ltarget = nativeValue[0].type.unqualified() # val.type.ltarget = nativeValue[0].type.unqualified()
return val return val