mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 04:24:43 +00:00
Allow conversion of 128-bit integers to Python
Currently, trying to convert a 128-bit integer from a gdb.Value to a Python integer will fail. This is surprising because Python uses bigints internally. The bug here is that valpy_long uses value_as_long, which fails for anything wider than LONGEST. This patch fixes the problem by using the recommended Python API. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33366 Approved-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
@@ -1866,7 +1866,7 @@ valpy_long (PyObject *self)
|
||||
{
|
||||
struct value *value = ((value_object *) self)->value;
|
||||
struct type *type = value->type ();
|
||||
LONGEST l = 0;
|
||||
PyObject *result;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1882,17 +1882,57 @@ valpy_long (PyObject *self)
|
||||
&& type->code () != TYPE_CODE_PTR)
|
||||
error (_("Cannot convert value to long."));
|
||||
|
||||
l = value_as_long (value);
|
||||
gdb::array_view<const gdb_byte> contents = value->contents ();
|
||||
#if PY_VERSION_HEX >= 0x030d0000
|
||||
int flags = (type_byte_order (type) == BFD_ENDIAN_BIG
|
||||
? Py_ASNATIVEBYTES_BIG_ENDIAN
|
||||
: Py_ASNATIVEBYTES_LITTLE_ENDIAN);
|
||||
if (type->is_unsigned ())
|
||||
flags |= Py_ASNATIVEBYTES_UNSIGNED_BUFFER;
|
||||
result = PyLong_FromNativeBytes (contents.data (), contents.size (),
|
||||
flags);
|
||||
#else
|
||||
/* Here we construct a call to "int.from_bytes", passing in the
|
||||
appropriate arguments. We need a somewhat roundabout
|
||||
approach because int.from_bytes requires "signed" to be a
|
||||
keyword arg. */
|
||||
|
||||
/* PyObject_Call requires a tuple argument. */
|
||||
gdbpy_ref<> empty_tuple (PyTuple_New (0));
|
||||
if (empty_tuple == nullptr)
|
||||
return nullptr;
|
||||
|
||||
/* Since we need a dictionary anyway, we pass all arguments as
|
||||
keywords, building the dictionary here. */
|
||||
gdbpy_ref<> args
|
||||
(Py_BuildValue ("{sy#sssO}",
|
||||
"bytes", contents.data (),
|
||||
(Py_ssize_t) contents.size (),
|
||||
"byteorder",
|
||||
(type_byte_order (type) == BFD_ENDIAN_BIG
|
||||
? "big" : "little"),
|
||||
"signed",
|
||||
type->is_unsigned ()
|
||||
? Py_False : Py_True));
|
||||
if (args == nullptr)
|
||||
return nullptr;
|
||||
|
||||
/* Find the "int.from_bytes" callable. */
|
||||
gdbpy_ref<> callable (PyObject_GetAttrString ((PyObject *) &PyLong_Type,
|
||||
"from_bytes"));
|
||||
if (callable == nullptr)
|
||||
return nullptr;
|
||||
|
||||
result = PyObject_Call (callable.get (), empty_tuple.get (),
|
||||
args.get ());
|
||||
#endif
|
||||
}
|
||||
catch (const gdb_exception &except)
|
||||
{
|
||||
return gdbpy_handle_gdb_exception (nullptr, except);
|
||||
}
|
||||
|
||||
if (type->is_unsigned ())
|
||||
return gdb_py_object_from_ulongest (l).release ();
|
||||
else
|
||||
return gdb_py_object_from_longest (l).release ();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Implements conversion to float. */
|
||||
|
||||
@@ -844,3 +844,15 @@ if {[allow_cplus_tests]} {
|
||||
test_subscript_regression "${binfile}-cxx" "c++"
|
||||
}
|
||||
}
|
||||
|
||||
if {[allow_rust_tests]} {
|
||||
gdb_test "set lang rust"
|
||||
|
||||
set cst 0x80000000000000000000000000000000
|
||||
gdb_test "python print(int(gdb.parse_and_eval('${cst}u128')))" \
|
||||
"170141183460469231731687303715884105728" \
|
||||
"convert 128 bit unsigned constant to python int"
|
||||
gdb_test "python print(int(gdb.parse_and_eval('${cst}i128')))" \
|
||||
"-170141183460469231731687303715884105728" \
|
||||
"convert 128 bit signed constant to python int"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user