gdb/python: new gdb.architecture_names function
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 15 Sep 2021 12:34:14 +0000 (13:34 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 22 Oct 2021 12:42:49 +0000 (13:42 +0100)
Add a new function to the Python API, gdb.architecture_names().  This
function returns a list containing all of the supported architecture
names within the current build of GDB.

The values returned in this list are all of the possible values that
can be returned from gdb.Architecture.name().

gdb/NEWS
gdb/doc/python.texi
gdb/python/py-arch.c
gdb/python/python-internal.h
gdb/python/python.c
gdb/testsuite/gdb.python/py-arch.exp

index bd26d2b1ec2e012ad104b406d9ee1b7eb7157ae9..d001a03145d98014867b37df0ab093c4a063ade4 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -45,6 +45,10 @@ maint show internal-warning backtrace
      event is triggered once GDB decides it is going to exit, but
      before GDB starts to clean up its internal state.
 
+  ** New function gdb.architecture_names(), which returns a list
+     containing all of the possible Architecture.name() values.  Each
+     entry is a string.
+
 *** Changes in GDB 11
 
 * The 'set disassembler-options' command now supports specifying options
index 15bf9dc3e21ae17002153adb6ac6ae3d6fe0e36f..90214f24238c989c8ab343b974d09d0fb987ea31 100644 (file)
@@ -557,6 +557,14 @@ such as those used by readline for command input, and annotation
 related prompts are prohibited from being changed.
 @end defun
 
+@defun gdb.architecture_names ()
+Return a list containing all of the architecture names that the
+current build of @value{GDBN} supports.  Each architecture name is a
+string.  The names returned in this list are the same names as are
+returned from @code{gdb.Architecture.name}
+(@pxref{gdbpy_architecture_name,,Architecture.name}).
+@end defun
+
 @node Exception Handling
 @subsubsection Exception Handling
 @cindex python exceptions
@@ -5834,6 +5842,7 @@ by an instance of the @code{gdb.Architecture} class.
 
 A @code{gdb.Architecture} class has the following methods:
 
+@anchor{gdbpy_architecture_name}
 @defun Architecture.name ()
 Return the name (string value) of the architecture.
 @end defun
index 66f2d28b94a5d5bfb28dd2fb006b207f53014891..3e7970ab76428d6f9f0b0874c9d0961460f14e95 100644 (file)
@@ -271,6 +271,29 @@ archpy_register_groups (PyObject *self, PyObject *args)
   return gdbpy_new_reggroup_iterator (gdbarch);
 }
 
+/* Implementation of gdb.architecture_names().  Return a list of all the
+   BFD architecture names that GDB understands.  */
+
+PyObject *
+gdbpy_all_architecture_names (PyObject *self, PyObject *args)
+{
+  gdbpy_ref<> list (PyList_New (0));
+  if (list == nullptr)
+    return nullptr;
+
+  std::vector<const char *> name_list = gdbarch_printable_names ();
+  for (const char *name : name_list)
+    {
+      gdbpy_ref <> py_name (PyString_FromString (name));
+      if (py_name == nullptr)
+       return nullptr;
+      if (PyList_Append (list.get (), py_name.get ()) < 0)
+       return nullptr;
+    }
+
+ return list.release ();
+}
+
 void _initialize_py_arch ();
 void
 _initialize_py_arch ()
index 022d4a67172c295db3cfbf001b7aa9f095b79ddd..2ad3bc944a76e578665cadc048c597fd7c617a66 100644 (file)
@@ -469,6 +469,7 @@ PyObject *objfpy_get_xmethods (PyObject *, void *);
 PyObject *gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw);
 
 PyObject *gdbarch_to_arch_object (struct gdbarch *gdbarch);
+PyObject *gdbpy_all_architecture_names (PyObject *self, PyObject *args);
 
 PyObject *gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch,
                                                  const char *group_name);
index 44ec4b7094cdada6c10a9af20a6c4ffdcf72736d..5b1c295fff62960c9087a4cd9581336ae8db8e6d 100644 (file)
@@ -2324,6 +2324,10 @@ Set the value of the convenience variable $NAME." },
 Register a TUI window constructor." },
 #endif /* TUI */
 
+  { "architecture_names", gdbpy_all_architecture_names, METH_NOARGS,
+    "architecture_names () -> List.\n\
+Return a list of all the architecture names GDB understands." },
+
   {NULL, NULL, 0, NULL}
 };
 
index 4f971127197ec7bc25141be0530cdc9c129ae8de..415fbd475b06eb8b313a87c38c7ad660a27bb857 100644 (file)
@@ -62,3 +62,54 @@ if { ![is_address_zero_readable] } {
     gdb_test "python arch.disassemble(0, 0)" ".*gdb\.MemoryError.*" \
        "test bad memory access"
 }
+
+# Test for gdb.architecture_names().  First we're going to grab the
+# complete list of architecture names using the 'complete' command.
+set arch_names []
+gdb_test_no_output "set max-completions unlimited"
+gdb_test_multiple "complete set architecture " "" {
+    -re "complete set architecture\[^\r\n\]+\r\n" {
+       exp_continue
+    }
+    -re "^set architecture \(\[^\r\n\]+\)\r\n" {
+       set arch $expect_out(1,string)
+       if { "$arch" != "auto" } {
+           set arch_names [lappend arch_names $arch]
+       }
+       exp_continue
+    }
+    -re "^$gdb_prompt $" {
+       gdb_assert { [llength $arch_names] > 0 }
+    }
+}
+
+# Now find all of the architecture names using Python.
+set py_arch_names []
+gdb_test_no_output "python all_arch = gdb.architecture_names()"
+gdb_test_no_output "python all_arch.sort()"
+gdb_test_multiple "python print(\"\\n\".join((\"Arch: %s\" % a) for a in all_arch))" "" {
+    -re "python \[^\r\n\]+\r\n" {
+       exp_continue
+    }
+    -re "^Arch: \(\[^\r\n\]+\)\r\n" {
+       set arch $expect_out(1,string)
+       set py_arch_names [lappend py_arch_names $arch]
+       exp_continue
+    }
+    -re "$gdb_prompt $" {
+       gdb_assert { [llength $py_arch_names] > 0 }
+    }
+}
+
+# Check the two lists of architecture names are the same length, and
+# that the list contents all match.
+gdb_assert { [llength $arch_names] == [llength $py_arch_names] }
+set lists_match true
+foreach a $arch_names b $py_arch_names {
+    if { $a != $b } {
+       set lists_match false
+       verbose -log "Mismatch is architecture list '$a' != '$b'"
+       break
+    }
+}
+gdb_assert { $lists_match }