gdb/mi: add regexp filtering to -file-list-exec-source-files

This commit extends the existing MI command
-file-list-exec-source-files to provide the same regular expression
based filtering that the equivalent CLI command "info sources"
provides.

The new command syntax is:

  -file-list-exec-source-files [--basename | --dirname] [--] [REGEXP]

All options are optional, which ensures the command is backward
compatible.

As part of this work I have unified the CLI and MI code.

As a result of the unified code I now provide additional information
in the MI command output, there is now a new field 'debug-fully-read'
included with each source file.  This field which has the values
'true' or 'false', indicates if the source file is from a compilation
unit that has had its debug information fully read.  However, as this
is additional information, a well written front-end should just ignore
this field if it doesn't understand it, so things should still be
backward compatible.

gdb/ChangeLog:

	* NEWS: Mention additions to -file-list-exec-source-files.
	* mi/mi-cmd-file.c (print_partial_file_name): Delete.
	(mi_cmd_file_list_exec_source_files): Rewrite to handle command
	options, and make use of info_sources_worker.
	* symtab.c (struct info_sources_filter): Moved to symtab.h.
	(info_sources_filter::print): Take uiout argument, produce output
	through uiout.
	(struct output_source_filename_data)
	<output_source_filename_data>: Take uiout argument, store into
	m_uiout.  <output>: Rewrite comment, add additional arguments to
	declaration.  <operator()>: Send more arguments to
	output. <m_uiout>: New member variable.
	(output_source_filename_data::output): Take extra arguments,
	produce output through m_uiout, and structure for MI.
	(output_source_filename_data::print_header): Produce output
	through m_uiout.
	(info_sources_worker): New function, the implementation is taken
	from info_sources_command, but modified so produce output through
	a ui_out.
	(info_sources_command): The second half of this function has gone
	to become info_sources_worker.
	* symtab.h (struct info_sources_filter): Moved from symtab.c, add
	extra parameter to print member function.
	(info_sources_worker): Declare.

gdb/doc/ChangeLog:

	* gdb.texinfo (GDB/MI File Commands): Document extensions to
	-file-list-exec-source-files.

gdb/testsuite/ChangeLog:

	* gdb.dwarf2/dw2-filename.exp: Update expected results.
	* gdb.mi/mi-file.exp: Likewise.
	* gdb.mi/mi-info-sources-base.c: New file.
	* gdb.mi/mi-info-sources.c: New file.
	* gdb.mi/mi-info-sources.exp: New file.
This commit is contained in:
Andrew Burgess 2021-05-18 13:46:19 +01:00
parent 4a0788e08c
commit 0e350a054b
13 changed files with 520 additions and 148 deletions

View File

@ -1,3 +1,30 @@
2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
* NEWS: Mention additions to -file-list-exec-source-files.
* mi/mi-cmd-file.c (print_partial_file_name): Delete.
(mi_cmd_file_list_exec_source_files): Rewrite to handle command
options, and make use of info_sources_worker.
* symtab.c (struct info_sources_filter): Moved to symtab.h.
(info_sources_filter::print): Take uiout argument, produce output
through uiout.
(struct output_source_filename_data)
<output_source_filename_data>: Take uiout argument, store into
m_uiout. <output>: Rewrite comment, add additional arguments to
declaration. <operator()>: Send more arguments to
output. <m_uiout>: New member variable.
(output_source_filename_data::output): Take extra arguments,
produce output through m_uiout, and structure for MI.
(output_source_filename_data::print_header): Produce output
through m_uiout.
(info_sources_worker): New function, the implementation is taken
from info_sources_command, but modified so produce output through
a ui_out.
(info_sources_command): The second half of this function has gone
to become info_sources_worker.
* symtab.h (struct info_sources_filter): Moved from symtab.c, add
extra parameter to print member function.
(info_sources_worker): Declare.
2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
* symtab.c (struct info_sources_filter): New.

View File

@ -49,6 +49,24 @@
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]'
The existing -file-list-exec-source-files command now takes an
optional REGEXP which is used to filter the source files that are
included in the results.
By default REGEXP is matched against the full filename of the
source file. When one of --basename or --dirname is given then
REGEXP is only matched against the specified part of the full
source filename.
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
unit that has had its debug information fully read in by GDB, a
value of 'false' indicates GDB has only performed a partial scan
of the debug information so far.
* GDB now supports core file debugging for x86_64 Cygwin programs.
* GDB will now look for the .gdbinit file in a config directory before

View File

@ -1,3 +1,8 @@
2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.texinfo (GDB/MI File Commands): Document extensions to
-file-list-exec-source-files.
2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
* python.texinfo (Breakpoints In Python): Add BP_CATCHPOINT

View File

@ -35623,18 +35623,49 @@ The @value{GDBN} equivalent is @samp{info source}
@subheading The @code{-file-list-exec-source-files} Command
@kindex info sources
@findex -file-list-exec-source-files
@subsubheading Synopsis
@smallexample
-file-list-exec-source-files
-file-list-exec-source-files @r{[} @var{--dirname} @r{|} @var{--basename} @r{]}
@r{[} -- @r{]}
@r{[} @var{regexp} @r{]}
@end smallexample
List the source files for the current executable.
This command returns information about the source files @value{GDBN}
knows about, it will output both the filename and fullname (absolute
file name) of a source file, though the fullname can be elided if this
information is not known to @value{GDBN}.
It will always output both the filename and fullname (absolute file
name) of a source file.
With no arguments this command returns a list of source files. Each
source file is represented by a tuple with the fields; @var{file},
@var{fullname}, and @var{debug-fully-read}. The @var{file} is the
display name for the file, while @var{fullname} is the absolute name
of the file. The @var{fullname} field can be elided if the absolute
name of the source file can't be computed. The field
@var{debug-fully-read} will be a string, either @code{true} or
@code{false}. When @code{true}, this indicates the full debug
information for the compilation unit describing this file has been
read in. When @code{false}, the full debug information has not yet
been read in. While reading in the full debug information it is
possible that @value{GDBN} could become aware of additional source
files.
The optional @var{regexp} can be used to filter the list of source
files returned. The @var{regexp} will be matched against the full
source file name. 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{-}).
If @code{--dirname} is provided, then @var{regexp} is matched only
against the directory name of each source file. If @code{--basename}
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.
@subsubheading @value{GDBN} Command
@ -35643,13 +35674,34 @@ The @value{GDBN} equivalent is @samp{info sources}.
@subsubheading Example
@smallexample
(gdb)
(@value{GDBP})
-file-list-exec-source-files
^done,files=[
@{file=foo.c,fullname=/home/foo.c@},
@{file=/home/bar.c,fullname=/home/bar.c@},
@{file=gdb_could_not_find_fullpath.c@}]
(gdb)
^done,files=[@{file="foo.c",fullname="/home/foo.c",debug-fully-read="true"@},
@{file="/home/bar.c",fullname="/home/bar.c",debug-fully-read="true"@},
@{file="gdb_could_not_find_fullpath.c",debug-fully-read="true"@}]
(@value{GDBP})
-file-list-exec-source-files
^done,files=[@{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"@},
@{file="helper.c",
fullname="/tmp/info-sources/helper.c",
debug-fully-read="true"@}]
(@value{GDBP})
-file-list-exec-source-files -- \\.c
^done,files=[@{file="test.c",
fullname="/tmp/info-sources/test.c",
debug-fully-read="true"@},
@{file="helper.c",
fullname="/tmp/info-sources/helper.c",
debug-fully-read="true"@}]
(@value{GDBP})
@end smallexample
@subheading The @code{-file-list-shared-libraries} Command

View File

@ -62,54 +62,64 @@ mi_cmd_file_list_exec_source_file (const char *command, char **argv, int argc)
COMPUNIT_MACRO_TABLE (SYMTAB_COMPUNIT (st.symtab)) != NULL);
}
/* A callback for map_partial_symbol_filenames. */
static void
print_partial_file_name (const char *filename, const char *fullname)
{
struct ui_out *uiout = current_uiout;
uiout->begin (ui_out_type_tuple, NULL);
uiout->field_string ("file", filename);
if (fullname)
uiout->field_string ("fullname", fullname);
uiout->end (ui_out_type_tuple);
}
/* Implement -file-list-exec-source-files command. */
void
mi_cmd_file_list_exec_source_files (const char *command, char **argv, int argc)
{
struct ui_out *uiout = current_uiout;
if (!mi_valid_noargs ("-file-list-exec-source-files", argc, argv))
error (_("-file-list-exec-source-files: Usage: No args"));
/* Print the table header. */
uiout->begin (ui_out_type_list, "files");
/* Look at all of the file symtabs. */
for (objfile *objfile : current_program_space->objfiles ())
enum opt
{
for (compunit_symtab *cu : objfile->compunits ())
MATCH_BASENAME_OPT,
MATCH_DIRNAME_OPT
};
static const struct mi_opt opts[] =
{
{"-basename", MATCH_BASENAME_OPT, 0},
{"-dirname", MATCH_DIRNAME_OPT, 0},
{ 0, 0, 0 }
};
/* Parse arguments. */
int oind = 0;
char *oarg;
bool match_on_basename = false;
bool match_on_dirname = false;
while (1)
{
int opt = mi_getopt ("-file-list-exec-source-files", argc, argv,
opts, &oind, &oarg);
if (opt < 0)
break;
switch ((enum opt) opt)
{
for (symtab *s : compunit_filetabs (cu))
{
uiout->begin (ui_out_type_tuple, NULL);
uiout->field_string ("file", symtab_to_filename_for_display (s));
uiout->field_string ("fullname", symtab_to_fullname (s));
uiout->end (ui_out_type_tuple);
}
case MATCH_BASENAME_OPT:
match_on_basename = true;
break;
case MATCH_DIRNAME_OPT:
match_on_dirname = true;
break;
}
}
map_symbol_filenames (print_partial_file_name, true /*need_fullname*/);
if ((argc - oind > 1) || (match_on_basename && match_on_dirname))
error (_("-file-list-exec-source-files: Usage: [--basename | --dirname] [--] REGEXP"));
uiout->end (ui_out_type_list);
const char *regexp = nullptr;
if (argc - oind == 1)
regexp = argv[oind];
info_sources_filter::match_on match_type;
if (match_on_dirname)
match_type = info_sources_filter::match_on::DIRNAME;
else if (match_on_basename)
match_type = info_sources_filter::match_on::BASENAME;
else
match_type = info_sources_filter::match_on::FULLNAME;
info_sources_filter filter (match_type, regexp);
info_sources_worker (current_uiout, filter);
}
/* See mi-cmds.h. */

View File

@ -4200,58 +4200,6 @@ operator_chars (const char *p, const char **end)
}
/* Class used to encapsulate the filename filtering for the "info sources"
command. */
struct info_sources_filter
{
/* If filename filtering is being used (see M_C_REGEXP) then which part
of the filename is being filtered against? */
enum class match_on
{
/* Match against the full filename. */
FULLNAME,
/* Match only against the directory part of the full filename. */
DIRNAME,
/* Match only against the basename part of the full filename. */
BASENAME
};
/* Create a filter of MATCH_TYPE using regular expression REGEXP. If
REGEXP is nullptr then all files will match the filter and MATCH_TYPE
is ignored.
The string pointed too by REGEXP must remain live and unchanged for
this lifetime of this object as the object only retains a copy of the
pointer. */
info_sources_filter (match_on match_type, const char *regexp);
DISABLE_COPY_AND_ASSIGN (info_sources_filter);
/* Does FULLNAME match the filter defined by this object, return true if
it does, otherwise, return false. If there is no filtering defined
then this function will always return true. */
bool matches (const char *fullname) const;
/* Print a single line describing this filter, used as part of the "info
sources" command output. If there is no filter in place then nothing
is printed. */
void print () const;
private:
/* The type of filtering in place. */
match_on m_match_type;
/* Points to the original regexp used to create this filter. */
const char *m_regexp;
/* A compiled version of M_REGEXP. This object is only given a value if
M_REGEXP is not nullptr and is not the empty string. */
gdb::optional<compiled_regex> m_c_regexp;
};
/* See class declaration. */
info_sources_filter::info_sources_filter (match_on match_type,
@ -4307,7 +4255,7 @@ info_sources_filter::matches (const char *fullname) const
/* See class declaration. */
void
info_sources_filter::print () const
info_sources_filter::print (struct ui_out *uiout) const
{
if (m_c_regexp.has_value ())
{
@ -4316,12 +4264,12 @@ info_sources_filter::print () const
switch (m_match_type)
{
case match_on::DIRNAME:
printf_filtered (_("(dirname matching regular expression \"%s\")"),
m_regexp);
uiout->message (_("(dirname matching regular expression \"%s\")"),
m_regexp);
break;
case match_on::BASENAME:
printf_filtered (_("(basename matching regular expression \"%s\")"),
m_regexp);
uiout->message (_("(basename matching regular expression \"%s\")"),
m_regexp);
break;
case match_on::FULLNAME:
printf_filtered (_("(filename matching regular expression \"%s\")"),
@ -4337,10 +4285,12 @@ info_sources_filter::print () const
struct output_source_filename_data
{
/* Create an object for displaying the results of the 'info sources'
command. FILTER must remain valid and unchanged for the lifetime of
this object as this object retains a reference to FILTER. */
output_source_filename_data (const info_sources_filter &filter)
: m_filter (filter)
command to UIOUT. FILTER must remain valid and unchanged for the
lifetime of this object as this object retains a reference to FILTER. */
output_source_filename_data (struct ui_out *uiout,
const info_sources_filter &filter)
: m_filter (filter),
m_uiout (uiout)
{ /* Nothing. */ }
DISABLE_COPY_AND_ASSIGN (output_source_filename_data);
@ -4353,9 +4303,14 @@ struct output_source_filename_data
m_filename_seen_cache.clear ();
}
/* Worker for sources_info. Force line breaks at ,'s. NAME is the name
to print. */
void output (const char *name);
/* Worker for sources_info, outputs the file name formatted for either
cli or mi (based on the current_uiout). In cli mode displays
FULLNAME with a comma separating this name from any previously
printed name (line breaks are added at the comma). In MI mode
outputs a tuple containing DISP_NAME (the files display name),
FULLNAME, and EXPANDED_P (true when this file is from a fully
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.
@ -4367,7 +4322,9 @@ struct output_source_filename_data
quick_symbol_functions::map_symbol_filenames. */
void operator() (const char *filename, const char *fullname)
{
output (fullname != nullptr ? fullname : filename);
/* The false here indicates that this file is from an unexpanded
symtab. */
output (filename, fullname, false);
}
private:
@ -4380,12 +4337,17 @@ private:
/* How source filename should be filtered. */
const info_sources_filter &m_filter;
/* The object to which output is sent. */
struct ui_out *m_uiout;
};
/* See comment in class declaration above. */
void
output_source_filename_data::output (const char *name)
output_source_filename_data::output (const char *disp_name,
const char *fullname,
bool expanded_p)
{
/* Since a single source file can result in several partial symbol
tables, we need to avoid printing it more than once. Note: if
@ -4397,20 +4359,37 @@ output_source_filename_data::output (const char *name)
symtabs; it doesn't hurt to check. */
/* Was NAME already seen? If so, then don't print it again. */
if (m_filename_seen_cache.seen (name))
if (m_filename_seen_cache.seen (fullname))
return;
/* If the filter rejects this file then don't print it. */
if (!m_filter.matches (name))
if (!m_filter.matches (fullname))
return;
ui_out_emit_tuple ui_emitter (m_uiout, nullptr);
/* Print it and reset *FIRST. */
if (!m_first)
printf_filtered (", ");
m_uiout->text (", ");
m_first = false;
wrap_here ("");
fputs_styled (name, file_name_style.style (), gdb_stdout);
if (m_uiout->is_mi_like_p ())
{
m_uiout->field_string ("file", disp_name, file_name_style.style ());
if (fullname != nullptr)
m_uiout->field_string ("fullname", fullname,
file_name_style.style ());
m_uiout->field_string ("debug-fully-read",
(expanded_p ? "true" : "false"));
}
else
{
if (fullname == nullptr)
fullname = disp_name;
m_uiout->field_string ("fullname", fullname,
file_name_style.style ());
}
}
/* See comment is class declaration above. */
@ -4418,9 +4397,9 @@ output_source_filename_data::output (const char *name)
void
output_source_filename_data::print_header (const char *symbol_msg)
{
puts_filtered (symbol_msg);
m_filter.print ();
puts_filtered ("\n");
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
@ -4476,6 +4455,42 @@ info_sources_command_completer (cmd_list_element *ignore,
return;
}
/* See symtab.h. */
void
info_sources_worker (struct ui_out *uiout,
const info_sources_filter &filter)
{
output_source_filename_data data (uiout, filter);
ui_out_emit_list results_emitter (uiout, "files");
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"));
for (objfile *objfile : current_program_space->objfiles ())
{
for (compunit_symtab *cu : objfile->compunits ())
{
for (symtab *s : compunit_filetabs (cu))
{
const char *file = symtab_to_filename_for_display (s);
const char *fullname = symtab_to_fullname (s);
data.output (file, fullname, true);
}
}
}
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. */
static void
@ -4493,7 +4508,7 @@ info_sources_command (const char *args, int from_tty)
error (_("You cannot give both -basename and -dirname to 'info sources'."));
const char *regex = nullptr;
if (args != nullptr && *args != '\000')
if (args != NULL && *args != '\000')
regex = args;
if ((match_opts.dirname || match_opts.basename) && regex == nullptr)
@ -4508,29 +4523,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);
output_source_filename_data data (filter);
data.print_header (_("Source files for which symbols have been read in:\n"));
for (objfile *objfile : current_program_space->objfiles ())
{
for (compunit_symtab *cu : objfile->compunits ())
{
for (symtab *s : compunit_filetabs (cu))
{
const char *fullname = symtab_to_fullname (s);
data.output (fullname);
}
}
}
printf_filtered ("\n\n");
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*/);
printf_filtered ("\n");
info_sources_worker (current_uiout, filter);
}
/* Compare FILE against all the entries of FILENAMES. If BASENAMES is
@ -6890,7 +6883,8 @@ Print information about all types matching REGEXP, or all types if no\n\
REGEXP is given. The optional flag -q disables printing of headers."));
set_cmd_completer_handle_brkchars (c, info_types_command_completer);
const auto info_sources_opts = make_info_sources_options_def_group (nullptr);
const auto info_sources_opts
= make_info_sources_options_def_group (nullptr);
static std::string info_sources_help
= gdb::option::build_help (_("\

View File

@ -2385,4 +2385,67 @@ private:
std::vector<bound_minimal_symbol> m_minimal_symbols;
};
/* Class used to encapsulate the filename filtering for the "info sources"
command. */
struct info_sources_filter
{
/* If filename filtering is being used (see M_C_REGEXP) then which part
of the filename is being filtered against? */
enum class match_on
{
/* Match against the full filename. */
FULLNAME,
/* Match only against the directory part of the full filename. */
DIRNAME,
/* Match only against the basename part of the full filename. */
BASENAME
};
/* Create a filter of MATCH_TYPE using regular expression REGEXP. If
REGEXP is nullptr then all files will match the filter and MATCH_TYPE
is ignored.
The string pointed too by REGEXP must remain live and unchanged for
this lifetime of this object as the object only retains a copy of the
pointer. */
info_sources_filter (match_on match_type, const char *regexp);
DISABLE_COPY_AND_ASSIGN (info_sources_filter);
/* Does FULLNAME match the filter defined by this object, return true if
it does, otherwise, return false. If there is no filtering defined
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. */
match_on m_match_type;
/* Points to the original regexp used to create this filter. */
const char *m_regexp;
/* A compiled version of M_REGEXP. This object is only given a value if
M_REGEXP is not nullptr and is not the empty string. */
gdb::optional<compiled_regex> m_c_regexp;
};
/* Perform the core of the 'info sources' command.
FILTER is used to perform regular expression based filtering on the
source files that will be displayed.
Output is written to UIOUT in CLI or MI style as appropriate. */
extern void info_sources_worker (struct ui_out *uiout,
const info_sources_filter &filter);
#endif /* !defined(SYMTAB_H) */

View File

@ -1,3 +1,11 @@
2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.dwarf2/dw2-filename.exp: Update expected results.
* gdb.mi/mi-file.exp: Likewise.
* gdb.mi/mi-info-sources-base.c: New file.
* gdb.mi/mi-info-sources.c: New file.
* gdb.mi/mi-info-sources.exp: New file.
2021-06-25 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.cp/method-call-in-c.cc (struct foo_type): Add static member

View File

@ -37,7 +37,7 @@ clean_restart ${testfile}
# the full path to that file. What we want to verify, most of all,
# is that the file and fullname fields are now inverted.
gdb_test "interpreter-exec mi -file-list-exec-source-files" \
".*{file=\"file1\\.txt\",fullname=\".+file1\\.txt\"}.*"
".*{file=\"file1\\.txt\",fullname=\".+file1\\.txt\",debug-fully-read=\"\[^\"\]+\"}.*"
# And `info sources' should return the fullname incl. the directories.
gdb_test "info sources" {[/]file1\.txt.*}

View File

@ -68,7 +68,7 @@ proc test_file_list_exec_source_files {} {
# get the path and absolute path to the current executable
mi_gdb_test "222-file-list-exec-source-files" \
"222\\\^done,files=\\\[\{file=\".*${srcfile}\",fullname=\"$fullname_syntax${srcfile}\"\}.*]" \
"222\\\^done,files=\\\[\{file=\".*${srcfile}\",fullname=\"$fullname_syntax${srcfile}\",debug-fully-read=\"\[^\"\]+\"\}.*]" \
"Getting a list of source files."
}

View File

@ -0,0 +1,23 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2019-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/>. */
/* This file was originally copied from gdb.base/info_sources_base.c. */
void some_other_func (void)
{
return;
}

View File

@ -0,0 +1,25 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2019-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/>. */
/* This file was originally copied from gdb.base/info_sources.c. */
extern void some_other_func (void);
int main ()
{
some_other_func ();
return 0;
}

View File

@ -0,0 +1,147 @@
# 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 the -file-list-exec-source-files command.
load_lib mi-support.exp
set MIFLAGS "-i=mi"
standard_testfile .c -base.c
if {[prepare_for_testing $testfile.exp $testfile \
[list $srcfile $srcfile2] debug]} {
untested $testfile.exp
return -1
}
mi_clean_restart $binfile
mi_runto_main
# Helper to build expected MI output pattern for a list. NAME is the
# name of the list (which can be the empty string) and args is one
# or more strings representing the fields of the list, which will be
# joined with a comma.
#
# If any of the fields in args matches ".*" then the comma before and
# after are dropped from the final pattern.
proc mi_list { name args } {
set str ""
if { $name != "" } {
set str "${name}="
}
set pattern ""
foreach a $args {
if { [string length $pattern] > 0 } {
if { [string range $pattern end-1 end] != ".*" \
&& [string range $a 0 1] != ".*" } {
set pattern "${pattern},"
}
}
set pattern "${pattern}${a}"
}
set str "$str\\\[${pattern}\\\]"
return ${str}
}
# Helper to build expected MI output pattern for a tuple. NAME is the
# name of the tuple (which can be the empty string) and args is one
# or more strings representing the fields of the tuple, which will be
# joined with a comma.
#
# If any of the fields in args matches ".*" then the comma before and
# after are dropped from the final pattern.
proc mi_tuple { name args } {
set str ""
if { $name != "" } {
set str "${name}="
}
set pattern ""
foreach a $args {
if { [string length $pattern] > 0 } {
if { [string range $pattern end-1 end] != ".*" \
&& [string range $a 0 1] != ".*" } {
set pattern "${pattern},"
}
}
set pattern "${pattern}${a}"
}
set str "$str\\{${pattern}\\}"
return ${str}
}
# Helper to build expected MI output pattern for a single field. NAME
# is the name of the field, and PATTERN matches the fields contents.
# This proc will add quotes around PATTERN.
proc mi_field { name pattern } {
set str ""
if { $name != "" } {
set str "${name}="
}
set str "$str\"${pattern}\""
return ${str}
}
# Run tests on '-file-list-exec-source-files'. DEBUG_FULLY_READ is either the string
# "true" or "false" and indicates if the GDB will have read all the
# debug for the test program or not yet.
proc check_info_sources { debug_fully_read } {
with_test_prefix "debug_read=${debug_fully_read}" {
if { $debug_fully_read } {
set p [mi_list "files" \
[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_tuple "" \
[mi_field "file" "\[^\"\]+/mi-info-sources\\.c"] \
[mi_field "fullname" "\[^\"\]+/mi-info-sources\\.c"] \
[mi_field "debug-fully-read" "true"]]]
} else {
set p [mi_list "files" \
[mi_tuple "" \
[mi_field "file" "\[^\"\]+/mi-info-sources\\.c"] \
[mi_field "fullname" "\[^\"\]+/mi-info-sources\\.c"] \
[mi_field "debug-fully-read" "true"]] \
[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" ".*\\^done,${p}" "-file-list-exec-source-files"
set p [mi_list "files" \
[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 --basename -- base" ".*\\^done,${p}" \
"-file-list-exec-source-files --basename -- base"
}
}
check_info_sources "false"
mi_continue_to "some_other_func"
check_info_sources "true"