diff options
-rw-r--r-- | gdb/build-id.c | 14 | ||||
-rw-r--r-- | gdb/build-id.h | 10 | ||||
-rw-r--r-- | gdb/coffread.c | 14 | ||||
-rw-r--r-- | gdb/disasm.h | 2 | ||||
-rw-r--r-- | gdb/elfread.c | 16 | ||||
-rw-r--r-- | gdb/symfile.c | 42 | ||||
-rw-r--r-- | gdb/symfile.h | 9 | ||||
-rw-r--r-- | gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp | 24 | ||||
-rw-r--r-- | gdb/testsuite/gdb.debuginfod/crc_mismatch.exp | 33 | ||||
-rw-r--r-- | gdb/ui-file.h | 4 | ||||
-rw-r--r-- | gdb/utils.h | 52 |
11 files changed, 167 insertions, 53 deletions
diff --git a/gdb/build-id.c b/gdb/build-id.c index 65b493f..f68384f 100644 --- a/gdb/build-id.c +++ b/gdb/build-id.c @@ -26,6 +26,7 @@ #include "objfiles.h" #include "filenames.h" #include "gdbcore.h" +#include "cli/cli-style.h" /* See build-id.h. */ @@ -209,7 +210,7 @@ build_id_to_exec_bfd (size_t build_id_len, const bfd_byte *build_id) std::string find_separate_debug_file_by_buildid (struct objfile *objfile, - std::vector<std::string> *warnings_vector) + deferred_warnings *warnings) { const struct bfd_build_id *build_id; @@ -228,12 +229,13 @@ find_separate_debug_file_by_buildid (struct objfile *objfile, && filename_cmp (bfd_get_filename (abfd.get ()), objfile_name (objfile)) == 0) { - std::string msg - = string_printf (_("\"%s\": separate debug info file has no " - "debug info"), bfd_get_filename (abfd.get ())); if (separate_debug_file_debug) - gdb_printf (gdb_stdlog, "%s", msg.c_str ()); - warnings_vector->emplace_back (std::move (msg)); + gdb_printf (gdb_stdlog, "\"%s\": separate debug info file has no " + "debug info", bfd_get_filename (abfd.get ())); + warnings->warn (_("\"%ps\": separate debug info file has no " + "debug info"), + styled_string (file_name_style.style (), + bfd_get_filename (abfd.get ()))); } else if (abfd != NULL) return std::string (bfd_get_filename (abfd.get ())); diff --git a/gdb/build-id.h b/gdb/build-id.h index 191720d..a5c8b85 100644 --- a/gdb/build-id.h +++ b/gdb/build-id.h @@ -52,13 +52,13 @@ extern gdb_bfd_ref_ptr build_id_to_exec_bfd (size_t build_id_len, separate debug file, otherwise, return an empty string. Any warnings that are generated by the lookup process should be added to - WARNINGS_VECTOR, one std::string per warning. If some other mechanism can - be used to lookup the debug information then the warning will not be shown, - however, if GDB fails to find suitable debug information using any - approach, then any warnings will be printed. */ + WARNINGS. If some other mechanism can be used to lookup the debug + information then the warning will not be shown, however, if GDB fails to + find suitable debug information using any approach, then any warnings + will be printed. */ extern std::string find_separate_debug_file_by_buildid - (struct objfile *objfile, std::vector<std::string> *warnings_vector); + (struct objfile *objfile, deferred_warnings *warnings); /* Return an hex-string representation of BUILD_ID. */ diff --git a/gdb/coffread.c b/gdb/coffread.c index ff4d4ae..33fb2ba 100644 --- a/gdb/coffread.c +++ b/gdb/coffread.c @@ -729,13 +729,13 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) /* Try to add separate debug file if no symbols table found. */ if (!objfile->has_partial_symbols ()) { - std::vector<std::string> warnings_vector; + deferred_warnings warnings; std::string debugfile - = find_separate_debug_file_by_buildid (objfile, &warnings_vector); + = find_separate_debug_file_by_buildid (objfile, &warnings); if (debugfile.empty ()) debugfile - = find_separate_debug_file_by_debuglink (objfile, &warnings_vector); + = find_separate_debug_file_by_debuglink (objfile, &warnings); if (!debugfile.empty ()) { @@ -745,10 +745,10 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) symfile_flags, objfile); } /* If all the methods to collect the debuginfo failed, print any - warnings that were collected. */ - if (debugfile.empty () && !warnings_vector.empty ()) - for (const std::string &w : warnings_vector) - warning ("%s", w.c_str ()); + warnings that were collected, this is a no-op if there are no + warnings. */ + if (debugfile.empty ()) + warnings.emit (); } } diff --git a/gdb/disasm.h b/gdb/disasm.h index 7e1bb8d..dbc63e5 100644 --- a/gdb/disasm.h +++ b/gdb/disasm.h @@ -150,7 +150,7 @@ protected: DIS_INFO pointer is a pointer to a gdb_printing_disassembler object. Content is written to the m_stream extracted from DIS_INFO. */ static int fprintf_func (void *dis_info, const char *format, ...) noexcept - ATTRIBUTE_PRINTF(2,3); + ATTRIBUTE_PRINTF (2, 3); /* Callback used as the disassemble_info's fprintf_styled_func callback. The DIS_INFO pointer is a pointer to a gdb_printing_disassembler diff --git a/gdb/elfread.c b/gdb/elfread.c index 7697106..349a8b7 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -1225,14 +1225,13 @@ elf_symfile_read_dwarf2 (struct objfile *objfile, && objfile->separate_debug_objfile == NULL && objfile->separate_debug_objfile_backlink == NULL) { - std::vector<std::string> warnings_vector; + deferred_warnings warnings; std::string debugfile - = find_separate_debug_file_by_buildid (objfile, &warnings_vector); + = find_separate_debug_file_by_buildid (objfile, &warnings); if (debugfile.empty ()) - debugfile = find_separate_debug_file_by_debuglink (objfile, - &warnings_vector); + debugfile = find_separate_debug_file_by_debuglink (objfile, &warnings); if (!debugfile.empty ()) { @@ -1275,11 +1274,10 @@ elf_symfile_read_dwarf2 (struct objfile *objfile, } } } - /* If all the methods to collect the debuginfo failed, print - the warnings, if there're any. */ - if (debugfile.empty () && !has_dwarf2 && !warnings_vector.empty ()) - for (const std::string &w : warnings_vector) - warning ("%s", w.c_str ()); + /* If all the methods to collect the debuginfo failed, print the + warnings, this is a no-op if there are no warnings. */ + if (debugfile.empty () && !has_dwarf2) + warnings.emit (); } return has_dwarf2; diff --git a/gdb/symfile.c b/gdb/symfile.c index 3a0aee1..d284040 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -1243,7 +1243,7 @@ bool separate_debug_file_debug = false; static int separate_debug_file_exists (const std::string &name, unsigned long crc, struct objfile *parent_objfile, - std::vector<std::string> *warnings_vector) + deferred_warnings *warnings) { unsigned long file_crc; int file_crc_p; @@ -1336,13 +1336,16 @@ separate_debug_file_exists (const std::string &name, unsigned long crc, if (verified_as_different || parent_crc != file_crc) { - std::string msg - = string_printf (_("the debug information found in \"%s\"" - " does not match \"%s\" (CRC mismatch).\n"), - name.c_str (), objfile_name (parent_objfile)); if (separate_debug_file_debug) - gdb_printf (gdb_stdlog, "%s", msg.c_str ()); - warnings_vector->emplace_back (std::move (msg)); + gdb_printf (gdb_stdlog, "the debug information found in \"%s\"" + " does not match \"%s\" (CRC mismatch).\n", + name.c_str (), objfile_name (parent_objfile)); + warnings->warn (_("the debug information found in \"%ps\"" + " does not match \"%ps\" (CRC mismatch)."), + styled_string (file_name_style.style (), + name.c_str ()), + styled_string (file_name_style.style (), + objfile_name (parent_objfile))); } return 0; @@ -1378,14 +1381,17 @@ show_debug_file_directory (struct ui_file *file, int from_tty, string. Any warnings generated as part of the lookup process are added to - WARNINGS_VECTOR, one std::string per warning. */ + WARNINGS. If some other mechanism can be used to lookup the debug + information then the warning will not be shown, however, if GDB fails to + find suitable debug information using any approach, then any warnings + will be printed. */ static std::string find_separate_debug_file (const char *dir, const char *canon_dir, const char *debuglink, unsigned long crc32, struct objfile *objfile, - std::vector<std::string> *warnings_vector) + deferred_warnings *warnings) { if (separate_debug_file_debug) gdb_printf (gdb_stdlog, @@ -1396,7 +1402,7 @@ find_separate_debug_file (const char *dir, std::string debugfile = dir; debugfile += debuglink; - if (separate_debug_file_exists (debugfile, crc32, objfile, warnings_vector)) + if (separate_debug_file_exists (debugfile, crc32, objfile, warnings)) return debugfile; /* Then try in the subdirectory named DEBUG_SUBDIRECTORY. */ @@ -1405,7 +1411,7 @@ find_separate_debug_file (const char *dir, debugfile += "/"; debugfile += debuglink; - if (separate_debug_file_exists (debugfile, crc32, objfile, warnings_vector)) + if (separate_debug_file_exists (debugfile, crc32, objfile, warnings)) return debugfile; /* Then try in the global debugfile directories. @@ -1450,8 +1456,7 @@ find_separate_debug_file (const char *dir, debugfile += dir_notarget; debugfile += debuglink; - if (separate_debug_file_exists (debugfile, crc32, objfile, - warnings_vector)) + if (separate_debug_file_exists (debugfile, crc32, objfile, warnings)) return debugfile; const char *base_path = NULL; @@ -1473,8 +1478,7 @@ find_separate_debug_file (const char *dir, debugfile += "/"; debugfile += debuglink; - if (separate_debug_file_exists (debugfile, crc32, objfile, - warnings_vector)) + if (separate_debug_file_exists (debugfile, crc32, objfile, warnings)) return debugfile; /* If the file is in the sysroot, try using its base path in @@ -1501,7 +1505,7 @@ find_separate_debug_file (const char *dir, debugfile += debuglink; if (separate_debug_file_exists (debugfile, crc32, objfile, - warnings_vector)) + warnings)) return debugfile; } } @@ -1533,7 +1537,7 @@ terminate_after_last_dir_separator (char *path) std::string find_separate_debug_file_by_debuglink - (struct objfile *objfile, std::vector<std::string> *warnings_vector) + (struct objfile *objfile, deferred_warnings *warnings) { uint32_t crc32; @@ -1554,7 +1558,7 @@ find_separate_debug_file_by_debuglink std::string debugfile = find_separate_debug_file (dir.c_str (), canon_dir.get (), debuglink.get (), crc32, objfile, - warnings_vector); + warnings); if (debugfile.empty ()) { @@ -1579,7 +1583,7 @@ find_separate_debug_file_by_debuglink debuglink.get (), crc32, objfile, - warnings_vector); + warnings); } } } diff --git a/gdb/symfile.h b/gdb/symfile.h index 7c800ea..296fee9 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -244,11 +244,14 @@ extern void symbol_file_add_separate (const gdb_bfd_ref_ptr &, const char *, /* Find separate debuginfo for OBJFILE (using .gnu_debuglink section). Returns pathname, or an empty string. - Any warnings generated as part of this lookup are added to - WARNINGS_VECTOR, one std::string per warning. */ + Any warnings generated as part of this lookup are added to WARNINGS. If + some other mechanism can be used to lookup the debug information then + the warning will not be shown, however, if GDB fails to find suitable + debug information using any approach, then any warnings will be + printed. */ extern std::string find_separate_debug_file_by_debuglink - (struct objfile *objfile, std::vector<std::string> *warnings_vector); + (struct objfile *objfile, deferred_warnings *warnings); /* Build (allocate and populate) a section_addr_info struct from an existing section table. */ diff --git a/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp b/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp index b49770f..148363a 100644 --- a/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp +++ b/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp @@ -95,6 +95,30 @@ gdb_test "file ${build_id_debug_file}" \ "\\(No debugging symbols found in \[^\r\n\]+\\)"] \ "load test file, expect a warning" +# Do the same thing again, but this time check that the styling is +# correct. +with_test_prefix "check styling" { + save_vars { env(TERM) } { + # We need an ANSI-capable terminal to get styled output. + setenv TERM ansi + + clean_restart + + gdb_test_no_output "set debug-file-directory ${debug_file_directory}" \ + "set debug-file-directory" + + # Now load the file into GDB, and look for the warning. + set debug_file_re [style [string_to_regexp $build_id_debug_file] file] + + gdb_test "file ${build_id_debug_file}" \ + [multi_line \ + "Reading symbols from $debug_file_re\\.\\.\\." \ + "warning: \"$debug_file_re\": separate debug info file has no debug info" \ + "\\(No debugging symbols found in \[^\r\n\]+\\)"] \ + "load test file, expect a warning" + } +} + # Now we should close GDB. gdb_exit diff --git a/gdb/testsuite/gdb.debuginfod/crc_mismatch.exp b/gdb/testsuite/gdb.debuginfod/crc_mismatch.exp index 588fb7e..074028e 100644 --- a/gdb/testsuite/gdb.debuginfod/crc_mismatch.exp +++ b/gdb/testsuite/gdb.debuginfod/crc_mismatch.exp @@ -58,12 +58,39 @@ if {[build_executable crc_mismatch.exp crc_mismatch-2 crc_mismatch-2.c debug] != # to trigger the "CRC mismatch" warning. remote_exec build "mv ${debugfile} [standard_output_file crc_mismatch-2.debug]" - gdb_exit - gdb_start + clean_restart set escapedobjdirsubdir [string_to_regexp [standard_output_file {}]] + gdb_test "file [standard_output_file crc_mismatch-2]" \ + [multi_line \ + "Reading symbols from ${escapedobjdirsubdir}/crc_mismatch-2\\.\\.\\." \ + "warning: the debug information found in \"${escapedobjdirsubdir}/crc_mismatch-2\\.debug\" does not match \"${escapedobjdirsubdir}/crc_mismatch-2\" \\(CRC mismatch\\)\\." \ + "\\(No debugging symbols found in .*\\)"] \ + "CRC mismatch is reported" + + # Do the same thing again, but this time check that the styling is + # correct. + with_test_prefix "check styling" { + save_vars { env(TERM) } { + # We need an ANSI-capable terminal to get styled output. + setenv TERM ansi + + clean_restart + + set debug_file_re [style "${escapedobjdirsubdir}/crc_mismatch-2\\.debug" file] + set exe_file_re [style "${escapedobjdirsubdir}/crc_mismatch-2" file] + + gdb_test "file [standard_output_file crc_mismatch-2]" \ + [multi_line \ + "Reading symbols from ${exe_file_re}\\.\\.\\." \ + "warning: the debug information found in \"${debug_file_re}\" does not match \"${exe_file_re}\" \\(CRC mismatch\\)\\." \ + "\\(No debugging symbols found in \[^\r\n\]+\\)"] \ + "CRC mismatch is reported" + } + } - gdb_test "file [standard_output_file crc_mismatch-2]" "warning: the debug information found in \"${escapedobjdirsubdir}/crc_mismatch-2\\.debug\" does not match \"${escapedobjdirsubdir}/crc_mismatch-2\" \\(CRC mismatch\\)\\..*\\(No debugging symbols found in .*\\).*" "CRC mismatch is reported" + # Restart GDB with styling disabled. + clean_restart } # Create CACHE and DB directories ready for debuginfod to use. diff --git a/gdb/ui-file.h b/gdb/ui-file.h index de24620..31f87ff 100644 --- a/gdb/ui-file.h +++ b/gdb/ui-file.h @@ -30,6 +30,8 @@ public: ui_file (); virtual ~ui_file () = 0; + ui_file (ui_file &&other) = default; + /* Public non-virtual API. */ void printf (const char *, ...) ATTRIBUTE_PRINTF (2, 3); @@ -177,6 +179,8 @@ public: explicit string_file (bool term_out) : m_term_out (term_out) {}; ~string_file () override; + string_file (string_file &&other) = default; + /* Override ui_file methods. */ void write (const char *buf, long length_buf) override; diff --git a/gdb/utils.h b/gdb/utils.h index ad0a867..c5364fa 100644 --- a/gdb/utils.h +++ b/gdb/utils.h @@ -367,4 +367,56 @@ assign_return_if_changed (T &lval, const T &val) return true; } +/* In some cases GDB needs to try several different solutions to a problem, + if any of the solutions work then as far as the user is concerned the + problem is solved, and GDB should continue without warnings. However, + if none of the solutions work then GDB should emit any warnings that + occurred while trying each possible solution. + + One example of this is locating separate debug info. There are several + different approaches for this; following the .gnu_debuglink, a build-id + based lookup, or using debuginfod. If any works, and debug info is + located, then the user doesn't want to see warnings from the earlier + approaches that were tried and failed. + + However, GDB should emit all the warnings using separate calls to + warning -- this ensures that each warning is formatted on its own line, + and that any styling is emitted correctly. + + This class helps with deferring warnings. Warnings can be added to an + instance of this class with the 'warn' function, and all warnings can be + emitted with a single call to 'emit'. */ + +struct deferred_warnings +{ + /* Add a warning to the list of deferred warnings. */ + void warn (const char *format, ...) ATTRIBUTE_PRINTF(2,3) + { + /* Generate the warning text into a string_file. We allow the text to + be styled only if gdb_stderr allows styling -- warnings are sent to + gdb_stderr. */ + string_file msg (gdb_stderr->can_emit_style_escape ()); + + va_list args; + va_start (args, format); + msg.vprintf (format, args); + va_end (args); + + /* Move the text into the list of deferred warnings. */ + m_warnings.emplace_back (std::move (msg)); + } + + /* Emit all warnings. */ + void emit () const + { + for (const auto &w : m_warnings) + warning ("%s", w.c_str ()); + } + +private: + + /* The list of all deferred warnings. */ + std::vector<string_file> m_warnings; +}; + #endif /* UTILS_H */ |