diff --git a/gdb/build-id.c b/gdb/build-id.c index 801eb004ad7..00250c20ae9 100644 --- a/gdb/build-id.c +++ b/gdb/build-id.c @@ -208,7 +208,8 @@ build_id_to_exec_bfd (size_t build_id_len, const bfd_byte *build_id) /* See build-id.h. */ std::string -find_separate_debug_file_by_buildid (struct objfile *objfile) +find_separate_debug_file_by_buildid (struct objfile *objfile, + std::vector *warnings_vector) { const struct bfd_build_id *build_id; @@ -226,8 +227,14 @@ find_separate_debug_file_by_buildid (struct objfile *objfile) if (abfd != NULL && filename_cmp (bfd_get_filename (abfd.get ()), objfile_name (objfile)) == 0) - warning (_("\"%s\": separate debug info file has no debug info"), - bfd_get_filename (abfd.get ())); + { + 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)); + } 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 4c3f8e0479a..191720ddf28 100644 --- a/gdb/build-id.h +++ b/gdb/build-id.h @@ -49,10 +49,16 @@ extern gdb_bfd_ref_ptr build_id_to_exec_bfd (size_t build_id_len, /* Find the separate debug file for OBJFILE, by using the build-id associated with OBJFILE's BFD. If successful, returns the file name for the - separate debug file, otherwise, return an empty string. */ + 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. */ extern std::string find_separate_debug_file_by_buildid - (struct objfile *objfile); + (struct objfile *objfile, std::vector *warnings_vector); /* Return an hex-string representation of BUILD_ID. */ diff --git a/gdb/coffread.c b/gdb/coffread.c index 4950a7324c8..8f2a8673e10 100644 --- a/gdb/coffread.c +++ b/gdb/coffread.c @@ -734,10 +734,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::string debugfile = find_separate_debug_file_by_buildid (objfile); + std::vector warnings_vector; + std::string debugfile + = find_separate_debug_file_by_buildid (objfile, &warnings_vector); if (debugfile.empty ()) - debugfile = find_separate_debug_file_by_debuglink (objfile); + debugfile + = find_separate_debug_file_by_debuglink (objfile, &warnings_vector); if (!debugfile.empty ()) { @@ -746,6 +749,11 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) symbol_file_add_separate (debug_bfd, debugfile.c_str (), 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 ()); } } diff --git a/gdb/elfread.c b/gdb/elfread.c index ccee37406c8..45cd73b01af 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -1213,10 +1213,14 @@ elf_symfile_read_dwarf2 (struct objfile *objfile, && objfile->separate_debug_objfile == NULL && objfile->separate_debug_objfile_backlink == NULL) { - std::string debugfile = find_separate_debug_file_by_buildid (objfile); + std::vector warnings_vector; + + std::string debugfile + = find_separate_debug_file_by_buildid (objfile, &warnings_vector); if (debugfile.empty ()) - debugfile = find_separate_debug_file_by_debuglink (objfile); + debugfile = find_separate_debug_file_by_debuglink (objfile, + &warnings_vector); if (!debugfile.empty ()) { @@ -1258,6 +1262,11 @@ 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 ()); } return has_dwarf2; diff --git a/gdb/symfile.c b/gdb/symfile.c index 181f859052a..373f5592107 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -1243,7 +1243,8 @@ bool separate_debug_file_debug = false; static int separate_debug_file_exists (const std::string &name, unsigned long crc, - struct objfile *parent_objfile) + struct objfile *parent_objfile, + std::vector *warnings_vector) { unsigned long file_crc; int file_crc_p; @@ -1335,12 +1336,15 @@ separate_debug_file_exists (const std::string &name, unsigned long crc, } if (verified_as_different || parent_crc != file_crc) - warning (_("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, _(" no, CRC doesn't match.\n")); + { + 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)); + } return 0; } @@ -1372,13 +1376,17 @@ show_debug_file_directory (struct ui_file *file, int from_tty, looking for. CANON_DIR is the "realpath" form of DIR. DIR must contain a trailing '/'. Returns the path of the file with separate debug info, or an empty - string. */ + string. + + Any warnings generated as part of the lookup process are added to + WARNINGS_VECTOR, one std::string per warning. */ static std::string find_separate_debug_file (const char *dir, const char *canon_dir, const char *debuglink, - unsigned long crc32, struct objfile *objfile) + unsigned long crc32, struct objfile *objfile, + std::vector *warnings_vector) { if (separate_debug_file_debug) gdb_printf (gdb_stdlog, @@ -1389,7 +1397,7 @@ find_separate_debug_file (const char *dir, std::string debugfile = dir; debugfile += debuglink; - if (separate_debug_file_exists (debugfile, crc32, objfile)) + if (separate_debug_file_exists (debugfile, crc32, objfile, warnings_vector)) return debugfile; /* Then try in the subdirectory named DEBUG_SUBDIRECTORY. */ @@ -1398,7 +1406,7 @@ find_separate_debug_file (const char *dir, debugfile += "/"; debugfile += debuglink; - if (separate_debug_file_exists (debugfile, crc32, objfile)) + if (separate_debug_file_exists (debugfile, crc32, objfile, warnings_vector)) return debugfile; /* Then try in the global debugfile directories. @@ -1443,7 +1451,8 @@ find_separate_debug_file (const char *dir, debugfile += dir_notarget; debugfile += debuglink; - if (separate_debug_file_exists (debugfile, crc32, objfile)) + if (separate_debug_file_exists (debugfile, crc32, objfile, + warnings_vector)) return debugfile; const char *base_path = NULL; @@ -1465,7 +1474,8 @@ find_separate_debug_file (const char *dir, debugfile += "/"; debugfile += debuglink; - if (separate_debug_file_exists (debugfile, crc32, objfile)) + if (separate_debug_file_exists (debugfile, crc32, objfile, + warnings_vector)) return debugfile; /* If the file is in the sysroot, try using its base path in @@ -1491,7 +1501,8 @@ find_separate_debug_file (const char *dir, debugfile += "/"; debugfile += debuglink; - if (separate_debug_file_exists (debugfile, crc32, objfile)) + if (separate_debug_file_exists (debugfile, crc32, objfile, + warnings_vector)) return debugfile; } } @@ -1519,11 +1530,11 @@ terminate_after_last_dir_separator (char *path) path[i + 1] = '\0'; } -/* Find separate debuginfo for OBJFILE (using .gnu_debuglink section). - Returns pathname, or an empty string. */ +/* See symtab.h. */ std::string -find_separate_debug_file_by_debuglink (struct objfile *objfile) +find_separate_debug_file_by_debuglink + (struct objfile *objfile, std::vector *warnings_vector) { unsigned long crc32; @@ -1543,7 +1554,8 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile) std::string debugfile = find_separate_debug_file (dir.c_str (), canon_dir.get (), - debuglink.get (), crc32, objfile); + debuglink.get (), crc32, objfile, + warnings_vector); if (debugfile.empty ()) { @@ -1567,7 +1579,8 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile) symlink_dir.get (), debuglink.get (), crc32, - objfile); + objfile, + warnings_vector); } } } diff --git a/gdb/symfile.h b/gdb/symfile.h index 81cf80d8719..b433e2be31a 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -241,7 +241,14 @@ extern struct objfile *symbol_file_add_from_bfd (const gdb_bfd_ref_ptr &, extern void symbol_file_add_separate (const gdb_bfd_ref_ptr &, const char *, symfile_add_flags, struct objfile *); -extern std::string find_separate_debug_file_by_debuglink (struct objfile *); +/* 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. */ + +extern std::string find_separate_debug_file_by_debuglink + (struct objfile *objfile, std::vector *warnings_vector); /* 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.c b/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.c new file mode 100644 index 00000000000..c40394562bf --- /dev/null +++ b/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.c @@ -0,0 +1,20 @@ +/* Copyright 2022-2023 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 . */ + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp b/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp new file mode 100644 index 00000000000..1102d9bf254 --- /dev/null +++ b/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp @@ -0,0 +1,142 @@ +# Copyright 2022-2023 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 test triggers the "separate debug info file has no debug info" warning by replacing +# the build-id based .debug file with the stripped binary and then loading it to gdb. +# It then also sets up local debuginfod server with the correct debug file to download +# to make sure no warnings are emmitted. + + +standard_testfile + +load_lib debuginfod-support.exp + +require allow_debuginfod_tests + +if {[build_executable "build executable" ${testfile} ${srcfile} \ + {debug build-id}] == -1} { + return -1 +} + +# Split BINFILE into BINFILE.stripped and BINFILE.debug, the first is +# the executable with the debug information removed, and the second is +# the debug information. +# +# However, by passing the "no-debuglink" flag we prevent this proc +# from adding a .gnu_debuglink section to the executable. Any lookup +# of the debug information by GDB will need to be done based on the +# build-id. +if {[gdb_gnu_strip_debug $binfile no-debuglink]} { + unsupported "cannot produce separate debug info files" + return -1 +} + +# Get the .build-id/PREFIX/SUFFIX.debug file name, and convert it to +# an absolute path, this is where we will place the debug information. +set build_id_debug_file \ + [standard_output_file [build_id_debug_filename_get $binfile]] + +# Get the BINFILE.debug filename. This is the file we should be +# moving to the BUILD_ID_DEBUG_FILE location, but we wont, we're going +# to move something else there instead. +set debugfile [standard_output_file "${binfile}.debug"] + +# Move debugfile to the directory to be used by the debuginfod +# server. +set debuginfod_debugdir [standard_output_file "debug"] +remote_exec build "mkdir $debuginfod_debugdir" +remote_exec build "mv $debugfile $debuginfod_debugdir" + +# This is BINFILE with the debug information removed. We are going to +# place this in the BUILD_ID_DEBUG_FILE location, this would usually +# represent a mistake by the user, and will trigger a warning from +# GDB, this is the warning we are checking for. +set stripped_binfile [standard_output_file "${binfile}.stripped"] + +# Create the .build-id/PREFIX directory name from +# .build-id/PREFIX/SUFFIX.debug filename. +set debugdir [file dirname ${build_id_debug_file}] +remote_exec build "mkdir -p $debugdir" + +# Now move the stripped executable into the .build-id directory +# instead of the debug information. Later on we're going to try and +# load this into GDB. GDB will then try to find the separate debug +# information, which will point back at this file, which also doesn't +# have debug information, which could cause a loop. But GDB will spot +# this and give a warning. +remote_exec build "mv ${stripped_binfile} ${build_id_debug_file}" + +# Now start GDB. +clean_restart + +# Tell GDB where to look for the .build-id directory. +set debug_file_directory [standard_output_file ""] +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. +gdb_test "file ${build_id_debug_file}" \ + [multi_line \ + ".*Reading symbols from.*debuginfo.*" \ + ".*separate debug info file has no debug info.*"] \ + "load test file, expect a warning" + +# Now we should close GDB. +gdb_exit + +# Create CACHE and DB directories ready for debuginfod to use. +prepare_for_debuginfod cache db + +# Start debuginfod server and test debuginfo is downloaded from +# it and we can se no warnings anymore. +proc_with_prefix local_debuginfod { } { + global db debuginfod_debugdir cache build_id_debug_file + + set url [start_debuginfod $db $debuginfod_debugdir] + if {$url eq ""} { + unresolved "failed to start debuginfod server" + return + } + + # Point the client to the server. + setenv DEBUGINFOD_URLS $url + + # GDB should now find the symbol and source files. + clean_restart + + # Enable debuginfod and fetch the debuginfo. + gdb_test_no_output "set debuginfod enabled on" + + # "separate debug info file has no debug info" warning should not be + # reported now because the correct debuginfo should be fetched from + # debuginfod. + gdb_test "file ${build_id_debug_file}" \ + [multi_line \ + "Reading symbols from ${build_id_debug_file}\\.\\.\\." \ + "Downloading separate debug info for ${build_id_debug_file}\\.\\.\\." \ + "Reading symbols from ${cache}/\[^\r\n\]+\\.\\.\\.(?:\r\nExpanding full symbols from \[^\r\n\]+)*"] \ + "debuginfod running, info downloaded, no warnings" +} + +# Restart GDB, and load the file, this time we should correctly get +# the debug symbols from the server, and should not see the warning. +with_debuginfod_env $cache { + local_debuginfod +} + +stop_debuginfod +# Spare debug files may confuse testsuite runs in the future. +remote_exec build "rm -f $debugfile" + diff --git a/gdb/testsuite/gdb.debuginfod/crc_mismatch-2.c b/gdb/testsuite/gdb.debuginfod/crc_mismatch-2.c new file mode 100644 index 00000000000..b74a9fc08a6 --- /dev/null +++ b/gdb/testsuite/gdb.debuginfod/crc_mismatch-2.c @@ -0,0 +1,22 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022-2023 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 . */ + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.debuginfod/crc_mismatch.c b/gdb/testsuite/gdb.debuginfod/crc_mismatch.c new file mode 100644 index 00000000000..3bfcf47b780 --- /dev/null +++ b/gdb/testsuite/gdb.debuginfod/crc_mismatch.c @@ -0,0 +1,20 @@ +/* Copyright 2022-2023 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 . */ + +int +main (int argc, char **argv, char **envp) +{ + return argc; +} diff --git a/gdb/testsuite/gdb.debuginfod/crc_mismatch.exp b/gdb/testsuite/gdb.debuginfod/crc_mismatch.exp new file mode 100644 index 00000000000..ff1a4663260 --- /dev/null +++ b/gdb/testsuite/gdb.debuginfod/crc_mismatch.exp @@ -0,0 +1,111 @@ +# Copyright 2022-2023 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 test compiles two executables: crc_mismatch and crc_mismatch-2 +# and then strips them of debuginfo creating separate debug files. The test +# then replaces crc_mismatch-2.debug with crc_mismatch.debug to trigger +# "CRC mismatch" warning. A local debuginfod server is setup to supply +# the correct debug file, now when GDB looks up the debug info no warning +# is given. + +standard_testfile .c -2.c + +load_lib debuginfod-support.exp + +require allow_debuginfod_tests + +if {[build_executable "build executable" $testfile $srcfile debug] == -1} { + untested "failed to compile" + return -1 +} + +# The procedure gdb_gnu_strip_debug will produce an executable called +# ${binfile}, which is just like the executable ($binfile) but without +# the debuginfo. Instead $binfile has a .gnu_debuglink section which +# contains the name of a debuginfo only file. +if {[gdb_gnu_strip_debug $binfile]} { + # Check that you have a recent version of strip and objcopy installed. + unsupported "cannot produce separate debug info files" + return -1 +} + +set debugfile "$[standard_output_file ${testfile}.debug]" +set debugdir [standard_output_file "debug"] +remote_exec build "mkdir $debugdir" +remote_exec build "mkdir -p [file dirname $debugfile]" +remote_exec build "mv -f [standard_output_file ${testfile}.debug] $debugfile" + +# Test CRC mismatch is reported. +if {[build_executable crc_mismatch.exp crc_mismatch-2 crc_mismatch-2.c debug] != -1 + && ![gdb_gnu_strip_debug [standard_output_file crc_mismatch-2]]} { + + # Copy the correct debug file for crc_mismatch-2 to the debugdir + # which is going to be used by local debuginfod. + remote_exec build "cp [standard_output_file crc_mismatch-2.debug] ${debugdir}" + # Move the unmatching debug file for crc_mismatch-2 instead of its real one + # to trigger the "CRC mismatch" warning. + remote_exec build "mv ${debugfile} [standard_output_file crc_mismatch-2.debug]" + + gdb_exit + gdb_start + + set escapedobjdirsubdir [string_to_regexp [standard_output_file {}]] + + 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" +} + +# Create CACHE and DB directories ready for debuginfod to use. +prepare_for_debuginfod cache db + +# Start debuginfod server, test the correct debuginfo was fetched +# from the server so there're not warnings anymore. +proc_with_prefix local_debuginfod { } { + global binfile db debugdir cache + set escapedobjdirsubdir [string_to_regexp [standard_output_file {}]] + + set url [start_debuginfod $db $debugdir] + if {$url eq ""} { + unresolved "failed to start debuginfod server" + return + } + + # Point the client to the server. + setenv DEBUGINFOD_URLS $url + + # GDB should now find the symbol and source files. + clean_restart + + # Enable debuginfod and fetch the debuginfo. + gdb_test_no_output "set debuginfod enabled on" + gdb_test "file $binfile" ".*Reading symbols from.*debuginfo.*" \ + "file [file tail $binfile] cmd on" + + # CRC mismatch should not be reported now because the correct debuginfo + # should be fetched from debuginfod. + gdb_test "file [standard_output_file crc_mismatch-2]" \ + [multi_line \ + "Reading symbols from ${escapedobjdirsubdir}/crc_mismatch-2\\.\\.\\." \ + "Downloading separate debug info for ${escapedobjdirsubdir}/crc_mismatch-2\\.\\.\\." \ + "Reading symbols from ${cache}/\[^\r\n\]+\\.\\.\\.(?:\r\nExpanding full symbols from \[^\r\n\]+)*"] \ + "debuginfod running, info downloaded, no CRC mismatch" +} + +with_debuginfod_env $cache { + local_debuginfod +} + +stop_debuginfod +# Spare debug files may confuse testsuite runs in the future. +remote_exec build "rm -f $debugfile" diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 7f273bb91f7..fe3a2c06d0a 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -7183,9 +7183,19 @@ proc build_id_debug_filename_get { filename } { return ".build-id/${data}.debug" } -# Create stripped files for DEST, replacing it. If ARGS is passed, it is a -# list of optional flags. The only currently supported flag is no-main, -# which removes the symbol entry for main from the separate debug file. +# DEST should be a file compiled with debug information. This proc +# creates two new files DEST.debug which contains the debug +# information extracted from DEST, and DEST.stripped, which is a copy +# of DEST with the debug information removed. A '.gnu_debuglink' +# section will be added to DEST.stripped that points to DEST.debug. +# +# If ARGS is passed, it is a list of optional flags. The currently +# supported flags are: +# +# - no-main : remove the symbol entry for main from the separate +# debug file DEST.debug, +# - no-debuglink : don't add the '.gnu_debuglink' section to +# DEST.stripped. # # Function returns zero on success. Function will return non-zero failure code # on some targets not supporting separate debug info (such as i386-msdos). @@ -7230,7 +7240,7 @@ proc gdb_gnu_strip_debug { dest args } { # leaves the symtab in the original file only. There's no way to get # objcopy or strip to remove the symbol table without also removing the # debugging sections, so this is as close as we can get. - if { [llength $args] == 1 && [lindex $args 0] == "no-main" } { + if {[lsearch -exact $args "no-main"] != -1} { set result [catch "exec $objcopy_program -N main ${debug_file} ${debug_file}-tmp" output] verbose "result is $result" verbose "output is $output" @@ -7241,15 +7251,17 @@ proc gdb_gnu_strip_debug { dest args } { file rename "${debug_file}-tmp" "${debug_file}" } - # Link the two previous output files together, adding the .gnu_debuglink - # section to the stripped_file, containing a pointer to the debug_file, - # save the new file in dest. - # This will be the regular executable filename, in the usual location. - set result [catch "exec $objcopy_program --add-gnu-debuglink=${debug_file} ${stripped_file} ${dest}" output] - verbose "result is $result" - verbose "output is $output" - if {$result == 1} { - return 1 + # Unless the "no-debuglink" flag is passed, then link the two + # previous output files together, adding the .gnu_debuglink + # section to the stripped_file, containing a pointer to the + # debug_file, save the new file in dest. + if {[lsearch -exact $args "no-debuglink"] == -1} { + set result [catch "exec $objcopy_program --add-gnu-debuglink=${debug_file} ${stripped_file} ${dest}" output] + verbose "result is $result" + verbose "output is $output" + if {$result == 1} { + return 1 + } } # Workaround PR binutils/10802: