gdb/fortran: Add new 'info modules' command
authorAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 9 Jul 2019 20:38:59 +0000 (21:38 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 31 Oct 2019 23:02:59 +0000 (23:02 +0000)
Add a new command 'info modules' that lists all of the modules GDB
knows about from the debug information.

A module is a debugging entity in the DWARF defined with
DW_TAG_module, currently Fortran is known to use this tag for its
modules.  I'm not aware of any other language that currently makes use
of DW_TAG_module.

The output style is similar to the 'info type' output:

    (gdb) info modules
    All defined modules:

    File info-types.f90:
    16:     mod1
    24:     mod2
    (gdb)

Where the user is told the file the module is defined in and, on the
left hand side, the line number at which the module is defined along
with the name of the module.

This patch is a new implementation of an idea originally worked on by
Mark O'Connor, Chris January, David Lecomber, and Xavier Oro from ARM.

gdb/ChangeLog:

* dwarf2read.c (dw2_symtab_iter_next): Handle MODULE_DOMAIN.
(dw2_expand_marked_cus): Handle MODULES_DOMAIN.
(dw2_debug_names_iterator::next): Handle MODULE_DOMAIN and
MODULES_DOMAIN.
(scan_partial_symbols): Only create partial module symbols for non
declarations.
* psymtab.c (recursively_search_psymtabs): Handle MODULE_DOMAIN
and MODULES_DOMAIN.
* symtab.c (search_domain_name): Likewise.
(search_symbols): Likewise.
(print_symbol_info): Likewise.
(symtab_symbol_info): Likewise.
(info_modules_command): New function.
(_initialize_symtab): Register 'info modules' command.
* symtab.h (enum search_domain): Add MODULES_DOMAIN.
* NEWS: Mention new 'info modules' command.

gdb/doc/ChangeLog:

* gdb.texinfo (Symbols): Document new 'info modules' command.

gdb/testsuite/ChangeLog:

* gdb.fortran/info-modules.exp: New file.
* gdb.fortran/info-types.exp: Build with new file.
* gdb.fortran/info-types.f90: Include and use new module.
* gdb.fortran/info-types-2.f90: New file.

Change-Id: I2b781dd5a06bcad04620ccdc45f01a0f711adfad

13 files changed:
gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/dwarf2read.c
gdb/psymtab.c
gdb/symtab.c
gdb/symtab.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.fortran/info-modules.exp [new file with mode: 0644]
gdb/testsuite/gdb.fortran/info-types-2.f90 [new file with mode: 0644]
gdb/testsuite/gdb.fortran/info-types.exp
gdb/testsuite/gdb.fortran/info-types.f90

index 9c97b824cc3d15264aed1c581154d57a6be65525..6dca96555ad3cdcb3a9c29c264420469fe440de8 100644 (file)
@@ -1,3 +1,22 @@
+2019-10-31  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * dwarf2read.c (dw2_symtab_iter_next): Handle MODULE_DOMAIN.
+       (dw2_expand_marked_cus): Handle MODULES_DOMAIN.
+       (dw2_debug_names_iterator::next): Handle MODULE_DOMAIN and
+       MODULES_DOMAIN.
+       (scan_partial_symbols): Only create partial module symbols for non
+       declarations.
+       * psymtab.c (recursively_search_psymtabs): Handle MODULE_DOMAIN
+       and MODULES_DOMAIN.
+       * symtab.c (search_domain_name): Likewise.
+       (search_symbols): Likewise.
+       (print_symbol_info): Likewise.
+       (symtab_symbol_info): Likewise.
+       (info_modules_command): New function.
+       (_initialize_symtab): Register 'info modules' command.
+       * symtab.h (enum search_domain): Add MODULES_DOMAIN.
+       * NEWS: Mention new 'info modules' command.
+
 2019-10-31  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
 
        * NEWS: Mention $_gdb_setting, $_gdb_setting_str, $_gdb_maint_setting
index ef21b5d97e0a901095dd698d916719efaf0ec83c..d46f7094d406729654a37e300ee82232d41d66b4 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -159,6 +159,10 @@ show print frame-info
   'frame', 'stepi'.  The python frame filtering also respect this setting.
   The 'backtrace' '-frame-info' option can override this global setting.
 
+info modules [-q] [REGEXP]
+  Return a list of Fortran modules matching REGEXP, or all modules if
+  no REGEXP is given.
+
 * Changed commands
 
 help
index 4d3f7558211e7f827035a16cfc6d1f420709c7b1..52497a17725f6c8beff74449a68d0e3d104ac208 100644 (file)
@@ -1,3 +1,7 @@
+2019-10-31  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.texinfo (Symbols): Document new 'info modules' command.
+
 2019-10-31  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
 
        * gdb.texinfo (Convenience Funs): Document the new
index 7cf4141d206fb574166eeb04ffb76f3767f6ae03..ee06df2bb2c7b45966086888756b92af93d42c1f 100644 (file)
@@ -18886,6 +18886,16 @@ If both @var{regexp} and @var{type_regexp} are provided, an argument
 is printed only if its name matches @var{regexp} and its type matches
 @var{type_regexp}.
 
+@kindex info modules
+@cindex modules
+@item info modules @r{[}-q@r{]} @r{[}@var{regexp}@r{]}
+List all Fortran modules in the program, or all modules matching the
+optional regular expression @var{regexp}.
+
+The optional flag @samp{-q}, which stands for @samp{quiet}, disables
+printing header information and messages explaining why no modules
+have been printed.
+
 @kindex info classes
 @cindex Objective-C, classes and selectors
 @item info classes
index cac719a9c6a662588a1f4cf59cb15e2e7e1c08d4..0a7a0334202429c70328763b83ef9323f4c45ea9 100644 (file)
@@ -4042,6 +4042,10 @@ dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
              if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
                continue;
              break;
+           case MODULE_DOMAIN:
+             if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
+               continue;
+             break;
            default:
              break;
            }
@@ -5064,6 +5068,10 @@ dw2_expand_marked_cus
              if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
                continue;
              break;
+           case MODULES_DOMAIN:
+             if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
+               continue;
+             break;
            default:
              break;
            }
@@ -5970,6 +5978,15 @@ dw2_debug_names_iterator::next ()
          goto again;
        }
       break;
+    case MODULE_DOMAIN:
+      switch (indexval.dwarf_tag)
+       {
+       case DW_TAG_module:
+         break;
+       default:
+         goto again;
+       }
+      break;
     default:
       break;
     }
@@ -6006,6 +6023,14 @@ dw2_debug_names_iterator::next ()
          goto again;
        }
       break;
+    case MODULES_DOMAIN:
+      switch (indexval.dwarf_tag)
+       {
+       case DW_TAG_module:
+         break;
+       default:
+         goto again;
+       }
     default:
       break;
     }
@@ -8733,7 +8758,8 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
              add_partial_namespace (pdi, lowpc, highpc, set_addrmap, cu);
              break;
            case DW_TAG_module:
-             add_partial_module (pdi, lowpc, highpc, set_addrmap, cu);
+             if (!pdi->is_declaration)
+               add_partial_module (pdi, lowpc, highpc, set_addrmap, cu);
              break;
            case DW_TAG_imported_unit:
              {
index b30d29e6efa836472b3ba19ea90af0d6d43880fb..df10a756fd180b56278b8cf10af726d90635215f 100644 (file)
@@ -1272,6 +1272,8 @@ recursively_search_psymtabs
          QUIT;
 
          if ((domain == ALL_DOMAIN
+              || (domain == MODULES_DOMAIN
+                  && (*psym)->domain == MODULE_DOMAIN)
               || (domain == VARIABLES_DOMAIN
                   && (*psym)->aclass != LOC_TYPEDEF
                   && (*psym)->aclass != LOC_BLOCK)
index 060e676bbb60ac3a1a099be6a9070fb4635ee529..4c14edae177668c41a159a97dbd1629136774214 100644 (file)
@@ -299,6 +299,7 @@ search_domain_name (enum search_domain e)
     case VARIABLES_DOMAIN: return "VARIABLES_DOMAIN";
     case FUNCTIONS_DOMAIN: return "FUNCTIONS_DOMAIN";
     case TYPES_DOMAIN: return "TYPES_DOMAIN";
+    case MODULES_DOMAIN: return "MODULES_DOMAIN";
     case ALL_DOMAIN: return "ALL_DOMAIN";
     default: gdb_assert_not_reached ("bad search_domain");
     }
@@ -4482,7 +4483,7 @@ search_symbols (const char *regexp, enum search_domain kind,
   gdb::optional<compiled_regex> preg;
   gdb::optional<compiled_regex> treg;
 
-  gdb_assert (kind <= TYPES_DOMAIN);
+  gdb_assert (kind != ALL_DOMAIN);
 
   ourtype = types[kind];
   ourtype2 = types2[kind];
@@ -4656,7 +4657,10 @@ search_symbols (const char *regexp, enum search_domain kind,
                                                                     sym)))
                              || (kind == TYPES_DOMAIN
                                  && SYMBOL_CLASS (sym) == LOC_TYPEDEF
-                                 && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN))))
+                                 && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN)
+                             || (kind == MODULES_DOMAIN
+                                 && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN
+                                 && SYMBOL_LINE (sym) != 0))))
                    {
                      /* match */
                      result.emplace_back (i, sym);
@@ -4787,6 +4791,11 @@ print_symbol_info (enum search_domain kind,
 
       printf_filtered (";\n");
     }
+  /* Printing of modules is currently done here, maybe at some future
+     point we might want a language specific method to print the module
+     symbol so that we can customise the output more.  */
+  else if (kind == MODULES_DOMAIN)
+    printf_filtered ("%s\n", SYMBOL_PRINT_NAME (sym));
 }
 
 /* This help function for symtab_symbol_info() prints information
@@ -4827,11 +4836,11 @@ symtab_symbol_info (bool quiet, bool exclude_minsyms,
                    const char *t_regexp, int from_tty)
 {
   static const char * const classnames[] =
-    {"variable", "function", "type"};
+    {"variable", "function", "type", "module"};
   const char *last_filename = "";
   int first = 1;
 
-  gdb_assert (kind <= TYPES_DOMAIN);
+  gdb_assert (kind != ALL_DOMAIN);
 
   if (regexp != nullptr && *regexp == '\0')
     regexp = nullptr;
@@ -5050,6 +5059,22 @@ info_types_command_completer (struct cmd_list_element *ignore,
   symbol_completer (ignore, tracker, text, word);
 }
 
+/* Implement the 'info modules' command.  */
+
+static void
+info_modules_command (const char *args, int from_tty)
+{
+  info_types_options opts;
+
+  auto grp = make_info_types_options_def_group (&opts);
+  gdb::option::process_options
+    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
+  if (args != nullptr && *args == '\0')
+    args = nullptr;
+  symtab_symbol_info (opts.quiet, true, args, MODULES_DOMAIN, NULL,
+                     from_tty);
+}
+
 /* Breakpoint all functions matching regular expression.  */
 
 void
@@ -6373,6 +6398,10 @@ Options:\n\
   c = add_info ("sources", info_sources_command, info_sources_help.c_str ());
   set_cmd_completer_handle_brkchars (c, info_sources_command_completer);
 
+  c = add_info ("modules", info_modules_command,
+               _("All module names, or those matching REGEXP."));
+  set_cmd_completer_handle_brkchars (c, info_types_command_completer);
+
   add_com ("rbreak", class_breakpoint, rbreak_command,
           _("Set a breakpoint for all functions matching REGEXP."));
 
index 20c11d16cf84b16e517e3ccf4b990d5985169a6a..72d1c7ff84854b3ae3486a3626bc1259b810dd09 100644 (file)
@@ -831,8 +831,11 @@ enum search_domain
   /* All defined types */
   TYPES_DOMAIN = 2,
 
+  /* All modules.  */
+  MODULES_DOMAIN = 3,
+
   /* Any type.  */
-  ALL_DOMAIN = 3
+  ALL_DOMAIN = 4
 };
 
 extern const char *search_domain_name (enum search_domain);
index 510a1e01385ac34decaed01602afda8a224fa9b1..6514c0764dc85f534b48c9f73fb9623d757e6157 100644 (file)
@@ -1,3 +1,10 @@
+2019-10-31  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.fortran/info-modules.exp: New file.
+       * gdb.fortran/info-types.exp: Build with new file.
+       * gdb.fortran/info-types.f90: Include and use new module.
+       * gdb.fortran/info-types-2.f90: New file.
+
 2019-10-31  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
 
        * gdb.base/setshow.exp: Test $_gdb_setting and $_gdb_setting_str.
diff --git a/gdb/testsuite/gdb.fortran/info-modules.exp b/gdb/testsuite/gdb.fortran/info-modules.exp
new file mode 100644 (file)
index 0000000..f961d28
--- /dev/null
@@ -0,0 +1,66 @@
+# Copyright 2019 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file tests 'info modules'.
+
+load_lib "fortran.exp"
+
+if { [skip_fortran_tests] } { continue }
+
+standard_testfile info-types.f90 info-types-2.f90
+
+if { [prepare_for_testing "failed to prepare" $testfile \
+         [list $srcfile $srcfile2] {debug f90}] } {
+    return -1
+}
+
+if { ![runto MAIN__] } {
+    perror "Could not run to breakpoint `MAIN__'."
+    continue
+}
+
+gdb_test "info modules" \
+    [multi_line \
+        "All defined modules:" \
+        "" \
+        "File .*${srcfile2}:" \
+        "18:\[\t \]+mod2" \
+        "" \
+        "File .*${srcfile}:" \
+        "16:\[\t \]+mod1" ]
+
+gdb_test "info modules 1" \
+    [multi_line \
+        "All modules matching regular expression \"1\":" \
+        "" \
+        "File .*${srcfile}:" \
+        "16:\[\t \]+mod1" ]
+
+gdb_test "info modules 2" \
+    [multi_line \
+        "All modules matching regular expression \"2\":" \
+        "" \
+        "File .*${srcfile2}:" \
+        "18:\[\t \]+mod2" ]
+
+gdb_test "info modules mod" \
+    [multi_line \
+        "All modules matching regular expression \"mod\":" \
+        "" \
+        "File .*${srcfile2}:" \
+        "18:\[\t \]+mod2" \
+        "" \
+        "File .*${srcfile}:" \
+        "16:\[\t \]+mod1" ]
diff --git a/gdb/testsuite/gdb.fortran/info-types-2.f90 b/gdb/testsuite/gdb.fortran/info-types-2.f90
new file mode 100644 (file)
index 0000000..a404418
--- /dev/null
@@ -0,0 +1,20 @@
+! Copyright 2019 Free Software Foundation, Inc.
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or
+! (at your option) any later version.
+!
+! This program is distributed in the hope that it will be useful,
+! but WITHOUT ANY WARRANTY; without even the implied warranty of
+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+! GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License
+! along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+! Comment just to change the line number on which
+! mod2 is defined.
+module mod2
+  integer :: mod2_var_1 = 123
+end module mod2
index 30646287ee968ef6edf90f3d4fdd8b61bb6cea19..954e083e4069efaaf8293d7269cc999880c4f982 100644 (file)
@@ -19,9 +19,10 @@ load_lib "fortran.exp"
 
 if { [skip_fortran_tests] } { continue }
 
-standard_testfile .f90
+standard_testfile info-types.f90 info-types-2.f90
 
-if { [prepare_for_testing "failed to prepare" $testfile $srcfile {debug f90}] } {
+if { [prepare_for_testing "failed to prepare" $testfile \
+         [list $srcfile2 $srcfile] {debug f90}] } {
     return -1
 }
 
index 0e27e1ddf088f16919b6ffde3848c0fe6983ba06..ec52ef98efc9973ff3d03b60390bc9e355587200 100644 (file)
@@ -21,6 +21,7 @@ end module mod1
 
 program info_types_test
   use mod1
+  use mod2
 
   type :: s1
      integer :: a
@@ -30,7 +31,7 @@ program info_types_test
   type (s1) :: var_a
   type (m1t1) :: var_b
 
-  var_a%a = 1
+  var_a%a = 1 + mod2_var_1
   var_b%b = 2
   l = .FALSE.
 end program info_types_test