Add gdb.Architecture.integer_type Python function
authorTom Tromey <tromey@adacore.com>
Fri, 22 Oct 2021 16:49:19 +0000 (10:49 -0600)
committerTom Tromey <tromey@adacore.com>
Fri, 29 Oct 2021 13:52:31 +0000 (07:52 -0600)
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
gdb/doc/python.texi
gdb/python/py-arch.c
gdb/testsuite/gdb.python/py-arch.exp

index c1e4dd07e68aca4b539645078ef5af03e0386861..9e950d2f80d645ea532a920441a140ffacbdb5bf 100644 (file)
--- 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.
index 90214f24238c989c8ab343b974d09d0fb987ea31..9a768133f4c150f452cf58ca95b0cbf8bd1c46ea 100644 (file)
@@ -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
index 3e7970ab76428d6f9f0b0874c9d0961460f14e95..aa9a652ef2652fb733a7bd9f1ec33ae4b727f0f4 100644 (file)
@@ -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\
index 415fbd475b06eb8b313a87c38c7ad660a27bb857..f3bf01d28284414c4af0bc124e17a9080cfdd9e9 100644 (file)
@@ -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 []