+2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * NEWS: Mention changes to 'info sources'.
+ * symtab.c (info_sources_filter::print): Delete.
+ (struct output_source_filename_data) <print_header>: Delete
+ declaration. <printed_filename_p>: New member function.
+ (output_source_filename_data::print_header): Delete.
+ (info_sources_worker): Update group-by-objfile style output to
+ make it CLI suitable, simplify non-group-by-objfile now this is
+ only used from the MI.
+ (info_sources_command): Make group-by-objfile be the default for
+ CLI info sources command.
+ * symtab.h (struct info_sources_filter) <print>: Delete.
+
2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
* NEWS: Mention additions to -file-list-exec-source-files.
offsets of struct members. Default behavior is given by 'show print
type hex'.
+info sources
+ The info sources command output has been restructured. The results
+ are now based around a list of objfiles (executable and libraries),
+ and for each objfile the source files that are part of that objfile
+ are listed.
+
* Removed targets and native configurations
ARM Symbian arm*-*-symbianelf*
+2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * gdb.texinfo (Symbols): Document new output format for 'info
+ sources'.
+
2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.texinfo (GDB/MI File Commands): Document --group-by-objfile
@kindex info sources
-@item info sources
-Print the names of all source files in your program for which there is
-debugging information, organized into two lists: files whose symbols
-have already been read, and files whose symbols will be read when needed.
-
-@item info sources [-dirname | -basename] [--] [@var{regexp}]
-Like @samp{info sources}, but only print the names of the files
-matching the provided @var{regexp}.
-By default, the @var{regexp} is used to match anywhere in the filename.
-If @code{-dirname}, only files having a dirname matching @var{regexp} are shown.
-If @code{-basename}, only files having a basename matching @var{regexp}
-are shown.
-The matching is case-sensitive, except on operating systems that
-have case-insensitive filesystem (e.g., MS-Windows).
+@item info sources @r{[}-dirname | -basename@r{]} @r{[}--@r{]} @r{[}@var{regexp}@r{]}
+
+
+With no options @samp{info sources} prints the names of all source
+files in your program for which there is debugging information. The
+source files are presented based on a list of object files
+(executables and libraries) currently loaded into @value{GDBN}. For
+each object file all of the associated source files are listed.
+
+Each source file will only be printed once for each object file, but a
+single source file can be repeated in the output if it is part of
+multiple object files.
+
+If the optional @var{regexp} is provided, then only source files that
+match the regular expression will be printed. The matching is
+case-sensitive, except on operating systems that have case-insensitive
+filesystem (e.g., MS-Windows). @samp{--} can be used before
+@var{regexp} to prevent @value{GDBN} interpreting @var{regexp} as a
+command option (e.g. if @var{regexp} starts with @samp{-}).
+
+By default, the @var{regexp} is used to match anywhere in the
+filename. If @code{-dirname}, only files having a dirname matching
+@var{regexp} are shown. If @code{-basename}, only files having a
+basename matching @var{regexp} are shown.
+
+It is possible that an object file may be printed in the list with no
+associated source files. This can happen when either no source files
+match @var{regexp}, or, the object file was compiled without debug
+information and so @value{GDBN} is unable to find any source file
+names.
@kindex info functions
@item info functions [-q] [-n]
return true;
}
-/* See class declaration. */
-
-void
-info_sources_filter::print (struct ui_out *uiout) const
-{
- if (m_c_regexp.has_value ())
- {
- gdb_assert (m_regexp != nullptr);
-
- switch (m_match_type)
- {
- case match_on::DIRNAME:
- uiout->message (_("(dirname matching regular expression \"%s\")"),
- m_regexp);
- break;
- case match_on::BASENAME:
- uiout->message (_("(basename matching regular expression \"%s\")"),
- m_regexp);
- break;
- case match_on::FULLNAME:
- printf_filtered (_("(filename matching regular expression \"%s\")"),
- m_regexp);
- break;
- }
- }
-}
-
/* Data structure to maintain the state used for printing the results of
the 'info sources' command. */
expanded symtab, otherwise false). */
void output (const char *disp_name, const char *fullname, bool expanded_p);
- /* Prints the header messages for the source files that will be printed
- with the matching info present in the current object state.
- SYMBOL_MSG is a message that describes what will or has been done with
- the symbols of the matching source files. */
- void print_header (const char *symbol_msg);
-
/* An overload suitable for use as a callback to
quick_symbol_functions::map_symbol_filenames. */
void operator() (const char *filename, const char *fullname)
output (filename, fullname, false);
}
+ /* Return true if at least one filename has been printed (after a call to
+ output) since either this object was created, or the last call to
+ reset_output. */
+ bool printed_filename_p () const
+ {
+ return !m_first;
+ }
+
private:
/* Flag of whether we're printing the first one. */
}
}
-/* See comment is class declaration above. */
-
-void
-output_source_filename_data::print_header (const char *symbol_msg)
-{
- m_uiout->text (symbol_msg);
- m_filter.print (m_uiout);
- m_uiout->text ("\n");
-}
-
/* For the 'info sources' command, what part of the file names should we be
matching the user supplied regular expression against? */
gdb::optional<ui_out_emit_tuple> output_tuple;
gdb::optional<ui_out_emit_list> sources_list;
- 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"));
- }
+ gdb_assert (group_by_objfile || uiout->is_mi_like_p ());
for (objfile *objfile : current_program_space->objfiles ())
{
{
output_tuple.emplace (uiout, nullptr);
uiout->field_string ("filename", objfile_name (objfile));
+ uiout->text (":\n");
bool debug_fully_readin = !objfile->has_unexpanded_symtabs ();
- const char *debug_info_state;
- if (objfile_has_symbols (objfile))
+ if (uiout->is_mi_like_p ())
{
- if (debug_fully_readin)
- debug_info_state = "fully-read";
+ 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 = "partially-read";
+ debug_info_state = "none";
+ current_uiout->field_string ("debug-info", debug_info_state);
}
else
- debug_info_state = "none";
- current_uiout->field_string ("debug-info", debug_info_state);
+ {
+ if (!debug_fully_readin)
+ uiout->text ("(Full debug information has not yet been read "
+ "for this file.)\n");
+ if (!objfile_has_symbols (objfile))
+ uiout->text ("(Objfile has no debug information.)\n");
+ uiout->text ("\n");
+ }
sources_list.emplace (uiout, "sources");
}
if (group_by_objfile)
{
objfile->map_symbol_filenames (data, true /* need_fullname */);
+ if (data.printed_filename_p ())
+ uiout->text ("\n\n");
data.reset_output ();
sources_list.reset ();
output_tuple.reset ();
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");
}
}
match_type = info_sources_filter::match_on::FULLNAME;
info_sources_filter filter (match_type, regex);
- info_sources_worker (current_uiout, false, filter);
+ info_sources_worker (current_uiout, true, filter);
}
/* Compare FILE against all the entries of FILENAMES. If BASENAMES is
then this function will always return true. */
bool matches (const char *fullname) const;
- /* Print a single line describing this filter to UIOUT, used as part of
- the "info sources" command output. If there is no filter in place
- then nothing is printed. */
- void print (struct ui_out *uiout) const;
-
private:
/* The type of filtering in place. */
+2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * gdb.base/info_sources_2-header.h: New file.
+ * gdb.base/info_sources_2-lib.c: New file.
+ * gdb.base/info_sources_2-test.c: New file.
+ * gdb.base/info_sources_2.exp: New file.
+
2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.mi/mi-info-sources.exp: Add additional tests.
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2021 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/>. */
+
+#ifndef INFO_SOURCES_2_HEADER
+#define INFO_SOURCES_2_HEADER
+
+extern int foo (void);
+
+inline static int compare_values (int a, int b)
+{
+ return a == b;
+}
+
+#endif /* INFO_SOURCES_2_HEADER */
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2021 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/>. */
+
+
+#include "info_sources_2-header.h"
+
+int
+foo ()
+{
+ return compare_values (0, 1);
+}
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2021 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/>. */
+
+
+#include "info_sources_2-header.h"
+
+int
+main ()
+{
+ int res = foo ();
+ return compare_values (res, 1);
+}
--- /dev/null
+# Copyright 2021 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/>.
+
+# Test 'info sources' when the test file makes use of a shared
+# library.
+
+if { [skip_shlib_tests] } {
+ return 0
+}
+
+standard_testfile -test.c -lib.c
+set solib_name [standard_output_file ${testfile}-lib.so]
+
+if { [gdb_compile_shlib ${srcdir}/${subdir}/${srcfile2} ${solib_name} \
+ {debug}] != "" } {
+ untested "failed to compile shared library"
+ return -1
+}
+
+if {[gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable \
+ [list debug shlib=${solib_name} ]] != ""} {
+ untested "failed to compile executable"
+ return -1
+}
+
+clean_restart ${binfile}
+
+if ![runto foo] {
+ untested "failed to run to function foo"
+ return -1
+}
+
+# Invoke 'info sources EXTRA_ARGS' and extract the results.
+# The results are then compared to the list ARGS.
+#
+# The list ARGS should consist of pairs of values, the first item being the
+# path to an object file, and the second item being the name of a source file.
+# This proc checks that source file was listed as being a source file for the
+# given object file.
+#
+# If the name of the source file starts with the character "!" (exclamation
+# character, without the quotes) then the check is inverted, that the source
+# file is NOT listed for the given object file.
+proc run_info_sources { extra_args args } {
+ global gdb_prompt srcdir subdir
+
+ with_test_prefix "args: ${extra_args}" {
+
+ # The results of running info sources will be placed into this local.
+ array set info_sources {}
+
+ # The command we are going to run.
+ set cmd "info sources ${extra_args}"
+ set command_regex [string_to_regexp $cmd]
+
+ # Run the command and extract the results into INFO_SOURCES.
+ set objfile_name ""
+ set source_files {}
+ gdb_test_multiple $cmd "" {
+ -re "${command_regex}\r\n" {
+ exp_continue
+ }
+
+ -re "^(\[^\r\n\]+):\r\n" {
+ set objfile_name $expect_out(1,string)
+ exp_continue
+ }
+
+ -re "^\\(Full debug information has not yet been read for this file\\.\\)\r\n" {
+ exp_continue
+ }
+
+ -re "^\r\n" {
+ exp_continue
+ }
+
+ -re "^$gdb_prompt $" {
+ pass $gdb_test_name
+ }
+
+ -re "^(\[^\r\n\]+)\r\n" {
+ if { $objfile_name == "" } {
+ fail "${gdb_test_name} (no objfile name)"
+ return
+ }
+
+ set files {}
+ foreach f [split $expect_out(1,string) ,] {
+ lappend files [string trim $f]
+ }
+ set info_sources($objfile_name) $files
+ set $objfile_name ""
+ exp_continue
+ }
+ }
+
+ # Now check ARGS agaisnt the values held in INFO_SOURCES map.
+ foreach {objfile sourcefile} $args {
+ # First, figure out if we're expecting SOURCEFILE to be present,
+ # or not.
+ set present True
+ set match_type "is"
+ if {[string index $sourcefile 0] == "!"} {
+ set present False
+ set match_type "is not"
+ set sourcefile [string range $sourcefile 1 end]
+ }
+
+ # Figure out the path for SOURCEFILE that we're looking for.
+ set sourcepath [file normalize ${srcdir}/${subdir}/${sourcefile}]
+
+ # Make sure we handle the case where there are no source files
+ # associated with a particular objfile.
+ set source_list {}
+ if [info exists info_sources($objfile)] {
+ set source_list $info_sources($objfile)
+ }
+
+ # Now perform the search, and check the results.
+ set idx [lsearch -exact $source_list $sourcepath]
+ gdb_assert {($present && $idx >= 0) || (!$present && $idx == -1)} \
+ "source file '$sourcefile' ${match_type} present for '[file tail $objfile]'"
+ }
+ }
+}
+
+# The actual tests.
+
+run_info_sources "" \
+ ${binfile} ${srcfile} \
+ ${binfile} ${testfile}-header.h \
+ ${solib_name} ${srcfile2} \
+ ${solib_name} ${testfile}-header.h
+
+run_info_sources "-basename info_sources_2" \
+ ${binfile} ${srcfile} \
+ ${binfile} ${testfile}-header.h \
+ ${solib_name} ${srcfile2} \
+ ${solib_name} ${testfile}-header.h
+
+run_info_sources "-basename \\.c" \
+ ${binfile} ${srcfile} \
+ ${binfile} !${testfile}-header.h \
+ ${solib_name} ${srcfile2} \
+ ${solib_name} !${testfile}-header.h
+
+run_info_sources "-basename -- -test\\.c" \
+ ${binfile} ${srcfile} \
+ ${binfile} !${testfile}-header.h \
+ ${solib_name} !${srcfile2} \
+ ${solib_name} !${testfile}-header.h
+
+run_info_sources "-basename -- -lib\\.c" \
+ ${binfile} !${srcfile} \
+ ${binfile} !${testfile}-header.h \
+ ${solib_name} ${srcfile2} \
+ ${solib_name} !${testfile}-header.h