aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/build-id.c14
-rw-r--r--gdb/build-id.h10
-rw-r--r--gdb/coffread.c14
-rw-r--r--gdb/disasm.h2
-rw-r--r--gdb/elfread.c16
-rw-r--r--gdb/symfile.c42
-rw-r--r--gdb/symfile.h9
-rw-r--r--gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp24
-rw-r--r--gdb/testsuite/gdb.debuginfod/crc_mismatch.exp33
-rw-r--r--gdb/ui-file.h4
-rw-r--r--gdb/utils.h52
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 */