From: Andrew Burgess Date: Tue, 18 May 2021 12:46:19 +0000 (+0100) Subject: gdb/mi: add regexp filtering to -file-list-exec-source-files X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0e350a054bbeb4d00f2c430c4815c82d5ffb47a7;p=binutils-gdb.git 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) : Take uiout argument, store into m_uiout. : Rewrite comment, add additional arguments to declaration. : Send more arguments to output. : 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f4805f8efee..aa1d458b2cf 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,30 @@ +2021-06-25 Andrew Burgess + + * 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) + : Take uiout argument, store into + m_uiout. : Rewrite comment, add additional arguments to + declaration. : Send more arguments to + output. : 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 * symtab.c (struct info_sources_filter): New. diff --git a/gdb/NEWS b/gdb/NEWS index aae3b49b408..8d79c50e1be 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -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 diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index fc16fc5f2a7..4dc190407d4 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2021-06-25 Andrew Burgess + + * gdb.texinfo (GDB/MI File Commands): Document extensions to + -file-list-exec-source-files. + 2021-06-25 Andrew Burgess * python.texinfo (Breakpoints In Python): Add BP_CATCHPOINT diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index dfc00b120b4..1e56c3a882b 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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 -@end smallexample + -file-list-exec-source-files @r{[} @var{--dirname} @r{|} @var{--basename} @r{]} + @r{[} -- @r{]} + @r{[} @var{regexp} @r{]} +@end smallexample + +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}. + +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. -List the source files for the current executable. +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{-}). -It will always output both the filename and fullname (absolute file -name) of a source file. +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 diff --git a/gdb/mi/mi-cmd-file.c b/gdb/mi/mi-cmd-file.c index 430449c919e..684f7eb3f0c 100644 --- a/gdb/mi/mi-cmd-file.c +++ b/gdb/mi/mi-cmd-file.c @@ -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 + { + 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) { - for (compunit_symtab *cu : objfile->compunits ()) + 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")); + + 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; - uiout->end (ui_out_type_list); + info_sources_filter filter (match_type, regexp); + info_sources_worker (current_uiout, filter); } /* See mi-cmds.h. */ diff --git a/gdb/symtab.c b/gdb/symtab.c index 2ff79e0cddf..e300596be6e 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -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 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 output_tuple; + gdb::optional 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 (_("\ diff --git a/gdb/symtab.h b/gdb/symtab.h index a5d0168faf0..db0df5cb4bb 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -2385,4 +2385,67 @@ private: std::vector 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 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) */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 9bf8e9ebcc1..7eb13b82dfa 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2021-06-25 Andrew Burgess + + * 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 * gdb.cp/method-call-in-c.cc (struct foo_type): Add static member diff --git a/gdb/testsuite/gdb.dwarf2/dw2-filename.exp b/gdb/testsuite/gdb.dwarf2/dw2-filename.exp index 3e60f7d2bc9..bd303c8547b 100644 --- a/gdb/testsuite/gdb.dwarf2/dw2-filename.exp +++ b/gdb/testsuite/gdb.dwarf2/dw2-filename.exp @@ -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.*} diff --git a/gdb/testsuite/gdb.mi/mi-file.exp b/gdb/testsuite/gdb.mi/mi-file.exp index 15d7d9f0944..4cae33c017e 100644 --- a/gdb/testsuite/gdb.mi/mi-file.exp +++ b/gdb/testsuite/gdb.mi/mi-file.exp @@ -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." } diff --git a/gdb/testsuite/gdb.mi/mi-info-sources-base.c b/gdb/testsuite/gdb.mi/mi-info-sources-base.c new file mode 100644 index 00000000000..cc736123600 --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-info-sources-base.c @@ -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 . */ + +/* This file was originally copied from gdb.base/info_sources_base.c. */ + +void some_other_func (void) +{ + return; +} diff --git a/gdb/testsuite/gdb.mi/mi-info-sources.c b/gdb/testsuite/gdb.mi/mi-info-sources.c new file mode 100644 index 00000000000..b91b8280c2b --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-info-sources.c @@ -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 . */ + +/* This file was originally copied from gdb.base/info_sources.c. */ + +extern void some_other_func (void); +int main () +{ + some_other_func (); + return 0; +} diff --git a/gdb/testsuite/gdb.mi/mi-info-sources.exp b/gdb/testsuite/gdb.mi/mi-info-sources.exp new file mode 100644 index 00000000000..c218af4ba80 --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-info-sources.exp @@ -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 . + +# 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"