From d3771fe234b74d60cfa553940bce9d047bd38e8d Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 22 Oct 2021 10:49:19 -0600 Subject: [PATCH] Add gdb.Architecture.integer_type Python function This adds a new Python function, gdb.Architecture.integer_type, which can be used to look up an integer type of a given size and signed-ness. This is useful to avoid dependency on debuginfo when a particular integer type would be useful. v2 moves this to be a method on gdb.Architecture and addresses other review comments. --- gdb/NEWS | 3 ++ gdb/doc/python.texi | 18 ++++++++++ gdb/python/py-arch.c | 54 ++++++++++++++++++++++++++++ gdb/testsuite/gdb.python/py-arch.exp | 14 ++++++++ 4 files changed, 89 insertions(+) diff --git a/gdb/NEWS b/gdb/NEWS index c1e4dd07e68..9e950d2f80d 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -49,6 +49,9 @@ maint show internal-warning backtrace containing all of the possible Architecture.name() values. Each entry is a string. + ** New function gdb.Architecture.integer_type(), which returns an + integer type given a size and a signed-ness. + * New features in the GDB remote stub, GDBserver ** GDBserver is now supported on OpenRISC GNU/Linux. diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 90214f24238..9a768133f4c 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -1125,6 +1125,9 @@ Ordinarily, this function will return an instance of @code{gdb.Type}. If the named type cannot be found, it will throw an exception. @end defun +Integer types can be found without looking them up by name. +@xref{Architectures In Python}, for the @code{integer_type} method. + If the type is a structure or class type, or an enum type, the fields of that type can be accessed using the Python @dfn{dictionary syntax}. For example, if @code{some_type} is a @code{gdb.Type} instance holding @@ -5883,6 +5886,21 @@ instruction in bytes. @end table @end defun +@findex Architecture.integer_type +@defun Architecture.integer_type (size @r{[}, signed@r{]}) +This function looks up an integer type by its @var{size}, and +optionally whether or not it is signed. + +@var{size} is the size, in bits, of the desired integer type. Only +certain sizes are currently supported: 0, 8, 16, 24, 32, 64, and 128. + +If @var{signed} is not specified, it defaults to @code{True}. If +@var{signed} is @code{False}, the returned type will be unsigned. + +If the indicated type cannot be found, this function will throw a +@code{ValueError} exception. +@end defun + @anchor{gdbpy_architecture_registers} @defun Architecture.registers (@r{[} @var{reggroup} @r{]}) Return a @code{gdb.RegisterDescriptorIterator} (@pxref{Registers In diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c index 3e7970ab764..aa9a652ef26 100644 --- a/gdb/python/py-arch.c +++ b/gdb/python/py-arch.c @@ -271,6 +271,55 @@ archpy_register_groups (PyObject *self, PyObject *args) return gdbpy_new_reggroup_iterator (gdbarch); } +/* Implementation of gdb.integer_type. */ +static PyObject * +archpy_integer_type (PyObject *self, PyObject *args, PyObject *kw) +{ + static const char *keywords[] = { "size", "signed", NULL }; + int size, is_signed = 1; + + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "i|p", keywords, + &size, &is_signed)) + return nullptr; + + struct gdbarch *gdbarch; + ARCHPY_REQUIRE_VALID (self, gdbarch); + + const struct builtin_type *builtins = builtin_type (gdbarch); + struct type *type = nullptr; + switch (size) + { + case 0: + type = builtins->builtin_int0; + break; + case 8: + type = is_signed ? builtins->builtin_int8 : builtins->builtin_uint8; + break; + case 16: + type = is_signed ? builtins->builtin_int16 : builtins->builtin_uint16; + break; + case 24: + type = is_signed ? builtins->builtin_int24 : builtins->builtin_uint24; + break; + case 32: + type = is_signed ? builtins->builtin_int32 : builtins->builtin_uint32; + break; + case 64: + type = is_signed ? builtins->builtin_int64 : builtins->builtin_uint64; + break; + case 128: + type = is_signed ? builtins->builtin_int128 : builtins->builtin_uint128; + break; + + default: + PyErr_SetString (PyExc_ValueError, + _("no integer type of that size is available")); + return nullptr; + } + + return type_to_type_object (type); +} + /* Implementation of gdb.architecture_names(). Return a list of all the BFD architecture names that GDB understands. */ @@ -323,6 +372,11 @@ Return the name of the architecture as a string value." }, "disassemble (start_pc [, end_pc [, count]]) -> List.\n\ Return a list of at most COUNT disassembled instructions from START_PC to\n\ END_PC." }, + { "integer_type", (PyCFunction) archpy_integer_type, + METH_VARARGS | METH_KEYWORDS, + "integer_type (size [, signed]) -> type\n\ +Return an integer Type corresponding to the given bitsize and signed-ness.\n\ +If not specified, the type defaults to signed." }, { "registers", (PyCFunction) archpy_registers, METH_VARARGS | METH_KEYWORDS, "registers ([ group-name ]) -> Iterator.\n\ diff --git a/gdb/testsuite/gdb.python/py-arch.exp b/gdb/testsuite/gdb.python/py-arch.exp index 415fbd475b0..f3bf01d2828 100644 --- a/gdb/testsuite/gdb.python/py-arch.exp +++ b/gdb/testsuite/gdb.python/py-arch.exp @@ -63,6 +63,20 @@ if { ![is_address_zero_readable] } { "test bad memory access" } +foreach size {0 1 2 3 4 8 16} { + foreach sign {"" ", True" ", False"} { + set fullsize [expr 8 * $size] + gdb_test_no_output "python t = arch.integer_type($fullsize$sign)" \ + "get integer type for $size$sign" + gdb_test "python print(t.sizeof)" "$size" \ + "print size of integer type for $size$sign" + } +} + +gdb_test "python arch.integer_type(95)" \ + ".*ValueError: no integer type of that size is available.*" \ + "call integer_type with invalid size" + # Test for gdb.architecture_names(). First we're going to grab the # complete list of architecture names using the 'complete' command. set arch_names [] -- 2.30.2