gdb/mi: add new --group-by-objfile flag for -file-list-exec-source-files
authorAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 18 May 2021 13:18:22 +0000 (14:18 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 25 Jun 2021 19:54:29 +0000 (20:54 +0100)
This commit adds a new option '--group-by-objfile' to the MI command
-file-list-exec-source-files.  With this option the output format is
changed; instead of a single list of source files the results are now
a list of objfiles.  For each objfile all of the source files
associated with that objfile are listed.

Here is an example of the new output format taken from the
documentation (the newlines are added just for readability):

  -file-list-exec-source-files --group-by-objfile
  ^done,files=[{filename="/tmp/info-sources/test.x",
                debug-info="fully-read",
                sources=[{file="test.c",
                          fullname="/tmp/info-sources/test.c",
                          debug-fully-read="true"},
                         {file="/usr/include/stdc-predef.h",
                          fullname="/usr/include/stdc-predef.h",
                          debug-fully-read="true"},
                         {file="header.h",
                          fullname="/tmp/info-sources/header.h",
                          debug-fully-read="true"}]},
               {filename="/lib64/ld-linux-x86-64.so.2",
                debug-info="none",
                sources=[]},
               {filename="system-supplied DSO at 0x7ffff7fcf000",
                debug-info="none",
                sources=[]},
               {filename="/tmp/info-sources/libhelper.so",
                debug-info="fully-read",
                sources=[{file="helper.c",
                          fullname="/tmp/info-sources/helper.c",
                          debug-fully-read="true"},
                         {file="/usr/include/stdc-predef.h",
                          fullname="/usr/include/stdc-predef.h",
                          debug-fully-read="true"},
                         {file="header.h",
                          fullname="/tmp/info-sources/header.h",
                          debug-fully-read="true"}]},
               {filename="/lib64/libc.so.6",
                debug-info="none",
                sources=[]}]

In the above output the 'debug-info' field associated with each
objfile will have one of the values 'none', 'partially-read', or
'fully-read'.  For example, /lib64/libc.so.6 has the value 'none',
this indicates that this object file has no debug information
associated with it, unsurprisingly then, the sources list of this
object file is empty.

An object file that was compiled with debug, for example
/tmp/info-sources/libhelper.so, has the value 'fully-read' above
indicating that this object file does have debug information, and the
information is fully read into GDB.  At different times this field
might have the value 'partially-read' indicating that that the object
file has debug information, but it has not been fully read into GDB
yet.

Source files can appear at most once for any single objfile, but can
appear multiple times in total, if the same source file is part of
multiple objfiles, for example /tmp/info-sources/header.h in the above
output.

The new output format is hidden behind a command option to ensure that
the default output is unchanged, this ensures backward compatibility.

The behaviour of the CLI "info sources" command is unchanged after
this commit.

gdb/ChangeLog:

* NEWS: Mention additions to -file-list-exec-source-files.
* mi/mi-cmd-file.c (mi_cmd_file_list_exec_source_files): Add
--group-by-objfile option.
* symtab.c (isrc_flag_option_def): Rename to...
(isrc_match_flag_option_def): ...this.
(info_sources_option_defs): Rename to...
(info_sources_match_option_defs): ...this, and update to rename of
isrc_flag_option_def.
(struct filename_grouping_opts): New struct.
(isrc_grouping_flag_option_def): New type.
(info_sources_grouping_option_defs): New static global.
(make_info_sources_options_def_group): Update to return two option
groups.
(info_sources_command_completer): Update for changes to
make_info_sources_options_def_group.
(info_sources_worker): Add extra parameter, use this to display
alternative output format.
(info_sources_command): Pass extra parameter to
info_sources_worker.
(_initialize_symtab): Update for changes to
make_info_sources_options_def_group.
* symtab.h (info_sources_worker): Add extra parameter.

gdb/doc/ChangeLog:

* gdb.texinfo (GDB/MI File Commands): Document --group-by-objfile
extension for -file-list-exec-source-files.

gdb/testsuite/ChangeLog:

* gdb.mi/mi-info-sources.exp: Add additional tests.

gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/mi/mi-cmd-file.c
gdb/symtab.c
gdb/symtab.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.mi/mi-info-sources.exp

index aa1d458b2cfd9e2cfa2897b13caca07200d91872..637fd096a9306c02f383b49c3a450fd8ba964349 100644 (file)
@@ -1,3 +1,28 @@
+2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * NEWS: Mention additions to -file-list-exec-source-files.
+       * mi/mi-cmd-file.c (mi_cmd_file_list_exec_source_files): Add
+       --group-by-objfile option.
+       * symtab.c (isrc_flag_option_def): Rename to...
+       (isrc_match_flag_option_def): ...this.
+       (info_sources_option_defs): Rename to...
+       (info_sources_match_option_defs): ...this, and update to rename of
+       isrc_flag_option_def.
+       (struct filename_grouping_opts): New struct.
+       (isrc_grouping_flag_option_def): New type.
+       (info_sources_grouping_option_defs): New static global.
+       (make_info_sources_options_def_group): Update to return two option
+       groups.
+       (info_sources_command_completer): Update for changes to
+       make_info_sources_options_def_group.
+       (info_sources_worker): Add extra parameter, use this to display
+       alternative output format.
+       (info_sources_command): Pass extra parameter to
+       info_sources_worker.
+       (_initialize_symtab): Update for changes to
+       make_info_sources_options_def_group.
+       * symtab.h (info_sources_worker): Add extra parameter.
+
 2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * NEWS: Mention additions to -file-list-exec-source-files.
index 8d79c50e1be3fde4f8caea67ef147a4c6eec94ed..f37ad425d3ae7ca6a4f59b51a32b27d00aa40210 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -49,7 +49,9 @@
     all locations of the selected breakpoint.  This is equivalent to
     the '-force' flag of the CLI's "cond" command.
 
- ** '-file-list-exec-source-files [--basename | --dirname] [--] [REGEXP]'
+ ** '-file-list-exec-source-files [--group-by-objfile]
+                                 [--basename | --dirname]
+                                  [--] [REGEXP]'
 
     The existing -file-list-exec-source-files command now takes an
     optional REGEXP which is used to filter the source files that are
     REGEXP is only matched against the specified part of the full
     source filename.
 
+    When the optional --group-by-objfile flag is used the output
+    format is changed, the results are now a list of object files
+    (executable and libraries) with the source files that are
+    associated with each object file.
+
     The results from -file-list-exec-source-files now include a
     'debug-fully-read' field which takes the value 'true' or 'false'.
     A 'true' value indicates the source file is from a compilation
index 4dc190407d4789ff92692fdef116c1799e49169d..20ea7f7d12d9e4a560d96bdfb5b833a27e05fbd7 100644 (file)
@@ -1,3 +1,8 @@
+2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.texinfo (GDB/MI File Commands): Document --group-by-objfile
+       extension for -file-list-exec-source-files.
+
 2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.texinfo (GDB/MI File Commands): Document extensions to
index 1e56c3a882bac8e7d9b9eb2ef55a4eee859144d3..19b6a5f2120258da4731d001438f22a6a9afdbb2 100644 (file)
@@ -35629,7 +35629,8 @@ The @value{GDBN} equivalent is @samp{info source}
 @subsubheading Synopsis
 
 @smallexample
- -file-list-exec-source-files @r{[} @var{--dirname} @r{|} @var{--basename} @r{]}
+ -file-list-exec-source-files @r{[} @var{--group-by-objfile} @r{]}
+                              @r{[} @var{--dirname} @r{|} @var{--basename} @r{]}
                               @r{[} -- @r{]}
                               @r{[} @var{regexp} @r{]}
 @end smallexample
@@ -35667,6 +35668,31 @@ is provided, then @var{regexp} is matched against the basename of each
 source file.  Only one of @code{--dirname} or @code{--basename} may be
 given, and if either is given then @var{regexp} is required.
 
+If @code{--group-by-objfile} is used then the format of the results is
+changed.  The results will now be a list of tuples, with each tuple
+representing an object file (executable or shared library) loaded into
+@value{GDBN}.  The fields of these tuples are; @var{filename},
+@var{debug-info}, and @var{sources}.  The @var{filename} is the
+absolute name of the object file, @var{debug-info} is a string with
+one of the following values:
+
+@table @code
+@item none
+This object file has no debug information.
+@item partially-read
+This object file has debug information, but it is not fully read in
+yet.  When it is read in later, GDB might become aware of additional
+source files.
+@item fully-read
+This object file has debug information, and this information is fully
+read into GDB.  The list of source files is complete.
+@end table
+
+The @var{sources} is a list or tuples, with each tuple describing a
+single source file with the same fields as described previously.  The
+@var{sources} list can be empty for object files that have no debug
+information.
+
 @subsubheading @value{GDBN} Command
 
 The @value{GDBN} equivalent is @samp{info sources}.
@@ -35702,6 +35728,38 @@ The @value{GDBN} equivalent is @samp{info sources}.
               fullname="/tmp/info-sources/helper.c",
               debug-fully-read="true"@}]
 (@value{GDBP})
+-file-list-exec-source-files --group-by-objfile
+^done,files=[@{filename="/tmp/info-sources/test.x",
+              debug-info="fully-read",
+              sources=[@{file="test.c",
+                        fullname="/tmp/info-sources/test.c",
+                        debug-fully-read="true"@},
+                       @{file="/usr/include/stdc-predef.h",
+                        fullname="/usr/include/stdc-predef.h",
+                        debug-fully-read="true"@},
+                       @{file="header.h",
+                        fullname="/tmp/info-sources/header.h",
+                        debug-fully-read="true"@}]@},
+             @{filename="/lib64/ld-linux-x86-64.so.2",
+              debug-info="none",
+              sources=[]@},
+             @{filename="system-supplied DSO at 0x7ffff7fcf000",
+              debug-info="none",
+              sources=[]@},
+             @{filename="/tmp/info-sources/libhelper.so",
+              debug-info="fully-read",
+              sources=[@{file="helper.c",
+                        fullname="/tmp/info-sources/helper.c",
+                        debug-fully-read="true"@},
+                       @{file="/usr/include/stdc-predef.h",
+                        fullname="/usr/include/stdc-predef.h",
+                        debug-fully-read="true"@},
+                       @{file="header.h",
+                        fullname="/tmp/info-sources/header.h",
+                        debug-fully-read="true"@}]@},
+             @{filename="/lib64/libc.so.6",
+              debug-info="none",
+              sources=[]@}]
 @end smallexample
 
 @subheading The @code{-file-list-shared-libraries} Command
index 684f7eb3f0c6703bc06da6107f3846ca7d297152..0970d369cc5a20f9f21c3410432294b5f1da5c96 100644 (file)
@@ -69,11 +69,13 @@ mi_cmd_file_list_exec_source_files (const char *command, char **argv, int argc)
 {
   enum opt
     {
+      GROUP_BY_OBJFILE_OPT,
       MATCH_BASENAME_OPT,
       MATCH_DIRNAME_OPT
     };
   static const struct mi_opt opts[] =
   {
+    {"-group-by-objfile", GROUP_BY_OBJFILE_OPT, 0},
     {"-basename", MATCH_BASENAME_OPT, 0},
     {"-dirname", MATCH_DIRNAME_OPT, 0},
     { 0, 0, 0 }
@@ -83,6 +85,7 @@ mi_cmd_file_list_exec_source_files (const char *command, char **argv, int argc)
   int oind = 0;
   char *oarg;
 
+  bool group_by_objfile = false;
   bool match_on_basename = false;
   bool match_on_dirname = false;
 
@@ -94,6 +97,9 @@ mi_cmd_file_list_exec_source_files (const char *command, char **argv, int argc)
        break;
       switch ((enum opt) opt)
        {
+       case GROUP_BY_OBJFILE_OPT:
+         group_by_objfile = true;
+         break;
        case MATCH_BASENAME_OPT:
          match_on_basename = true;
          break;
@@ -104,7 +110,7 @@ mi_cmd_file_list_exec_source_files (const char *command, char **argv, int argc)
     }
 
   if ((argc - oind > 1) || (match_on_basename && match_on_dirname))
-    error (_("-file-list-exec-source-files: Usage: [--basename | --dirname] [--] REGEXP"));
+    error (_("-file-list-exec-source-files: Usage: [--group-by-objfile] [--basename | --dirname] [--] REGEXP"));
 
   const char *regexp = nullptr;
   if (argc - oind == 1)
@@ -119,7 +125,7 @@ mi_cmd_file_list_exec_source_files (const char *command, char **argv, int argc)
     match_type = info_sources_filter::match_on::FULLNAME;
 
   info_sources_filter filter (match_type, regexp);
-  info_sources_worker (current_uiout, filter);
+  info_sources_worker (current_uiout, group_by_objfile, filter);
 }
 
 /* See mi-cmds.h.  */
index e300596be6ec5becdf1110cc574b07e485b8ee1c..cd6da0631417b28b28f7cd0ff2a7fd20c85e0d78 100644 (file)
@@ -4459,6 +4459,7 @@ info_sources_command_completer (cmd_list_element *ignore,
 
 void
 info_sources_worker (struct ui_out *uiout,
+                    bool group_by_objfile,
                     const info_sources_filter &filter)
 {
   output_source_filename_data data (uiout, filter);
@@ -4467,11 +4468,35 @@ info_sources_worker (struct ui_out *uiout,
   gdb::optional<ui_out_emit_tuple> output_tuple;
   gdb::optional<ui_out_emit_list> sources_list;
 
-  if (!uiout->is_mi_like_p ())
-    data.print_header (_("Source files for which symbols have been read in:\n"));
+  gdb_assert (!group_by_objfile || uiout->is_mi_like_p ());
+
+  if (!group_by_objfile)
+    {
+      if (!uiout->is_mi_like_p ())
+       data.print_header (_("Source files for which symbols have been read in:\n"));
+    }
 
   for (objfile *objfile : current_program_space->objfiles ())
     {
+      if (group_by_objfile)
+       {
+         output_tuple.emplace (uiout, nullptr);
+         uiout->field_string ("filename", objfile_name (objfile));
+         bool debug_fully_readin = !objfile->has_unexpanded_symtabs ();
+         const char *debug_info_state;
+         if (objfile_has_symbols (objfile))
+           {
+             if (debug_fully_readin)
+               debug_info_state = "fully-read";
+             else
+               debug_info_state = "partially-read";
+           }
+         else
+           debug_info_state = "none";
+         current_uiout->field_string ("debug-info", debug_info_state);
+         sources_list.emplace (uiout, "sources");
+       }
+
       for (compunit_symtab *cu : objfile->compunits ())
        {
          for (symtab *s : compunit_filetabs (cu))
@@ -4481,14 +4506,25 @@ info_sources_worker (struct ui_out *uiout,
              data.output (file, fullname, true);
            }
        }
+
+      if (group_by_objfile)
+       {
+         objfile->map_symbol_filenames (data, true /* need_fullname */);
+         data.reset_output ();
+         sources_list.reset ();
+         output_tuple.reset ();
+       }
     }
 
-  uiout->text ("\n\n");
-  if (!uiout->is_mi_like_p ())
-    data.print_header (_("Source files for which symbols will be read in on demand:\n"));
-  data.reset_output ();
-  map_symbol_filenames (data, true /*need_fullname*/);
-  uiout->text ("\n");
+  if (!group_by_objfile)
+    {
+      uiout->text ("\n\n");
+      if (!uiout->is_mi_like_p ())
+       data.print_header (_("Source files for which symbols will be read in on demand:\n"));
+      data.reset_output ();
+      map_symbol_filenames (data, true /*need_fullname*/);
+      uiout->text ("\n");
+    }
 }
 
 /* Implement the 'info sources' command.  */
@@ -4523,7 +4559,7 @@ info_sources_command (const char *args, int from_tty)
     match_type = info_sources_filter::match_on::FULLNAME;
 
   info_sources_filter filter (match_type, regex);
-  info_sources_worker (current_uiout, filter);
+  info_sources_worker (current_uiout, false, filter);
 }
 
 /* Compare FILE against all the entries of FILENAMES.  If BASENAMES is
index db0df5cb4bba28b9722f6aae404a7360bb5cfed5..968b4476993adb7f743fc6a82c1576214452e87b 100644 (file)
@@ -2446,6 +2446,7 @@ private:
    Output is written to UIOUT in CLI or MI style as appropriate.  */
 
 extern void info_sources_worker (struct ui_out *uiout,
+                                bool group_by_objfile,
                                 const info_sources_filter &filter);
 
 #endif /* !defined(SYMTAB_H) */
index 7eb13b82dfa67c4ae40f91b041c1d04759a6bf05..8a8c7f22ea38bca6022a3711a24e12d067a2771c 100644 (file)
@@ -1,3 +1,7 @@
+2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.mi/mi-info-sources.exp: Add additional tests.
+
 2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.dwarf2/dw2-filename.exp: Update expected results.
index c218af4ba80da17cac3ee385e1a31cfcb6f17d0f..c4d6b910ef82781db4aac4c4055c549c9f44ced0 100644 (file)
@@ -137,6 +137,43 @@ proc check_info_sources { debug_fully_read } {
                        [mi_field "debug-fully-read" "${debug_fully_read}"]]]
        mi_gdb_test "-file-list-exec-source-files --basename -- base" ".*\\^done,${p}" \
            "-file-list-exec-source-files --basename -- base"
+
+       # Figure out the value for the 'debug-info' field.
+       if {${debug_fully_read} == "true"} {
+           set debug_info "fully-read"
+       } else {
+           set debug_info "partially-read"
+       }
+
+       set p [mi_list "files" \
+                  [mi_tuple "" \
+                       [mi_field "filename" "\[^\"\]+/mi-info-sources"] \
+                       [mi_field "debug-info" "${debug_info}"] \
+                       [mi_list "sources" \
+                            ".*" \
+                            [mi_tuple "" \
+                                 [mi_field "file" "\[^\"\]+/mi-info-sources\\.c"] \
+                                 [mi_field "fullname" "\[^\"\]+/mi-info-sources\\.c"] \
+                                 [mi_field "debug-fully-read" "true"]] \
+                            ".*"]]]
+       mi_gdb_test "-file-list-exec-source-files --group-by-objfile" \
+           ".*\\^done,${p}" \
+           "-file-list-exec-source-files --group-by-objfile, look for mi-info-sources.c"
+
+       set p [mi_list "files" \
+                  [mi_tuple "" \
+                       [mi_field "filename" "\[^\"\]+/mi-info-sources"] \
+                       [mi_field "debug-info" "${debug_info}"] \
+                       [mi_list "sources" \
+                            ".*" \
+                            [mi_tuple "" \
+                                 [mi_field "file" "\[^\"\]+/mi-info-sources-base\\.c"] \
+                                 [mi_field "fullname" "\[^\"\]+/mi-info-sources-base\\.c"] \
+                                 [mi_field "debug-fully-read" "${debug_fully_read}"]] \
+                            ".*"]]]
+       mi_gdb_test "-file-list-exec-source-files --group-by-objfile" \
+           ".*\\^done,${p}" \
+           "-file-list-exec-source-files --group-by-objfile, look for mi-info-sources-base.c"
     }
 }