index_wip_file (const char *dir, const char *basename,
const char *suffix)
{
+ /* Validate DIR is a valid directory. */
+ struct stat buf;
+ if (stat (dir, &buf) == -1)
+ perror_with_name (string_printf (_("`%s'"), dir).c_str ());
+ if ((buf.st_mode & S_IFDIR) != S_IFDIR)
+ error (_("`%s': Is not a directory."), dir);
+
filename = (std::string (dir) + SLASH_STRING + basename
+ suffix);
scoped_fd out_file_fd = gdb_mkostemp_cloexec (filename_temp.data (),
O_BINARY);
if (out_file_fd.get () == -1)
- perror_with_name (("mkstemp"));
+ perror_with_name (string_printf (_("couldn't open `%s'"),
+ filename_temp.data ()).c_str ());
out_file = out_file_fd.to_file ("wb");
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 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 <http://www.gnu.org/licenses/>. */
+
+int
+main ()
+{
+ return 0;
+}
--- /dev/null
+# Copyright 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 <http://www.gnu.org/licenses/>.
+
+# Test some error messages that can arise from the 'save gdb-index'
+# command.
+
+standard_testfile
+
+if {[prepare_for_testing "prepare for test" $testfile $srcfile] == -1} {
+ return -1
+}
+
+# This test isn't going to work when the board file automatically adds
+# an index section, or if the debug information is split into a
+# separate objfile.
+set index_type [get_index_type $binfile "check debug style"]
+if { $index_type ne "cooked" } {
+ unsupported "cannot test without a cooked index"
+ return -1
+}
+
+
+# The name of a directory that doesn't exist.
+set bad_dir [standard_output_file "non-existent"]
+
+# Try to write the index into a non-existent directory.
+foreach_with_prefix flag { "" "-dwarf-5" } {
+ gdb_test "save gdb-index ${flag} ${bad_dir}" \
+ "Error while writing index for `[string_to_regexp $binfile]': `[string_to_regexp $bad_dir]': No such file or directory\\." \
+ "try to write index to non-existent directory"
+}
+
+# Create a text-file.
+set text_file [standard_output_file "text-file"]
+set fd [open $text_file w]
+puts $fd "A line of text.\n"
+close $fd
+
+# Try to write the index into something that is not a directory.
+foreach_with_prefix flag { "" "-dwarf-5" } {
+ gdb_test "save gdb-index ${flag} ${text_file}" \
+ "Error while writing index for `[string_to_regexp $binfile]': `[string_to_regexp $text_file]': Is not a directory\\." \
+ "try to write index to something that's not a directory"
+}
+
+# Create a directory which can't be written too.
+set non_writable_dir [standard_output_file "private"]
+remote_exec host "mkdir -p ${non_writable_dir}"
+remote_exec host "chmod u-w,g-w ${non_writable_dir}"
+
+# Try to write the index into a non-writable directory.
+foreach_with_prefix flag { "" "-dwarf-5" } {
+ gdb_test "save gdb-index ${flag} ${non_writable_dir}" \
+ "Error while writing index for `[string_to_regexp $binfile]': couldn't open `[string_to_regexp $non_writable_dir]/${gdb_test_file_name}.*': Permission denied\\." \
+ "try to write index to a non-writable directory"
+}
+
+# Create copies of the executable, we will add an index section to
+# each of these.
+remote_exec host "cp $binfile ${binfile}.gdb_index"
+remote_exec host "cp $binfile ${binfile}.dwarf_5"
+
+# Create a directory in which we can try to generate the index files.
+set already_indexed_dir [standard_output_file "already_indexed"]
+remote_exec host "mkdir -p $already_indexed_dir"
+
+foreach_with_prefix flag { "" "-dwarf-5" } {
+ if { $flag eq "" } {
+ set extension "gdb_index"
+ } else {
+ set extension "dwarf_5"
+ }
+
+ # Add the index section to the executable.
+ clean_restart ${binfile}.${extension}
+ gdb_assert {[ensure_gdb_index ${binfile}.${extension} ${flag}] == 1} \
+ "add index to executable"
+
+ # Reload the executable (which now has an index), and try to
+ # generate and index from it. This will fail.
+ clean_restart ${binfile}.${extension}
+ gdb_test "save gdb-index ${flag} $already_indexed_dir" \
+ "Error while writing index for `[string_to_regexp $binfile.$extension]': Cannot use an index to create the index" \
+ "try to generate an index from a binary with an index"
+}
|| [lsearch -exact $::GDBFLAGS --readnow] != -1}]
}
-# Return index name if symbols were read in using an index.
-# Otherwise, return "".
+# Return 'gdb_index' if the symbols from OBJFILE were read using a
+# .gdb_index index. Return 'debug_names' if the symbols were read
+# using a DWARF-5 style .debug_names index. Otherwise, return an
+# empty string.
proc have_index { objfile } {
+
# This proc is mostly used with $binfile, but that gives problems with
# remote host, while using $testfile would work.
# Fix this by reducing $binfile to $testfile.
set objfile [file tail $objfile]
- set res ""
- set cmd "maint print objfiles $objfile"
- gdb_test_multiple $cmd "" -lbl {
- -re "\r\n.gdb_index: faked for \"readnow\"" {
- set res ""
- exp_continue
- }
- -re "\r\n.gdb_index:" {
- set res "gdb_index"
- exp_continue
- }
- -re "\r\n.debug_names:" {
- set res "debug_names"
- exp_continue
- }
- -re -wrap "" {
- # We don't care about any other input.
- }
- }
+ set index_type [get_index_type $objfile]
- return $res
+ if { $index_type eq "gdb" } {
+ return "gdb_index"
+ } elseif { $index_type eq "dwarf5" } {
+ return "debug_names"
+ } else {
+ return ""
+ }
}
# Return 1 if partial symbols are available. Otherwise, return 0.
return 1
}
-# Add a .gdb_index section to PROGRAM, unless it alread has an index
-# (.gdb_index/.debug_names). Gdb doesn't support building an index from a
-# program already using one. Return 1 if a .gdb_index was added, return 0
-# if it already contained an index, and -1 if an error occurred.
+# Use 'maint print objfiles OBJFILE' to determine what (if any) type
+# of index is present in OBJFILE. Return a string indicating the
+# index type:
#
-# STYLE controls which style of index to add, if needed. The empty
-# string (the default) means .gdb_index; "-dwarf-5" means .debug_names.
-
-proc ensure_gdb_index { binfile {style ""} } {
- global decimal
+# 'gdb' - Contains a .gdb_index style index,
+#
+# 'dwarf5' - Contain DWARF5 style index sections,
+#
+# 'readnow' - A fake .gdb_index as a result of readnow being used,
+#
+# 'cooked' - The cooked index created when reading non-indexed debug
+# information,
+#
+# 'none' - There's no index, and no debug information to create a
+# cooked index from.
+#
+# If something goes wrong then this proc will emit a FAIL and return
+# an empty string.
+#
+# TESTNAME is used as part of any pass/fail emitted from this proc.
+proc get_index_type { objfile { testname "" } } {
+ if { $testname eq "" } {
+ set testname "find index type"
+ }
- set testfile [file tail $binfile]
- set test "check if index present"
- set has_index 0
- set has_readnow 0
- gdb_test_multiple "mt print objfiles ${testfile}" $test -lbl {
- -re "\r\n\\.gdb_index: version ${decimal}(?=\r\n)" {
- set has_index 1
+ set index_type "unknown"
+ gdb_test_multiple "maint print objfiles ${objfile}" $testname -lbl {
+ -re "\r\n\\.gdb_index: version ${::decimal}(?=\r\n)" {
+ set index_type "gdb"
gdb_test_lines "" $gdb_test_name ".*"
}
-re "\r\n\\.debug_names: exists(?=\r\n)" {
- set has_index 1
+ set index_type "dwarf5"
gdb_test_lines "" $gdb_test_name ".*"
}
-re "\r\n(Cooked index in use:|Psymtabs)(?=\r\n)" {
+ set index_type "cooked"
gdb_test_lines "" $gdb_test_name ".*"
}
-re ".gdb_index: faked for \"readnow\"" {
- set has_readnow 1
+ set index_type "readnow"
gdb_test_lines "" $gdb_test_name ".*"
}
-re -wrap "" {
- fail $gdb_test_name
+ set index_type "none"
}
}
- if { $has_index } {
+ gdb_assert { $index_type ne "unknown" } \
+ "$testname, check type is valid"
+
+ if { $index_type eq "unknown" } {
+ set index_type ""
+ }
+
+ return $index_type
+}
+
+# Add a .gdb_index section to PROGRAM, unless it alread has an index
+# (.gdb_index/.debug_names). Gdb doesn't support building an index from a
+# program already using one. Return 1 if a .gdb_index was added, return 0
+# if it already contained an index, and -1 if an error occurred.
+#
+# STYLE controls which style of index to add, if needed. The empty
+# string (the default) means .gdb_index; "-dwarf-5" means .debug_names.
+
+proc ensure_gdb_index { binfile {style ""} } {
+ set testfile [file tail $binfile]
+
+ set test "check if index present"
+ set index_type [get_index_type $testfile $test]
+
+ if { $index_type eq "gdb" || $index_type eq "dwarf5" } {
return 0
}
- if { $has_readnow } {
+ if { $index_type eq "readnow" } {
return -1
}