Rebase to FSF GDB 11.1.
Adjust build-id related patches. Drop backported patches which are no longer relevant. Bump 'snapgnulib' date. Backport upstream patch which papers over Fortran lexical analyzer bug (RHBZ 2012976, Tom de Vries).
This commit is contained in:
parent
e625e4584d
commit
9cd9368e86
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
/new-fedora-release
|
||||
/gdb-libstdc++-v3-python-8.1.1-20180626.tar.xz
|
||||
/v2.0.4.tar.gz
|
||||
/gdb-10.2.tar.xz
|
||||
/gdb-11.1.tar.xz
|
||||
|
@ -314,107 +314,14 @@ Patch074: gdb-rhbz1398387-tab-crash-test.patch
|
||||
# =fedoratest
|
||||
Patch075: gdb-rhbz1553104-s390x-arch12-test.patch
|
||||
|
||||
# Fix off-by-one error in ada_fold_name.patch (RH BZ 1905996)
|
||||
# Upstream patch proposal: https://sourceware.org/pipermail/gdb-patches/2020-December/173935.html
|
||||
# =fedoratest
|
||||
Patch076: gdb-rhbz1905996-fix-off-by-one-error-in-ada_fold_name.patch
|
||||
|
||||
# Backport fix for libstdc++ assert when performing tab completion
|
||||
# (RH BZ 1912985).
|
||||
Patch077: gdb-rhbz1912985-libstdc++-assert.patch
|
||||
|
||||
# Backport fix for frame_id_p assertion failure (RH BZ 1909902).
|
||||
Patch078: gdb-rhbz1909902-frame_id_p-assert-1.patch
|
||||
|
||||
# Backport patch #2 which fixes a frame_id_p assertion failure (RH BZ 1909902).
|
||||
Patch079: gdb-rhbz1909902-frame_id_p-assert-2.patch
|
||||
|
||||
# Backport change which fixes gdbserver testing hang on f34 and rawhide.
|
||||
Patch080: gdb-rhbz1941080-fix-gdbserver-hang.patch
|
||||
|
||||
# Backport "Disable bracketed paste mode in GDB tests"
|
||||
# (Tom Tromey)
|
||||
Patch081: testing-custom-inputrc.patch
|
||||
|
||||
# Backport "Save/restore file offset while reading notes in core file"
|
||||
# (Keith Seitz, RHBZ 1931344)
|
||||
Patch082: gdb-rhbz1931344-bfd_seek-elf_read_notes.patch
|
||||
|
||||
# [fortran] Backport Andrew Burgess's commit which cleans up
|
||||
# array/string expression evaluation.
|
||||
Patch083: gdb-rhbz1964167-fortran-clean-up-array-expression-evaluation.patch
|
||||
|
||||
# [fortran] Backport Andrew Burgess's commit which moves Fortran
|
||||
# expression handling to f-lang.c.
|
||||
Patch084: gdb-rhbz1964167-move-fortran-expr-handling.patch
|
||||
|
||||
# [fortran] Backport Andrew Burgess's commit which eliminates undesirable
|
||||
# whitespace when printing arrays.
|
||||
Patch085: gdb-rhbz1964167-fortran-whitespace_array.patch
|
||||
|
||||
# [fortran] Backport Andrew Burgess's commit which changes enum
|
||||
# range_type into a bit field enum.
|
||||
Patch086: gdb-rhbz1964167-convert-enum-range_type.patch
|
||||
|
||||
# [fortran] Backport Andrew Burgess's commit which renames enum
|
||||
# range_type to enum range_flag.
|
||||
Patch087: gdb-rhbz1964167-fortran-range_type-to-range_flag.patch
|
||||
|
||||
# [fortran] Backport Andrew Burgess's commit which adds support
|
||||
# for array strides in expressions.
|
||||
Patch088: gdb-rhbz1964167-fortran-array-strides-in-expressions.patch
|
||||
|
||||
# [fortran] Backport Andrew Burgess's commit for Fortran array
|
||||
# slice support
|
||||
Patch089: gdb-rhbz1964167-fortran-array-slices-at-prompt.patch
|
||||
|
||||
# [fortran] Backport Simon Marchi's commit which fixes a 32-bit build
|
||||
# problem in gdb/f-lang.c.
|
||||
Patch090: gdb-rhbz1964167-fortran-fix-type-format-mismatch-in-f-lang.c.patch
|
||||
|
||||
# Backport of "Exclude debuginfo files from 'outside of ELF segments'
|
||||
# warning" (Keith Seitz)
|
||||
Patch091: gdb-rhbz1898252-loadable-section-outside-ELF-segments.patch
|
||||
|
||||
# Backport "Fix crash when expanding partial symtabs with DW_TAG_imported_unit"
|
||||
# (Tom Tromey, gdb/27743)
|
||||
Patch092: gdb-gdb27743-psymtab-imported-unit.patch
|
||||
|
||||
# Backport "[gdb/server] Don't overwrite fs/gs_base with -m32"
|
||||
# (Tom de Vries)
|
||||
Patch093: gdb-dont-overwrite-fsgsbase-m32.patch
|
||||
|
||||
# Backport patch fixing gdb on glibc-2.34 machines with regard to attaching
|
||||
# to processes (RH BZ 1971096).
|
||||
Patch094: gdb-rhbz1971096-glibc2.34-1.patch
|
||||
|
||||
# Backport patch fixing gdb on glibc-2.34 machines w/ regard to
|
||||
# libthread_db initialization.
|
||||
Patch095: gdb-rhbz1971096-glibc2.34-2.patch
|
||||
|
||||
# Backport testsuite patch for matching new libthread_db related output
|
||||
# when testing gdb on glibc-2.34 matchines (RH BZ 1971096).
|
||||
Patch096: gdb-rhbz1971096-glibc2.34-3.patch
|
||||
|
||||
# Backport patch adjusting test gdb.base/print-symbol-loading.exp.
|
||||
# (RH BZ 1971096).
|
||||
Patch097: gdb-rhbz1971096-glibc2.34-4.patch
|
||||
|
||||
# Backport patch adjusting test gdb.mi/mi-sym-info.exp (RH BZ 1971096).
|
||||
Patch098: gdb-rhbz1971096-glibc2.34-5.patch
|
||||
|
||||
#[gdb/cli] Don't assert on empty string for core-file
|
||||
#(Tom de Vries)
|
||||
Patch099: gdb-rhbz1916516-pathstuffs132-internal-error.patch
|
||||
|
||||
#[gdb] Improve early exits for env var in debuginfod-support.c
|
||||
#(Tom de Vries)
|
||||
Patch100: gdb-rhbz1970741-early-exit-for-empty-debuginfod-url.patch
|
||||
|
||||
#Backport upstream patch which fixes internal-error: Unexpected
|
||||
#type field location kind (RHBZ 1976887).
|
||||
Patch101: gdb-rhbz1976887-field-location-kind.patch
|
||||
Patch076: gdb-rhbz1976887-field-location-kind.patch
|
||||
|
||||
# Backport test for RHBZ 1976887 (Kevin Buettner).
|
||||
Patch102: gdb-test-for-rhbz1976887.patch
|
||||
Patch077: gdb-test-for-rhbz1976887.patch
|
||||
|
||||
# Backport gdb.fortran testsuite changes in order to avoid Fortran
|
||||
# lexical analyzer bug.
|
||||
Patch078: gdb-rhbz2012976-paper-over-fortran-lex-problems.patch
|
||||
|
||||
|
@ -76,27 +76,3 @@
|
||||
%patch076 -p1
|
||||
%patch077 -p1
|
||||
%patch078 -p1
|
||||
%patch079 -p1
|
||||
%patch080 -p1
|
||||
%patch081 -p1
|
||||
%patch082 -p1
|
||||
%patch083 -p1
|
||||
%patch084 -p1
|
||||
%patch085 -p1
|
||||
%patch086 -p1
|
||||
%patch087 -p1
|
||||
%patch088 -p1
|
||||
%patch089 -p1
|
||||
%patch090 -p1
|
||||
%patch091 -p1
|
||||
%patch092 -p1
|
||||
%patch093 -p1
|
||||
%patch094 -p1
|
||||
%patch095 -p1
|
||||
%patch096 -p1
|
||||
%patch097 -p1
|
||||
%patch098 -p1
|
||||
%patch099 -p1
|
||||
%patch100 -p1
|
||||
%patch101 -p1
|
||||
%patch102 -p1
|
||||
|
@ -1 +1 @@
|
||||
ce35d7163e779b1321058b22f005c70ce1524b25
|
||||
8cdd8568bfe4ea86a93e4b80bf2fc6e6f9cad84c
|
||||
|
26
_patch_order
26
_patch_order
@ -73,30 +73,6 @@ gdb-linux_perf-bundle.patch
|
||||
gdb-libexec-add-index.patch
|
||||
gdb-rhbz1398387-tab-crash-test.patch
|
||||
gdb-rhbz1553104-s390x-arch12-test.patch
|
||||
gdb-rhbz1905996-fix-off-by-one-error-in-ada_fold_name.patch
|
||||
gdb-rhbz1912985-libstdc++-assert.patch
|
||||
gdb-rhbz1909902-frame_id_p-assert-1.patch
|
||||
gdb-rhbz1909902-frame_id_p-assert-2.patch
|
||||
gdb-rhbz1941080-fix-gdbserver-hang.patch
|
||||
testing-custom-inputrc.patch
|
||||
gdb-rhbz1931344-bfd_seek-elf_read_notes.patch
|
||||
gdb-rhbz1964167-fortran-clean-up-array-expression-evaluation.patch
|
||||
gdb-rhbz1964167-move-fortran-expr-handling.patch
|
||||
gdb-rhbz1964167-fortran-whitespace_array.patch
|
||||
gdb-rhbz1964167-convert-enum-range_type.patch
|
||||
gdb-rhbz1964167-fortran-range_type-to-range_flag.patch
|
||||
gdb-rhbz1964167-fortran-array-strides-in-expressions.patch
|
||||
gdb-rhbz1964167-fortran-array-slices-at-prompt.patch
|
||||
gdb-rhbz1964167-fortran-fix-type-format-mismatch-in-f-lang.c.patch
|
||||
gdb-rhbz1898252-loadable-section-outside-ELF-segments.patch
|
||||
gdb-gdb27743-psymtab-imported-unit.patch
|
||||
gdb-dont-overwrite-fsgsbase-m32.patch
|
||||
gdb-rhbz1971096-glibc2.34-1.patch
|
||||
gdb-rhbz1971096-glibc2.34-2.patch
|
||||
gdb-rhbz1971096-glibc2.34-3.patch
|
||||
gdb-rhbz1971096-glibc2.34-4.patch
|
||||
gdb-rhbz1971096-glibc2.34-5.patch
|
||||
gdb-rhbz1916516-pathstuffs132-internal-error.patch
|
||||
gdb-rhbz1970741-early-exit-for-empty-debuginfod-url.patch
|
||||
gdb-rhbz1976887-field-location-kind.patch
|
||||
gdb-test-for-rhbz1976887.patch
|
||||
gdb-rhbz2012976-paper-over-fortran-lex-problems.patch
|
||||
|
@ -16,7 +16,7 @@ Subject: gdb-6.3-gstack-20050411.patch
|
||||
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
--- a/gdb/Makefile.in
|
||||
+++ b/gdb/Makefile.in
|
||||
@@ -1726,7 +1726,7 @@ info install-info clean-info dvi pdf install-pdf html install-html: force
|
||||
@@ -1753,7 +1753,7 @@ info install-info clean-info dvi pdf install-pdf html install-html: force
|
||||
install: all
|
||||
@$(MAKE) $(FLAGS_TO_PASS) install-only
|
||||
|
||||
@ -25,7 +25,7 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
transformed_name=`t='$(program_transform_name)'; \
|
||||
echo gdb | sed -e "$$t"` ; \
|
||||
if test "x$$transformed_name" = x; then \
|
||||
@@ -1775,7 +1775,25 @@ install-guile:
|
||||
@@ -1802,7 +1802,25 @@ install-guile:
|
||||
install-python:
|
||||
$(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(GDB_DATADIR)/python/gdb
|
||||
|
||||
@ -52,7 +52,7 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
transformed_name=`t='$(program_transform_name)'; \
|
||||
echo gdb | sed -e $$t` ; \
|
||||
if test "x$$transformed_name" = x; then \
|
||||
@@ -1798,6 +1816,18 @@ uninstall: force $(CONFIG_UNINSTALL)
|
||||
@@ -1825,6 +1843,18 @@ uninstall: force $(CONFIG_UNINSTALL)
|
||||
fi
|
||||
@$(MAKE) DO=uninstall "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
|
||||
|
||||
|
@ -27,7 +27,7 @@ diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest
|
||||
diff --git a/gdb/top.c b/gdb/top.c
|
||||
--- a/gdb/top.c
|
||||
+++ b/gdb/top.c
|
||||
@@ -2163,7 +2163,7 @@ init_gdb_version_vars (void)
|
||||
@@ -2195,7 +2195,7 @@ init_gdb_version_vars (void)
|
||||
struct internalvar *major_version_var = create_internalvar ("_gdb_major");
|
||||
struct internalvar *minor_version_var = create_internalvar ("_gdb_minor");
|
||||
int vmajor = 0, vminor = 0, vrevision = 0;
|
||||
|
@ -44,17 +44,17 @@ glibc-debuginfo-2.7-2.x86_64: /usr/lib/debug/lib64/libc.so.6.debug:
|
||||
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
|
||||
--- a/gdb/printcmd.c
|
||||
+++ b/gdb/printcmd.c
|
||||
@@ -1210,6 +1210,10 @@ print_command_1 (const char *args, int voidprint)
|
||||
@@ -1306,6 +1306,10 @@ process_print_command_args (const char *args, value_print_options *print_opts,
|
||||
|
||||
if (exp != nullptr && *exp)
|
||||
{
|
||||
+ /* '*((int *(*) (void)) __errno_location) ()' is incompatible with
|
||||
+ function descriptors. */
|
||||
+ if (target_has_execution && strcmp (exp, "errno") == 0)
|
||||
+ if (target_has_execution () && strcmp (exp, "errno") == 0)
|
||||
+ exp = "*(*(int *(*)(void)) __errno_location) ()";
|
||||
expression_up expr = parse_expression (exp);
|
||||
val = evaluate_expression (expr.get ());
|
||||
}
|
||||
/* VOIDPRINT is true to indicate that we do want to print a void
|
||||
value, so invert it for parse_expression. */
|
||||
expression_up expr = parse_expression (exp, nullptr, !voidprint);
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-errno.c b/gdb/testsuite/gdb.dwarf2/dw2-errno.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
|
@ -98,7 +98,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -3034,6 +3034,16 @@ read_gdb_index_from_buffer (const char *filename,
|
||||
@@ -2801,6 +2801,16 @@ read_gdb_index_from_buffer (const char *filename,
|
||||
"set use-deprecated-index-sections on". */
|
||||
if (version < 6 && !deprecated_ok)
|
||||
{
|
||||
@ -115,7 +115,7 @@ diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
static int warning_printed = 0;
|
||||
if (!warning_printed)
|
||||
{
|
||||
@@ -3045,6 +3055,10 @@ to use the section anyway."),
|
||||
@@ -2812,6 +2822,10 @@ to use the section anyway."),
|
||||
warning_printed = 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -696,7 +696,7 @@ diff --git a/gdb/config.in b/gdb/config.in
|
||||
/* Define to 1 if translation of program messages to the user's native
|
||||
language is requested. */
|
||||
#undef ENABLE_NLS
|
||||
@@ -247,6 +250,9 @@
|
||||
@@ -246,6 +249,9 @@
|
||||
/* Define if you have the mpfr library. */
|
||||
#undef HAVE_LIBMPFR
|
||||
|
||||
@ -709,7 +709,7 @@ diff --git a/gdb/config.in b/gdb/config.in
|
||||
diff --git a/gdb/configure b/gdb/configure
|
||||
--- a/gdb/configure
|
||||
+++ b/gdb/configure
|
||||
@@ -769,6 +769,11 @@ PKG_CONFIG
|
||||
@@ -771,6 +771,11 @@ PKG_CONFIG
|
||||
HAVE_NATIVE_GCORE_TARGET
|
||||
TARGET_OBS
|
||||
subdirs
|
||||
@ -721,7 +721,7 @@ diff --git a/gdb/configure b/gdb/configure
|
||||
GDB_DATADIR
|
||||
DEBUGDIR
|
||||
MAKEINFO_EXTRA_FLAGS
|
||||
@@ -873,6 +878,7 @@ with_gdb_datadir
|
||||
@@ -876,6 +881,7 @@ with_gdb_datadir
|
||||
with_relocated_sources
|
||||
with_auto_load_dir
|
||||
with_auto_load_safe_path
|
||||
@ -729,7 +729,7 @@ diff --git a/gdb/configure b/gdb/configure
|
||||
enable_targets
|
||||
enable_64_bit_bfd
|
||||
enable_gdbmi
|
||||
@@ -949,6 +955,8 @@ PKG_CONFIG_PATH
|
||||
@@ -953,6 +959,8 @@ PKG_CONFIG_PATH
|
||||
PKG_CONFIG_LIBDIR
|
||||
DEBUGINFOD_CFLAGS
|
||||
DEBUGINFOD_LIBS
|
||||
@ -738,7 +738,7 @@ diff --git a/gdb/configure b/gdb/configure
|
||||
YACC
|
||||
YFLAGS
|
||||
XMKMF'
|
||||
@@ -1621,6 +1629,8 @@ Optional Packages:
|
||||
@@ -1625,6 +1633,8 @@ Optional Packages:
|
||||
do not restrict auto-loaded files locations
|
||||
--with-debuginfod Enable debuginfo lookups with debuginfod
|
||||
(auto/yes/no)
|
||||
@ -747,7 +747,7 @@ diff --git a/gdb/configure b/gdb/configure
|
||||
--with-libunwind-ia64 use libunwind frame unwinding for ia64 targets
|
||||
--with-curses use the curses library instead of the termcap
|
||||
library
|
||||
@@ -1702,6 +1712,8 @@ Some influential environment variables:
|
||||
@@ -1705,6 +1715,8 @@ Some influential environment variables:
|
||||
C compiler flags for DEBUGINFOD, overriding pkg-config
|
||||
DEBUGINFOD_LIBS
|
||||
linker flags for DEBUGINFOD, overriding pkg-config
|
||||
@ -756,7 +756,7 @@ diff --git a/gdb/configure b/gdb/configure
|
||||
YACC The `Yet Another Compiler Compiler' implementation to use.
|
||||
Defaults to the first program found out of: `bison -y', `byacc',
|
||||
`yacc'.
|
||||
@@ -6666,6 +6678,494 @@ _ACEOF
|
||||
@@ -6616,6 +6628,494 @@ _ACEOF
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_auto_load_safe_path" >&5
|
||||
$as_echo "$with_auto_load_safe_path" >&6; }
|
||||
|
||||
@ -1254,7 +1254,7 @@ diff --git a/gdb/configure b/gdb/configure
|
||||
diff --git a/gdb/configure.ac b/gdb/configure.ac
|
||||
--- a/gdb/configure.ac
|
||||
+++ b/gdb/configure.ac
|
||||
@@ -143,6 +143,199 @@ AC_DEFINE_DIR(AUTO_LOAD_SAFE_PATH, escape_dir,
|
||||
@@ -153,6 +153,199 @@ AC_DEFINE_DIR(AUTO_LOAD_SAFE_PATH, escape_dir,
|
||||
[Directories safe to hold auto-loaded files.])
|
||||
AC_MSG_RESULT([$with_auto_load_safe_path])
|
||||
|
||||
@ -1457,7 +1457,7 @@ diff --git a/gdb/configure.ac b/gdb/configure.ac
|
||||
diff --git a/gdb/event-top.c b/gdb/event-top.c
|
||||
--- a/gdb/event-top.c
|
||||
+++ b/gdb/event-top.c
|
||||
@@ -42,6 +42,7 @@
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "gdbsupport/gdb_select.h"
|
||||
#include "gdbsupport/gdb-sigmask.h"
|
||||
#include "async-event.h"
|
||||
@ -1465,7 +1465,7 @@ diff --git a/gdb/event-top.c b/gdb/event-top.c
|
||||
|
||||
/* readline include files. */
|
||||
#include "readline/readline.h"
|
||||
@@ -364,6 +365,8 @@ display_gdb_prompt (const char *new_prompt)
|
||||
@@ -363,6 +364,8 @@ display_gdb_prompt (const char *new_prompt)
|
||||
/* Reset the nesting depth used when trace-commands is set. */
|
||||
reset_command_nest_depth ();
|
||||
|
||||
@ -1489,11 +1489,11 @@ diff --git a/gdb/event-top.c b/gdb/event-top.c
|
||||
diff --git a/gdb/symfile.h b/gdb/symfile.h
|
||||
--- a/gdb/symfile.h
|
||||
+++ b/gdb/symfile.h
|
||||
@@ -560,6 +560,7 @@ extern void generic_load (const char *args, int from_tty);
|
||||
@@ -342,6 +342,7 @@ extern void generic_load (const char *args, int from_tty);
|
||||
/* build-id support. */
|
||||
extern struct bfd_build_id *build_id_addr_get (CORE_ADDR addr);
|
||||
extern void debug_print_missing (const char *binary, const char *debug);
|
||||
+extern void debug_flush_missing (void);
|
||||
#define BUILD_ID_MAIN_EXECUTABLE_FILENAME _("the main executable file")
|
||||
|
||||
/* From dwarf2read.c */
|
||||
/* From minidebug.c. */
|
||||
|
@ -14,7 +14,7 @@ https://bugzilla.redhat.com/show_bug.cgi?id=1339862
|
||||
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
--- a/gdb/solib-svr4.c
|
||||
+++ b/gdb/solib-svr4.c
|
||||
@@ -1340,14 +1340,27 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
@@ -1350,14 +1350,28 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
}
|
||||
|
||||
{
|
||||
@ -38,13 +38,14 @@ diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
+ not do any build-id checking of the libraries. There may be missing
|
||||
+ build-ids dumped in the core file and we would map all the libraries
|
||||
+ to the only existing file loaded that time - the executable. */
|
||||
+ if (symfile_objfile != NULL
|
||||
+ && (symfile_objfile->flags & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
+ if (current_program_space->symfile_object_file != NULL
|
||||
+ && (current_program_space->symfile_object_file->flags
|
||||
+ & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
+ build_id = build_id_addr_get (li->l_ld);
|
||||
if (build_id != NULL)
|
||||
{
|
||||
char *name, *build_id_filename;
|
||||
@@ -1362,23 +1375,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
@@ -1372,23 +1386,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
xfree (name);
|
||||
}
|
||||
else
|
||||
@ -60,8 +61,8 @@ diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
- instead) if the on-disk files no longer match the
|
||||
- running program version. */
|
||||
-
|
||||
- if (symfile_objfile != NULL
|
||||
- && (symfile_objfile->flags
|
||||
- if (current_program_space->symfile_object_file != NULL
|
||||
- && (current_program_space->symfile_object_file->flags
|
||||
- & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
- newobj->so_name[0] = 0;
|
||||
- }
|
||||
|
@ -9,7 +9,7 @@ Subject: gdb-6.6-buildid-locate.patch
|
||||
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
|
||||
--- a/bfd/libbfd-in.h
|
||||
+++ b/bfd/libbfd-in.h
|
||||
@@ -121,7 +121,7 @@ static inline char *
|
||||
@@ -115,7 +115,7 @@ static inline char *
|
||||
bfd_strdup (const char *str)
|
||||
{
|
||||
size_t len = strlen (str) + 1;
|
||||
@ -21,7 +21,7 @@ diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
|
||||
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
|
||||
--- a/bfd/libbfd.h
|
||||
+++ b/bfd/libbfd.h
|
||||
@@ -126,7 +126,7 @@ static inline char *
|
||||
@@ -120,7 +120,7 @@ static inline char *
|
||||
bfd_strdup (const char *str)
|
||||
{
|
||||
size_t len = strlen (str) + 1;
|
||||
@ -890,7 +890,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
+ char *build_id_filename_cstr = NULL;
|
||||
gdb_bfd_ref_ptr abfd (build_id_to_debug_bfd (build_id->size,
|
||||
- build_id->data));
|
||||
+ build_id->data,
|
||||
+ build_id->data,
|
||||
+ (!build_id_filename_return ? NULL : &build_id_filename_cstr)));
|
||||
+ if (build_id_filename_return)
|
||||
+ {
|
||||
@ -906,7 +906,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
/* Prevent looping on a stripped .debug file. */
|
||||
if (abfd != NULL
|
||||
&& filename_cmp (bfd_get_filename (abfd.get ()),
|
||||
@@ -223,3 +897,21 @@ find_separate_debug_file_by_buildid (struct objfile *objfile)
|
||||
@@ -223,3 +897,22 @@ find_separate_debug_file_by_buildid (struct objfile *objfile)
|
||||
|
||||
return std::string ();
|
||||
}
|
||||
@ -926,7 +926,8 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
+ show_build_id_verbose,
|
||||
+ &setlist, &showlist);
|
||||
+
|
||||
+ gdb::observers::executable_changed.attach (debug_print_executable_changed);
|
||||
+ gdb::observers::executable_changed.attach (debug_print_executable_changed,
|
||||
+ "build-id");
|
||||
+}
|
||||
diff --git a/gdb/build-id.h b/gdb/build-id.h
|
||||
--- a/gdb/build-id.h
|
||||
@ -950,7 +951,7 @@ diff --git a/gdb/build-id.h b/gdb/build-id.h
|
||||
extern gdb_bfd_ref_ptr build_id_to_debug_bfd (size_t build_id_len,
|
||||
- const bfd_byte *build_id);
|
||||
+ const bfd_byte *build_id,
|
||||
+ char **link_return);
|
||||
+ char **link_return = NULL);
|
||||
+
|
||||
+extern char *build_id_to_filename (const struct bfd_build_id *build_id,
|
||||
+ char **link_return);
|
||||
@ -978,9 +979,9 @@ diff --git a/gdb/build-id.h b/gdb/build-id.h
|
||||
diff --git a/gdb/coffread.c b/gdb/coffread.c
|
||||
--- a/gdb/coffread.c
|
||||
+++ b/gdb/coffread.c
|
||||
@@ -709,7 +709,8 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
|
||||
@@ -710,7 +710,8 @@ 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 (objfile))
|
||||
if (!objfile->has_partial_symbols ())
|
||||
{
|
||||
- std::string debugfile = find_separate_debug_file_by_buildid (objfile);
|
||||
+ std::string debugfile = find_separate_debug_file_by_buildid (objfile,
|
||||
@ -1002,7 +1003,7 @@ diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
#include "inferior.h"
|
||||
#include "infrun.h"
|
||||
#include "symtab.h"
|
||||
@@ -362,6 +366,8 @@ add_to_thread_list (bfd *abfd, asection *asect, void *reg_sect_arg)
|
||||
@@ -356,6 +360,8 @@ add_to_thread_list (asection *asect, asection *reg_sect)
|
||||
switch_to_thread (thr); /* Yes, make it current. */
|
||||
}
|
||||
|
||||
@ -1011,7 +1012,7 @@ diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
/* Issue a message saying we have no core to debug, if FROM_TTY. */
|
||||
|
||||
static void
|
||||
@@ -398,19 +404,25 @@ core_file_command (const char *filename, int from_tty)
|
||||
@@ -392,19 +398,26 @@ core_file_command (const char *filename, int from_tty)
|
||||
static void
|
||||
locate_exec_from_corefile_build_id (bfd *abfd, int from_tty)
|
||||
{
|
||||
@ -1031,16 +1032,17 @@ diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
exec_file_attach (bfd_get_filename (execbfd.get ()), from_tty);
|
||||
symbol_file_add_main (bfd_get_filename (execbfd.get ()),
|
||||
symfile_add_flag (from_tty ? SYMFILE_VERBOSE : 0));
|
||||
+ if (symfile_objfile != NULL)
|
||||
+ symfile_objfile->flags |= OBJF_BUILD_ID_CORE_LOADED;
|
||||
+ if (current_program_space->symfile_object_file != NULL)
|
||||
+ current_program_space->symfile_object_file->flags |=
|
||||
+ OBJF_BUILD_ID_CORE_LOADED;
|
||||
}
|
||||
+ else
|
||||
+ debug_print_missing (BUILD_ID_MAIN_EXECUTABLE_FILENAME, build_id_filename);
|
||||
}
|
||||
|
||||
/* See gdbcore.h. */
|
||||
@@ -1189,4 +1201,11 @@ _initialize_corelow ()
|
||||
maintenance_print_core_file_backed_mappings,
|
||||
@@ -1209,4 +1222,11 @@ _initialize_corelow ()
|
||||
maintenance_print_core_file_backed_mappings,
|
||||
_("Print core file's file-backed mappings."),
|
||||
&maintenanceprintlist);
|
||||
+
|
||||
@ -1054,7 +1056,7 @@ diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
--- a/gdb/doc/gdb.texinfo
|
||||
+++ b/gdb/doc/gdb.texinfo
|
||||
@@ -21074,6 +21074,27 @@ information files.
|
||||
@@ -21415,6 +21415,27 @@ information files.
|
||||
|
||||
@end table
|
||||
|
||||
@ -1107,16 +1109,7 @@ diff --git a/gdb/dwarf2/index-cache.c b/gdb/dwarf2/index-cache.c
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -2225,7 +2225,7 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd)
|
||||
}
|
||||
|
||||
if (dwz_bfd == NULL)
|
||||
- dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
|
||||
+ dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid, NULL);
|
||||
|
||||
if (dwz_bfd == nullptr)
|
||||
{
|
||||
@@ -5989,7 +5989,7 @@ get_gdb_index_contents_from_section (objfile *obj, T *section_owner)
|
||||
@@ -5447,7 +5447,7 @@ get_gdb_index_contents_from_section (objfile *obj, T *section_owner)
|
||||
static gdb::array_view<const gdb_byte>
|
||||
get_gdb_index_contents_from_cache (objfile *obj, dwarf2_per_bfd *dwarf2_per_bfd)
|
||||
{
|
||||
@ -1125,7 +1118,7 @@ diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
if (build_id == nullptr)
|
||||
return {};
|
||||
|
||||
@@ -6002,7 +6002,7 @@ get_gdb_index_contents_from_cache (objfile *obj, dwarf2_per_bfd *dwarf2_per_bfd)
|
||||
@@ -5460,7 +5460,7 @@ get_gdb_index_contents_from_cache (objfile *obj, dwarf2_per_bfd *dwarf2_per_bfd)
|
||||
static gdb::array_view<const gdb_byte>
|
||||
get_gdb_index_contents_from_cache_dwz (objfile *obj, dwz_file *dwz)
|
||||
{
|
||||
@ -1137,7 +1130,7 @@ diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
diff --git a/gdb/elfread.c b/gdb/elfread.c
|
||||
--- a/gdb/elfread.c
|
||||
+++ b/gdb/elfread.c
|
||||
@@ -1298,7 +1298,9 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
|
||||
@@ -1272,7 +1272,9 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
|
||||
&& objfile->separate_debug_objfile == NULL
|
||||
&& objfile->separate_debug_objfile_backlink == NULL)
|
||||
{
|
||||
@ -1148,7 +1141,7 @@ diff --git a/gdb/elfread.c b/gdb/elfread.c
|
||||
|
||||
if (debugfile.empty ())
|
||||
debugfile = find_separate_debug_file_by_debuglink (objfile);
|
||||
@@ -1313,7 +1315,7 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
|
||||
@@ -1287,7 +1289,7 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
|
||||
else
|
||||
{
|
||||
has_dwarf2 = false;
|
||||
@ -1157,7 +1150,7 @@ diff --git a/gdb/elfread.c b/gdb/elfread.c
|
||||
|
||||
if (build_id != nullptr)
|
||||
{
|
||||
@@ -1338,6 +1340,10 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
|
||||
@@ -1312,6 +1314,10 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
|
||||
has_dwarf2 = true;
|
||||
}
|
||||
}
|
||||
@ -1171,16 +1164,16 @@ diff --git a/gdb/elfread.c b/gdb/elfread.c
|
||||
diff --git a/gdb/exec.c b/gdb/exec.c
|
||||
--- a/gdb/exec.c
|
||||
+++ b/gdb/exec.c
|
||||
@@ -264,7 +264,7 @@ validate_exec_file (int from_tty)
|
||||
reopen_exec_file ();
|
||||
@@ -237,7 +237,7 @@ validate_exec_file (int from_tty)
|
||||
current_exec_file = get_exec_file (0);
|
||||
|
||||
- const bfd_build_id *exec_file_build_id = build_id_bfd_get (exec_bfd);
|
||||
+ const bfd_build_id *exec_file_build_id = build_id_bfd_shdr_get (exec_bfd);
|
||||
const bfd_build_id *exec_file_build_id
|
||||
- = build_id_bfd_get (current_program_space->exec_bfd ());
|
||||
+ = build_id_bfd_shdr_get (current_program_space->exec_bfd ());
|
||||
if (exec_file_build_id != nullptr)
|
||||
{
|
||||
/* Prepend the target prefix, to force gdb_bfd_open to open the
|
||||
@@ -277,7 +277,7 @@ validate_exec_file (int from_tty)
|
||||
@@ -250,7 +250,7 @@ validate_exec_file (int from_tty)
|
||||
if (abfd != nullptr)
|
||||
{
|
||||
const bfd_build_id *target_exec_file_build_id
|
||||
@ -1192,7 +1185,7 @@ diff --git a/gdb/exec.c b/gdb/exec.c
|
||||
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
|
||||
--- a/gdb/objfiles.h
|
||||
+++ b/gdb/objfiles.h
|
||||
@@ -714,6 +714,10 @@ struct objfile
|
||||
@@ -812,6 +812,10 @@ struct objfile
|
||||
bool skip_jit_symbol_lookup = false;
|
||||
};
|
||||
|
||||
@ -1235,7 +1228,7 @@ diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
|
||||
static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
|
||||
static int svr4_have_link_map_offsets (void);
|
||||
@@ -1338,9 +1339,51 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
@@ -1348,9 +1349,51 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1277,8 +1270,8 @@ diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
+ instead) if the on-disk files no longer match the
|
||||
+ running program version. */
|
||||
+
|
||||
+ if (symfile_objfile != NULL
|
||||
+ && (symfile_objfile->flags
|
||||
+ if (current_program_space->symfile_object_file != NULL
|
||||
+ && (current_program_space->symfile_object_file->flags
|
||||
+ & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
+ newobj->so_name[0] = 0;
|
||||
+ }
|
||||
@ -1293,7 +1286,7 @@ diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
diff --git a/gdb/source.c b/gdb/source.c
|
||||
--- a/gdb/source.c
|
||||
+++ b/gdb/source.c
|
||||
@@ -1165,7 +1165,7 @@ open_source_file (struct symtab *s)
|
||||
@@ -1178,7 +1178,7 @@ open_source_file (struct symtab *s)
|
||||
srcpath += s->filename;
|
||||
}
|
||||
|
||||
@ -1305,9 +1298,9 @@ diff --git a/gdb/source.c b/gdb/source.c
|
||||
diff --git a/gdb/symfile.h b/gdb/symfile.h
|
||||
--- a/gdb/symfile.h
|
||||
+++ b/gdb/symfile.h
|
||||
@@ -550,12 +550,18 @@ void expand_symtabs_matching
|
||||
void map_symbol_filenames (symbol_filename_ftype *fun, void *data,
|
||||
int need_fullname);
|
||||
@@ -332,12 +332,18 @@ bool expand_symtabs_matching
|
||||
void map_symbol_filenames (gdb::function_view<symbol_filename_ftype> fun,
|
||||
bool need_fullname);
|
||||
|
||||
+
|
||||
/* Target-agnostic function to load the sections of an executable into memory.
|
||||
@ -1321,9 +1314,9 @@ diff --git a/gdb/symfile.h b/gdb/symfile.h
|
||||
+extern void debug_print_missing (const char *binary, const char *debug);
|
||||
+#define BUILD_ID_MAIN_EXECUTABLE_FILENAME _("the main executable file")
|
||||
+
|
||||
/* From dwarf2read.c */
|
||||
/* From minidebug.c. */
|
||||
|
||||
/* Names for a dwarf2 debugging section. The field NORMAL is the normal
|
||||
extern gdb_bfd_ref_ptr find_separate_debug_file_in_section (struct objfile *);
|
||||
diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp
|
||||
--- a/gdb/testsuite/gdb.base/corefile.exp
|
||||
+++ b/gdb/testsuite/gdb.base/corefile.exp
|
||||
@ -1364,7 +1357,7 @@ diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefi
|
||||
diff --git a/gdb/testsuite/gdb.base/gdbinit-history.exp b/gdb/testsuite/gdb.base/gdbinit-history.exp
|
||||
--- a/gdb/testsuite/gdb.base/gdbinit-history.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gdbinit-history.exp
|
||||
@@ -181,7 +181,8 @@ proc test_empty_history_filename { } {
|
||||
@@ -185,7 +185,8 @@ proc test_empty_history_filename { } {
|
||||
global env
|
||||
global gdb_prompt
|
||||
|
||||
@ -1388,7 +1381,7 @@ diff --git a/gdb/testsuite/gdb.base/new-ui-pending-input.exp b/gdb/testsuite/gdb
|
||||
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
|
||||
--- a/gdb/testsuite/lib/gdb.exp
|
||||
+++ b/gdb/testsuite/lib/gdb.exp
|
||||
@@ -2011,6 +2011,17 @@ proc default_gdb_start { } {
|
||||
@@ -2130,6 +2130,17 @@ proc default_gdb_start { } {
|
||||
}
|
||||
}
|
||||
|
||||
@ -1409,7 +1402,7 @@ diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
|
||||
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
|
||||
--- a/gdb/testsuite/lib/mi-support.exp
|
||||
+++ b/gdb/testsuite/lib/mi-support.exp
|
||||
@@ -308,6 +308,16 @@ proc default_mi_gdb_start { args } {
|
||||
@@ -322,6 +322,16 @@ proc default_mi_gdb_start { args } {
|
||||
warning "Couldn't set the width to 0."
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ Subject: gdb-ccache-workaround.patch
|
||||
diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp
|
||||
--- a/gdb/testsuite/gdb.base/macscp.exp
|
||||
+++ b/gdb/testsuite/gdb.base/macscp.exp
|
||||
@@ -25,6 +25,14 @@ if { [test_compiler_info "gcc-*"] || [test_compiler_info "clang-*"] } {
|
||||
lappend options additional_flags=-g3
|
||||
@@ -27,6 +27,14 @@ if { [test_compiler_info "gcc-*"] } {
|
||||
lappend options additional_flags=-fdebug-macro
|
||||
}
|
||||
|
||||
+# Workaround ccache making lineno non-zero for command-line definitions.
|
||||
|
@ -9,7 +9,7 @@ Subject: gdb-container-rh-pkg.patch
|
||||
diff --git a/gdb/remote.c b/gdb/remote.c
|
||||
--- a/gdb/remote.c
|
||||
+++ b/gdb/remote.c
|
||||
@@ -14031,7 +14031,17 @@ remote_target::pid_to_exec_file (int pid)
|
||||
@@ -14290,7 +14290,17 @@ remote_target::pid_to_exec_file (int pid)
|
||||
char *annex = NULL;
|
||||
|
||||
if (packet_support (PACKET_qXfer_exec_file) != PACKET_ENABLE)
|
||||
|
@ -1,139 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 1 Jun 2021 10:14:31 -0700
|
||||
Subject: gdb-dont-overwrite-fsgsbase-m32.patch
|
||||
|
||||
;; Backport "[gdb/server] Don't overwrite fs/gs_base with -m32"
|
||||
;; (Tom de Vries)
|
||||
|
||||
Consider a minimal test-case test.c:
|
||||
...
|
||||
int main (void) { return 0; }
|
||||
...
|
||||
compiled with -m32:
|
||||
...
|
||||
$ gcc test.c -m32
|
||||
...
|
||||
|
||||
When running the exec using gdbserver on openSUSE Factory (currently running a
|
||||
linux kernel version 5.10.5):
|
||||
...
|
||||
$ gdbserver localhost:12345 a.out
|
||||
...
|
||||
to which we connect in a gdb session, we run into a segfault in the inferior:
|
||||
...
|
||||
$ gdb -batch -q -ex "target remote localhost:12345" -ex continue
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
0xf7dd8bd2 in init_cacheinfo () at ../sysdeps/x86/cacheinfo.c:761
|
||||
...
|
||||
|
||||
The segfault is caused by gdbserver overwriting $gs_base with 0 using
|
||||
PTRACE_SETREGS. After it is overwritten, the next use of $gs in the inferior
|
||||
will trigger the segfault.
|
||||
|
||||
Before linux kernel version 5.9, the value used by PTRACE_SETREGS for $gs_base
|
||||
was ignored, but starting version 5.9, the linux kernel has support for
|
||||
intel architecture extension FSGSBASE, which allows users to modify $gs_base,
|
||||
and consequently PTRACE_SETREGS can no longer ignore the $gs_base value.
|
||||
|
||||
The overwrite of $gs_base with 0 is done by a memset in x86_fill_gregset,
|
||||
which was added in commit 9e0aa64f551 "Fix gdbserver qGetTLSAddr for
|
||||
x86_64 -m32". The memset intends to zero-extend 32-bit registers that are
|
||||
tracked in the regcache to 64-bit when writing them into the PTRACE_SETREGS
|
||||
data argument. But in addition, it overwrites other registers that are
|
||||
not tracked in the regcache, such as $gs_base.
|
||||
|
||||
Fix the segfault by redoing the fix from commit 9e0aa64f551 in minimal form.
|
||||
|
||||
Tested on x86_64-linux:
|
||||
- openSUSE Leap 15.2 (using kernel version 5.3.18):
|
||||
- native
|
||||
- gdbserver -m32
|
||||
- -m32
|
||||
- openSUSE Factory (using kernel version 5.10.5):
|
||||
- native
|
||||
- m32
|
||||
|
||||
gdbserver/ChangeLog:
|
||||
|
||||
2021-01-20 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
* linux-x86-low.cc (collect_register_i386): New function.
|
||||
(x86_fill_gregset): Remove memset. Use collect_register_i386.
|
||||
|
||||
diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc
|
||||
--- a/gdbserver/linux-x86-low.cc
|
||||
+++ b/gdbserver/linux-x86-low.cc
|
||||
@@ -397,6 +397,35 @@ x86_target::low_cannot_fetch_register (int regno)
|
||||
return regno >= I386_NUM_REGS;
|
||||
}
|
||||
|
||||
+static void
|
||||
+collect_register_i386 (struct regcache *regcache, int regno, void *buf)
|
||||
+{
|
||||
+ collect_register (regcache, regno, buf);
|
||||
+
|
||||
+#ifdef __x86_64__
|
||||
+ /* In case of x86_64 -m32, collect_register only writes 4 bytes, but the
|
||||
+ space reserved in buf for the register is 8 bytes. Make sure the entire
|
||||
+ reserved space is initialized. */
|
||||
+
|
||||
+ gdb_assert (register_size (regcache->tdesc, regno) == 4);
|
||||
+
|
||||
+ if (regno == RAX)
|
||||
+ {
|
||||
+ /* Sign extend EAX value to avoid potential syscall restart
|
||||
+ problems.
|
||||
+
|
||||
+ See amd64_linux_collect_native_gregset() in
|
||||
+ gdb/amd64-linux-nat.c for a detailed explanation. */
|
||||
+ *(int64_t *) buf = *(int32_t *) buf;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Zero-extend. */
|
||||
+ *(uint64_t *) buf = *(uint32_t *) buf;
|
||||
+ }
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
static void
|
||||
x86_fill_gregset (struct regcache *regcache, void *buf)
|
||||
{
|
||||
@@ -411,32 +440,14 @@ x86_fill_gregset (struct regcache *regcache, void *buf)
|
||||
|
||||
return;
|
||||
}
|
||||
-
|
||||
- /* 32-bit inferior registers need to be zero-extended.
|
||||
- Callers would read uninitialized memory otherwise. */
|
||||
- memset (buf, 0x00, X86_64_USER_REGS * 8);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < I386_NUM_REGS; i++)
|
||||
- collect_register (regcache, i, ((char *) buf) + i386_regmap[i]);
|
||||
-
|
||||
- collect_register_by_name (regcache, "orig_eax",
|
||||
- ((char *) buf) + ORIG_EAX * REGSIZE);
|
||||
+ collect_register_i386 (regcache, i, ((char *) buf) + i386_regmap[i]);
|
||||
|
||||
-#ifdef __x86_64__
|
||||
- /* Sign extend EAX value to avoid potential syscall restart
|
||||
- problems.
|
||||
-
|
||||
- See amd64_linux_collect_native_gregset() in gdb/amd64-linux-nat.c
|
||||
- for a detailed explanation. */
|
||||
- if (register_size (regcache->tdesc, 0) == 4)
|
||||
- {
|
||||
- void *ptr = ((gdb_byte *) buf
|
||||
- + i386_regmap[find_regno (regcache->tdesc, "eax")]);
|
||||
-
|
||||
- *(int64_t *) ptr = *(int32_t *) ptr;
|
||||
- }
|
||||
-#endif
|
||||
+ /* Handle ORIG_EAX, which is not in i386_regmap. */
|
||||
+ collect_register_i386 (regcache, find_regno (regcache->tdesc, "orig_eax"),
|
||||
+ ((char *) buf) + ORIG_EAX * REGSIZE);
|
||||
}
|
||||
|
||||
static void
|
@ -12,7 +12,7 @@ https://bugzilla.redhat.com/show_bug.cgi?id=1270534
|
||||
diff --git a/gdb/configure b/gdb/configure
|
||||
--- a/gdb/configure
|
||||
+++ b/gdb/configure
|
||||
@@ -9649,6 +9649,7 @@ if test x"$prefer_curses" = xyes; then
|
||||
@@ -9544,6 +9544,7 @@ if test x"$prefer_curses" = xyes; then
|
||||
# search /usr/local/include, if ncurses is installed in /usr/local. A
|
||||
# default installation of ncurses on alpha*-dec-osf* will lead to such
|
||||
# a situation.
|
||||
@ -20,7 +20,7 @@ diff --git a/gdb/configure b/gdb/configure
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing waddstr" >&5
|
||||
$as_echo_n "checking for library containing waddstr... " >&6; }
|
||||
if ${ac_cv_search_waddstr+:} false; then :
|
||||
@@ -9673,7 +9674,7 @@ return waddstr ();
|
||||
@@ -9568,7 +9569,7 @@ return waddstr ();
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
@ -29,7 +29,7 @@ diff --git a/gdb/configure b/gdb/configure
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
@@ -9747,6 +9748,7 @@ case $host_os in
|
||||
@@ -9642,6 +9643,7 @@ case $host_os in
|
||||
esac
|
||||
|
||||
# These are the libraries checked by Readline.
|
||||
@ -37,7 +37,7 @@ diff --git a/gdb/configure b/gdb/configure
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing tgetent" >&5
|
||||
$as_echo_n "checking for library containing tgetent... " >&6; }
|
||||
if ${ac_cv_search_tgetent+:} false; then :
|
||||
@@ -9771,7 +9773,7 @@ return tgetent ();
|
||||
@@ -9666,7 +9668,7 @@ return tgetent ();
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
@ -49,7 +49,7 @@ diff --git a/gdb/configure b/gdb/configure
|
||||
diff --git a/gdb/configure.ac b/gdb/configure.ac
|
||||
--- a/gdb/configure.ac
|
||||
+++ b/gdb/configure.ac
|
||||
@@ -712,7 +712,8 @@ if test x"$prefer_curses" = xyes; then
|
||||
@@ -736,7 +736,8 @@ if test x"$prefer_curses" = xyes; then
|
||||
# search /usr/local/include, if ncurses is installed in /usr/local. A
|
||||
# default installation of ncurses on alpha*-dec-osf* will lead to such
|
||||
# a situation.
|
||||
@ -59,7 +59,7 @@ diff --git a/gdb/configure.ac b/gdb/configure.ac
|
||||
|
||||
if test "$ac_cv_search_waddstr" != no; then
|
||||
curses_found=yes
|
||||
@@ -754,7 +755,8 @@ case $host_os in
|
||||
@@ -778,7 +779,8 @@ case $host_os in
|
||||
esac
|
||||
|
||||
# These are the libraries checked by Readline.
|
||||
|
@ -1,281 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Tom Tromey <tromey@adacore.com>
|
||||
Date: Fri, 23 Apr 2021 11:28:48 -0600
|
||||
Subject: gdb-gdb27743-psymtab-imported-unit.patch
|
||||
|
||||
;; Backport "Fix crash when expanding partial symtabs with DW_TAG_imported_unit"
|
||||
;; (Tom Tromey, gdb/27743)
|
||||
|
||||
From e7d77ce0c408e7019f9885b8be64c9cdb46dd312 Mon Sep 17 00:00:00 2001
|
||||
Subject: [PATCH] Fix crash when expanding partial symtabs with
|
||||
DW_TAG_imported_unit
|
||||
|
||||
PR gdb/27743 points out a gdb crash when expanding partial symtabs,
|
||||
where one of the compilation units uses DW_TAG_imported_unit.
|
||||
|
||||
The bug is that partial_map_expand_apply expects only to be called for
|
||||
the outermost psymtab. However, filename searching doesn't (and
|
||||
probably shouldn't) guarantee this. The fix is to walk upward to find
|
||||
the outermost CU.
|
||||
|
||||
A new test case is included. It is mostly copied from other test
|
||||
cases, which really sped up the effort.
|
||||
|
||||
This bug does not occur on trunk. There,
|
||||
psym_map_symtabs_matching_filename is gone, replaced by
|
||||
psymbol_functions::expand_symtabs_matching. When this find a match,
|
||||
it calls psymtab_to_symtab, which does this same upward walk.
|
||||
|
||||
Tested on x86-64 Fedora 32.
|
||||
|
||||
I propose checking in this patch on the gdb-10 branch, and just the
|
||||
new test case on trunk.
|
||||
|
||||
gdb/ChangeLog
|
||||
2021-04-23 Tom Tromey <tromey@adacore.com>
|
||||
|
||||
PR gdb/27743:
|
||||
* psymtab.c (partial_map_expand_apply): Expand outermost psymtab.
|
||||
|
||||
gdb/testsuite/ChangeLog
|
||||
2021-04-23 Tom Tromey <tromey@adacore.com>
|
||||
|
||||
PR gdb/27743:
|
||||
* gdb.dwarf2/imported-unit-bp.exp: New file.
|
||||
* gdb.dwarf2/imported-unit-bp-main.c: New file.
|
||||
* gdb.dwarf2/imported-unit-bp-alt.c: New file.
|
||||
|
||||
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
|
||||
--- a/gdb/psymtab.c
|
||||
+++ b/gdb/psymtab.c
|
||||
@@ -127,9 +127,10 @@ partial_map_expand_apply (struct objfile *objfile,
|
||||
{
|
||||
struct compunit_symtab *last_made = objfile->compunit_symtabs;
|
||||
|
||||
- /* Shared psymtabs should never be seen here. Instead they should
|
||||
- be handled properly by the caller. */
|
||||
- gdb_assert (pst->user == NULL);
|
||||
+ /* We may see a shared psymtab here, but we want to expand the
|
||||
+ outermost symtab. */
|
||||
+ while (pst->user != nullptr)
|
||||
+ pst = pst->user;
|
||||
|
||||
/* Don't visit already-expanded psymtabs. */
|
||||
if (pst->readin_p (objfile))
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/imported-unit-bp-alt.c b/gdb/testsuite/gdb.dwarf2/imported-unit-bp-alt.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/imported-unit-bp-alt.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+/* Copyright 2020-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 <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* Used to insert labels with which we can build a fake line table. */
|
||||
+#define LL(N) asm ("line_label_" #N ": .globl line_label_" #N)
|
||||
+
|
||||
+volatile int var;
|
||||
+volatile int bar;
|
||||
+
|
||||
+/* Generate some code to take up some space. */
|
||||
+#define FILLER do { \
|
||||
+ var = 99; \
|
||||
+} while (0)
|
||||
+
|
||||
+int
|
||||
+func (void)
|
||||
+{ /* func prologue */
|
||||
+ asm ("func_label: .globl func_label");
|
||||
+ LL (1); // F1, Ln 16
|
||||
+ FILLER;
|
||||
+ LL (2); // F1, Ln 17
|
||||
+ FILLER;
|
||||
+ LL (3); // F2, Ln 21
|
||||
+ FILLER;
|
||||
+ LL (4); // F2, Ln 22 // F1, Ln 18, !S
|
||||
+ FILLER;
|
||||
+ LL (5); // F1, Ln 19 !S
|
||||
+ FILLER;
|
||||
+ LL (6); // F1, Ln 20
|
||||
+ FILLER;
|
||||
+ LL (7);
|
||||
+ FILLER;
|
||||
+ return 0; /* func end */
|
||||
+}
|
||||
+
|
||||
+#ifdef WITHMAIN
|
||||
+int main () { return 0; }
|
||||
+#endif
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/imported-unit-bp-main.c b/gdb/testsuite/gdb.dwarf2/imported-unit-bp-main.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/imported-unit-bp-main.c
|
||||
@@ -0,0 +1,24 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2004-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 <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+extern int func (void);
|
||||
+
|
||||
+int
|
||||
+main()
|
||||
+{
|
||||
+ return func ();
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/imported-unit-bp.exp b/gdb/testsuite/gdb.dwarf2/imported-unit-bp.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/imported-unit-bp.exp
|
||||
@@ -0,0 +1,128 @@
|
||||
+# Copyright 2020-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 <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# Test that "break /absolute/file:line" works ok with imported CUs.
|
||||
+
|
||||
+load_lib dwarf.exp
|
||||
+
|
||||
+# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
+if {![dwarf2_support]} {
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+# The .c files use __attribute__.
|
||||
+if [get_compiler_info] {
|
||||
+ return -1
|
||||
+}
|
||||
+if !$gcc_compiled {
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+standard_testfile imported-unit-bp-alt.c .S imported-unit-bp-main.c
|
||||
+
|
||||
+set build_options {nodebug optimize=-O1}
|
||||
+
|
||||
+set asm_file [standard_output_file $srcfile2]
|
||||
+Dwarf::assemble $asm_file {
|
||||
+ global srcdir subdir srcfile srcfile
|
||||
+ global build_options
|
||||
+ declare_labels lines_label callee_subprog_label cu_label
|
||||
+
|
||||
+ get_func_info func "$build_options additional_flags=-DWITHMAIN"
|
||||
+
|
||||
+ cu {} {
|
||||
+ compile_unit {
|
||||
+ {language @DW_LANG_C}
|
||||
+ {name "<artificial>"}
|
||||
+ } {
|
||||
+ imported_unit {
|
||||
+ {import %$cu_label}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ cu {} {
|
||||
+ cu_label: compile_unit {
|
||||
+ {producer "gcc"}
|
||||
+ {language @DW_LANG_C}
|
||||
+ {name ${srcfile}}
|
||||
+ {comp_dir "/tmp"}
|
||||
+ {low_pc 0 addr}
|
||||
+ {stmt_list ${lines_label} DW_FORM_sec_offset}
|
||||
+ } {
|
||||
+ callee_subprog_label: subprogram {
|
||||
+ {external 1 flag}
|
||||
+ {name callee}
|
||||
+ {inline 3 data1}
|
||||
+ }
|
||||
+ subprogram {
|
||||
+ {external 1 flag}
|
||||
+ {name func}
|
||||
+ {low_pc $func_start addr}
|
||||
+ {high_pc "$func_start + $func_len" addr}
|
||||
+ } {
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ lines {version 2 default_is_stmt 1} lines_label {
|
||||
+ include_dir "/tmp"
|
||||
+ file_name "$srcfile" 1
|
||||
+
|
||||
+ program {
|
||||
+ {DW_LNE_set_address line_label_1}
|
||||
+ {DW_LNS_advance_line 15}
|
||||
+ {DW_LNS_copy}
|
||||
+
|
||||
+ {DW_LNE_set_address line_label_2}
|
||||
+ {DW_LNS_advance_line 1}
|
||||
+ {DW_LNS_copy}
|
||||
+
|
||||
+ {DW_LNE_set_address line_label_3}
|
||||
+ {DW_LNS_advance_line 4}
|
||||
+ {DW_LNS_copy}
|
||||
+
|
||||
+ {DW_LNE_set_address line_label_4}
|
||||
+ {DW_LNS_advance_line 1}
|
||||
+ {DW_LNS_copy}
|
||||
+
|
||||
+ {DW_LNS_advance_line -4}
|
||||
+ {DW_LNS_negate_stmt}
|
||||
+ {DW_LNS_copy}
|
||||
+
|
||||
+ {DW_LNE_set_address line_label_5}
|
||||
+ {DW_LNS_advance_line 1}
|
||||
+ {DW_LNS_copy}
|
||||
+
|
||||
+ {DW_LNE_set_address line_label_6}
|
||||
+ {DW_LNS_advance_line 1}
|
||||
+ {DW_LNS_negate_stmt}
|
||||
+ {DW_LNS_copy}
|
||||
+
|
||||
+ {DW_LNE_set_address line_label_7}
|
||||
+ {DW_LNE_end_sequence}
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if { [prepare_for_testing "failed to prepare" ${testfile} \
|
||||
+ [list $srcfile $asm_file $srcfile3] $build_options] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_reinitialize_dir /tmp
|
||||
+
|
||||
+# Using an absolute path is important to see the bug.
|
||||
+gdb_test "break /tmp/${srcfile}:19" "Breakpoint .* file $srcfile, line .*"
|
@ -213,7 +213,7 @@ diff --git a/gdb/nat/linux-btrace.h b/gdb/nat/linux-btrace.h
|
||||
diff --git a/gdbsupport/common.m4 b/gdbsupport/common.m4
|
||||
--- a/gdbsupport/common.m4
|
||||
+++ b/gdbsupport/common.m4
|
||||
@@ -145,7 +145,7 @@ AC_DEFUN([GDB_AC_COMMON], [
|
||||
@@ -135,7 +135,7 @@ AC_DEFUN([GDB_AC_COMMON], [
|
||||
AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <linux/perf_event.h>
|
||||
#ifndef PERF_ATTR_SIZE_VER5
|
||||
|
@ -42,22 +42,24 @@ diff --git a/gdb/testsuite/gdb.python/py-typeprint.exp b/gdb/testsuite/gdb.pytho
|
||||
diff --git a/gdb/testsuite/gdb.python/py-typeprint.py b/gdb/testsuite/gdb.python/py-typeprint.py
|
||||
--- a/gdb/testsuite/gdb.python/py-typeprint.py
|
||||
+++ b/gdb/testsuite/gdb.python/py-typeprint.py
|
||||
@@ -15,7 +15,7 @@
|
||||
@@ -15,8 +15,7 @@
|
||||
|
||||
import gdb
|
||||
|
||||
-
|
||||
-class Recognizer(object):
|
||||
+class StringRecognizer(object):
|
||||
def __init__(self):
|
||||
self.enabled = True
|
||||
|
||||
@@ -30,6 +30,26 @@ class StringTypePrinter(object):
|
||||
@@ -32,7 +31,27 @@ class StringTypePrinter(object):
|
||||
self.enabled = True
|
||||
|
||||
def instantiate(self):
|
||||
- return Recognizer()
|
||||
+ return StringRecognizer()
|
||||
|
||||
|
||||
gdb.type_printers.append(StringTypePrinter())
|
||||
+
|
||||
+class OtherRecognizer(object):
|
||||
|
@ -1,67 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Keith Seitz <keiths@redhat.com>
|
||||
Date: Mon, 16 Nov 2020 12:42:09 -0500
|
||||
Subject: gdb-rhbz1898252-loadable-section-outside-ELF-segments.patch
|
||||
|
||||
;; Backport of "Exclude debuginfo files from 'outside of ELF segments'
|
||||
;; warning" (Keith Seitz)
|
||||
|
||||
Exclude debuginfo files from "outside of ELF segments" warning
|
||||
|
||||
When GDB loads an ELF file, it will warn when a section is not located
|
||||
in an ELF segment:
|
||||
|
||||
$ ./gdb -q -iex "set build-id-verbose 0" --ex "b systemctl_main" -ex "r" -batch --args systemctl kexec
|
||||
Breakpoint 1 at 0xc24d: file ../src/systemctl/systemctl.c, line 8752.
|
||||
warning: Loadable section ".note.gnu.property" outside of ELF segments
|
||||
in .gnu_debugdata for /lib64/libgcc_s.so.1
|
||||
[Thread debugging using libthread_db enabled]
|
||||
Using host libthread_db library "/lib64/libthread_db.so.1".
|
||||
warning: Loadable section ".note.gnu.property" outside of ELF segments
|
||||
in .gnu_debugdata for /lib64/libcap.so.2
|
||||
warning: Loadable section ".note.gnu.property" outside of ELF segments
|
||||
in .gnu_debugdata for /lib64/libacl.so.1
|
||||
warning: Loadable section ".note.gnu.property" outside of ELF segments
|
||||
in .gnu_debugdata for /lib64/libcryptsetup.so.12
|
||||
warning: Loadable section ".note.gnu.property" outside of ELF segments
|
||||
in .gnu_debugdata for /lib64/libgcrypt.so.20
|
||||
warning: Loadable section ".note.gnu.property" outside of ELF segments
|
||||
in .gnu_debugdata for /lib64/libip4tc.so.2
|
||||
[snip]
|
||||
This has feature has also been reported by various users, most notably
|
||||
the Fedora-EOL'd bug 1553086.
|
||||
|
||||
Mark Wielaard explains the issue quite nicely in
|
||||
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=24717#c2
|
||||
|
||||
The short of it is, the ELF program headers for debuginfo files are
|
||||
not suited to this particular use case. Consequently, the warning
|
||||
generated above really is useless and should be ignored.
|
||||
|
||||
This patch follows the same heuristic that BFD itself uses.
|
||||
|
||||
gdb/ChangeLog
|
||||
2020-11-13 Keith Seitz <keiths@redhat.com>
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1553086
|
||||
* elfread.c (elf_symfile_segments): Omit "Loadable section ...
|
||||
outside of ELF segments" warning for debugin
|
||||
|
||||
diff --git a/gdb/elfread.c b/gdb/elfread.c
|
||||
--- a/gdb/elfread.c
|
||||
+++ b/gdb/elfread.c
|
||||
@@ -147,7 +147,12 @@ elf_symfile_segments (bfd *abfd)
|
||||
RealView) use SHT_NOBITS for uninitialized data. Since it is
|
||||
uninitialized, it doesn't need a program header. Such
|
||||
binaries are not relocatable. */
|
||||
- if (bfd_section_size (sect) > 0 && j == num_segments
|
||||
+
|
||||
+ /* Exclude debuginfo files from this warning, too, since those
|
||||
+ are often not strictly compliant with the standard. See, e.g.,
|
||||
+ ld/24717 for more discussion. */
|
||||
+ if (!is_debuginfo_file (abfd)
|
||||
+ && bfd_section_size (sect) > 0 && j == num_segments
|
||||
&& (bfd_section_flags (sect) & SEC_LOAD) != 0)
|
||||
warning (_("Loadable section \"%s\" outside of ELF segments"),
|
||||
bfd_section_name (sect));
|
@ -1,82 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Tue, 8 Dec 2020 14:07:45 -0700
|
||||
Subject: gdb-rhbz1905996-fix-off-by-one-error-in-ada_fold_name.patch
|
||||
|
||||
;; Fix off-by-one error in ada_fold_name.patch (RH BZ 1905996)
|
||||
;; Upstream patch proposal: https://sourceware.org/pipermail/gdb-patches/2020-December/173935.html
|
||||
;; =fedoratest
|
||||
|
||||
Fix off-by-one error in ada_fold_name
|
||||
|
||||
I'm seeing a libstdc++ assertion failure when running GDB's "maint selftest"
|
||||
command when GDB is configured with the following CFLAGS and CXXFLAGS as
|
||||
part of the configure line:
|
||||
|
||||
CFLAGS='-D_GLIBCXX_DEBUG -g3 -O0' CXXFLAGS='-D_GLIBCXX_DEBUG -g3 -O0'
|
||||
|
||||
This is what I see when running the self tests:
|
||||
|
||||
(gdb) maint selftest
|
||||
Running selftest aarch64-analyze-prologue.
|
||||
Running selftest aarch64-process-record.
|
||||
Running selftest arm-record.
|
||||
Running selftest arm_analyze_prologue.
|
||||
Running selftest array_view.
|
||||
Running selftest child_path.
|
||||
Running selftest cli_utils.
|
||||
Running selftest command_structure_invariants.
|
||||
Running selftest copy_bitwise.
|
||||
Running selftest copy_integer_to_size.
|
||||
Running selftest cp_remove_params.
|
||||
Running selftest cp_symbol_name_matches.
|
||||
Running selftest dw2_expand_symtabs_matching.
|
||||
/usr/include/c++/11/string_view:211: constexpr const value_type& std::basic_string_view<_CharT, _Traits>::operator[](std::basic_string_view<_CharT, _Traits>::size_type) const [with _CharT = char; _Traits = std::char_traits<char>; std::basic_string_view<_CharT, _Traits>::const_reference = const char&; std::basic_string_view<_CharT, _Traits>::size_type = long unsigned int]: Assertion '__pos < this->_M_len' failed.
|
||||
Aborted (core dumped)
|
||||
|
||||
Here's a partial stack trace:
|
||||
|
||||
#0 0x00007ffff6ef6262 in raise () from /lib64/libc.so.6
|
||||
#1 0x00007ffff6edf8a4 in abort () from /lib64/libc.so.6
|
||||
#2 0x00000000004249bf in std::__replacement_assert (
|
||||
__file=0xef7480 "/usr/include/c++/11/string_view", __line=211,
|
||||
__function=0xef7328 "constexpr const value_type& std::basic_string_view<_CharT, _Traits>::operator[](std::basic_string_view<_CharT, _Traits>::size_type) const [with _CharT = char; _Traits = std::char_traits<char>; std::ba"...,
|
||||
__condition=0xef7311 "__pos < this->_M_len")
|
||||
at /usr/include/c++/11/x86_64-redhat-linux/bits/c++config.h:2624
|
||||
#3 0x0000000000451737 in std::basic_string_view<char, std::char_traits<char> >::operator[] (this=0x7fffffffc200, __pos=8)
|
||||
at /usr/include/c++/11/string_view:211
|
||||
#4 0x00000000004329f5 in ada_fold_name (name="function")
|
||||
at /ironwood1/sourceware-git/rawhide-master/bld/../../worktree-master/gdb/ada-lang.c:988
|
||||
|
||||
And, looking at frame #4...
|
||||
|
||||
(top-gdb) up 4
|
||||
at /ironwood1/sourceware-git/rawhide-master/bld/../../worktree-master/gdb/ada-lang.c:988
|
||||
988 fold_buffer[i] = tolower (name[i]);
|
||||
(top-gdb) p i
|
||||
$1 = 8
|
||||
(top-gdb) p name.size()
|
||||
$2 = 8
|
||||
|
||||
My patch adjusts the comparison to only copy name.size() characters
|
||||
from the string. I've added a separate statement for NUL character
|
||||
termination of fold_buffer[].
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* ada-lang.c (ada_fold_name): Fix off-by-one error.
|
||||
|
||||
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
|
||||
--- a/gdb/ada-lang.c
|
||||
+++ b/gdb/ada-lang.c
|
||||
@@ -1006,8 +1006,9 @@ ada_fold_name (gdb::string_view name)
|
||||
{
|
||||
int i;
|
||||
|
||||
- for (i = 0; i <= len; i += 1)
|
||||
+ for (i = 0; i < len; i += 1)
|
||||
fold_buffer[i] = tolower (name[i]);
|
||||
+ fold_buffer[i] = '\0';
|
||||
}
|
||||
|
||||
return fold_buffer;
|
@ -1,593 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Pedro Alves <pedro@palves.net>
|
||||
Date: Fri, 30 Oct 2020 18:26:15 +0100
|
||||
Subject: gdb-rhbz1909902-frame_id_p-assert-1.patch
|
||||
|
||||
;; Backport fix for frame_id_p assertion failure (RH BZ 1909902).
|
||||
|
||||
Make scoped_restore_current_thread's cdtors exception free (RFC)
|
||||
|
||||
If the remote target closes while we're reading registers/memory for
|
||||
restoring the selected frame in scoped_restore_current_thread's dtor,
|
||||
the corresponding TARGET_CLOSE_ERROR error is swallowed by the
|
||||
scoped_restore_current_thread's dtor, because letting exceptions
|
||||
escape from a dtor is bad. It isn't great to lose that errors like
|
||||
that, though. I've been thinking about how to avoid it, and I came up
|
||||
with this patch.
|
||||
|
||||
The idea here is to make scoped_restore_current_thread's dtor do as
|
||||
little as possible, to avoid any work that might throw in the first
|
||||
place. And to do that, instead of having the dtor call
|
||||
restore_selected_frame, which re-finds the previously selected frame,
|
||||
just record the frame_id/level of the desired selected frame, and have
|
||||
get_selected_frame find the frame the next time it is called. In
|
||||
effect, this implements most of Cagney's suggestion, here:
|
||||
|
||||
/* On demand, create the selected frame and then return it. If the
|
||||
selected frame can not be created, this function prints then throws
|
||||
an error. When MESSAGE is non-NULL, use it for the error message,
|
||||
otherwize use a generic error message. */
|
||||
/* FIXME: cagney/2002-11-28: At present, when there is no selected
|
||||
frame, this function always returns the current (inner most) frame.
|
||||
It should instead, when a thread has previously had its frame
|
||||
selected (but not resumed) and the frame cache invalidated, find
|
||||
and then return that thread's previously selected frame. */
|
||||
extern struct frame_info *get_selected_frame (const char *message);
|
||||
|
||||
The only thing missing to fully implement that would be to make
|
||||
reinit_frame_cache just clear selected_frame instead of calling
|
||||
select_frame(NULL), and the call select_frame(NULL) explicitly in the
|
||||
places where we really wanted reinit_frame_cache to go back to the
|
||||
current frame too. That can done separately, though, I'm not
|
||||
proposing to do that in this patch.
|
||||
|
||||
Note that this patch renames restore_selected_frame to
|
||||
lookup_selected_frame, and adds a new restore_selected_frame function
|
||||
that doesn't throw, to be paired with the also-new save_selected_frame
|
||||
function.
|
||||
|
||||
There's a restore_selected_frame function in infrun.c that I think can
|
||||
be replaced by the new one in frame.c.
|
||||
|
||||
Also done in this patch is make the get_selected_frame's parameter be
|
||||
optional, so that we don't have to pass down nullptr explicitly all
|
||||
over the place.
|
||||
|
||||
lookup_selected_frame should really move from thread.c to frame.c, but
|
||||
I didn't do that here, just to avoid churn in the patch while it
|
||||
collects comments. I did make it extern and declared it in frame.h
|
||||
already, preparing for the move. I will do the move as a follow up
|
||||
patch if people agree with this approach.
|
||||
|
||||
Incidentally, this patch alone would fix the crashes fixed by the
|
||||
previous patches in the series, because with this,
|
||||
scoped_restore_current_thread's constructor doesn't throw either.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* blockframe.c (block_innermost_frame): Use get_selected_frame.
|
||||
* frame.c
|
||||
(scoped_restore_selected_frame::scoped_restore_selected_frame):
|
||||
Use save_selected_frame. Save language as well.
|
||||
(scoped_restore_selected_frame::~scoped_restore_selected_frame):
|
||||
Use restore_selected_frame, and restore language as well.
|
||||
(selected_frame_id, selected_frame_level): New.
|
||||
(selected_frame): Update comments.
|
||||
(save_selected_frame, restore_selected_frame): New.
|
||||
(get_selected_frame): Use lookup_selected_frame.
|
||||
(get_selected_frame_if_set): Delete.
|
||||
(select_frame): Record selected_frame_level and selected_frame_id.
|
||||
* frame.h (scoped_restore_selected_frame) <m_level, m_lang>: New
|
||||
fields.
|
||||
(get_selected_frame): Make 'message' parameter optional.
|
||||
(get_selected_frame_if_set): Delete declaration.
|
||||
(select_frame): Update comments.
|
||||
(save_selected_frame, restore_selected_frame)
|
||||
(lookup_selected_frame): Declare.
|
||||
* gdbthread.h (scoped_restore_current_thread) <m_lang>: New field.
|
||||
* infrun.c (struct infcall_control_state) <selected_frame_level>:
|
||||
New field.
|
||||
(save_infcall_control_state): Use save_selected_frame.
|
||||
(restore_selected_frame): Delete.
|
||||
(restore_infcall_control_state): Use restore_selected_frame.
|
||||
* stack.c (select_frame_command_core, frame_command_core): Use
|
||||
get_selected_frame.
|
||||
* thread.c (restore_selected_frame): Rename to ...
|
||||
(lookup_selected_frame): ... this and make extern. Select the
|
||||
current frame if the frame level is -1.
|
||||
(scoped_restore_current_thread::restore): Also restore the
|
||||
language.
|
||||
(scoped_restore_current_thread::~scoped_restore_current_thread):
|
||||
Don't try/catch.
|
||||
(scoped_restore_current_thread::scoped_restore_current_thread):
|
||||
Save the language as well. Use save_selected_frame.
|
||||
|
||||
Change-Id: I73fd1cfc40d8513c28e5596383b7ecd8bcfe700f
|
||||
|
||||
diff --git a/gdb/blockframe.c b/gdb/blockframe.c
|
||||
--- a/gdb/blockframe.c
|
||||
+++ b/gdb/blockframe.c
|
||||
@@ -464,14 +464,10 @@ find_gnu_ifunc_target_type (CORE_ADDR resolver_funaddr)
|
||||
struct frame_info *
|
||||
block_innermost_frame (const struct block *block)
|
||||
{
|
||||
- struct frame_info *frame;
|
||||
-
|
||||
if (block == NULL)
|
||||
return NULL;
|
||||
|
||||
- frame = get_selected_frame_if_set ();
|
||||
- if (frame == NULL)
|
||||
- frame = get_current_frame ();
|
||||
+ frame_info *frame = get_selected_frame ();
|
||||
while (frame != NULL)
|
||||
{
|
||||
const struct block *frame_block = get_frame_block (frame, NULL);
|
||||
diff --git a/gdb/frame.c b/gdb/frame.c
|
||||
--- a/gdb/frame.c
|
||||
+++ b/gdb/frame.c
|
||||
@@ -317,17 +317,15 @@ frame_stash_invalidate (void)
|
||||
/* See frame.h */
|
||||
scoped_restore_selected_frame::scoped_restore_selected_frame ()
|
||||
{
|
||||
- m_fid = get_frame_id (get_selected_frame (NULL));
|
||||
+ m_lang = current_language->la_language;
|
||||
+ save_selected_frame (&m_fid, &m_level);
|
||||
}
|
||||
|
||||
/* See frame.h */
|
||||
scoped_restore_selected_frame::~scoped_restore_selected_frame ()
|
||||
{
|
||||
- frame_info *frame = frame_find_by_id (m_fid);
|
||||
- if (frame == NULL)
|
||||
- warning (_("Unable to restore previously selected frame."));
|
||||
- else
|
||||
- select_frame (frame);
|
||||
+ restore_selected_frame (m_fid, m_level);
|
||||
+ set_language (m_lang);
|
||||
}
|
||||
|
||||
/* Flag to control debugging. */
|
||||
@@ -1685,10 +1683,63 @@ get_current_frame (void)
|
||||
}
|
||||
|
||||
/* The "selected" stack frame is used by default for local and arg
|
||||
- access. May be zero, for no selected frame. */
|
||||
-
|
||||
+ access.
|
||||
+
|
||||
+ The "single source of truth" for the selected frame is the
|
||||
+ SELECTED_FRAME_ID / SELECTED_FRAME_LEVEL pair.
|
||||
+
|
||||
+ Frame IDs can be saved/restored across reinitializing the frame
|
||||
+ cache, while frame_info pointers can't (frame_info objects are
|
||||
+ invalidated). If we know the corresponding frame_info object, it
|
||||
+ is cached in SELECTED_FRAME.
|
||||
+
|
||||
+ If SELECTED_FRAME_ID / SELECTED_FRAME_LEVEL are null_frame_id / -1,
|
||||
+ and the target has stack and is stopped, the selected frame is the
|
||||
+ current (innermost) frame. This means that SELECTED_FRAME_LEVEL is
|
||||
+ never 0 and SELECTED_FRAME_ID is never the ID of the innermost
|
||||
+ frame.
|
||||
+
|
||||
+ If SELECTED_FRAME_ID / SELECTED_FRAME_LEVEL are null_frame_id / -1,
|
||||
+ and the target has no stack or is executing, then there's no
|
||||
+ selected frame. */
|
||||
+static frame_id selected_frame_id = null_frame_id;
|
||||
+static int selected_frame_level = -1;
|
||||
+
|
||||
+/* The cached frame_info object pointing to the selected frame.
|
||||
+ Looked up on demand by get_selected_frame. */
|
||||
static struct frame_info *selected_frame;
|
||||
|
||||
+/* See frame.h. */
|
||||
+
|
||||
+void
|
||||
+save_selected_frame (frame_id *frame_id, int *frame_level)
|
||||
+ noexcept
|
||||
+{
|
||||
+ *frame_id = selected_frame_id;
|
||||
+ *frame_level = selected_frame_level;
|
||||
+}
|
||||
+
|
||||
+/* See frame.h. */
|
||||
+
|
||||
+void
|
||||
+restore_selected_frame (frame_id frame_id, int frame_level)
|
||||
+ noexcept
|
||||
+{
|
||||
+ /* save_selected_frame never returns level == 0, so we shouldn't see
|
||||
+ it here either. */
|
||||
+ gdb_assert (frame_level != 0);
|
||||
+
|
||||
+ /* FRAME_ID can be null_frame_id only IFF frame_level is -1. */
|
||||
+ gdb_assert ((frame_level == -1 && !frame_id_p (frame_id))
|
||||
+ || (frame_level != -1 && frame_id_p (frame_id)));
|
||||
+
|
||||
+ selected_frame_id = frame_id;
|
||||
+ selected_frame_level = frame_level;
|
||||
+
|
||||
+ /* Will be looked up later by get_selected_frame. */
|
||||
+ selected_frame = nullptr;
|
||||
+}
|
||||
+
|
||||
bool
|
||||
has_stack_frames ()
|
||||
{
|
||||
@@ -1715,9 +1766,7 @@ has_stack_frames ()
|
||||
return true;
|
||||
}
|
||||
|
||||
-/* Return the selected frame. Always non-NULL (unless there isn't an
|
||||
- inferior sufficient for creating a frame) in which case an error is
|
||||
- thrown. */
|
||||
+/* See frame.h. */
|
||||
|
||||
struct frame_info *
|
||||
get_selected_frame (const char *message)
|
||||
@@ -1726,24 +1775,14 @@ get_selected_frame (const char *message)
|
||||
{
|
||||
if (message != NULL && !has_stack_frames ())
|
||||
error (("%s"), message);
|
||||
- /* Hey! Don't trust this. It should really be re-finding the
|
||||
- last selected frame of the currently selected thread. This,
|
||||
- though, is better than nothing. */
|
||||
- select_frame (get_current_frame ());
|
||||
+
|
||||
+ lookup_selected_frame (selected_frame_id, selected_frame_level);
|
||||
}
|
||||
/* There is always a frame. */
|
||||
gdb_assert (selected_frame != NULL);
|
||||
return selected_frame;
|
||||
}
|
||||
|
||||
-/* If there is a selected frame, return it. Otherwise, return NULL. */
|
||||
-
|
||||
-struct frame_info *
|
||||
-get_selected_frame_if_set (void)
|
||||
-{
|
||||
- return selected_frame;
|
||||
-}
|
||||
-
|
||||
/* This is a variant of get_selected_frame() which can be called when
|
||||
the inferior does not have a frame; in that case it will return
|
||||
NULL instead of calling error(). */
|
||||
@@ -1756,12 +1795,42 @@ deprecated_safe_get_selected_frame (void)
|
||||
return get_selected_frame (NULL);
|
||||
}
|
||||
|
||||
-/* Select frame FI (or NULL - to invalidate the current frame). */
|
||||
+/* Select frame FI (or NULL - to invalidate the selected frame). */
|
||||
|
||||
void
|
||||
select_frame (struct frame_info *fi)
|
||||
{
|
||||
selected_frame = fi;
|
||||
+ selected_frame_level = frame_relative_level (fi);
|
||||
+ if (selected_frame_level == 0)
|
||||
+ {
|
||||
+ /* Treat the current frame especially -- we want to always
|
||||
+ save/restore it without warning, even if the frame ID changes
|
||||
+ (see lookup_selected_frame). E.g.:
|
||||
+
|
||||
+ // The current frame is selected, the target had just stopped.
|
||||
+ {
|
||||
+ scoped_restore_selected_frame restore_frame;
|
||||
+ some_operation_that_changes_the_stack ();
|
||||
+ }
|
||||
+ // scoped_restore_selected_frame's dtor runs, but the
|
||||
+ // original frame_id can't be found. No matter whether it
|
||||
+ // is found or not, we still end up with the now-current
|
||||
+ // frame selected. Warning in lookup_selected_frame in this
|
||||
+ // case seems pointless.
|
||||
+
|
||||
+ Also get_frame_id may access the target's registers/memory,
|
||||
+ and thus skipping get_frame_id optimizes the common case.
|
||||
+
|
||||
+ Saving the selected frame this way makes get_selected_frame
|
||||
+ and restore_current_frame return/re-select whatever frame is
|
||||
+ the innermost (current) then. */
|
||||
+ selected_frame_level = -1;
|
||||
+ selected_frame_id = null_frame_id;
|
||||
+ }
|
||||
+ else
|
||||
+ selected_frame_id = get_frame_id (fi);
|
||||
+
|
||||
/* NOTE: cagney/2002-05-04: FI can be NULL. This occurs when the
|
||||
frame is being invalidated. */
|
||||
|
||||
diff --git a/gdb/frame.h b/gdb/frame.h
|
||||
--- a/gdb/frame.h
|
||||
+++ b/gdb/frame.h
|
||||
@@ -186,8 +186,14 @@ class scoped_restore_selected_frame
|
||||
|
||||
private:
|
||||
|
||||
- /* The ID of the previously selected frame. */
|
||||
+ /* The ID and level of the previously selected frame. */
|
||||
struct frame_id m_fid;
|
||||
+ int m_level;
|
||||
+
|
||||
+ /* Save/restore the language as well, because selecting a frame
|
||||
+ changes the current language to the frame's language if "set
|
||||
+ language auto". */
|
||||
+ enum language m_lang;
|
||||
};
|
||||
|
||||
/* Methods for constructing and comparing Frame IDs. */
|
||||
@@ -316,24 +322,49 @@ extern bool has_stack_frames ();
|
||||
modifies the target invalidating the frame cache). */
|
||||
extern void reinit_frame_cache (void);
|
||||
|
||||
-/* On demand, create the selected frame and then return it. If the
|
||||
- selected frame can not be created, this function prints then throws
|
||||
- an error. When MESSAGE is non-NULL, use it for the error message,
|
||||
+/* Return the selected frame. Always returns non-NULL. If there
|
||||
+ isn't an inferior sufficient for creating a frame, an error is
|
||||
+ thrown. When MESSAGE is non-NULL, use it for the error message,
|
||||
otherwise use a generic error message. */
|
||||
/* FIXME: cagney/2002-11-28: At present, when there is no selected
|
||||
frame, this function always returns the current (inner most) frame.
|
||||
It should instead, when a thread has previously had its frame
|
||||
selected (but not resumed) and the frame cache invalidated, find
|
||||
and then return that thread's previously selected frame. */
|
||||
-extern struct frame_info *get_selected_frame (const char *message);
|
||||
-
|
||||
-/* If there is a selected frame, return it. Otherwise, return NULL. */
|
||||
-extern struct frame_info *get_selected_frame_if_set (void);
|
||||
+extern struct frame_info *get_selected_frame (const char *message = nullptr);
|
||||
|
||||
-/* Select a specific frame. NULL, apparently implies re-select the
|
||||
- inner most frame. */
|
||||
+/* Select a specific frame. NULL implies re-select the inner most
|
||||
+ frame. */
|
||||
extern void select_frame (struct frame_info *);
|
||||
|
||||
+/* Save the frame ID and frame level of the selected frame in FRAME_ID
|
||||
+ and FRAME_LEVEL, to be restored later with restore_selected_frame.
|
||||
+
|
||||
+ This is preferred over getting the same info out of
|
||||
+ get_selected_frame directly because this function does not create
|
||||
+ the selected-frame's frame_info object if it hasn't been created
|
||||
+ yet, and thus is more efficient and doesn't throw. */
|
||||
+extern void save_selected_frame (frame_id *frame_id, int *frame_level)
|
||||
+ noexcept;
|
||||
+
|
||||
+/* Restore selected frame as saved with save_selected_frame.
|
||||
+
|
||||
+ Does not try to find the corresponding frame_info object. Instead
|
||||
+ the next call to get_selected_frame will look it up and cache the
|
||||
+ result.
|
||||
+
|
||||
+ This function does not throw. It is designed to be safe to called
|
||||
+ from the destructors of RAII types. */
|
||||
+extern void restore_selected_frame (frame_id frame_id, int frame_level)
|
||||
+ noexcept;
|
||||
+
|
||||
+/* Lookup the frame_info object for the selected frame FRAME_ID /
|
||||
+ FRAME_LEVEL and cache the result.
|
||||
+
|
||||
+ If FRAME_LEVEL > 0 and the originally selected frame isn't found,
|
||||
+ warn and select the innermost (current) frame. */
|
||||
+extern void lookup_selected_frame (frame_id frame_id, int frame_level);
|
||||
+
|
||||
/* Given a FRAME, return the next (more inner, younger) or previous
|
||||
(more outer, older) frame. */
|
||||
extern struct frame_info *get_prev_frame (struct frame_info *);
|
||||
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
|
||||
--- a/gdb/gdbthread.h
|
||||
+++ b/gdb/gdbthread.h
|
||||
@@ -673,6 +673,10 @@ class scoped_restore_current_thread
|
||||
frame_id m_selected_frame_id;
|
||||
int m_selected_frame_level;
|
||||
bool m_was_stopped;
|
||||
+ /* Save/restore the language as well, because selecting a frame
|
||||
+ changes the current language to the frame's language if "set
|
||||
+ language auto". */
|
||||
+ enum language m_lang;
|
||||
};
|
||||
|
||||
/* Returns a pointer into the thread_info corresponding to
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -9006,8 +9006,10 @@ struct infcall_control_state
|
||||
enum stop_stack_kind stop_stack_dummy = STOP_NONE;
|
||||
int stopped_by_random_signal = 0;
|
||||
|
||||
- /* ID if the selected frame when the inferior function call was made. */
|
||||
+ /* ID and level of the selected frame when the inferior function
|
||||
+ call was made. */
|
||||
struct frame_id selected_frame_id {};
|
||||
+ int selected_frame_level = -1;
|
||||
};
|
||||
|
||||
/* Save all of the information associated with the inferior<==>gdb
|
||||
@@ -9036,27 +9038,12 @@ save_infcall_control_state ()
|
||||
inf_status->stop_stack_dummy = stop_stack_dummy;
|
||||
inf_status->stopped_by_random_signal = stopped_by_random_signal;
|
||||
|
||||
- inf_status->selected_frame_id = get_frame_id (get_selected_frame (NULL));
|
||||
+ save_selected_frame (&inf_status->selected_frame_id,
|
||||
+ &inf_status->selected_frame_level);
|
||||
|
||||
return inf_status;
|
||||
}
|
||||
|
||||
-static void
|
||||
-restore_selected_frame (const frame_id &fid)
|
||||
-{
|
||||
- frame_info *frame = frame_find_by_id (fid);
|
||||
-
|
||||
- /* If inf_status->selected_frame_id is NULL, there was no previously
|
||||
- selected frame. */
|
||||
- if (frame == NULL)
|
||||
- {
|
||||
- warning (_("Unable to restore previously selected frame."));
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- select_frame (frame);
|
||||
-}
|
||||
-
|
||||
/* Restore inferior session state to INF_STATUS. */
|
||||
|
||||
void
|
||||
@@ -9084,21 +9071,8 @@ restore_infcall_control_state (struct infcall_control_state *inf_status)
|
||||
|
||||
if (target_has_stack)
|
||||
{
|
||||
- /* The point of the try/catch is that if the stack is clobbered,
|
||||
- walking the stack might encounter a garbage pointer and
|
||||
- error() trying to dereference it. */
|
||||
- try
|
||||
- {
|
||||
- restore_selected_frame (inf_status->selected_frame_id);
|
||||
- }
|
||||
- catch (const gdb_exception_error &ex)
|
||||
- {
|
||||
- exception_fprintf (gdb_stderr, ex,
|
||||
- "Unable to restore previously selected frame:\n");
|
||||
- /* Error in restoring the selected frame. Select the
|
||||
- innermost frame. */
|
||||
- select_frame (get_current_frame ());
|
||||
- }
|
||||
+ restore_selected_frame (inf_status->selected_frame_id,
|
||||
+ inf_status->selected_frame_level);
|
||||
}
|
||||
|
||||
delete inf_status;
|
||||
diff --git a/gdb/stack.c b/gdb/stack.c
|
||||
--- a/gdb/stack.c
|
||||
+++ b/gdb/stack.c
|
||||
@@ -1842,9 +1842,9 @@ trailing_outermost_frame (int count)
|
||||
static void
|
||||
select_frame_command_core (struct frame_info *fi, bool ignored)
|
||||
{
|
||||
- struct frame_info *prev_frame = get_selected_frame_if_set ();
|
||||
+ frame_info *prev_frame = get_selected_frame ();
|
||||
select_frame (fi);
|
||||
- if (get_selected_frame_if_set () != prev_frame)
|
||||
+ if (get_selected_frame () != prev_frame)
|
||||
gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
|
||||
}
|
||||
|
||||
@@ -1863,10 +1863,9 @@ select_frame_for_mi (struct frame_info *fi)
|
||||
static void
|
||||
frame_command_core (struct frame_info *fi, bool ignored)
|
||||
{
|
||||
- struct frame_info *prev_frame = get_selected_frame_if_set ();
|
||||
-
|
||||
+ frame_info *prev_frame = get_selected_frame ();
|
||||
select_frame (fi);
|
||||
- if (get_selected_frame_if_set () != prev_frame)
|
||||
+ if (get_selected_frame () != prev_frame)
|
||||
gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
|
||||
else
|
||||
print_selected_thread_frame (current_uiout, USER_SELECTED_FRAME);
|
||||
diff --git a/gdb/thread.c b/gdb/thread.c
|
||||
--- a/gdb/thread.c
|
||||
+++ b/gdb/thread.c
|
||||
@@ -1325,20 +1325,26 @@ switch_to_thread (process_stratum_target *proc_target, ptid_t ptid)
|
||||
switch_to_thread (thr);
|
||||
}
|
||||
|
||||
-static void
|
||||
-restore_selected_frame (struct frame_id a_frame_id, int frame_level)
|
||||
+/* See frame.h. */
|
||||
+
|
||||
+void
|
||||
+lookup_selected_frame (struct frame_id a_frame_id, int frame_level)
|
||||
{
|
||||
struct frame_info *frame = NULL;
|
||||
int count;
|
||||
|
||||
- /* This means there was no selected frame. */
|
||||
+ /* This either means there was no selected frame, or the selected
|
||||
+ frame was the current frame. In either case, select the current
|
||||
+ frame. */
|
||||
if (frame_level == -1)
|
||||
{
|
||||
- select_frame (NULL);
|
||||
+ select_frame (get_current_frame ());
|
||||
return;
|
||||
}
|
||||
|
||||
- gdb_assert (frame_level >= 0);
|
||||
+ /* select_frame never saves 0 in SELECTED_FRAME_LEVEL, so we
|
||||
+ shouldn't see it here. */
|
||||
+ gdb_assert (frame_level > 0);
|
||||
|
||||
/* Restore by level first, check if the frame id is the same as
|
||||
expected. If that fails, try restoring by frame id. If that
|
||||
@@ -1409,64 +1415,28 @@ scoped_restore_current_thread::restore ()
|
||||
&& target_has_stack
|
||||
&& target_has_memory)
|
||||
restore_selected_frame (m_selected_frame_id, m_selected_frame_level);
|
||||
+
|
||||
+ set_language (m_lang);
|
||||
}
|
||||
|
||||
scoped_restore_current_thread::~scoped_restore_current_thread ()
|
||||
{
|
||||
if (!m_dont_restore)
|
||||
- {
|
||||
- try
|
||||
- {
|
||||
- restore ();
|
||||
- }
|
||||
- catch (const gdb_exception &ex)
|
||||
- {
|
||||
- /* We're in a dtor, there's really nothing else we can do
|
||||
- but swallow the exception. */
|
||||
- }
|
||||
- }
|
||||
+ restore ();
|
||||
}
|
||||
|
||||
scoped_restore_current_thread::scoped_restore_current_thread ()
|
||||
{
|
||||
m_inf = inferior_ref::new_reference (current_inferior ());
|
||||
|
||||
+ m_lang = current_language->la_language;
|
||||
+
|
||||
if (inferior_ptid != null_ptid)
|
||||
{
|
||||
m_thread = thread_info_ref::new_reference (inferior_thread ());
|
||||
|
||||
- struct frame_info *frame;
|
||||
-
|
||||
m_was_stopped = m_thread->state == THREAD_STOPPED;
|
||||
- if (m_was_stopped
|
||||
- && target_has_registers
|
||||
- && target_has_stack
|
||||
- && target_has_memory)
|
||||
- {
|
||||
- /* When processing internal events, there might not be a
|
||||
- selected frame. If we naively call get_selected_frame
|
||||
- here, then we can end up reading debuginfo for the
|
||||
- current frame, but we don't generally need the debuginfo
|
||||
- at this point. */
|
||||
- frame = get_selected_frame_if_set ();
|
||||
- }
|
||||
- else
|
||||
- frame = NULL;
|
||||
-
|
||||
- try
|
||||
- {
|
||||
- m_selected_frame_id = get_frame_id (frame);
|
||||
- m_selected_frame_level = frame_relative_level (frame);
|
||||
- }
|
||||
- catch (const gdb_exception_error &ex)
|
||||
- {
|
||||
- m_selected_frame_id = null_frame_id;
|
||||
- m_selected_frame_level = -1;
|
||||
-
|
||||
- /* Better let this propagate. */
|
||||
- if (ex.error == TARGET_CLOSE_ERROR)
|
||||
- throw;
|
||||
- }
|
||||
+ save_selected_frame (&m_selected_frame_id, &m_selected_frame_level);
|
||||
}
|
||||
}
|
||||
|
@ -1,169 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Pedro Alves <pedro@palves.net>
|
||||
Date: Sat, 31 Oct 2020 00:27:18 +0000
|
||||
Subject: gdb-rhbz1909902-frame_id_p-assert-2.patch
|
||||
|
||||
;; Backport patch #2 which fixes a frame_id_p assertion failure (RH BZ 1909902).
|
||||
|
||||
Fix frame cycle detection
|
||||
|
||||
The recent commit to make scoped_restore_current_thread's cdtors
|
||||
exception free regressed gdb.base/eh_return.exp:
|
||||
|
||||
Breakpoint 1, 0x00000000004012bb in eh2 (gdb/frame.c:641: internal-error: frame_id get_frame_id(frame_info*): Assertion `stashed' failed.
|
||||
A problem internal to GDB has been detected,
|
||||
further debugging may prove unreliable.
|
||||
Quit this debugging session? (y or n) FAIL: gdb.base/eh_return.exp: hit breakpoint (GDB internal error)
|
||||
|
||||
That testcase uses __builtin_eh_return and, before the regression, the
|
||||
backtrace at eh2 looked like this:
|
||||
|
||||
(gdb) bt
|
||||
#0 0x00000000004006eb in eh2 (p=0x4006ec <continuation>) at src/gdb/testsuite/gdb.base/eh_return.c:54
|
||||
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
|
||||
|
||||
That "previous frame identical to this frame" is caught by the cycle
|
||||
detection based on frame id.
|
||||
|
||||
The assertion failing is this one:
|
||||
|
||||
638 /* Since this is the first frame in the chain, this should
|
||||
639 always succeed. */
|
||||
640 bool stashed = frame_stash_add (fi);
|
||||
641 gdb_assert (stashed);
|
||||
|
||||
originally added by
|
||||
|
||||
commit f245535cf583ae4ca13b10d47b3c7d3334593ece
|
||||
Author: Pedro Alves <palves@redhat.com>
|
||||
AuthorDate: Mon Sep 5 18:41:38 2016 +0100
|
||||
|
||||
Fix PR19927: Avoid unwinder recursion if sniffer uses calls parse_and_eval
|
||||
|
||||
The assertion is failing because frame #1's frame id was stashed
|
||||
before the id of frame #0 is stashed. The frame id of frame #1 was
|
||||
stashed here:
|
||||
|
||||
(top-gdb) bt
|
||||
#0 frame_stash_add (frame=0x1e24c90) at src/gdb/frame.c:276
|
||||
#1 0x0000000000669c1b in get_prev_frame_if_no_cycle (this_frame=0x19f8370) at src/gdb/frame.c:2120
|
||||
#2 0x000000000066a339 in get_prev_frame_always_1 (this_frame=0x19f8370) at src/gdb/frame.c:2303
|
||||
#3 0x000000000066a360 in get_prev_frame_always (this_frame=0x19f8370) at src/gdb/frame.c:2319
|
||||
#4 0x000000000066b56c in get_frame_unwind_stop_reason (frame=0x19f8370) at src/gdb/frame.c:3028
|
||||
#5 0x000000000059f929 in dwarf2_frame_cfa (this_frame=0x19f8370) at src/gdb/dwarf2/frame.c:1462
|
||||
#6 0x00000000005ce434 in dwarf_evaluate_loc_desc::get_frame_cfa (this=0x7fffffffc070) at src/gdb/dwarf2/loc.c:666
|
||||
#7 0x00000000005989a9 in dwarf_expr_context::execute_stack_op (this=0x7fffffffc070, op_ptr=0x1b2a053 "\364\003", op_end=0x1b2a053 "\364\003") at src/gdb/dwarf2/expr.c:1161
|
||||
#8 0x0000000000596af6 in dwarf_expr_context::eval (this=0x7fffffffc070, addr=0x1b2a052 "\234\364\003", len=1) at src/gdb/dwarf2/expr.c:303
|
||||
#9 0x0000000000597b4e in dwarf_expr_context::execute_stack_op (this=0x7fffffffc070, op_ptr=0x1b2a063 "", op_end=0x1b2a063 "") at src/gdb/dwarf2/expr.c:865
|
||||
#10 0x0000000000596af6 in dwarf_expr_context::eval (this=0x7fffffffc070, addr=0x1b2a061 "\221X", len=2) at src/gdb/dwarf2/expr.c:303
|
||||
#11 0x00000000005c8b5a in dwarf2_evaluate_loc_desc_full (type=0x1b564d0, frame=0x19f8370, data=0x1b2a061 "\221X", size=2, per_cu=0x1b28760, per_objfile=0x1a84930, subobj_type=0x1b564d0, subobj_byte_offset=0) at src/gdb/dwarf2/loc.c:2260
|
||||
#12 0x00000000005c9243 in dwarf2_evaluate_loc_desc (type=0x1b564d0, frame=0x19f8370, data=0x1b2a061 "\221X", size=2, per_cu=0x1b28760, per_objfile=0x1a84930) at src/gdb/dwarf2/loc.c:2444
|
||||
#13 0x00000000005cb769 in locexpr_read_variable (symbol=0x1b59840, frame=0x19f8370) at src/gdb/dwarf2/loc.c:3687
|
||||
#14 0x0000000000663137 in language_defn::read_var_value (this=0x122ea60 <c_language_defn>, var=0x1b59840, var_block=0x0, frame=0x19f8370) at src/gdb/findvar.c:618
|
||||
#15 0x0000000000663c3b in read_var_value (var=0x1b59840, var_block=0x0, frame=0x19f8370) at src/gdb/findvar.c:822
|
||||
#16 0x00000000008c7d9f in read_frame_arg (fp_opts=..., sym=0x1b59840, frame=0x19f8370, argp=0x7fffffffc470, entryargp=0x7fffffffc490) at src/gdb/stack.c:542
|
||||
#17 0x00000000008c89cd in print_frame_args (fp_opts=..., func=0x1b597c0, frame=0x19f8370, num=-1, stream=0x1aba860) at src/gdb/stack.c:890
|
||||
#18 0x00000000008c9bf8 in print_frame (fp_opts=..., frame=0x19f8370, print_level=0, print_what=SRC_AND_LOC, print_args=1, sal=...) at src/gdb/stack.c:1394
|
||||
#19 0x00000000008c92b9 in print_frame_info (fp_opts=..., frame=0x19f8370, print_level=0, print_what=SRC_AND_LOC, print_args=1, set_current_sal=1) at src/gdb/stack.c:1119
|
||||
#20 0x00000000008c75f0 in print_stack_frame (frame=0x19f8370, print_level=0, print_what=SRC_AND_LOC, set_current_sal=1) at src/gdb/stack.c:366
|
||||
#21 0x000000000070250b in print_stop_location (ws=0x7fffffffc9e0) at src/gdb/infrun.c:8110
|
||||
#22 0x0000000000702569 in print_stop_event (uiout=0x1a8b9e0, displays=true) at src/gdb/infrun.c:8126
|
||||
#23 0x000000000096d04b in tui_on_normal_stop (bs=0x1bcd1c0, print_frame=1) at src/gdb/tui/tui-interp.c:98
|
||||
...
|
||||
|
||||
Before the commit to make scoped_restore_current_thread's cdtors
|
||||
exception free, scoped_restore_current_thread's dtor would call
|
||||
get_frame_id on the selected frame, and we use
|
||||
scoped_restore_current_thread pervasively. That had the side effect
|
||||
of stashing the frame id of frame #0 before reaching the path shown in
|
||||
the backtrace. I.e., the frame id of frame #0 happened to be stashed
|
||||
before the frame id of frame #1. But that was by chance, not by
|
||||
design.
|
||||
|
||||
This commit:
|
||||
|
||||
commit 256ae5dbc73d1348850f86ee77a0dc3b04bc7cc0
|
||||
Author: Kevin Buettner <kevinb@redhat.com>
|
||||
AuthorDate: Mon Oct 31 12:47:42 2016 -0700
|
||||
|
||||
Stash frame id of current frame before stashing frame id for previous frame
|
||||
|
||||
Fixed a similar problem, by making sure get_prev_frame computes the
|
||||
frame id of the current frame before unwinding the previous frame, so
|
||||
that the cycle detection works properly. That fix misses the scenario
|
||||
we're now running against, because if you notice, the backtrace above
|
||||
shows that frame #4 calls get_prev_frame_always, not get_prev_frame.
|
||||
I.e., nothing is calling get_frame_id on the current frame.
|
||||
|
||||
The fix here is to move Kevin's fix down from get_prev_frame to
|
||||
get_prev_frame_always. Or actually, a bit further down to
|
||||
get_prev_frame_always_1 -- note that inline_frame_this_id calls
|
||||
get_prev_frame_always, so we need to be careful to avoid recursion in
|
||||
that scenario.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* frame.c (get_prev_frame): Move get_frame_id call from here ...
|
||||
(get_prev_frame_always_1): ... to here.
|
||||
* inline-frame.c (inline_frame_this_id): Mention
|
||||
get_prev_frame_always_1 in comment.
|
||||
|
||||
Change-Id: Id960c98ab2d072c48a436c3eb160cc4b2a5cfd1d
|
||||
|
||||
diff --git a/gdb/frame.c b/gdb/frame.c
|
||||
--- a/gdb/frame.c
|
||||
+++ b/gdb/frame.c
|
||||
@@ -2133,6 +2133,23 @@ get_prev_frame_always_1 (struct frame_info *this_frame)
|
||||
if (get_frame_type (this_frame) == INLINE_FRAME)
|
||||
return get_prev_frame_if_no_cycle (this_frame);
|
||||
|
||||
+ /* If this_frame is the current frame, then compute and stash its
|
||||
+ frame id prior to fetching and computing the frame id of the
|
||||
+ previous frame. Otherwise, the cycle detection code in
|
||||
+ get_prev_frame_if_no_cycle() will not work correctly. When
|
||||
+ get_frame_id() is called later on, an assertion error will be
|
||||
+ triggered in the event of a cycle between the current frame and
|
||||
+ its previous frame.
|
||||
+
|
||||
+ Note we do this after the INLINE_FRAME check above. That is
|
||||
+ because the inline frame's frame id computation needs to fetch
|
||||
+ the frame id of its previous real stack frame. I.e., we need to
|
||||
+ avoid recursion in that case. This is OK since we're sure the
|
||||
+ inline frame won't create a cycle with the real stack frame. See
|
||||
+ inline_frame_this_id. */
|
||||
+ if (this_frame->level == 0)
|
||||
+ get_frame_id (this_frame);
|
||||
+
|
||||
/* Check that this frame is unwindable. If it isn't, don't try to
|
||||
unwind to the prev frame. */
|
||||
this_frame->stop_reason
|
||||
@@ -2410,16 +2427,6 @@ get_prev_frame (struct frame_info *this_frame)
|
||||
something should be calling get_selected_frame() or
|
||||
get_current_frame(). */
|
||||
gdb_assert (this_frame != NULL);
|
||||
-
|
||||
- /* If this_frame is the current frame, then compute and stash
|
||||
- its frame id prior to fetching and computing the frame id of the
|
||||
- previous frame. Otherwise, the cycle detection code in
|
||||
- get_prev_frame_if_no_cycle() will not work correctly. When
|
||||
- get_frame_id() is called later on, an assertion error will
|
||||
- be triggered in the event of a cycle between the current
|
||||
- frame and its previous frame. */
|
||||
- if (this_frame->level == 0)
|
||||
- get_frame_id (this_frame);
|
||||
|
||||
frame_pc_p = get_frame_pc_if_available (this_frame, &frame_pc);
|
||||
|
||||
diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
|
||||
--- a/gdb/inline-frame.c
|
||||
+++ b/gdb/inline-frame.c
|
||||
@@ -161,7 +161,8 @@ inline_frame_this_id (struct frame_info *this_frame,
|
||||
real frame's this_id method. So we must call
|
||||
get_prev_frame_always. Because we are inlined into some
|
||||
function, there must be previous frames, so this is safe - as
|
||||
- long as we're careful not to create any cycles. */
|
||||
+ long as we're careful not to create any cycles. See related
|
||||
+ comments in get_prev_frame_always_1. */
|
||||
*this_id = get_frame_id (get_prev_frame_always (this_frame));
|
||||
|
||||
/* We need a valid frame ID, so we need to be based on a valid
|
@ -1,64 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Wed, 17 Feb 2021 17:58:54 -0700
|
||||
Subject: gdb-rhbz1912985-libstdc++-assert.patch
|
||||
|
||||
;; Backport fix for libstdc++ assert when performing tab completion
|
||||
;; (RH BZ 1912985).
|
||||
|
||||
Fix completion related libstdc++ assert when using -D_GLIBCXX_DEBUG
|
||||
|
||||
This commit fixes a libstdc++ assertion failure encountered when
|
||||
running gdb.base/completion.exp. In order to see this problem,
|
||||
GDB must be built with the follow CFLAGS and CXXFLAGS as part
|
||||
of the configure line:
|
||||
|
||||
CFLAGS='-D_GLIBCXX_DEBUG' CXXFLAGS='-D_GLIBCXX_DEBUG'
|
||||
|
||||
(Also, this problem was encountered using Fedora rawhide. It might
|
||||
not be reproducible in Fedora versions prior to Fedora 34.)
|
||||
|
||||
Using the gdb.base/completion.exp test program, the problem can be
|
||||
observed as follows:
|
||||
|
||||
[kev@rawhide-1 gdb]$ ./gdb -q testsuite/outputs/gdb.base/completion/completion
|
||||
Reading symbols from testsuite/outputs/gdb.base/completion/completion...
|
||||
(gdb) start
|
||||
Temporary breakpoint 1 at 0x401179: file ../../worktree-master/gdb/testsuite/gdb.base/break.c, line 43.
|
||||
Starting program: testsuite/outputs/gdb.base/completion/completion
|
||||
|
||||
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffd718, envp=0x7fffffffd728) at ../../worktree-master/gdb/testsuite/gdb.base/break.c:43
|
||||
43 if (argc == 12345) { /* an unlikely value < 2^16, in case uninited */ /* set breakpoint 6 here */
|
||||
(gdb) p <TAB>/usr/include/c++/11/string_view:211: constexpr const value_type& std::basic_string_view<_CharT, _Traits>::operator[](std::basic_string_view<_CharT, _Traits>::size_type) const [with _CharT = char; _Traits = std::char_traits<char>; std::basic_string_view<_CharT, _Traits>::const_reference = const char&; std::basic_string_view<_CharT, _Traits>::size_type = long unsigned int]: Assertion '__pos < this->_M_len' failed.
|
||||
Aborted (core dumped)
|
||||
|
||||
(Note that I added "<TAB>" to make it clear where the tab key was
|
||||
pressed.)
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* ada-lang.c (ada_fold_name): Check for non-empty string prior
|
||||
to accessing it.
|
||||
(ada_lookup_name_info): Likewise.
|
||||
|
||||
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
|
||||
--- a/gdb/ada-lang.c
|
||||
+++ b/gdb/ada-lang.c
|
||||
@@ -997,7 +997,7 @@ ada_fold_name (gdb::string_view name)
|
||||
int len = name.size ();
|
||||
GROW_VECT (fold_buffer, fold_buffer_size, len + 1);
|
||||
|
||||
- if (name[0] == '\'')
|
||||
+ if (!name.empty () && name[0] == '\'')
|
||||
{
|
||||
strncpy (fold_buffer, name.data () + 1, len - 2);
|
||||
fold_buffer[len - 2] = '\000';
|
||||
@@ -13597,7 +13597,7 @@ ada_lookup_name_info::ada_lookup_name_info (const lookup_name_info &lookup_name)
|
||||
{
|
||||
gdb::string_view user_name = lookup_name.name ();
|
||||
|
||||
- if (user_name[0] == '<')
|
||||
+ if (!user_name.empty () && user_name[0] == '<')
|
||||
{
|
||||
if (user_name.back () == '>')
|
||||
m_encoded_name
|
@ -1,67 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Bruno Larsen <blarsen@redhat.com>
|
||||
Date: Wed, 22 Sep 2021 12:22:44 -0300
|
||||
Subject: gdb-rhbz1916516-pathstuffs132-internal-error.patch
|
||||
|
||||
;;[gdb/cli] Don't assert on empty string for core-file
|
||||
;;(Tom de Vries)
|
||||
|
||||
With current gdb we run into:
|
||||
...
|
||||
$ gdb -batch '' ''
|
||||
: No such file or directory.
|
||||
pathstuff.cc:132: internal-error: \
|
||||
gdb::unique_xmalloc_ptr<char> gdb_abspath(const char*): \
|
||||
Assertion `path != NULL && path[0] != '\0'' failed.
|
||||
...
|
||||
|
||||
Fix this by skipping the call to gdb_abspath in core_target_open in the
|
||||
empty-string case, such that we have instead:
|
||||
...
|
||||
$ gdb -batch '' ''
|
||||
: No such file or directory.
|
||||
: No such file or directory.
|
||||
$
|
||||
...
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
2021-08-30 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
PR cli/28290
|
||||
* gdb/corelow.c (core_target_open): Skip call to gdb_abspath in the
|
||||
empty-string case.
|
||||
|
||||
gdb/testsuite/ChangeLog:
|
||||
|
||||
2021-08-30 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
PR cli/28290
|
||||
* gdb.base/batch-exit-status.exp: Add gdb '' and gdb '' '' tests.
|
||||
|
||||
diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
--- a/gdb/corelow.c
|
||||
+++ b/gdb/corelow.c
|
||||
@@ -446,7 +446,8 @@ core_target_open (const char *arg, int from_tty)
|
||||
}
|
||||
|
||||
gdb::unique_xmalloc_ptr<char> filename (tilde_expand (arg));
|
||||
- if (!IS_ABSOLUTE_PATH (filename.get ()))
|
||||
+ if (strlen (filename.get ()) != 0
|
||||
+ && !IS_ABSOLUTE_PATH (filename.get ()))
|
||||
filename = gdb_abspath (filename.get ());
|
||||
|
||||
flags = O_BINARY | O_LARGEFILE;
|
||||
diff --git a/gdb/testsuite/gdb.base/batch-exit-status.exp b/gdb/testsuite/gdb.base/batch-exit-status.exp
|
||||
--- a/gdb/testsuite/gdb.base/batch-exit-status.exp
|
||||
+++ b/gdb/testsuite/gdb.base/batch-exit-status.exp
|
||||
@@ -76,3 +76,7 @@ test_exit_status 1 "-batch -x $good_commands -x $bad_commands" \
|
||||
"-batch -x good-commands -x bad-commands"
|
||||
test_exit_status 1 "-batch -x $good_commands -ex \"set not-a-thing 4\"" \
|
||||
"-batch -x good-commands -ex \"set not-a-thing 4\""
|
||||
+
|
||||
+set no_such_re ": No such file or directory\\."
|
||||
+test_exit_status 1 "-batch \"\"" $no_such_re
|
||||
+test_exit_status 1 "-batch \"\" \"\"" [multi_line $no_such_re $no_such_re]
|
@ -1,87 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Keith Seitz <keiths@redhat.com>
|
||||
Date: Thu, 25 Mar 2021 10:31:48 -0700
|
||||
Subject: gdb-rhbz1931344-bfd_seek-elf_read_notes.patch
|
||||
|
||||
;; Backport "Save/restore file offset while reading notes in core file"
|
||||
;; (Keith Seitz, RHBZ 1931344)
|
||||
|
||||
A recent bug (RH BZ 1931344) has exposed a bug in the core file
|
||||
build-ID support that I introduced a while ago. It is pretty
|
||||
easy to demonstate the problem following a simplified procedure
|
||||
outlined in that bug:
|
||||
|
||||
[shell1]
|
||||
shell1$ /usr/libexec/qemu-kvm
|
||||
|
||||
[shell2]
|
||||
shell2$ pkill -SEGV -x qemu-kvm
|
||||
|
||||
[shell1]
|
||||
Segmentation fault (core dumped)
|
||||
|
||||
Load this core file into GDB without specifying an executable
|
||||
(an unfortunate Fedora/RHEL-ism), and GDB will inform the user
|
||||
to install debuginfo for the "missing" executable:
|
||||
|
||||
$ gdb -nx -q core.12345
|
||||
...
|
||||
Missing separate debuginfo for the main executable file
|
||||
Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/e2/e9c66d3117fb2bbb5b2be122f04f2664e5df54
|
||||
Core was generated by `/usr/libexec/qemu-kvm'.
|
||||
Program terminated with signal SIGSEGV, Segmentation fault.
|
||||
...
|
||||
|
||||
The suggested build-ID is actaully for gmp not qemu-kvm. The problem
|
||||
lies in _bfd_elf_core_find_build_id, where we loop over program headers
|
||||
looking for note segments:
|
||||
|
||||
/* Read in program headers and parse notes. */
|
||||
for (i = 0; i < i_ehdr.e_phnum; ++i, ++i_phdr)
|
||||
{
|
||||
Elf_External_Phdr x_phdr;
|
||||
|
||||
if (bfd_bread (&x_phdr, sizeof (x_phdr), abfd) != sizeof (x_phdr))
|
||||
goto fail;
|
||||
elf_swap_phdr_in (abfd, &x_phdr, i_phdr);
|
||||
|
||||
if (i_phdr->p_type == PT_NOTE && i_phdr->p_filesz > 0)
|
||||
{
|
||||
elf_read_notes (abfd, offset + i_phdr->p_offset,
|
||||
i_phdr->p_filesz, i_phdr->p_align);
|
||||
|
||||
if (abfd->build_id != NULL)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
elf_read_notes uses bfd_seek to forward the stream to the location of
|
||||
the note segment. When control returns to _bfd_elf_core_fild_build_id,
|
||||
the stream is no longer in the location looking at program headers, and
|
||||
all subsequent reads will read from the wrong file offset.
|
||||
|
||||
To fix this, this patch marks the stream location and ensures
|
||||
that it is restored after elf_read_notes is called.
|
||||
|
||||
bfd/ChangeLog
|
||||
2021-03-26 Keith Seitz <keiths@redhat.com>
|
||||
|
||||
* elfcore.h (_bfd_elf_core_find_build_id): Seek file
|
||||
offset of program headers after calling elf_read_notes.
|
||||
|
||||
diff --git a/bfd/elfcore.h b/bfd/elfcore.h
|
||||
--- a/bfd/elfcore.h
|
||||
+++ b/bfd/elfcore.h
|
||||
@@ -410,6 +410,13 @@ NAME(_bfd_elf, core_find_build_id)
|
||||
{
|
||||
elf_read_notes (abfd, offset + i_phdr->p_offset,
|
||||
i_phdr->p_filesz, i_phdr->p_align);
|
||||
+
|
||||
+ /* Make sure ABFD returns to processing the program headers. */
|
||||
+ if (bfd_seek (abfd, (file_ptr) (offset + i_ehdr.e_phoff
|
||||
+ + (i + 1) * sizeof (x_phdr)),
|
||||
+ SEEK_SET) != 0)
|
||||
+ goto fail;
|
||||
+
|
||||
if (abfd->build_id != NULL)
|
||||
return TRUE;
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Fri, 19 Mar 2021 15:14:04 -0700
|
||||
Subject: gdb-rhbz1941080-fix-gdbserver-hang.patch
|
||||
|
||||
;; Backport change which fixes gdbserver testing hang on f34 and rawhide.
|
||||
|
||||
Fix potential hang during gdbserver testing
|
||||
|
||||
We're currently seeing testing of native-extended-gdbserver hang while
|
||||
testing the x86_64 architecture on both Fedora 34 and Fedora Rawhide.
|
||||
The test responsible for the hang is gdb.threads/fork-plus-threads.exp.
|
||||
|
||||
While there is clearly a problem/bug with this test on F34 and
|
||||
Rawhide, it's also the case that testing should not hang. This commit
|
||||
prevents the hang by waiting with the "-nowait" flag in
|
||||
close_gdbserver.
|
||||
|
||||
The -nowait flag is also used in the kill_wait_spawned_process proc in
|
||||
gdb/testsuite/lib/gdb.exp, so there is precedent for doing this.
|
||||
|
||||
There are also 15 other uses of "wait -i" scattered throughout the
|
||||
test suite. While it's tempting to change these to also use the
|
||||
-nowait flag, I think it might be safer to defer doing so until we
|
||||
actually see a problem.
|
||||
|
||||
I've tested this patch on Fedora 32, 33, 34, and Rawhide. Results are
|
||||
comparable on Fedora 32 and 33. On Fedora 34 and Rawhide, with this
|
||||
commit in place, testing completes when the target_board is
|
||||
native-extended-gdbserver. On those OSes, when not using this commit,
|
||||
testing usually hangs due to a problem with
|
||||
gdb.threads/fork-plus-threads.exp. I've also tested on all of the
|
||||
mentioned OSes with target_board=native-gdbserver; for that testing,
|
||||
I achieved comparable results over a number of runs. (Unfortunately
|
||||
results are rarely identical due to racy tests.)
|
||||
|
||||
gdb/testsuite/ChangeLog:
|
||||
|
||||
* lib/gdbserver-support.exp (gdbserver_exit): Use the
|
||||
"-nowait" flag when waiting for gdbserver to exit.
|
||||
|
||||
diff --git a/gdb/testsuite/lib/gdbserver-support.exp b/gdb/testsuite/lib/gdbserver-support.exp
|
||||
--- a/gdb/testsuite/lib/gdbserver-support.exp
|
||||
+++ b/gdb/testsuite/lib/gdbserver-support.exp
|
||||
@@ -418,7 +418,12 @@ proc close_gdbserver {} {
|
||||
verbose "Quitting GDBserver"
|
||||
|
||||
catch "close -i $server_spawn_id"
|
||||
- catch "wait -i $server_spawn_id"
|
||||
+
|
||||
+ # If gdbserver misbehaves, and ignores the close, waiting for it
|
||||
+ # without the -nowait flag will cause testing to hang. Passing
|
||||
+ # -nowait makes expect tell Tcl to wait for the process in the
|
||||
+ # background.
|
||||
+ catch "wait -nowait -i $server_spawn_id"
|
||||
unset server_spawn_id
|
||||
}
|
||||
|
@ -1,375 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 24 May 2021 17:10:28 -0700
|
||||
Subject: gdb-rhbz1964167-convert-enum-range_type.patch
|
||||
|
||||
;; [fortran] Backport Andrew Burgess's commit which changes enum
|
||||
;; range_type into a bit field enum.
|
||||
|
||||
gdb: Convert enum range_type to a bit field enum
|
||||
|
||||
The expression range_type enum represents the following ideas:
|
||||
|
||||
- Lower bound is set to default,
|
||||
- Upper bound is set to default,
|
||||
- Upper bound is exclusive.
|
||||
|
||||
There are currently 6 entries in the enum to represent the combination
|
||||
of all those ideas.
|
||||
|
||||
In a future commit I'd like to add stride information to the range,
|
||||
this could in theory appear with any of the existing enum entries, so
|
||||
this would take us to 12 enum entries.
|
||||
|
||||
This feels like its getting a little out of hand, so in this commit I
|
||||
switch the range_type enum over to being a flags style enum. There's
|
||||
one entry to represent no flags being set, then 3 flags to represent
|
||||
the 3 ideas above. Adding stride information will require adding only
|
||||
one more enum flag.
|
||||
|
||||
I've then gone through and updated the code to handle this change.
|
||||
|
||||
There should be no user visible changes after this commit.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* expprint.c (print_subexp_standard): Update to reflect changes to
|
||||
enum range_type.
|
||||
(dump_subexp_body_standard): Likewise.
|
||||
* expression.h (enum range_type): Convert to a bit field enum, and
|
||||
make the enum unsigned.
|
||||
* f-exp.y (subrange): Update to reflect changes to enum
|
||||
range_type.
|
||||
* f-lang.c (value_f90_subarray): Likewise.
|
||||
* parse.c (operator_length_standard): Likewise.
|
||||
* rust-exp.y (rust_parser::convert_ast_to_expression): Likewise.
|
||||
* rust-lang.c (rust_range): Likewise.
|
||||
(rust_compute_range): Likewise.
|
||||
(rust_subscript): Likewise.
|
||||
|
||||
diff --git a/gdb/expprint.c b/gdb/expprint.c
|
||||
--- a/gdb/expprint.c
|
||||
+++ b/gdb/expprint.c
|
||||
@@ -584,17 +584,13 @@ print_subexp_standard (struct expression *exp, int *pos,
|
||||
longest_to_int (exp->elts[pc + 1].longconst);
|
||||
*pos += 2;
|
||||
|
||||
- if (range_type == NONE_BOUND_DEFAULT_EXCLUSIVE
|
||||
- || range_type == LOW_BOUND_DEFAULT_EXCLUSIVE)
|
||||
+ if (range_type & RANGE_HIGH_BOUND_EXCLUSIVE)
|
||||
fputs_filtered ("EXCLUSIVE_", stream);
|
||||
fputs_filtered ("RANGE(", stream);
|
||||
- if (range_type == HIGH_BOUND_DEFAULT
|
||||
- || range_type == NONE_BOUND_DEFAULT
|
||||
- || range_type == NONE_BOUND_DEFAULT_EXCLUSIVE)
|
||||
+ if (!(range_type & RANGE_LOW_BOUND_DEFAULT))
|
||||
print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
|
||||
fputs_filtered ("..", stream);
|
||||
- if (range_type == LOW_BOUND_DEFAULT
|
||||
- || range_type == NONE_BOUND_DEFAULT)
|
||||
+ if (!(range_type & RANGE_HIGH_BOUND_DEFAULT))
|
||||
print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
|
||||
fputs_filtered (")", stream);
|
||||
return;
|
||||
@@ -1114,36 +1110,19 @@ dump_subexp_body_standard (struct expression *exp,
|
||||
longest_to_int (exp->elts[elt].longconst);
|
||||
elt += 2;
|
||||
|
||||
- switch (range_type)
|
||||
- {
|
||||
- case BOTH_BOUND_DEFAULT:
|
||||
- fputs_filtered ("Range '..'", stream);
|
||||
- break;
|
||||
- case LOW_BOUND_DEFAULT:
|
||||
- fputs_filtered ("Range '..EXP'", stream);
|
||||
- break;
|
||||
- case LOW_BOUND_DEFAULT_EXCLUSIVE:
|
||||
- fputs_filtered ("ExclusiveRange '..EXP'", stream);
|
||||
- break;
|
||||
- case HIGH_BOUND_DEFAULT:
|
||||
- fputs_filtered ("Range 'EXP..'", stream);
|
||||
- break;
|
||||
- case NONE_BOUND_DEFAULT:
|
||||
- fputs_filtered ("Range 'EXP..EXP'", stream);
|
||||
- break;
|
||||
- case NONE_BOUND_DEFAULT_EXCLUSIVE:
|
||||
- fputs_filtered ("ExclusiveRange 'EXP..EXP'", stream);
|
||||
- break;
|
||||
- default:
|
||||
- fputs_filtered ("Invalid Range!", stream);
|
||||
- break;
|
||||
- }
|
||||
+ if (range_type & RANGE_HIGH_BOUND_EXCLUSIVE)
|
||||
+ fputs_filtered ("Exclusive", stream);
|
||||
+ fputs_filtered ("Range '", stream);
|
||||
+ if (!(range_type & RANGE_LOW_BOUND_DEFAULT))
|
||||
+ fputs_filtered ("EXP", stream);
|
||||
+ fputs_filtered ("..", stream);
|
||||
+ if (!(range_type & RANGE_HIGH_BOUND_DEFAULT))
|
||||
+ fputs_filtered ("EXP", stream);
|
||||
+ fputs_filtered ("'", stream);
|
||||
|
||||
- if (range_type == HIGH_BOUND_DEFAULT
|
||||
- || range_type == NONE_BOUND_DEFAULT)
|
||||
+ if (!(range_type & RANGE_LOW_BOUND_DEFAULT))
|
||||
elt = dump_subexp (exp, stream, elt);
|
||||
- if (range_type == LOW_BOUND_DEFAULT
|
||||
- || range_type == NONE_BOUND_DEFAULT)
|
||||
+ if (!(range_type & RANGE_HIGH_BOUND_DEFAULT))
|
||||
elt = dump_subexp (exp, stream, elt);
|
||||
}
|
||||
break;
|
||||
diff --git a/gdb/expression.h b/gdb/expression.h
|
||||
--- a/gdb/expression.h
|
||||
+++ b/gdb/expression.h
|
||||
@@ -185,22 +185,22 @@ extern void dump_prefix_expression (struct expression *, struct ui_file *);
|
||||
or inclusive. So we have six sorts of subrange. This enumeration
|
||||
type is to identify this. */
|
||||
|
||||
-enum range_type
|
||||
+enum range_type : unsigned
|
||||
{
|
||||
- /* Neither the low nor the high bound was given -- so this refers to
|
||||
- the entire available range. */
|
||||
- BOTH_BOUND_DEFAULT,
|
||||
- /* The low bound was not given and the high bound is inclusive. */
|
||||
- LOW_BOUND_DEFAULT,
|
||||
- /* The high bound was not given and the low bound in inclusive. */
|
||||
- HIGH_BOUND_DEFAULT,
|
||||
- /* Both bounds were given and both are inclusive. */
|
||||
- NONE_BOUND_DEFAULT,
|
||||
- /* The low bound was not given and the high bound is exclusive. */
|
||||
- NONE_BOUND_DEFAULT_EXCLUSIVE,
|
||||
- /* Both bounds were given. The low bound is inclusive and the high
|
||||
- bound is exclusive. */
|
||||
- LOW_BOUND_DEFAULT_EXCLUSIVE,
|
||||
+ /* This is a standard range. Both the lower and upper bounds are
|
||||
+ defined, and the bounds are inclusive. */
|
||||
+ RANGE_STANDARD = 0,
|
||||
+
|
||||
+ /* The low bound was not given. */
|
||||
+ RANGE_LOW_BOUND_DEFAULT = 1 << 0,
|
||||
+
|
||||
+ /* The high bound was not given. */
|
||||
+ RANGE_HIGH_BOUND_DEFAULT = 1 << 1,
|
||||
+
|
||||
+ /* The high bound of this range is exclusive. */
|
||||
+ RANGE_HIGH_BOUND_EXCLUSIVE = 1 << 2,
|
||||
};
|
||||
|
||||
+DEF_ENUM_FLAGS_TYPE (enum range_type, range_types);
|
||||
+
|
||||
#endif /* !defined (EXPRESSION_H) */
|
||||
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
|
||||
--- a/gdb/f-exp.y
|
||||
+++ b/gdb/f-exp.y
|
||||
@@ -287,26 +287,30 @@ arglist : arglist ',' exp %prec ABOVE_COMMA
|
||||
/* There are four sorts of subrange types in F90. */
|
||||
|
||||
subrange: exp ':' exp %prec ABOVE_COMMA
|
||||
- { write_exp_elt_opcode (pstate, OP_RANGE);
|
||||
- write_exp_elt_longcst (pstate, NONE_BOUND_DEFAULT);
|
||||
+ { write_exp_elt_opcode (pstate, OP_RANGE);
|
||||
+ write_exp_elt_longcst (pstate, RANGE_STANDARD);
|
||||
write_exp_elt_opcode (pstate, OP_RANGE); }
|
||||
;
|
||||
|
||||
subrange: exp ':' %prec ABOVE_COMMA
|
||||
{ write_exp_elt_opcode (pstate, OP_RANGE);
|
||||
- write_exp_elt_longcst (pstate, HIGH_BOUND_DEFAULT);
|
||||
+ write_exp_elt_longcst (pstate,
|
||||
+ RANGE_HIGH_BOUND_DEFAULT);
|
||||
write_exp_elt_opcode (pstate, OP_RANGE); }
|
||||
;
|
||||
|
||||
subrange: ':' exp %prec ABOVE_COMMA
|
||||
{ write_exp_elt_opcode (pstate, OP_RANGE);
|
||||
- write_exp_elt_longcst (pstate, LOW_BOUND_DEFAULT);
|
||||
+ write_exp_elt_longcst (pstate,
|
||||
+ RANGE_LOW_BOUND_DEFAULT);
|
||||
write_exp_elt_opcode (pstate, OP_RANGE); }
|
||||
;
|
||||
|
||||
subrange: ':' %prec ABOVE_COMMA
|
||||
{ write_exp_elt_opcode (pstate, OP_RANGE);
|
||||
- write_exp_elt_longcst (pstate, BOTH_BOUND_DEFAULT);
|
||||
+ write_exp_elt_longcst (pstate,
|
||||
+ (RANGE_LOW_BOUND_DEFAULT
|
||||
+ | RANGE_HIGH_BOUND_DEFAULT));
|
||||
write_exp_elt_opcode (pstate, OP_RANGE); }
|
||||
;
|
||||
|
||||
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
|
||||
--- a/gdb/f-lang.c
|
||||
+++ b/gdb/f-lang.c
|
||||
@@ -131,12 +131,12 @@ value_f90_subarray (struct value *array,
|
||||
|
||||
*pos += 3;
|
||||
|
||||
- if (range_type == LOW_BOUND_DEFAULT || range_type == BOTH_BOUND_DEFAULT)
|
||||
+ if (range_type & RANGE_LOW_BOUND_DEFAULT)
|
||||
low_bound = range->bounds ()->low.const_val ();
|
||||
else
|
||||
low_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
|
||||
|
||||
- if (range_type == HIGH_BOUND_DEFAULT || range_type == BOTH_BOUND_DEFAULT)
|
||||
+ if (range_type & RANGE_HIGH_BOUND_DEFAULT)
|
||||
high_bound = range->bounds ()->high.const_val ();
|
||||
else
|
||||
high_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
|
||||
diff --git a/gdb/parse.c b/gdb/parse.c
|
||||
--- a/gdb/parse.c
|
||||
+++ b/gdb/parse.c
|
||||
@@ -921,21 +921,13 @@ operator_length_standard (const struct expression *expr, int endpos,
|
||||
range_type = (enum range_type)
|
||||
longest_to_int (expr->elts[endpos - 2].longconst);
|
||||
|
||||
- switch (range_type)
|
||||
- {
|
||||
- case LOW_BOUND_DEFAULT:
|
||||
- case LOW_BOUND_DEFAULT_EXCLUSIVE:
|
||||
- case HIGH_BOUND_DEFAULT:
|
||||
- args = 1;
|
||||
- break;
|
||||
- case BOTH_BOUND_DEFAULT:
|
||||
- args = 0;
|
||||
- break;
|
||||
- case NONE_BOUND_DEFAULT:
|
||||
- case NONE_BOUND_DEFAULT_EXCLUSIVE:
|
||||
- args = 2;
|
||||
- break;
|
||||
- }
|
||||
+ /* Assume the range has 2 arguments (low bound and high bound), then
|
||||
+ reduce the argument count if any bounds are set to default. */
|
||||
+ args = 2;
|
||||
+ if (range_type & RANGE_LOW_BOUND_DEFAULT)
|
||||
+ --args;
|
||||
+ if (range_type & RANGE_HIGH_BOUND_DEFAULT)
|
||||
+ --args;
|
||||
|
||||
break;
|
||||
|
||||
diff --git a/gdb/rust-exp.y b/gdb/rust-exp.y
|
||||
--- a/gdb/rust-exp.y
|
||||
+++ b/gdb/rust-exp.y
|
||||
@@ -2492,24 +2492,29 @@ rust_parser::convert_ast_to_expression (const struct rust_op *operation,
|
||||
|
||||
case OP_RANGE:
|
||||
{
|
||||
- enum range_type kind = BOTH_BOUND_DEFAULT;
|
||||
+ enum range_type kind = (RANGE_HIGH_BOUND_DEFAULT
|
||||
+ | RANGE_LOW_BOUND_DEFAULT);
|
||||
|
||||
if (operation->left.op != NULL)
|
||||
{
|
||||
convert_ast_to_expression (operation->left.op, top);
|
||||
- kind = HIGH_BOUND_DEFAULT;
|
||||
+ kind &= ~RANGE_LOW_BOUND_DEFAULT;
|
||||
}
|
||||
if (operation->right.op != NULL)
|
||||
{
|
||||
convert_ast_to_expression (operation->right.op, top);
|
||||
- if (kind == BOTH_BOUND_DEFAULT)
|
||||
- kind = (operation->inclusive
|
||||
- ? LOW_BOUND_DEFAULT : LOW_BOUND_DEFAULT_EXCLUSIVE);
|
||||
+ if (kind == (RANGE_HIGH_BOUND_DEFAULT | RANGE_LOW_BOUND_DEFAULT))
|
||||
+ {
|
||||
+ kind = RANGE_LOW_BOUND_DEFAULT;
|
||||
+ if (!operation->inclusive)
|
||||
+ kind |= RANGE_HIGH_BOUND_EXCLUSIVE;
|
||||
+ }
|
||||
else
|
||||
{
|
||||
- gdb_assert (kind == HIGH_BOUND_DEFAULT);
|
||||
- kind = (operation->inclusive
|
||||
- ? NONE_BOUND_DEFAULT : NONE_BOUND_DEFAULT_EXCLUSIVE);
|
||||
+ gdb_assert (kind == RANGE_HIGH_BOUND_DEFAULT);
|
||||
+ kind = RANGE_STANDARD;
|
||||
+ if (!operation->inclusive)
|
||||
+ kind |= RANGE_HIGH_BOUND_EXCLUSIVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
|
||||
--- a/gdb/rust-lang.c
|
||||
+++ b/gdb/rust-lang.c
|
||||
@@ -1082,13 +1082,11 @@ rust_range (struct expression *exp, int *pos, enum noside noside)
|
||||
kind = (enum range_type) longest_to_int (exp->elts[*pos + 1].longconst);
|
||||
*pos += 3;
|
||||
|
||||
- if (kind == HIGH_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT
|
||||
- || kind == NONE_BOUND_DEFAULT_EXCLUSIVE)
|
||||
+ if (!(kind & RANGE_LOW_BOUND_DEFAULT))
|
||||
low = evaluate_subexp (nullptr, exp, pos, noside);
|
||||
- if (kind == LOW_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT_EXCLUSIVE
|
||||
- || kind == NONE_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT_EXCLUSIVE)
|
||||
+ if (!(kind & RANGE_HIGH_BOUND_DEFAULT))
|
||||
high = evaluate_subexp (nullptr, exp, pos, noside);
|
||||
- bool inclusive = (kind == NONE_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT);
|
||||
+ bool inclusive = !(kind & RANGE_HIGH_BOUND_EXCLUSIVE);
|
||||
|
||||
if (noside == EVAL_SKIP)
|
||||
return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1);
|
||||
@@ -1171,13 +1169,13 @@ rust_range (struct expression *exp, int *pos, enum noside noside)
|
||||
static void
|
||||
rust_compute_range (struct type *type, struct value *range,
|
||||
LONGEST *low, LONGEST *high,
|
||||
- enum range_type *kind)
|
||||
+ range_types *kind)
|
||||
{
|
||||
int i;
|
||||
|
||||
*low = 0;
|
||||
*high = 0;
|
||||
- *kind = BOTH_BOUND_DEFAULT;
|
||||
+ *kind = RANGE_LOW_BOUND_DEFAULT | RANGE_HIGH_BOUND_DEFAULT;
|
||||
|
||||
if (type->num_fields () == 0)
|
||||
return;
|
||||
@@ -1185,15 +1183,15 @@ rust_compute_range (struct type *type, struct value *range,
|
||||
i = 0;
|
||||
if (strcmp (TYPE_FIELD_NAME (type, 0), "start") == 0)
|
||||
{
|
||||
- *kind = HIGH_BOUND_DEFAULT;
|
||||
+ *kind = RANGE_HIGH_BOUND_DEFAULT;
|
||||
*low = value_as_long (value_field (range, 0));
|
||||
++i;
|
||||
}
|
||||
if (type->num_fields () > i
|
||||
&& strcmp (TYPE_FIELD_NAME (type, i), "end") == 0)
|
||||
{
|
||||
- *kind = (*kind == BOTH_BOUND_DEFAULT
|
||||
- ? LOW_BOUND_DEFAULT : NONE_BOUND_DEFAULT);
|
||||
+ *kind = (*kind == (RANGE_LOW_BOUND_DEFAULT | RANGE_HIGH_BOUND_DEFAULT)
|
||||
+ ? RANGE_LOW_BOUND_DEFAULT : RANGE_STANDARD);
|
||||
*high = value_as_long (value_field (range, i));
|
||||
|
||||
if (rust_inclusive_range_type_p (type))
|
||||
@@ -1211,7 +1209,7 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
|
||||
struct type *rhstype;
|
||||
LONGEST low, high_bound;
|
||||
/* Initialized to appease the compiler. */
|
||||
- enum range_type kind = BOTH_BOUND_DEFAULT;
|
||||
+ range_types kind = RANGE_LOW_BOUND_DEFAULT | RANGE_HIGH_BOUND_DEFAULT;
|
||||
LONGEST high = 0;
|
||||
int want_slice = 0;
|
||||
|
||||
@@ -1308,8 +1306,7 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
|
||||
else
|
||||
error (_("Cannot subscript non-array type"));
|
||||
|
||||
- if (want_slice
|
||||
- && (kind == BOTH_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT))
|
||||
+ if (want_slice && (kind & RANGE_LOW_BOUND_DEFAULT))
|
||||
low = low_bound;
|
||||
if (low < 0)
|
||||
error (_("Index less than zero"));
|
||||
@@ -1327,7 +1324,7 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
|
||||
CORE_ADDR addr;
|
||||
struct value *addrval, *tem;
|
||||
|
||||
- if (kind == BOTH_BOUND_DEFAULT || kind == HIGH_BOUND_DEFAULT)
|
||||
+ if (kind & RANGE_HIGH_BOUND_DEFAULT)
|
||||
high = high_bound;
|
||||
if (high < 0)
|
||||
error (_("High index less than zero"));
|
File diff suppressed because it is too large
Load Diff
@ -1,193 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 24 May 2021 22:30:32 -0700
|
||||
Subject: gdb-rhbz1964167-fortran-array-strides-in-expressions.patch
|
||||
|
||||
;; [fortran] Backport Andrew Burgess's commit which adds support
|
||||
;; for array strides in expressions.
|
||||
|
||||
gdb/fortran: add support for parsing array strides in expressions
|
||||
|
||||
With this commit GDB now understands the syntax of Fortran array
|
||||
strides, a user can type an expression including an array stride, but
|
||||
they will only get an error informing them that array strides are not
|
||||
supported.
|
||||
|
||||
This alone is an improvement on what we had before in GDB, better to
|
||||
give the user a helpful message that a particular feature is not
|
||||
supported than to just claim a syntax error.
|
||||
|
||||
Before:
|
||||
|
||||
(gdb) p array (1:10:2, 2:10:2)
|
||||
A syntax error in expression, near `:2, 2:10:2)'.
|
||||
|
||||
Now:
|
||||
|
||||
(gdb) p array (1:10:2, 2:10:2)
|
||||
Fortran array strides are not currently supported
|
||||
|
||||
Later commits will allow GDB to handle array strides correctly.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* expprint.c (dump_subexp_body_standard): Print RANGE_HAS_STRIDE.
|
||||
* expression.h (enum range_type): Add RANGE_HAS_STRIDE.
|
||||
* f-exp.y (arglist): Allow for a series of subranges.
|
||||
(subrange): Add cases for subranges with strides.
|
||||
* f-lang.c (value_f90_subarray): Catch use of array strides and
|
||||
throw an error.
|
||||
* parse.c (operator_length_standard): Handle RANGE_HAS_STRIDE.
|
||||
|
||||
gdb/testsuite/ChangeLog:
|
||||
|
||||
* gdb.fortran/array-slices.exp: Add a new test.
|
||||
|
||||
diff --git a/gdb/expprint.c b/gdb/expprint.c
|
||||
--- a/gdb/expprint.c
|
||||
+++ b/gdb/expprint.c
|
||||
@@ -1118,12 +1118,16 @@ dump_subexp_body_standard (struct expression *exp,
|
||||
fputs_filtered ("..", stream);
|
||||
if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
|
||||
fputs_filtered ("EXP", stream);
|
||||
+ if (range_flag & RANGE_HAS_STRIDE)
|
||||
+ fputs_filtered (":EXP", stream);
|
||||
fputs_filtered ("'", stream);
|
||||
|
||||
if (!(range_flag & RANGE_LOW_BOUND_DEFAULT))
|
||||
elt = dump_subexp (exp, stream, elt);
|
||||
if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
|
||||
elt = dump_subexp (exp, stream, elt);
|
||||
+ if (range_flag & RANGE_HAS_STRIDE)
|
||||
+ elt = dump_subexp (exp, stream, elt);
|
||||
}
|
||||
break;
|
||||
|
||||
diff --git a/gdb/expression.h b/gdb/expression.h
|
||||
--- a/gdb/expression.h
|
||||
+++ b/gdb/expression.h
|
||||
@@ -199,6 +199,9 @@ enum range_flag : unsigned
|
||||
|
||||
/* The high bound of this range is exclusive. */
|
||||
RANGE_HIGH_BOUND_EXCLUSIVE = 1 << 2,
|
||||
+
|
||||
+ /* The range has a stride. */
|
||||
+ RANGE_HAS_STRIDE = 1 << 3,
|
||||
};
|
||||
|
||||
DEF_ENUM_FLAGS_TYPE (enum range_flag, range_flags);
|
||||
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
|
||||
--- a/gdb/f-exp.y
|
||||
+++ b/gdb/f-exp.y
|
||||
@@ -284,6 +284,10 @@ arglist : arglist ',' exp %prec ABOVE_COMMA
|
||||
{ pstate->arglist_len++; }
|
||||
;
|
||||
|
||||
+arglist : arglist ',' subrange %prec ABOVE_COMMA
|
||||
+ { pstate->arglist_len++; }
|
||||
+ ;
|
||||
+
|
||||
/* There are four sorts of subrange types in F90. */
|
||||
|
||||
subrange: exp ':' exp %prec ABOVE_COMMA
|
||||
@@ -314,6 +318,38 @@ subrange: ':' %prec ABOVE_COMMA
|
||||
write_exp_elt_opcode (pstate, OP_RANGE); }
|
||||
;
|
||||
|
||||
+/* And each of the four subrange types can also have a stride. */
|
||||
+subrange: exp ':' exp ':' exp %prec ABOVE_COMMA
|
||||
+ { write_exp_elt_opcode (pstate, OP_RANGE);
|
||||
+ write_exp_elt_longcst (pstate, RANGE_HAS_STRIDE);
|
||||
+ write_exp_elt_opcode (pstate, OP_RANGE); }
|
||||
+ ;
|
||||
+
|
||||
+subrange: exp ':' ':' exp %prec ABOVE_COMMA
|
||||
+ { write_exp_elt_opcode (pstate, OP_RANGE);
|
||||
+ write_exp_elt_longcst (pstate,
|
||||
+ (RANGE_HIGH_BOUND_DEFAULT
|
||||
+ | RANGE_HAS_STRIDE));
|
||||
+ write_exp_elt_opcode (pstate, OP_RANGE); }
|
||||
+ ;
|
||||
+
|
||||
+subrange: ':' exp ':' exp %prec ABOVE_COMMA
|
||||
+ { write_exp_elt_opcode (pstate, OP_RANGE);
|
||||
+ write_exp_elt_longcst (pstate,
|
||||
+ (RANGE_LOW_BOUND_DEFAULT
|
||||
+ | RANGE_HAS_STRIDE));
|
||||
+ write_exp_elt_opcode (pstate, OP_RANGE); }
|
||||
+ ;
|
||||
+
|
||||
+subrange: ':' ':' exp %prec ABOVE_COMMA
|
||||
+ { write_exp_elt_opcode (pstate, OP_RANGE);
|
||||
+ write_exp_elt_longcst (pstate,
|
||||
+ (RANGE_LOW_BOUND_DEFAULT
|
||||
+ | RANGE_HIGH_BOUND_DEFAULT
|
||||
+ | RANGE_HAS_STRIDE));
|
||||
+ write_exp_elt_opcode (pstate, OP_RANGE); }
|
||||
+ ;
|
||||
+
|
||||
complexnum: exp ',' exp
|
||||
{ }
|
||||
;
|
||||
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
|
||||
--- a/gdb/f-lang.c
|
||||
+++ b/gdb/f-lang.c
|
||||
@@ -124,7 +124,7 @@ value_f90_subarray (struct value *array,
|
||||
struct expression *exp, int *pos, enum noside noside)
|
||||
{
|
||||
int pc = (*pos) + 1;
|
||||
- LONGEST low_bound, high_bound;
|
||||
+ LONGEST low_bound, high_bound, stride;
|
||||
struct type *range = check_typedef (value_type (array)->index_type ());
|
||||
enum range_flag range_flag
|
||||
= (enum range_flag) longest_to_int (exp->elts[pc].longconst);
|
||||
@@ -141,6 +141,14 @@ value_f90_subarray (struct value *array,
|
||||
else
|
||||
high_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
|
||||
|
||||
+ if (range_flag & RANGE_HAS_STRIDE)
|
||||
+ stride = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
|
||||
+ else
|
||||
+ stride = 1;
|
||||
+
|
||||
+ if (stride != 1)
|
||||
+ error (_("Fortran array strides are not currently supported"));
|
||||
+
|
||||
return value_slice (array, low_bound, high_bound - low_bound + 1);
|
||||
}
|
||||
|
||||
diff --git a/gdb/parse.c b/gdb/parse.c
|
||||
--- a/gdb/parse.c
|
||||
+++ b/gdb/parse.c
|
||||
@@ -924,6 +924,8 @@ operator_length_standard (const struct expression *expr, int endpos,
|
||||
/* Assume the range has 2 arguments (low bound and high bound), then
|
||||
reduce the argument count if any bounds are set to default. */
|
||||
args = 2;
|
||||
+ if (range_flag & RANGE_HAS_STRIDE)
|
||||
+ ++args;
|
||||
if (range_flag & RANGE_LOW_BOUND_DEFAULT)
|
||||
--args;
|
||||
if (range_flag & RANGE_HIGH_BOUND_DEFAULT)
|
||||
diff --git a/gdb/testsuite/gdb.fortran/array-slices.exp b/gdb/testsuite/gdb.fortran/array-slices.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/array-slices.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/array-slices.exp
|
||||
@@ -66,3 +66,19 @@ foreach result $array_contents msg $message_strings {
|
||||
}
|
||||
|
||||
gdb_continue_to_breakpoint "continue to Final Breakpoint"
|
||||
+
|
||||
+# Next test that asking for an array with stride at the CLI gives an
|
||||
+# error.
|
||||
+clean_restart ${testfile}
|
||||
+
|
||||
+if ![fortran_runto_main] then {
|
||||
+ perror "couldn't run to main"
|
||||
+ continue
|
||||
+}
|
||||
+
|
||||
+gdb_breakpoint "show"
|
||||
+gdb_continue_to_breakpoint "show"
|
||||
+gdb_test "up" ".*"
|
||||
+gdb_test "p array (1:10:2, 1:10:2)" \
|
||||
+ "Fortran array strides are not currently supported" \
|
||||
+ "using array stride gives an error"
|
@ -1,209 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 24 May 2021 16:53:22 -0700
|
||||
Subject: gdb-rhbz1964167-fortran-clean-up-array-expression-evaluation.patch
|
||||
|
||||
;; [fortran] Backport Andrew Burgess's commit which cleans up
|
||||
;; array/string expression evaluation.
|
||||
|
||||
gdb/fortran: Clean up array/string expression evaluation
|
||||
|
||||
This commit is a refactor of part of the Fortran array and string
|
||||
handling code.
|
||||
|
||||
The current code is split into two blocks, linked, weirdly, with a
|
||||
goto. After this commit all the code is moved to its own function,
|
||||
and arrays and strings are now handled using the same code; this will
|
||||
be useful later when I want to add array stride support where strings
|
||||
will want to be treated just like arrays, but is a good clean up even
|
||||
without the array stride work, which is why I'm merging it now.
|
||||
|
||||
For now the new function is added as a static within eval.c, even
|
||||
though the function is Fortran only. A following commit will remove
|
||||
some of the Fortran specific code from eval.c into one of the Fortran
|
||||
specific files, including this new function.
|
||||
|
||||
There should be no user visible changes after this commit.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* eval.c (fortran_value_subarray): New function, content is taken
|
||||
from...
|
||||
(evaluate_subexp_standard): ...here, in two places. Now arrays
|
||||
and strings both call the new function.
|
||||
(calc_f77_array_dims): Add header comment, handle strings.
|
||||
|
||||
diff --git a/gdb/eval.c b/gdb/eval.c
|
||||
--- a/gdb/eval.c
|
||||
+++ b/gdb/eval.c
|
||||
@@ -1260,6 +1260,67 @@ is_integral_or_integral_reference (struct type *type)
|
||||
&& is_integral_type (TYPE_TARGET_TYPE (type)));
|
||||
}
|
||||
|
||||
+/* Called from evaluate_subexp_standard to perform array indexing, and
|
||||
+ sub-range extraction, for Fortran. As well as arrays this function
|
||||
+ also handles strings as they can be treated like arrays of characters.
|
||||
+ ARRAY is the array or string being accessed. EXP, POS, and NOSIDE are
|
||||
+ as for evaluate_subexp_standard, and NARGS is the number of arguments
|
||||
+ in this access (e.g. 'array (1,2,3)' would be NARGS 3). */
|
||||
+
|
||||
+static struct value *
|
||||
+fortran_value_subarray (struct value *array, struct expression *exp,
|
||||
+ int *pos, int nargs, enum noside noside)
|
||||
+{
|
||||
+ if (exp->elts[*pos].opcode == OP_RANGE)
|
||||
+ return value_f90_subarray (array, exp, pos, noside);
|
||||
+
|
||||
+ if (noside == EVAL_SKIP)
|
||||
+ {
|
||||
+ skip_undetermined_arglist (nargs, exp, pos, noside);
|
||||
+ /* Return the dummy value with the correct type. */
|
||||
+ return array;
|
||||
+ }
|
||||
+
|
||||
+ LONGEST subscript_array[MAX_FORTRAN_DIMS];
|
||||
+ int ndimensions = 1;
|
||||
+ struct type *type = check_typedef (value_type (array));
|
||||
+
|
||||
+ if (nargs > MAX_FORTRAN_DIMS)
|
||||
+ error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS);
|
||||
+
|
||||
+ ndimensions = calc_f77_array_dims (type);
|
||||
+
|
||||
+ if (nargs != ndimensions)
|
||||
+ error (_("Wrong number of subscripts"));
|
||||
+
|
||||
+ gdb_assert (nargs > 0);
|
||||
+
|
||||
+ /* Now that we know we have a legal array subscript expression let us
|
||||
+ actually find out where this element exists in the array. */
|
||||
+
|
||||
+ /* Take array indices left to right. */
|
||||
+ for (int i = 0; i < nargs; i++)
|
||||
+ {
|
||||
+ /* Evaluate each subscript; it must be a legal integer in F77. */
|
||||
+ value *arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
+
|
||||
+ /* Fill in the subscript array. */
|
||||
+ subscript_array[i] = value_as_long (arg2);
|
||||
+ }
|
||||
+
|
||||
+ /* Internal type of array is arranged right to left. */
|
||||
+ for (int i = nargs; i > 0; i--)
|
||||
+ {
|
||||
+ struct type *array_type = check_typedef (value_type (array));
|
||||
+ LONGEST index = subscript_array[i - 1];
|
||||
+
|
||||
+ array = value_subscripted_rvalue (array, index,
|
||||
+ f77_get_lowerbound (array_type));
|
||||
+ }
|
||||
+
|
||||
+ return array;
|
||||
+}
|
||||
+
|
||||
struct value *
|
||||
evaluate_subexp_standard (struct type *expect_type,
|
||||
struct expression *exp, int *pos,
|
||||
@@ -1953,33 +2014,8 @@ evaluate_subexp_standard (struct type *expect_type,
|
||||
switch (code)
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
- if (exp->elts[*pos].opcode == OP_RANGE)
|
||||
- return value_f90_subarray (arg1, exp, pos, noside);
|
||||
- else
|
||||
- {
|
||||
- if (noside == EVAL_SKIP)
|
||||
- {
|
||||
- skip_undetermined_arglist (nargs, exp, pos, noside);
|
||||
- /* Return the dummy value with the correct type. */
|
||||
- return arg1;
|
||||
- }
|
||||
- goto multi_f77_subscript;
|
||||
- }
|
||||
-
|
||||
case TYPE_CODE_STRING:
|
||||
- if (exp->elts[*pos].opcode == OP_RANGE)
|
||||
- return value_f90_subarray (arg1, exp, pos, noside);
|
||||
- else
|
||||
- {
|
||||
- if (noside == EVAL_SKIP)
|
||||
- {
|
||||
- skip_undetermined_arglist (nargs, exp, pos, noside);
|
||||
- /* Return the dummy value with the correct type. */
|
||||
- return arg1;
|
||||
- }
|
||||
- arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
- return value_subscript (arg1, value_as_long (arg2));
|
||||
- }
|
||||
+ return fortran_value_subarray (arg1, exp, pos, nargs, noside);
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_FUNC:
|
||||
@@ -2400,49 +2436,6 @@ evaluate_subexp_standard (struct type *expect_type,
|
||||
}
|
||||
return (arg1);
|
||||
|
||||
- multi_f77_subscript:
|
||||
- {
|
||||
- LONGEST subscript_array[MAX_FORTRAN_DIMS];
|
||||
- int ndimensions = 1, i;
|
||||
- struct value *array = arg1;
|
||||
-
|
||||
- if (nargs > MAX_FORTRAN_DIMS)
|
||||
- error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS);
|
||||
-
|
||||
- ndimensions = calc_f77_array_dims (type);
|
||||
-
|
||||
- if (nargs != ndimensions)
|
||||
- error (_("Wrong number of subscripts"));
|
||||
-
|
||||
- gdb_assert (nargs > 0);
|
||||
-
|
||||
- /* Now that we know we have a legal array subscript expression
|
||||
- let us actually find out where this element exists in the array. */
|
||||
-
|
||||
- /* Take array indices left to right. */
|
||||
- for (i = 0; i < nargs; i++)
|
||||
- {
|
||||
- /* Evaluate each subscript; it must be a legal integer in F77. */
|
||||
- arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
-
|
||||
- /* Fill in the subscript array. */
|
||||
-
|
||||
- subscript_array[i] = value_as_long (arg2);
|
||||
- }
|
||||
-
|
||||
- /* Internal type of array is arranged right to left. */
|
||||
- for (i = nargs; i > 0; i--)
|
||||
- {
|
||||
- struct type *array_type = check_typedef (value_type (array));
|
||||
- LONGEST index = subscript_array[i - 1];
|
||||
-
|
||||
- array = value_subscripted_rvalue (array, index,
|
||||
- f77_get_lowerbound (array_type));
|
||||
- }
|
||||
-
|
||||
- return array;
|
||||
- }
|
||||
-
|
||||
case BINOP_LOGICAL_AND:
|
||||
arg1 = evaluate_subexp (nullptr, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
@@ -3354,12 +3347,17 @@ parse_and_eval_type (char *p, int length)
|
||||
return expr->elts[1].type;
|
||||
}
|
||||
|
||||
+/* Return the number of dimensions for a Fortran array or string. */
|
||||
+
|
||||
int
|
||||
calc_f77_array_dims (struct type *array_type)
|
||||
{
|
||||
int ndimen = 1;
|
||||
struct type *tmp_type;
|
||||
|
||||
+ if ((array_type->code () == TYPE_CODE_STRING))
|
||||
+ return 1;
|
||||
+
|
||||
if ((array_type->code () != TYPE_CODE_ARRAY))
|
||||
error (_("Can't get dimensions for a non-array type"));
|
||||
|
@ -1,128 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Tue, 25 May 2021 17:34:57 -0700
|
||||
Subject: gdb-rhbz1964167-fortran-fix-type-format-mismatch-in-f-lang.c.patch
|
||||
|
||||
;; [fortran] Backport Simon Marchi's commit which fixes a 32-bit build
|
||||
;; problem in gdb/f-lang.c.
|
||||
|
||||
gdb: fix format string warnings in f-lang.c
|
||||
|
||||
I get a bunch of these warnings when compiling for i386 (32-bit):
|
||||
|
||||
CXX f-lang.o
|
||||
/home/simark/src/binutils-gdb/gdb/f-lang.c: In function 'value* fortran_value_subarray(value*, expression*, int*, int, noside)':
|
||||
/home/simark/src/binutils-gdb/gdb/f-lang.c:453:48: error: format '%ld' expects argument of type 'long int', but argument 2 has type 'LONGEST' {aka 'long long int'} [-Werror=format=]
|
||||
453 | debug_printf ("| | |-> Low bound: %ld\n", lb);
|
||||
| ~~^ ~~
|
||||
| | |
|
||||
| | LONGEST {aka long long int}
|
||||
| long int
|
||||
| %lld
|
||||
|
||||
Fix them by using plongest/pulongest.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* f-lang.c (fortran_value_subarray): Use plongest/pulongest.
|
||||
|
||||
Change-Id: I666ead5593653d5a1a3dab2ffdc72942c928c7d2
|
||||
|
||||
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
|
||||
--- a/gdb/f-lang.c
|
||||
+++ b/gdb/f-lang.c
|
||||
@@ -463,21 +463,21 @@ fortran_value_subarray (struct value *array, struct expression *exp,
|
||||
std::string str = type_to_string (dim_type);
|
||||
debug_printf ("| |-> Type: %s\n", str.c_str ());
|
||||
debug_printf ("| |-> Array:\n");
|
||||
- debug_printf ("| | |-> Low bound: %ld\n", lb);
|
||||
- debug_printf ("| | |-> High bound: %ld\n", ub);
|
||||
- debug_printf ("| | |-> Bit stride: %ld\n", sd);
|
||||
- debug_printf ("| | |-> Byte stride: %ld\n", sd / 8);
|
||||
- debug_printf ("| | |-> Type size: %ld\n",
|
||||
- TYPE_LENGTH (dim_type));
|
||||
- debug_printf ("| | '-> Target type size: %ld\n",
|
||||
- TYPE_LENGTH (target_type));
|
||||
+ debug_printf ("| | |-> Low bound: %s\n", plongest (lb));
|
||||
+ debug_printf ("| | |-> High bound: %s\n", plongest (ub));
|
||||
+ debug_printf ("| | |-> Bit stride: %s\n", plongest (sd));
|
||||
+ debug_printf ("| | |-> Byte stride: %s\n", plongest (sd / 8));
|
||||
+ debug_printf ("| | |-> Type size: %s\n",
|
||||
+ pulongest (TYPE_LENGTH (dim_type)));
|
||||
+ debug_printf ("| | '-> Target type size: %s\n",
|
||||
+ pulongest (TYPE_LENGTH (target_type)));
|
||||
debug_printf ("| |-> Accessing:\n");
|
||||
- debug_printf ("| | |-> Low bound: %ld\n",
|
||||
- low);
|
||||
- debug_printf ("| | |-> High bound: %ld\n",
|
||||
- high);
|
||||
- debug_printf ("| | '-> Element stride: %ld\n",
|
||||
- stride);
|
||||
+ debug_printf ("| | |-> Low bound: %s\n",
|
||||
+ plongest (low));
|
||||
+ debug_printf ("| | |-> High bound: %s\n",
|
||||
+ plongest (high));
|
||||
+ debug_printf ("| | '-> Element stride: %s\n",
|
||||
+ plongest (stride));
|
||||
}
|
||||
|
||||
/* Check the user hasn't asked for something invalid. */
|
||||
@@ -519,13 +519,17 @@ fortran_value_subarray (struct value *array, struct expression *exp,
|
||||
if (fortran_array_slicing_debug)
|
||||
{
|
||||
debug_printf ("| '-> Results:\n");
|
||||
- debug_printf ("| |-> Offset = %ld\n", offset);
|
||||
- debug_printf ("| |-> Elements = %ld\n", e_count);
|
||||
- debug_printf ("| |-> Low bound = %ld\n", new_low);
|
||||
- debug_printf ("| |-> High bound = %ld\n", new_high);
|
||||
- debug_printf ("| |-> Byte stride = %ld\n", new_stride);
|
||||
- debug_printf ("| |-> Last element = %ld\n", last_elem);
|
||||
- debug_printf ("| |-> Remainder = %ld\n", remainder);
|
||||
+ debug_printf ("| |-> Offset = %s\n", plongest (offset));
|
||||
+ debug_printf ("| |-> Elements = %s\n", plongest (e_count));
|
||||
+ debug_printf ("| |-> Low bound = %s\n", plongest (new_low));
|
||||
+ debug_printf ("| |-> High bound = %s\n",
|
||||
+ plongest (new_high));
|
||||
+ debug_printf ("| |-> Byte stride = %s\n",
|
||||
+ plongest (new_stride));
|
||||
+ debug_printf ("| |-> Last element = %s\n",
|
||||
+ plongest (last_elem));
|
||||
+ debug_printf ("| |-> Remainder = %s\n",
|
||||
+ plongest (remainder));
|
||||
debug_printf ("| '-> Contiguous = %s\n",
|
||||
(is_dim_contiguous ? "Yes" : "No"));
|
||||
}
|
||||
@@ -561,14 +565,16 @@ fortran_value_subarray (struct value *array, struct expression *exp,
|
||||
std::string str = type_to_string (dim_type);
|
||||
debug_printf ("| |-> Type: %s\n", str.c_str ());
|
||||
debug_printf ("| |-> Array:\n");
|
||||
- debug_printf ("| | |-> Low bound: %ld\n", lb);
|
||||
- debug_printf ("| | |-> High bound: %ld\n", ub);
|
||||
- debug_printf ("| | |-> Byte stride: %ld\n", sd);
|
||||
- debug_printf ("| | |-> Type size: %ld\n", TYPE_LENGTH (dim_type));
|
||||
- debug_printf ("| | '-> Target type size: %ld\n",
|
||||
- TYPE_LENGTH (target_type));
|
||||
+ debug_printf ("| | |-> Low bound: %s\n", plongest (lb));
|
||||
+ debug_printf ("| | |-> High bound: %s\n", plongest (ub));
|
||||
+ debug_printf ("| | |-> Byte stride: %s\n", plongest (sd));
|
||||
+ debug_printf ("| | |-> Type size: %s\n",
|
||||
+ pulongest (TYPE_LENGTH (dim_type)));
|
||||
+ debug_printf ("| | '-> Target type size: %s\n",
|
||||
+ pulongest (TYPE_LENGTH (target_type)));
|
||||
debug_printf ("| '-> Accessing:\n");
|
||||
- debug_printf ("| '-> Index: %ld\n", index);
|
||||
+ debug_printf ("| '-> Index: %s\n",
|
||||
+ plongest (index));
|
||||
}
|
||||
|
||||
/* If the array has actual content then check the index is in
|
||||
@@ -625,7 +631,8 @@ fortran_value_subarray (struct value *array, struct expression *exp,
|
||||
debug_printf ("'-> Final result:\n");
|
||||
debug_printf (" |-> Type: %s\n",
|
||||
type_to_string (array_slice_type).c_str ());
|
||||
- debug_printf (" |-> Total offset: %ld\n", total_offset);
|
||||
+ debug_printf (" |-> Total offset: %s\n",
|
||||
+ plongest (total_offset));
|
||||
debug_printf (" |-> Base address: %s\n",
|
||||
core_addr_to_string (value_address (array)));
|
||||
debug_printf (" '-> Contiguous = %s\n",
|
@ -1,224 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 24 May 2021 17:15:27 -0700
|
||||
Subject: gdb-rhbz1964167-fortran-range_type-to-range_flag.patch
|
||||
|
||||
;; [fortran] Backport Andrew Burgess's commit which renames enum
|
||||
;; range_type to enum range_flag.
|
||||
|
||||
gdb: rename 'enum range_type' to 'enum range_flag'
|
||||
|
||||
To avoid confusion with other parts of GDB relating to types and
|
||||
ranges, rename this enum to make it clearer that it is a set of
|
||||
individual flags rather than an enumeration of different types of
|
||||
range.
|
||||
|
||||
There should be no user visible changes after this commit.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* expprint.c (print_subexp_standard): Change enum range_type to
|
||||
range_flag and rename variables to match.
|
||||
(dump_subexp_body_standard): Likewise.
|
||||
* expression.h (enum range_type): Rename to...
|
||||
(enum range_flag): ...this.
|
||||
(range_types): Rename to...
|
||||
(range_flags): ...this.
|
||||
* f-lang.c (value_f90_subarray): Change enum range_type to
|
||||
range_flag and rename variables to match.
|
||||
* parse.c (operator_length_standard): Likewise.
|
||||
* rust-exp.y (rust_parser::convert_ast_to_expression): Change enum
|
||||
range_type to range_flag.
|
||||
* rust-lang.c (rust_evaluate_funcall): Likewise.
|
||||
(rust_range): Likewise.
|
||||
(rust_compute_range): Likewise.
|
||||
(rust_subscript): Likewise.
|
||||
|
||||
diff --git a/gdb/expprint.c b/gdb/expprint.c
|
||||
--- a/gdb/expprint.c
|
||||
+++ b/gdb/expprint.c
|
||||
@@ -578,19 +578,19 @@ print_subexp_standard (struct expression *exp, int *pos,
|
||||
|
||||
case OP_RANGE:
|
||||
{
|
||||
- enum range_type range_type;
|
||||
+ enum range_flag range_flag;
|
||||
|
||||
- range_type = (enum range_type)
|
||||
+ range_flag = (enum range_flag)
|
||||
longest_to_int (exp->elts[pc + 1].longconst);
|
||||
*pos += 2;
|
||||
|
||||
- if (range_type & RANGE_HIGH_BOUND_EXCLUSIVE)
|
||||
+ if (range_flag & RANGE_HIGH_BOUND_EXCLUSIVE)
|
||||
fputs_filtered ("EXCLUSIVE_", stream);
|
||||
fputs_filtered ("RANGE(", stream);
|
||||
- if (!(range_type & RANGE_LOW_BOUND_DEFAULT))
|
||||
+ if (!(range_flag & RANGE_LOW_BOUND_DEFAULT))
|
||||
print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
|
||||
fputs_filtered ("..", stream);
|
||||
- if (!(range_type & RANGE_HIGH_BOUND_DEFAULT))
|
||||
+ if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
|
||||
print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
|
||||
fputs_filtered (")", stream);
|
||||
return;
|
||||
@@ -1104,25 +1104,25 @@ dump_subexp_body_standard (struct expression *exp,
|
||||
break;
|
||||
case OP_RANGE:
|
||||
{
|
||||
- enum range_type range_type;
|
||||
+ enum range_flag range_flag;
|
||||
|
||||
- range_type = (enum range_type)
|
||||
+ range_flag = (enum range_flag)
|
||||
longest_to_int (exp->elts[elt].longconst);
|
||||
elt += 2;
|
||||
|
||||
- if (range_type & RANGE_HIGH_BOUND_EXCLUSIVE)
|
||||
+ if (range_flag & RANGE_HIGH_BOUND_EXCLUSIVE)
|
||||
fputs_filtered ("Exclusive", stream);
|
||||
fputs_filtered ("Range '", stream);
|
||||
- if (!(range_type & RANGE_LOW_BOUND_DEFAULT))
|
||||
+ if (!(range_flag & RANGE_LOW_BOUND_DEFAULT))
|
||||
fputs_filtered ("EXP", stream);
|
||||
fputs_filtered ("..", stream);
|
||||
- if (!(range_type & RANGE_HIGH_BOUND_DEFAULT))
|
||||
+ if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
|
||||
fputs_filtered ("EXP", stream);
|
||||
fputs_filtered ("'", stream);
|
||||
|
||||
- if (!(range_type & RANGE_LOW_BOUND_DEFAULT))
|
||||
+ if (!(range_flag & RANGE_LOW_BOUND_DEFAULT))
|
||||
elt = dump_subexp (exp, stream, elt);
|
||||
- if (!(range_type & RANGE_HIGH_BOUND_DEFAULT))
|
||||
+ if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
|
||||
elt = dump_subexp (exp, stream, elt);
|
||||
}
|
||||
break;
|
||||
diff --git a/gdb/expression.h b/gdb/expression.h
|
||||
--- a/gdb/expression.h
|
||||
+++ b/gdb/expression.h
|
||||
@@ -185,7 +185,7 @@ extern void dump_prefix_expression (struct expression *, struct ui_file *);
|
||||
or inclusive. So we have six sorts of subrange. This enumeration
|
||||
type is to identify this. */
|
||||
|
||||
-enum range_type : unsigned
|
||||
+enum range_flag : unsigned
|
||||
{
|
||||
/* This is a standard range. Both the lower and upper bounds are
|
||||
defined, and the bounds are inclusive. */
|
||||
@@ -201,6 +201,6 @@ enum range_type : unsigned
|
||||
RANGE_HIGH_BOUND_EXCLUSIVE = 1 << 2,
|
||||
};
|
||||
|
||||
-DEF_ENUM_FLAGS_TYPE (enum range_type, range_types);
|
||||
+DEF_ENUM_FLAGS_TYPE (enum range_flag, range_flags);
|
||||
|
||||
#endif /* !defined (EXPRESSION_H) */
|
||||
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
|
||||
--- a/gdb/f-lang.c
|
||||
+++ b/gdb/f-lang.c
|
||||
@@ -126,17 +126,17 @@ value_f90_subarray (struct value *array,
|
||||
int pc = (*pos) + 1;
|
||||
LONGEST low_bound, high_bound;
|
||||
struct type *range = check_typedef (value_type (array)->index_type ());
|
||||
- enum range_type range_type
|
||||
- = (enum range_type) longest_to_int (exp->elts[pc].longconst);
|
||||
+ enum range_flag range_flag
|
||||
+ = (enum range_flag) longest_to_int (exp->elts[pc].longconst);
|
||||
|
||||
*pos += 3;
|
||||
|
||||
- if (range_type & RANGE_LOW_BOUND_DEFAULT)
|
||||
+ if (range_flag & RANGE_LOW_BOUND_DEFAULT)
|
||||
low_bound = range->bounds ()->low.const_val ();
|
||||
else
|
||||
low_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
|
||||
|
||||
- if (range_type & RANGE_HIGH_BOUND_DEFAULT)
|
||||
+ if (range_flag & RANGE_HIGH_BOUND_DEFAULT)
|
||||
high_bound = range->bounds ()->high.const_val ();
|
||||
else
|
||||
high_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
|
||||
diff --git a/gdb/parse.c b/gdb/parse.c
|
||||
--- a/gdb/parse.c
|
||||
+++ b/gdb/parse.c
|
||||
@@ -774,7 +774,7 @@ operator_length_standard (const struct expression *expr, int endpos,
|
||||
{
|
||||
int oplen = 1;
|
||||
int args = 0;
|
||||
- enum range_type range_type;
|
||||
+ enum range_flag range_flag;
|
||||
int i;
|
||||
|
||||
if (endpos < 1)
|
||||
@@ -918,15 +918,15 @@ operator_length_standard (const struct expression *expr, int endpos,
|
||||
|
||||
case OP_RANGE:
|
||||
oplen = 3;
|
||||
- range_type = (enum range_type)
|
||||
+ range_flag = (enum range_flag)
|
||||
longest_to_int (expr->elts[endpos - 2].longconst);
|
||||
|
||||
/* Assume the range has 2 arguments (low bound and high bound), then
|
||||
reduce the argument count if any bounds are set to default. */
|
||||
args = 2;
|
||||
- if (range_type & RANGE_LOW_BOUND_DEFAULT)
|
||||
+ if (range_flag & RANGE_LOW_BOUND_DEFAULT)
|
||||
--args;
|
||||
- if (range_type & RANGE_HIGH_BOUND_DEFAULT)
|
||||
+ if (range_flag & RANGE_HIGH_BOUND_DEFAULT)
|
||||
--args;
|
||||
|
||||
break;
|
||||
diff --git a/gdb/rust-exp.y b/gdb/rust-exp.y
|
||||
--- a/gdb/rust-exp.y
|
||||
+++ b/gdb/rust-exp.y
|
||||
@@ -2492,7 +2492,7 @@ rust_parser::convert_ast_to_expression (const struct rust_op *operation,
|
||||
|
||||
case OP_RANGE:
|
||||
{
|
||||
- enum range_type kind = (RANGE_HIGH_BOUND_DEFAULT
|
||||
+ unsigned int kind = (RANGE_HIGH_BOUND_DEFAULT
|
||||
| RANGE_LOW_BOUND_DEFAULT);
|
||||
|
||||
if (operation->left.op != NULL)
|
||||
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
|
||||
--- a/gdb/rust-lang.c
|
||||
+++ b/gdb/rust-lang.c
|
||||
@@ -1070,7 +1070,6 @@ rust_evaluate_funcall (struct expression *exp, int *pos, enum noside noside)
|
||||
static struct value *
|
||||
rust_range (struct expression *exp, int *pos, enum noside noside)
|
||||
{
|
||||
- enum range_type kind;
|
||||
struct value *low = NULL, *high = NULL;
|
||||
struct value *addrval, *result;
|
||||
CORE_ADDR addr;
|
||||
@@ -1079,7 +1078,8 @@ rust_range (struct expression *exp, int *pos, enum noside noside)
|
||||
struct type *temp_type;
|
||||
const char *name;
|
||||
|
||||
- kind = (enum range_type) longest_to_int (exp->elts[*pos + 1].longconst);
|
||||
+ auto kind
|
||||
+ = (enum range_flag) longest_to_int (exp->elts[*pos + 1].longconst);
|
||||
*pos += 3;
|
||||
|
||||
if (!(kind & RANGE_LOW_BOUND_DEFAULT))
|
||||
@@ -1169,7 +1169,7 @@ rust_range (struct expression *exp, int *pos, enum noside noside)
|
||||
static void
|
||||
rust_compute_range (struct type *type, struct value *range,
|
||||
LONGEST *low, LONGEST *high,
|
||||
- range_types *kind)
|
||||
+ range_flags *kind)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1209,7 +1209,7 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
|
||||
struct type *rhstype;
|
||||
LONGEST low, high_bound;
|
||||
/* Initialized to appease the compiler. */
|
||||
- range_types kind = RANGE_LOW_BOUND_DEFAULT | RANGE_HIGH_BOUND_DEFAULT;
|
||||
+ range_flags kind = RANGE_LOW_BOUND_DEFAULT | RANGE_HIGH_BOUND_DEFAULT;
|
||||
LONGEST high = 0;
|
||||
int want_slice = 0;
|
||||
|
@ -1,137 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 24 May 2021 17:07:36 -0700
|
||||
Subject: gdb-rhbz1964167-fortran-whitespace_array.patch
|
||||
|
||||
;; [fortran] Backport Andrew Burgess's commit which eliminates undesirable
|
||||
;; whitespace when printing arrays.
|
||||
|
||||
gdb/fortran: Change whitespace when printing arrays
|
||||
|
||||
This commit makes the whitespace usage when printing Fortran arrays
|
||||
more consistent, and more inline with how we print C arrays.
|
||||
|
||||
Currently a 2 dimensional Fotran array is printed like this, I find
|
||||
the marked whitespace unpleasant:
|
||||
|
||||
(( 1, 2, 3) ( 4, 5, 6) )
|
||||
^ ^ ^
|
||||
|
||||
After this commit the same array is printed like this:
|
||||
|
||||
((1, 2, 3) (4, 5, 6))
|
||||
|
||||
Which seems more inline with how we print C arrays, in the case of C
|
||||
arrays we don't add extra whitespace before the first element.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* f-valprint.c (f77_print_array_1): Adjust printing of whitespace
|
||||
for arrays.
|
||||
|
||||
gdb/testsuite/ChangeLog:
|
||||
|
||||
* gdb.fortran/array-slices.exp: Update expected results.
|
||||
* gdb.fortran/class-allocatable-array.exp: Likewise.
|
||||
* gdb.fortran/multi-dim.exp: Likewise.
|
||||
* gdb.fortran/vla-type.exp: Likewise.
|
||||
* gdb.mi/mi-vla-fortran.exp: Likewise.
|
||||
|
||||
diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c
|
||||
--- a/gdb/f-valprint.c
|
||||
+++ b/gdb/f-valprint.c
|
||||
@@ -137,14 +137,17 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type,
|
||||
(TYPE_TARGET_TYPE (type), value_contents_for_printing_const (val)
|
||||
+ offs, addr + offs);
|
||||
|
||||
- fprintf_filtered (stream, "( ");
|
||||
+ fprintf_filtered (stream, "(");
|
||||
f77_print_array_1 (nss + 1, ndimensions, value_type (subarray),
|
||||
value_contents_for_printing (subarray),
|
||||
value_embedded_offset (subarray),
|
||||
value_address (subarray),
|
||||
stream, recurse, subarray, options, elts);
|
||||
offs += byte_stride;
|
||||
- fprintf_filtered (stream, ") ");
|
||||
+ fprintf_filtered (stream, ")");
|
||||
+
|
||||
+ if (i < upperbound)
|
||||
+ fprintf_filtered (stream, " ");
|
||||
}
|
||||
if (*elts >= options->print_max && i < upperbound)
|
||||
fprintf_filtered (stream, "...");
|
||||
diff --git a/gdb/testsuite/gdb.fortran/array-slices.exp b/gdb/testsuite/gdb.fortran/array-slices.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/array-slices.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/array-slices.exp
|
||||
@@ -38,14 +38,14 @@ gdb_breakpoint [gdb_get_line_number "Final Breakpoint"]
|
||||
|
||||
set array_contents \
|
||||
[list \
|
||||
- " = \\(\\( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10\\) \\( 11, 12, 13, 14, 15, 16, 17, 18, 19, 20\\) \\( 21, 22, 23, 24, 25, 26, 27, 28, 29, 30\\) \\( 31, 32, 33, 34, 35, 36, 37, 38, 39, 40\\) \\( 41, 42, 43, 44, 45, 46, 47, 48, 49, 50\\) \\( 51, 52, 53, 54, 55, 56, 57, 58, 59, 60\\) \\( 61, 62, 63, 64, 65, 66, 67, 68, 69, 70\\) \\( 71, 72, 73, 74, 75, 76, 77, 78, 79, 80\\) \\( 81, 82, 83, 84, 85, 86, 87, 88, 89, 90\\) \\( 91, 92, 93, 94, 95, 96, 97, 98, 99, 100\\) \\)" \
|
||||
- " = \\(\\( 1, 2, 3, 4, 5\\) \\( 11, 12, 13, 14, 15\\) \\( 21, 22, 23, 24, 25\\) \\( 31, 32, 33, 34, 35\\) \\( 41, 42, 43, 44, 45\\) \\)" \
|
||||
- " = \\(\\( 1, 3, 5, 7, 9\\) \\( 21, 23, 25, 27, 29\\) \\( 41, 43, 45, 47, 49\\) \\( 61, 63, 65, 67, 69\\) \\( 81, 83, 85, 87, 89\\) \\)" \
|
||||
- " = \\(\\( 1, 4, 7, 10\\) \\( 21, 24, 27, 30\\) \\( 41, 44, 47, 50\\) \\( 61, 64, 67, 70\\) \\( 81, 84, 87, 90\\) \\)" \
|
||||
- " = \\(\\( 1, 5, 9\\) \\( 31, 35, 39\\) \\( 61, 65, 69\\) \\( 91, 95, 99\\) \\)" \
|
||||
- " = \\(\\( -26, -25, -24, -23, -22, -21, -20, -19, -18, -17\\) \\( -19, -18, -17, -16, -15, -14, -13, -12, -11, -10\\) \\( -12, -11, -10, -9, -8, -7, -6, -5, -4, -3\\) \\( -5, -4, -3, -2, -1, 0, 1, 2, 3, 4\\) \\( 2, 3, 4, 5, 6, 7, 8, 9, 10, 11\\) \\( 9, 10, 11, 12, 13, 14, 15, 16, 17, 18\\) \\( 16, 17, 18, 19, 20, 21, 22, 23, 24, 25\\) \\( 23, 24, 25, 26, 27, 28, 29, 30, 31, 32\\) \\( 30, 31, 32, 33, 34, 35, 36, 37, 38, 39\\) \\( 37, 38, 39, 40, 41, 42, 43, 44, 45, 46\\) \\)" \
|
||||
- " = \\(\\( -26, -25, -24, -23, -22, -21\\) \\( -19, -18, -17, -16, -15, -14\\) \\( -12, -11, -10, -9, -8, -7\\) \\)" \
|
||||
- " = \\(\\( -26, -24, -22, -20, -18\\) \\( -5, -3, -1, 1, 3\\) \\( 16, 18, 20, 22, 24\\) \\( 37, 39, 41, 43, 45\\) \\)" ]
|
||||
+ " = \\(\\(1, 2, 3, 4, 5, 6, 7, 8, 9, 10\\) \\(11, 12, 13, 14, 15, 16, 17, 18, 19, 20\\) \\(21, 22, 23, 24, 25, 26, 27, 28, 29, 30\\) \\(31, 32, 33, 34, 35, 36, 37, 38, 39, 40\\) \\(41, 42, 43, 44, 45, 46, 47, 48, 49, 50\\) \\(51, 52, 53, 54, 55, 56, 57, 58, 59, 60\\) \\(61, 62, 63, 64, 65, 66, 67, 68, 69, 70\\) \\(71, 72, 73, 74, 75, 76, 77, 78, 79, 80\\) \\(81, 82, 83, 84, 85, 86, 87, 88, 89, 90\\) \\(91, 92, 93, 94, 95, 96, 97, 98, 99, 100\\)\\)" \
|
||||
+ " = \\(\\(1, 2, 3, 4, 5\\) \\(11, 12, 13, 14, 15\\) \\(21, 22, 23, 24, 25\\) \\(31, 32, 33, 34, 35\\) \\(41, 42, 43, 44, 45\\)\\)" \
|
||||
+ " = \\(\\(1, 3, 5, 7, 9\\) \\(21, 23, 25, 27, 29\\) \\(41, 43, 45, 47, 49\\) \\(61, 63, 65, 67, 69\\) \\(81, 83, 85, 87, 89\\)\\)" \
|
||||
+ " = \\(\\(1, 4, 7, 10\\) \\(21, 24, 27, 30\\) \\(41, 44, 47, 50\\) \\(61, 64, 67, 70\\) \\(81, 84, 87, 90\\)\\)" \
|
||||
+ " = \\(\\(1, 5, 9\\) \\(31, 35, 39\\) \\(61, 65, 69\\) \\(91, 95, 99\\)\\)" \
|
||||
+ " = \\(\\(-26, -25, -24, -23, -22, -21, -20, -19, -18, -17\\) \\(-19, -18, -17, -16, -15, -14, -13, -12, -11, -10\\) \\(-12, -11, -10, -9, -8, -7, -6, -5, -4, -3\\) \\(-5, -4, -3, -2, -1, 0, 1, 2, 3, 4\\) \\(2, 3, 4, 5, 6, 7, 8, 9, 10, 11\\) \\(9, 10, 11, 12, 13, 14, 15, 16, 17, 18\\) \\(16, 17, 18, 19, 20, 21, 22, 23, 24, 25\\) \\(23, 24, 25, 26, 27, 28, 29, 30, 31, 32\\) \\(30, 31, 32, 33, 34, 35, 36, 37, 38, 39\\) \\(37, 38, 39, 40, 41, 42, 43, 44, 45, 46\\)\\)" \
|
||||
+ " = \\(\\(-26, -25, -24, -23, -22, -21\\) \\(-19, -18, -17, -16, -15, -14\\) \\(-12, -11, -10, -9, -8, -7\\)\\)" \
|
||||
+ " = \\(\\(-26, -24, -22, -20, -18\\) \\(-5, -3, -1, 1, 3\\) \\(16, 18, 20, 22, 24\\) \\(37, 39, 41, 43, 45\\)\\)" ]
|
||||
|
||||
set message_strings \
|
||||
[list \
|
||||
diff --git a/gdb/testsuite/gdb.fortran/class-allocatable-array.exp b/gdb/testsuite/gdb.fortran/class-allocatable-array.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/class-allocatable-array.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/class-allocatable-array.exp
|
||||
@@ -40,4 +40,4 @@ gdb_continue_to_breakpoint "Break Here"
|
||||
# cetainly going to fail.
|
||||
gdb_test "print this" " = \\( _data = \[^\r\n\]+, _vptr = \[^\r\n\]+\\)"
|
||||
gdb_test "print this%_data" " = \\(PTR TO -> \\( Type test_type \\)\\) \[^\r\n\]+"
|
||||
-gdb_test "print this%_data%b" " = \\(\\( 1, 2, 3\\) \\( 4, 5, 6\\) \\)"
|
||||
+gdb_test "print this%_data%b" " = \\(\\(1, 2, 3\\) \\(4, 5, 6\\)\\)"
|
||||
diff --git a/gdb/testsuite/gdb.fortran/multi-dim.exp b/gdb/testsuite/gdb.fortran/multi-dim.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/multi-dim.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/multi-dim.exp
|
||||
@@ -57,7 +57,7 @@ gdb_test "print foo(3,3,4)" \
|
||||
"print an invalid array index (3,3,4)"
|
||||
|
||||
gdb_test "print foo" \
|
||||
- { = \(\( \( 10, 10\) \( 10, 10\) \( 10, 10\) \) \( \( 10, 10\) \( 10, 10\) \( 10, 10\) \) \( \( 10, 10\) \( 10, 10\) \( 10, 10\) \) \( \( 10, 10\) \( 10, 10\) \( 10, 20\) \) \)} \
|
||||
+ { = \(\(\(10, 10\) \(10, 10\) \(10, 10\)\) \(\(10, 10\) \(10, 10\) \(10, 10\)\) \(\(10, 10\) \(10, 10\) \(10, 10\)\) \(\(10, 10\) \(10, 10\) \(10, 20\)\)\)} \
|
||||
"print full contents of the array"
|
||||
|
||||
gdb_breakpoint [gdb_get_line_number "break-variable"]
|
||||
diff --git a/gdb/testsuite/gdb.fortran/vla-type.exp b/gdb/testsuite/gdb.fortran/vla-type.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/vla-type.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/vla-type.exp
|
||||
@@ -66,9 +66,9 @@ gdb_test "ptype twov" \
|
||||
"\\s+$int, allocatable :: ivla1\\\(5,12,99\\\)" \
|
||||
"\\s+$int, allocatable :: ivla2\\\(9,12\\\)" \
|
||||
"End Type two" ]
|
||||
-gdb_test "print twov" " = \\\( ivla1 = \\\(\\\( \\\( 1, 1, 1, 1, 1\\\)\
|
||||
- \\\( 1, 1, 321, 1, 1\\\)\
|
||||
- \\\( 1, 1, 1, 1, 1\\\) .*"
|
||||
+gdb_test "print twov" " = \\\( ivla1 = \\\(\\\(\\\(1, 1, 1, 1, 1\\\)\
|
||||
+ \\\(1, 1, 321, 1, 1\\\)\
|
||||
+ \\\(1, 1, 1, 1, 1\\\) .*"
|
||||
|
||||
# Check type with attribute at beginn of type
|
||||
gdb_breakpoint [gdb_get_line_number "threev-filled"]
|
||||
diff --git a/gdb/testsuite/gdb.mi/mi-vla-fortran.exp b/gdb/testsuite/gdb.mi/mi-vla-fortran.exp
|
||||
--- a/gdb/testsuite/gdb.mi/mi-vla-fortran.exp
|
||||
+++ b/gdb/testsuite/gdb.mi/mi-vla-fortran.exp
|
||||
@@ -180,7 +180,7 @@ mi_run_cmd
|
||||
mi_expect_stop "breakpoint-hit" "vla" "" ".*vla.f90" "$bp_lineno" \
|
||||
{ "" "disp=\"del\"" } "run to breakpoint at line $bp_lineno"
|
||||
mi_gdb_test "590-data-evaluate-expression pvla2" \
|
||||
- "590\\^done,value=\"\\(\\( 2, 2, 2, 2, 2\\) \\( 2, 2, 2, 2, 2\\) \\)\"" \
|
||||
+ "590\\^done,value=\"\\(\\(2, 2, 2, 2, 2\\) \\(2, 2, 2, 2, 2\\)\\)\"" \
|
||||
"evaluate associated vla"
|
||||
|
||||
mi_create_varobj_checked pvla2_associated pvla2 \
|
@ -1,787 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 24 May 2021 17:00:17 -0700
|
||||
Subject: gdb-rhbz1964167-move-fortran-expr-handling.patch
|
||||
|
||||
;; [fortran] Backport Andrew Burgess's commit which moves Fortran
|
||||
;; expression handling to f-lang.c.
|
||||
|
||||
gdb/fortran: Move Fortran expression handling into f-lang.c
|
||||
|
||||
The Fortran specific OP_F77_UNDETERMINED_ARGLIST is currently handled
|
||||
in the generic expression handling code. There's no reason why this
|
||||
should be the case, so this commit moves handling of this into Fortran
|
||||
specific files.
|
||||
|
||||
There should be no user visible changes after this commit.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* eval.c: Remove 'f-lang.h' include.
|
||||
(value_f90_subarray): Moved to f-lang.c.
|
||||
(eval_call): Renamed to...
|
||||
(evaluate_subexp_do_call): ...this, is no longer static, header
|
||||
comment moved into header file.
|
||||
(evaluate_funcall): Update call to eval_call.
|
||||
(skip_undetermined_arglist): Moved to f-lang.c.
|
||||
(fortran_value_subarray): Likewise.
|
||||
(evaluate_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling
|
||||
moved to evaluate_subexp_f.
|
||||
(calc_f77_array_dims): Moved to f-lang.c
|
||||
* expprint.c (print_subexp_funcall): New function.
|
||||
(print_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling
|
||||
moved to print_subexp_f, OP_FUNCALL uses new function.
|
||||
(dump_subexp_body_funcall): New function.
|
||||
(dump_subexp_body_standard): OP_F77_UNDETERMINED_ARGLIST handling
|
||||
moved to dump_subexp_f, OP_FUNCALL uses new function.
|
||||
* expression.h (evaluate_subexp_do_call): Declare.
|
||||
* f-lang.c (value_f90_subarray): Moved from eval.c.
|
||||
(skip_undetermined_arglist): Likewise.
|
||||
(calc_f77_array_dims): Likewise.
|
||||
(fortran_value_subarray): Likewise.
|
||||
(evaluate_subexp_f): Add OP_F77_UNDETERMINED_ARGLIST support.
|
||||
(operator_length_f): Likewise.
|
||||
(print_subexp_f): Likewise.
|
||||
(dump_subexp_body_f): Likewise.
|
||||
* fortran-operator.def (OP_F77_UNDETERMINED_ARGLIST): Move
|
||||
declaration of this operation to here.
|
||||
* parse.c (operator_length_standard): OP_F77_UNDETERMINED_ARGLIST
|
||||
support moved to operator_length_f.
|
||||
* parser-defs.h (dump_subexp_body_funcall): Declare.
|
||||
(print_subexp_funcall): Declare.
|
||||
* std-operator.def (OP_F77_UNDETERMINED_ARGLIST): Moved to
|
||||
fortran-operator.def.
|
||||
|
||||
diff --git a/gdb/eval.c b/gdb/eval.c
|
||||
--- a/gdb/eval.c
|
||||
+++ b/gdb/eval.c
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "frame.h"
|
||||
#include "gdbthread.h"
|
||||
#include "language.h" /* For CAST_IS_CONVERSION. */
|
||||
-#include "f-lang.h" /* For array bound stuff. */
|
||||
#include "cp-abi.h"
|
||||
#include "infcall.h"
|
||||
#include "objc-lang.h"
|
||||
@@ -371,32 +370,6 @@ init_array_element (struct value *array, struct value *element,
|
||||
return index;
|
||||
}
|
||||
|
||||
-static struct value *
|
||||
-value_f90_subarray (struct value *array,
|
||||
- struct expression *exp, int *pos, enum noside noside)
|
||||
-{
|
||||
- int pc = (*pos) + 1;
|
||||
- LONGEST low_bound, high_bound;
|
||||
- struct type *range = check_typedef (value_type (array)->index_type ());
|
||||
- enum range_type range_type
|
||||
- = (enum range_type) longest_to_int (exp->elts[pc].longconst);
|
||||
-
|
||||
- *pos += 3;
|
||||
-
|
||||
- if (range_type == LOW_BOUND_DEFAULT || range_type == BOTH_BOUND_DEFAULT)
|
||||
- low_bound = range->bounds ()->low.const_val ();
|
||||
- else
|
||||
- low_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
|
||||
-
|
||||
- if (range_type == HIGH_BOUND_DEFAULT || range_type == BOTH_BOUND_DEFAULT)
|
||||
- high_bound = range->bounds ()->high.const_val ();
|
||||
- else
|
||||
- high_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
|
||||
-
|
||||
- return value_slice (array, low_bound, high_bound - low_bound + 1);
|
||||
-}
|
||||
-
|
||||
-
|
||||
/* Promote value ARG1 as appropriate before performing a unary operation
|
||||
on this argument.
|
||||
If the result is not appropriate for any particular language then it
|
||||
@@ -749,17 +722,13 @@ eval_skip_value (expression *exp)
|
||||
return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1);
|
||||
}
|
||||
|
||||
-/* Evaluate a function call. The function to be called is in
|
||||
- ARGVEC[0] and the arguments passed to the function are in
|
||||
- ARGVEC[1..NARGS]. FUNCTION_NAME is the name of the function, if
|
||||
- known. DEFAULT_RETURN_TYPE is used as the function's return type
|
||||
- if the return type is unknown. */
|
||||
+/* See expression.h. */
|
||||
|
||||
-static value *
|
||||
-eval_call (expression *exp, enum noside noside,
|
||||
- int nargs, value **argvec,
|
||||
- const char *function_name,
|
||||
- type *default_return_type)
|
||||
+value *
|
||||
+evaluate_subexp_do_call (expression *exp, enum noside noside,
|
||||
+ int nargs, value **argvec,
|
||||
+ const char *function_name,
|
||||
+ type *default_return_type)
|
||||
{
|
||||
if (argvec[0] == NULL)
|
||||
error (_("Cannot evaluate function -- may be inlined"));
|
||||
@@ -1230,20 +1199,8 @@ evaluate_funcall (type *expect_type, expression *exp, int *pos,
|
||||
/* Nothing to be done; argvec already correctly set up. */
|
||||
}
|
||||
|
||||
- return eval_call (exp, noside, nargs, argvec, var_func_name, expect_type);
|
||||
-}
|
||||
-
|
||||
-/* Helper for skipping all the arguments in an undetermined argument list.
|
||||
- This function was designed for use in the OP_F77_UNDETERMINED_ARGLIST
|
||||
- case of evaluate_subexp_standard as multiple, but not all, code paths
|
||||
- require a generic skip. */
|
||||
-
|
||||
-static void
|
||||
-skip_undetermined_arglist (int nargs, struct expression *exp, int *pos,
|
||||
- enum noside noside)
|
||||
-{
|
||||
- for (int i = 0; i < nargs; ++i)
|
||||
- evaluate_subexp (nullptr, exp, pos, noside);
|
||||
+ return evaluate_subexp_do_call (exp, noside, nargs, argvec,
|
||||
+ var_func_name, expect_type);
|
||||
}
|
||||
|
||||
/* Return true if type is integral or reference to integral */
|
||||
@@ -1260,67 +1217,6 @@ is_integral_or_integral_reference (struct type *type)
|
||||
&& is_integral_type (TYPE_TARGET_TYPE (type)));
|
||||
}
|
||||
|
||||
-/* Called from evaluate_subexp_standard to perform array indexing, and
|
||||
- sub-range extraction, for Fortran. As well as arrays this function
|
||||
- also handles strings as they can be treated like arrays of characters.
|
||||
- ARRAY is the array or string being accessed. EXP, POS, and NOSIDE are
|
||||
- as for evaluate_subexp_standard, and NARGS is the number of arguments
|
||||
- in this access (e.g. 'array (1,2,3)' would be NARGS 3). */
|
||||
-
|
||||
-static struct value *
|
||||
-fortran_value_subarray (struct value *array, struct expression *exp,
|
||||
- int *pos, int nargs, enum noside noside)
|
||||
-{
|
||||
- if (exp->elts[*pos].opcode == OP_RANGE)
|
||||
- return value_f90_subarray (array, exp, pos, noside);
|
||||
-
|
||||
- if (noside == EVAL_SKIP)
|
||||
- {
|
||||
- skip_undetermined_arglist (nargs, exp, pos, noside);
|
||||
- /* Return the dummy value with the correct type. */
|
||||
- return array;
|
||||
- }
|
||||
-
|
||||
- LONGEST subscript_array[MAX_FORTRAN_DIMS];
|
||||
- int ndimensions = 1;
|
||||
- struct type *type = check_typedef (value_type (array));
|
||||
-
|
||||
- if (nargs > MAX_FORTRAN_DIMS)
|
||||
- error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS);
|
||||
-
|
||||
- ndimensions = calc_f77_array_dims (type);
|
||||
-
|
||||
- if (nargs != ndimensions)
|
||||
- error (_("Wrong number of subscripts"));
|
||||
-
|
||||
- gdb_assert (nargs > 0);
|
||||
-
|
||||
- /* Now that we know we have a legal array subscript expression let us
|
||||
- actually find out where this element exists in the array. */
|
||||
-
|
||||
- /* Take array indices left to right. */
|
||||
- for (int i = 0; i < nargs; i++)
|
||||
- {
|
||||
- /* Evaluate each subscript; it must be a legal integer in F77. */
|
||||
- value *arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
-
|
||||
- /* Fill in the subscript array. */
|
||||
- subscript_array[i] = value_as_long (arg2);
|
||||
- }
|
||||
-
|
||||
- /* Internal type of array is arranged right to left. */
|
||||
- for (int i = nargs; i > 0; i--)
|
||||
- {
|
||||
- struct type *array_type = check_typedef (value_type (array));
|
||||
- LONGEST index = subscript_array[i - 1];
|
||||
-
|
||||
- array = value_subscripted_rvalue (array, index,
|
||||
- f77_get_lowerbound (array_type));
|
||||
- }
|
||||
-
|
||||
- return array;
|
||||
-}
|
||||
-
|
||||
struct value *
|
||||
evaluate_subexp_standard (struct type *expect_type,
|
||||
struct expression *exp, int *pos,
|
||||
@@ -1335,7 +1231,6 @@ evaluate_subexp_standard (struct type *expect_type,
|
||||
struct type *type;
|
||||
int nargs;
|
||||
struct value **argvec;
|
||||
- int code;
|
||||
int ix;
|
||||
long mem_offset;
|
||||
struct type **arg_types;
|
||||
@@ -1976,84 +1871,6 @@ evaluate_subexp_standard (struct type *expect_type,
|
||||
case OP_FUNCALL:
|
||||
return evaluate_funcall (expect_type, exp, pos, noside);
|
||||
|
||||
- case OP_F77_UNDETERMINED_ARGLIST:
|
||||
-
|
||||
- /* Remember that in F77, functions, substring ops and
|
||||
- array subscript operations cannot be disambiguated
|
||||
- at parse time. We have made all array subscript operations,
|
||||
- substring operations as well as function calls come here
|
||||
- and we now have to discover what the heck this thing actually was.
|
||||
- If it is a function, we process just as if we got an OP_FUNCALL. */
|
||||
-
|
||||
- nargs = longest_to_int (exp->elts[pc + 1].longconst);
|
||||
- (*pos) += 2;
|
||||
-
|
||||
- /* First determine the type code we are dealing with. */
|
||||
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
|
||||
- type = check_typedef (value_type (arg1));
|
||||
- code = type->code ();
|
||||
-
|
||||
- if (code == TYPE_CODE_PTR)
|
||||
- {
|
||||
- /* Fortran always passes variable to subroutines as pointer.
|
||||
- So we need to look into its target type to see if it is
|
||||
- array, string or function. If it is, we need to switch
|
||||
- to the target value the original one points to. */
|
||||
- struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
-
|
||||
- if (target_type->code () == TYPE_CODE_ARRAY
|
||||
- || target_type->code () == TYPE_CODE_STRING
|
||||
- || target_type->code () == TYPE_CODE_FUNC)
|
||||
- {
|
||||
- arg1 = value_ind (arg1);
|
||||
- type = check_typedef (value_type (arg1));
|
||||
- code = type->code ();
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- switch (code)
|
||||
- {
|
||||
- case TYPE_CODE_ARRAY:
|
||||
- case TYPE_CODE_STRING:
|
||||
- return fortran_value_subarray (arg1, exp, pos, nargs, noside);
|
||||
-
|
||||
- case TYPE_CODE_PTR:
|
||||
- case TYPE_CODE_FUNC:
|
||||
- case TYPE_CODE_INTERNAL_FUNCTION:
|
||||
- /* It's a function call. */
|
||||
- /* Allocate arg vector, including space for the function to be
|
||||
- called in argvec[0] and a terminating NULL. */
|
||||
- argvec = (struct value **)
|
||||
- alloca (sizeof (struct value *) * (nargs + 2));
|
||||
- argvec[0] = arg1;
|
||||
- tem = 1;
|
||||
- for (; tem <= nargs; tem++)
|
||||
- {
|
||||
- argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
- /* Arguments in Fortran are passed by address. Coerce the
|
||||
- arguments here rather than in value_arg_coerce as otherwise
|
||||
- the call to malloc to place the non-lvalue parameters in
|
||||
- target memory is hit by this Fortran specific logic. This
|
||||
- results in malloc being called with a pointer to an integer
|
||||
- followed by an attempt to malloc the arguments to malloc in
|
||||
- target memory. Infinite recursion ensues. */
|
||||
- if (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC)
|
||||
- {
|
||||
- bool is_artificial
|
||||
- = TYPE_FIELD_ARTIFICIAL (value_type (arg1), tem - 1);
|
||||
- argvec[tem] = fortran_argument_convert (argvec[tem],
|
||||
- is_artificial);
|
||||
- }
|
||||
- }
|
||||
- argvec[tem] = 0; /* signal end of arglist */
|
||||
- if (noside == EVAL_SKIP)
|
||||
- return eval_skip_value (exp);
|
||||
- return eval_call (exp, noside, nargs, argvec, NULL, expect_type);
|
||||
-
|
||||
- default:
|
||||
- error (_("Cannot perform substring on this type"));
|
||||
- }
|
||||
-
|
||||
case OP_COMPLEX:
|
||||
/* We have a complex number, There should be 2 floating
|
||||
point numbers that compose it. */
|
||||
@@ -3346,27 +3163,3 @@ parse_and_eval_type (char *p, int length)
|
||||
error (_("Internal error in eval_type."));
|
||||
return expr->elts[1].type;
|
||||
}
|
||||
-
|
||||
-/* Return the number of dimensions for a Fortran array or string. */
|
||||
-
|
||||
-int
|
||||
-calc_f77_array_dims (struct type *array_type)
|
||||
-{
|
||||
- int ndimen = 1;
|
||||
- struct type *tmp_type;
|
||||
-
|
||||
- if ((array_type->code () == TYPE_CODE_STRING))
|
||||
- return 1;
|
||||
-
|
||||
- if ((array_type->code () != TYPE_CODE_ARRAY))
|
||||
- error (_("Can't get dimensions for a non-array type"));
|
||||
-
|
||||
- tmp_type = array_type;
|
||||
-
|
||||
- while ((tmp_type = TYPE_TARGET_TYPE (tmp_type)))
|
||||
- {
|
||||
- if (tmp_type->code () == TYPE_CODE_ARRAY)
|
||||
- ++ndimen;
|
||||
- }
|
||||
- return ndimen;
|
||||
-}
|
||||
diff --git a/gdb/expprint.c b/gdb/expprint.c
|
||||
--- a/gdb/expprint.c
|
||||
+++ b/gdb/expprint.c
|
||||
@@ -53,6 +53,25 @@ print_subexp (struct expression *exp, int *pos,
|
||||
exp->language_defn->la_exp_desc->print_subexp (exp, pos, stream, prec);
|
||||
}
|
||||
|
||||
+/* See parser-defs.h. */
|
||||
+
|
||||
+void
|
||||
+print_subexp_funcall (struct expression *exp, int *pos,
|
||||
+ struct ui_file *stream)
|
||||
+{
|
||||
+ (*pos) += 2;
|
||||
+ unsigned nargs = longest_to_int (exp->elts[*pos].longconst);
|
||||
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
|
||||
+ fputs_filtered (" (", stream);
|
||||
+ for (unsigned tem = 0; tem < nargs; tem++)
|
||||
+ {
|
||||
+ if (tem != 0)
|
||||
+ fputs_filtered (", ", stream);
|
||||
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
|
||||
+ }
|
||||
+ fputs_filtered (")", stream);
|
||||
+}
|
||||
+
|
||||
/* Standard implementation of print_subexp for use in language_defn
|
||||
vectors. */
|
||||
void
|
||||
@@ -187,18 +206,7 @@ print_subexp_standard (struct expression *exp, int *pos,
|
||||
return;
|
||||
|
||||
case OP_FUNCALL:
|
||||
- case OP_F77_UNDETERMINED_ARGLIST:
|
||||
- (*pos) += 2;
|
||||
- nargs = longest_to_int (exp->elts[pc + 1].longconst);
|
||||
- print_subexp (exp, pos, stream, PREC_SUFFIX);
|
||||
- fputs_filtered (" (", stream);
|
||||
- for (tem = 0; tem < nargs; tem++)
|
||||
- {
|
||||
- if (tem != 0)
|
||||
- fputs_filtered (", ", stream);
|
||||
- print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
|
||||
- }
|
||||
- fputs_filtered (")", stream);
|
||||
+ print_subexp_funcall (exp, pos, stream);
|
||||
return;
|
||||
|
||||
case OP_NAME:
|
||||
@@ -796,6 +804,22 @@ dump_subexp_body (struct expression *exp, struct ui_file *stream, int elt)
|
||||
return exp->language_defn->la_exp_desc->dump_subexp_body (exp, stream, elt);
|
||||
}
|
||||
|
||||
+/* See parser-defs.h. */
|
||||
+
|
||||
+int
|
||||
+dump_subexp_body_funcall (struct expression *exp,
|
||||
+ struct ui_file *stream, int elt)
|
||||
+{
|
||||
+ int nargs = longest_to_int (exp->elts[elt].longconst);
|
||||
+ fprintf_filtered (stream, "Number of args: %d", nargs);
|
||||
+ elt += 2;
|
||||
+
|
||||
+ for (int i = 1; i <= nargs + 1; i++)
|
||||
+ elt = dump_subexp (exp, stream, elt);
|
||||
+
|
||||
+ return elt;
|
||||
+}
|
||||
+
|
||||
/* Default value for subexp_body in exp_descriptor vector. */
|
||||
|
||||
int
|
||||
@@ -931,18 +955,7 @@ dump_subexp_body_standard (struct expression *exp,
|
||||
elt += 2;
|
||||
break;
|
||||
case OP_FUNCALL:
|
||||
- case OP_F77_UNDETERMINED_ARGLIST:
|
||||
- {
|
||||
- int i, nargs;
|
||||
-
|
||||
- nargs = longest_to_int (exp->elts[elt].longconst);
|
||||
-
|
||||
- fprintf_filtered (stream, "Number of args: %d", nargs);
|
||||
- elt += 2;
|
||||
-
|
||||
- for (i = 1; i <= nargs + 1; i++)
|
||||
- elt = dump_subexp (exp, stream, elt);
|
||||
- }
|
||||
+ elt = dump_subexp_body_funcall (exp, stream, elt);
|
||||
break;
|
||||
case OP_ARRAY:
|
||||
{
|
||||
diff --git a/gdb/expression.h b/gdb/expression.h
|
||||
--- a/gdb/expression.h
|
||||
+++ b/gdb/expression.h
|
||||
@@ -155,6 +155,18 @@ enum noside
|
||||
extern struct value *evaluate_subexp_standard
|
||||
(struct type *, struct expression *, int *, enum noside);
|
||||
|
||||
+/* Evaluate a function call. The function to be called is in ARGVEC[0] and
|
||||
+ the arguments passed to the function are in ARGVEC[1..NARGS].
|
||||
+ FUNCTION_NAME is the name of the function, if known.
|
||||
+ DEFAULT_RETURN_TYPE is used as the function's return type if the return
|
||||
+ type is unknown. */
|
||||
+
|
||||
+extern struct value *evaluate_subexp_do_call (expression *exp,
|
||||
+ enum noside noside,
|
||||
+ int nargs, value **argvec,
|
||||
+ const char *function_name,
|
||||
+ type *default_return_type);
|
||||
+
|
||||
/* From expprint.c */
|
||||
|
||||
extern void print_expression (struct expression *, struct ui_file *);
|
||||
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
|
||||
--- a/gdb/f-lang.c
|
||||
+++ b/gdb/f-lang.c
|
||||
@@ -114,6 +114,134 @@ enum f_primitive_types {
|
||||
nr_f_primitive_types
|
||||
};
|
||||
|
||||
+/* Called from fortran_value_subarray to take a slice of an array or a
|
||||
+ string. ARRAY is the array or string to be accessed. EXP, POS, and
|
||||
+ NOSIDE are as for evaluate_subexp_standard. Return a value that is a
|
||||
+ slice of the array. */
|
||||
+
|
||||
+static struct value *
|
||||
+value_f90_subarray (struct value *array,
|
||||
+ struct expression *exp, int *pos, enum noside noside)
|
||||
+{
|
||||
+ int pc = (*pos) + 1;
|
||||
+ LONGEST low_bound, high_bound;
|
||||
+ struct type *range = check_typedef (value_type (array)->index_type ());
|
||||
+ enum range_type range_type
|
||||
+ = (enum range_type) longest_to_int (exp->elts[pc].longconst);
|
||||
+
|
||||
+ *pos += 3;
|
||||
+
|
||||
+ if (range_type == LOW_BOUND_DEFAULT || range_type == BOTH_BOUND_DEFAULT)
|
||||
+ low_bound = range->bounds ()->low.const_val ();
|
||||
+ else
|
||||
+ low_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
|
||||
+
|
||||
+ if (range_type == HIGH_BOUND_DEFAULT || range_type == BOTH_BOUND_DEFAULT)
|
||||
+ high_bound = range->bounds ()->high.const_val ();
|
||||
+ else
|
||||
+ high_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
|
||||
+
|
||||
+ return value_slice (array, low_bound, high_bound - low_bound + 1);
|
||||
+}
|
||||
+
|
||||
+/* Helper for skipping all the arguments in an undetermined argument list.
|
||||
+ This function was designed for use in the OP_F77_UNDETERMINED_ARGLIST
|
||||
+ case of evaluate_subexp_standard as multiple, but not all, code paths
|
||||
+ require a generic skip. */
|
||||
+
|
||||
+static void
|
||||
+skip_undetermined_arglist (int nargs, struct expression *exp, int *pos,
|
||||
+ enum noside noside)
|
||||
+{
|
||||
+ for (int i = 0; i < nargs; ++i)
|
||||
+ evaluate_subexp (nullptr, exp, pos, noside);
|
||||
+}
|
||||
+
|
||||
+/* Return the number of dimensions for a Fortran array or string. */
|
||||
+
|
||||
+int
|
||||
+calc_f77_array_dims (struct type *array_type)
|
||||
+{
|
||||
+ int ndimen = 1;
|
||||
+ struct type *tmp_type;
|
||||
+
|
||||
+ if ((array_type->code () == TYPE_CODE_STRING))
|
||||
+ return 1;
|
||||
+
|
||||
+ if ((array_type->code () != TYPE_CODE_ARRAY))
|
||||
+ error (_("Can't get dimensions for a non-array type"));
|
||||
+
|
||||
+ tmp_type = array_type;
|
||||
+
|
||||
+ while ((tmp_type = TYPE_TARGET_TYPE (tmp_type)))
|
||||
+ {
|
||||
+ if (tmp_type->code () == TYPE_CODE_ARRAY)
|
||||
+ ++ndimen;
|
||||
+ }
|
||||
+ return ndimen;
|
||||
+}
|
||||
+
|
||||
+/* Called from evaluate_subexp_standard to perform array indexing, and
|
||||
+ sub-range extraction, for Fortran. As well as arrays this function
|
||||
+ also handles strings as they can be treated like arrays of characters.
|
||||
+ ARRAY is the array or string being accessed. EXP, POS, and NOSIDE are
|
||||
+ as for evaluate_subexp_standard, and NARGS is the number of arguments
|
||||
+ in this access (e.g. 'array (1,2,3)' would be NARGS 3). */
|
||||
+
|
||||
+static struct value *
|
||||
+fortran_value_subarray (struct value *array, struct expression *exp,
|
||||
+ int *pos, int nargs, enum noside noside)
|
||||
+{
|
||||
+ if (exp->elts[*pos].opcode == OP_RANGE)
|
||||
+ return value_f90_subarray (array, exp, pos, noside);
|
||||
+
|
||||
+ if (noside == EVAL_SKIP)
|
||||
+ {
|
||||
+ skip_undetermined_arglist (nargs, exp, pos, noside);
|
||||
+ /* Return the dummy value with the correct type. */
|
||||
+ return array;
|
||||
+ }
|
||||
+
|
||||
+ LONGEST subscript_array[MAX_FORTRAN_DIMS];
|
||||
+ int ndimensions = 1;
|
||||
+ struct type *type = check_typedef (value_type (array));
|
||||
+
|
||||
+ if (nargs > MAX_FORTRAN_DIMS)
|
||||
+ error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS);
|
||||
+
|
||||
+ ndimensions = calc_f77_array_dims (type);
|
||||
+
|
||||
+ if (nargs != ndimensions)
|
||||
+ error (_("Wrong number of subscripts"));
|
||||
+
|
||||
+ gdb_assert (nargs > 0);
|
||||
+
|
||||
+ /* Now that we know we have a legal array subscript expression let us
|
||||
+ actually find out where this element exists in the array. */
|
||||
+
|
||||
+ /* Take array indices left to right. */
|
||||
+ for (int i = 0; i < nargs; i++)
|
||||
+ {
|
||||
+ /* Evaluate each subscript; it must be a legal integer in F77. */
|
||||
+ value *arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
+
|
||||
+ /* Fill in the subscript array. */
|
||||
+ subscript_array[i] = value_as_long (arg2);
|
||||
+ }
|
||||
+
|
||||
+ /* Internal type of array is arranged right to left. */
|
||||
+ for (int i = nargs; i > 0; i--)
|
||||
+ {
|
||||
+ struct type *array_type = check_typedef (value_type (array));
|
||||
+ LONGEST index = subscript_array[i - 1];
|
||||
+
|
||||
+ array = value_subscripted_rvalue (array, index,
|
||||
+ f77_get_lowerbound (array_type));
|
||||
+ }
|
||||
+
|
||||
+ return array;
|
||||
+}
|
||||
+
|
||||
/* Special expression evaluation cases for Fortran. */
|
||||
|
||||
static struct value *
|
||||
@@ -285,6 +413,87 @@ evaluate_subexp_f (struct type *expect_type, struct expression *exp,
|
||||
TYPE_LENGTH (type));
|
||||
return value_from_longest (builtin_type (exp->gdbarch)->builtin_int,
|
||||
TYPE_LENGTH (TYPE_TARGET_TYPE (type)));
|
||||
+
|
||||
+
|
||||
+ case OP_F77_UNDETERMINED_ARGLIST:
|
||||
+ /* Remember that in F77, functions, substring ops and array subscript
|
||||
+ operations cannot be disambiguated at parse time. We have made
|
||||
+ all array subscript operations, substring operations as well as
|
||||
+ function calls come here and we now have to discover what the heck
|
||||
+ this thing actually was. If it is a function, we process just as
|
||||
+ if we got an OP_FUNCALL. */
|
||||
+ int nargs = longest_to_int (exp->elts[pc + 1].longconst);
|
||||
+ (*pos) += 2;
|
||||
+
|
||||
+ /* First determine the type code we are dealing with. */
|
||||
+ arg1 = evaluate_subexp (nullptr, exp, pos, noside);
|
||||
+ type = check_typedef (value_type (arg1));
|
||||
+ enum type_code code = type->code ();
|
||||
+
|
||||
+ if (code == TYPE_CODE_PTR)
|
||||
+ {
|
||||
+ /* Fortran always passes variable to subroutines as pointer.
|
||||
+ So we need to look into its target type to see if it is
|
||||
+ array, string or function. If it is, we need to switch
|
||||
+ to the target value the original one points to. */
|
||||
+ struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
+
|
||||
+ if (target_type->code () == TYPE_CODE_ARRAY
|
||||
+ || target_type->code () == TYPE_CODE_STRING
|
||||
+ || target_type->code () == TYPE_CODE_FUNC)
|
||||
+ {
|
||||
+ arg1 = value_ind (arg1);
|
||||
+ type = check_typedef (value_type (arg1));
|
||||
+ code = type->code ();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ switch (code)
|
||||
+ {
|
||||
+ case TYPE_CODE_ARRAY:
|
||||
+ case TYPE_CODE_STRING:
|
||||
+ return fortran_value_subarray (arg1, exp, pos, nargs, noside);
|
||||
+
|
||||
+ case TYPE_CODE_PTR:
|
||||
+ case TYPE_CODE_FUNC:
|
||||
+ case TYPE_CODE_INTERNAL_FUNCTION:
|
||||
+ {
|
||||
+ /* It's a function call. Allocate arg vector, including
|
||||
+ space for the function to be called in argvec[0] and a
|
||||
+ termination NULL. */
|
||||
+ struct value **argvec = (struct value **)
|
||||
+ alloca (sizeof (struct value *) * (nargs + 2));
|
||||
+ argvec[0] = arg1;
|
||||
+ int tem = 1;
|
||||
+ for (; tem <= nargs; tem++)
|
||||
+ {
|
||||
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
+ /* Arguments in Fortran are passed by address. Coerce the
|
||||
+ arguments here rather than in value_arg_coerce as
|
||||
+ otherwise the call to malloc to place the non-lvalue
|
||||
+ parameters in target memory is hit by this Fortran
|
||||
+ specific logic. This results in malloc being called
|
||||
+ with a pointer to an integer followed by an attempt to
|
||||
+ malloc the arguments to malloc in target memory.
|
||||
+ Infinite recursion ensues. */
|
||||
+ if (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC)
|
||||
+ {
|
||||
+ bool is_artificial
|
||||
+ = TYPE_FIELD_ARTIFICIAL (value_type (arg1), tem - 1);
|
||||
+ argvec[tem] = fortran_argument_convert (argvec[tem],
|
||||
+ is_artificial);
|
||||
+ }
|
||||
+ }
|
||||
+ argvec[tem] = 0; /* signal end of arglist */
|
||||
+ if (noside == EVAL_SKIP)
|
||||
+ return eval_skip_value (exp);
|
||||
+ return evaluate_subexp_do_call (exp, noside, nargs, argvec, NULL,
|
||||
+ expect_type);
|
||||
+ }
|
||||
+
|
||||
+ default:
|
||||
+ error (_("Cannot perform substring on this type"));
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Should be unreachable. */
|
||||
@@ -318,6 +527,11 @@ operator_length_f (const struct expression *exp, int pc, int *oplenp,
|
||||
oplen = 1;
|
||||
args = 2;
|
||||
break;
|
||||
+
|
||||
+ case OP_F77_UNDETERMINED_ARGLIST:
|
||||
+ oplen = 3;
|
||||
+ args = 1 + longest_to_int (exp->elts[pc - 2].longconst);
|
||||
+ break;
|
||||
}
|
||||
|
||||
*oplenp = oplen;
|
||||
@@ -390,6 +604,10 @@ print_subexp_f (struct expression *exp, int *pos,
|
||||
case BINOP_FORTRAN_MODULO:
|
||||
print_binop_subexp_f (exp, pos, stream, prec, "MODULO");
|
||||
return;
|
||||
+
|
||||
+ case OP_F77_UNDETERMINED_ARGLIST:
|
||||
+ print_subexp_funcall (exp, pos, stream);
|
||||
+ return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,6 +650,9 @@ dump_subexp_body_f (struct expression *exp,
|
||||
case BINOP_FORTRAN_MODULO:
|
||||
operator_length_f (exp, (elt + 1), &oplen, &nargs);
|
||||
break;
|
||||
+
|
||||
+ case OP_F77_UNDETERMINED_ARGLIST:
|
||||
+ return dump_subexp_body_funcall (exp, stream, elt);
|
||||
}
|
||||
|
||||
elt += oplen;
|
||||
diff --git a/gdb/fortran-operator.def b/gdb/fortran-operator.def
|
||||
--- a/gdb/fortran-operator.def
|
||||
+++ b/gdb/fortran-operator.def
|
||||
@@ -17,6 +17,14 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
+/* This is EXACTLY like OP_FUNCALL but is semantically different.
|
||||
+ In F77, array subscript expressions, substring expressions and
|
||||
+ function calls are all exactly the same syntactically. They
|
||||
+ may only be disambiguated at runtime. Thus this operator,
|
||||
+ which indicates that we have found something of the form
|
||||
+ <name> ( <stuff> ). */
|
||||
+OP (OP_F77_UNDETERMINED_ARGLIST)
|
||||
+
|
||||
/* Single operand builtins. */
|
||||
OP (UNOP_FORTRAN_KIND)
|
||||
OP (UNOP_FORTRAN_FLOOR)
|
||||
diff --git a/gdb/parse.c b/gdb/parse.c
|
||||
--- a/gdb/parse.c
|
||||
+++ b/gdb/parse.c
|
||||
@@ -817,7 +817,6 @@ operator_length_standard (const struct expression *expr, int endpos,
|
||||
break;
|
||||
|
||||
case OP_FUNCALL:
|
||||
- case OP_F77_UNDETERMINED_ARGLIST:
|
||||
oplen = 3;
|
||||
args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
|
||||
break;
|
||||
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
|
||||
--- a/gdb/parser-defs.h
|
||||
+++ b/gdb/parser-defs.h
|
||||
@@ -338,6 +338,13 @@ extern int dump_subexp (struct expression *, struct ui_file *, int);
|
||||
extern int dump_subexp_body_standard (struct expression *,
|
||||
struct ui_file *, int);
|
||||
|
||||
+/* Dump (to STREAM) a function call like expression at position ELT in the
|
||||
+ expression array EXP. Return a new value for ELT just after the
|
||||
+ function call expression. */
|
||||
+
|
||||
+extern int dump_subexp_body_funcall (struct expression *exp,
|
||||
+ struct ui_file *stream, int elt);
|
||||
+
|
||||
extern void operator_length (const struct expression *, int, int *, int *);
|
||||
|
||||
extern void operator_length_standard (const struct expression *, int, int *,
|
||||
@@ -440,6 +447,15 @@ extern void print_subexp (struct expression *, int *, struct ui_file *,
|
||||
extern void print_subexp_standard (struct expression *, int *,
|
||||
struct ui_file *, enum precedence);
|
||||
|
||||
+/* Print a function call like expression to STREAM. This is called as a
|
||||
+ helper function by which point the expression node identifying this as a
|
||||
+ function call has already been stripped off and POS should point to the
|
||||
+ number of function call arguments. EXP is the object containing the
|
||||
+ list of expression elements. */
|
||||
+
|
||||
+extern void print_subexp_funcall (struct expression *exp, int *pos,
|
||||
+ struct ui_file *stream);
|
||||
+
|
||||
/* Function used to avoid direct calls to fprintf
|
||||
in the code generated by the bison parser. */
|
||||
|
||||
diff --git a/gdb/std-operator.def b/gdb/std-operator.def
|
||||
--- a/gdb/std-operator.def
|
||||
+++ b/gdb/std-operator.def
|
||||
@@ -168,14 +168,6 @@ OP (OP_FUNCALL)
|
||||
pointer. This is an Objective C message. */
|
||||
OP (OP_OBJC_MSGCALL)
|
||||
|
||||
-/* This is EXACTLY like OP_FUNCALL but is semantically different.
|
||||
- In F77, array subscript expressions, substring expressions and
|
||||
- function calls are all exactly the same syntactically. They
|
||||
- may only be disambiguated at runtime. Thus this operator,
|
||||
- which indicates that we have found something of the form
|
||||
- <name> ( <stuff> ). */
|
||||
-OP (OP_F77_UNDETERMINED_ARGLIST)
|
||||
-
|
||||
/* OP_COMPLEX takes a type in the following element, followed by another
|
||||
OP_COMPLEX, making three exp_elements. It is followed by two double
|
||||
args, and converts them into a complex number of the given type. */
|
@ -1,51 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Bruno Larsen <blarsen@redhat.com>
|
||||
Date: Wed, 22 Sep 2021 12:29:11 -0300
|
||||
Subject: gdb-rhbz1970741-early-exit-for-empty-debuginfod-url.patch
|
||||
|
||||
;;[gdb] Improve early exits for env var in debuginfod-support.c
|
||||
;;(Tom de Vries)
|
||||
|
||||
There's an early exit in libdebuginfod's debuginfod_query_server, which checks
|
||||
both for:
|
||||
- getenv (DEBUGINFOD_URLS_ENV_VAR) == NULL, and
|
||||
- (getenv (DEBUGINFOD_URLS_ENV_VAR))[0] == '\0'.
|
||||
|
||||
In debuginfod_source_query and debuginfod_debuginfo_query (which both
|
||||
end up calling debuginfod_query_server) there are also early exits checking
|
||||
the same env var, but those just check for NULL.
|
||||
|
||||
Make the early exit tests in debuginfod-support.c match those in
|
||||
libdebuginfod.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
2020-11-18 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
* debuginfod-support.c (debuginfod_source_query)
|
||||
(debuginfod_debuginfo_query): Also do early exit if
|
||||
"(getenv (DEBUGINFOD_URLS_ENV_VAR))[0] == '\0'".
|
||||
|
||||
diff --git a/gdb/debuginfod-support.c b/gdb/debuginfod-support.c
|
||||
--- a/gdb/debuginfod-support.c
|
||||
+++ b/gdb/debuginfod-support.c
|
||||
@@ -98,7 +98,8 @@ debuginfod_source_query (const unsigned char *build_id,
|
||||
const char *srcpath,
|
||||
gdb::unique_xmalloc_ptr<char> *destname)
|
||||
{
|
||||
- if (getenv (DEBUGINFOD_URLS_ENV_VAR) == NULL)
|
||||
+ const char *urls_env_var = getenv (DEBUGINFOD_URLS_ENV_VAR);
|
||||
+ if (urls_env_var == NULL || urls_env_var[0] == '\0')
|
||||
return scoped_fd (-ENOSYS);
|
||||
|
||||
debuginfod_client *c = debuginfod_init ();
|
||||
@@ -135,7 +136,8 @@ debuginfod_debuginfo_query (const unsigned char *build_id,
|
||||
const char *filename,
|
||||
gdb::unique_xmalloc_ptr<char> *destname)
|
||||
{
|
||||
- if (getenv (DEBUGINFOD_URLS_ENV_VAR) == NULL)
|
||||
+ const char *urls_env_var = getenv (DEBUGINFOD_URLS_ENV_VAR);
|
||||
+ if (urls_env_var == NULL || urls_env_var[0] == '\0')
|
||||
return scoped_fd (-ENOSYS);
|
||||
|
||||
debuginfod_client *c = debuginfod_init ();
|
@ -1,307 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 14 Jun 2021 19:12:06 -0700
|
||||
Subject: gdb-rhbz1971096-glibc2.34-1.patch
|
||||
|
||||
;; Backport patch fixing gdb on glibc-2.34 machines with regard to attaching
|
||||
;; to processes (RH BZ 1971096).
|
||||
|
||||
gdb: try to load libthread_db only after reading all shared libraries when attaching / handling a fork child
|
||||
|
||||
When trying to attach to a pthread process on a Linux system with glibc 2.33,
|
||||
we get:
|
||||
|
||||
$ ./gdb -q -nx --data-directory=data-directory -p 1472010
|
||||
Attaching to process 1472010
|
||||
[New LWP 1472013]
|
||||
[New LWP 1472014]
|
||||
[New LWP 1472015]
|
||||
Error while reading shared library symbols for /usr/lib/libpthread.so.0:
|
||||
Cannot find user-level thread for LWP 1472015: generic error
|
||||
0x00007ffff6d3637f in poll () from /usr/lib/libc.so.6
|
||||
(gdb)
|
||||
|
||||
When attaching to a process (or handling a fork child, an operation very
|
||||
similar to attaching), GDB reads the shared library list from the
|
||||
process. For each shared library (if "set auto-solib-add" is on), it
|
||||
reads its symbols and calls the "new_objfile" observable.
|
||||
|
||||
The libthread-db code monitors this observable, and if it sees an
|
||||
objfile named somewhat like "libpthread.so" go by, it tries to load
|
||||
libthread_db.so in the GDB process itself. libthread_db knows how to
|
||||
navigate libpthread's data structures to get information about the
|
||||
existing threads.
|
||||
|
||||
To locate these data structures, libthread_db calls ps_pglobal_lookup
|
||||
(implemented in proc-service.c), passing in a symbol name and expecting
|
||||
an address in return.
|
||||
|
||||
Before glibc 2.33, libthread_db always asked for symbols found in
|
||||
libpthread. There was no ordering problem: since we were always trying
|
||||
to load libthread_db in reaction to processing libpthread (and reading
|
||||
in its symbols) and libthread_db only asked symbols from libpthread, the
|
||||
requested symbols could always be found. Starting with glibc 2.33,
|
||||
libthread_db now asks for a symbol name that can be found in
|
||||
/lib/ld-linux-x86-64.so.2 (_rtld_global). And the ordering in which GDB
|
||||
reads the shared libraries from the inferior when attaching is
|
||||
unfortunate, in that libpthread is processed before ld-linux. So when
|
||||
loading libthread_db in reaction to processing libpthread, and
|
||||
libthread_db requests the symbol that is from ld-linux, GDB is not yet
|
||||
able to supply it.
|
||||
|
||||
That problematic symbol lookup happens in the thread_from_lwp function,
|
||||
when we call td_ta_map_lwp2thr_p, and an exception is thrown at this
|
||||
point:
|
||||
|
||||
#0 0x00007ffff6681012 in __cxxabiv1::__cxa_throw (obj=0x60e000006100, tinfo=0x555560033b50 <typeinfo for gdb_exception_error>, dest=0x55555d9404bc <gdb_exception_error::~gdb_exception_error()>) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:78
|
||||
#1 0x000055555e5d3734 in throw_it(return_reason, errors, const char *, typedef __va_list_tag __va_list_tag *) (reason=RETURN_ERROR, error=GENERIC_ERROR, fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", ap=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdbsupport/common-exceptions.cc:200
|
||||
#2 0x000055555e5d37d4 in throw_verror (error=GENERIC_ERROR, fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", ap=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdbsupport/common-exceptions.cc:208
|
||||
#3 0x000055555e0b0ed2 in verror (string=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", args=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdb/utils.c:171
|
||||
#4 0x000055555e5e898a in error (fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s") at /home/simark/src/binutils-gdb/gdbsupport/errors.cc:43
|
||||
#5 0x000055555d06b4bc in thread_from_lwp (stopped=0x617000035d80, ptid=...) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:418
|
||||
#6 0x000055555d07040d in try_thread_db_load_1 (info=0x60c000011140) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:912
|
||||
#7 0x000055555d071103 in try_thread_db_load (library=0x55555f0c62a0 "libthread_db.so.1", check_auto_load_safe=false) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1014
|
||||
#8 0x000055555d072168 in try_thread_db_load_from_sdir () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1091
|
||||
#9 0x000055555d072d1c in thread_db_load_search () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1146
|
||||
#10 0x000055555d07365c in thread_db_load () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1203
|
||||
#11 0x000055555d07373e in check_for_thread_db () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1246
|
||||
#12 0x000055555d0738ab in thread_db_new_objfile (objfile=0x61300000c0c0) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1275
|
||||
#13 0x000055555bd10740 in std::__invoke_impl<void, void (*&)(objfile*), objfile*> (__f=@0x616000068d88: 0x55555d073745 <thread_db_new_objfile(objfile*)>) at /usr/include/c++/10.2.0/bits/invoke.h:60
|
||||
#14 0x000055555bd02096 in std::__invoke_r<void, void (*&)(objfile*), objfile*> (__fn=@0x616000068d88: 0x55555d073745 <thread_db_new_objfile(objfile*)>) at /usr/include/c++/10.2.0/bits/invoke.h:153
|
||||
#15 0x000055555bce0392 in std::_Function_handler<void (objfile*), void (*)(objfile*)>::_M_invoke(std::_Any_data const&, objfile*&&) (__functor=..., __args#0=@0x7fffffffb4a0: 0x61300000c0c0) at /usr/include/c++/10.2.0/bits/std_function.h:291
|
||||
#16 0x000055555d3595c0 in std::function<void (objfile*)>::operator()(objfile*) const (this=0x616000068d88, __args#0=0x61300000c0c0) at /usr/include/c++/10.2.0/bits/std_function.h:622
|
||||
#17 0x000055555d356b7f in gdb::observers::observable<objfile*>::notify (this=0x555566727020 <gdb::observers::new_objfile>, args#0=0x61300000c0c0) at /home/simark/src/binutils-gdb/gdb/../gdbsupport/observable.h:106
|
||||
#18 0x000055555da3f228 in symbol_file_add_with_addrs (abfd=0x61200001ccc0, name=0x6190000d9090 "/usr/lib/libpthread.so.0", add_flags=..., addrs=0x7fffffffbc10, flags=..., parent=0x0) at /home/simark/src/binutils-gdb/gdb/symfile.c:1131
|
||||
#19 0x000055555da3f763 in symbol_file_add_from_bfd (abfd=0x61200001ccc0, name=0x6190000d9090 "/usr/lib/libpthread.so.0", add_flags=<error reading variable: Cannot access memory at address 0xffffffffffffffb0>, addrs=0x7fffffffbc10, flags=<error reading variable: Cannot access memory at address 0xffffffffffffffc0>, parent=0x0) at /home/simark/src/binutils-gdb/gdb/symfile.c:1167
|
||||
#20 0x000055555d95f9fa in solib_read_symbols (so=0x6190000d8e80, flags=...) at /home/simark/src/binutils-gdb/gdb/solib.c:681
|
||||
#21 0x000055555d96233d in solib_add (pattern=0x0, from_tty=0, readsyms=1) at /home/simark/src/binutils-gdb/gdb/solib.c:987
|
||||
#22 0x000055555d93646e in enable_break (info=0x608000008f20, from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:2238
|
||||
#23 0x000055555d93cfc0 in svr4_solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:3049
|
||||
#24 0x000055555d96610d in solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib.c:1195
|
||||
#25 0x000055555cdee318 in post_create_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:318
|
||||
#26 0x000055555ce00e6e in setup_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:2439
|
||||
#27 0x000055555ce59c34 in handle_one (event=...) at /home/simark/src/binutils-gdb/gdb/infrun.c:4887
|
||||
#28 0x000055555ce5cd00 in stop_all_threads () at /home/simark/src/binutils-gdb/gdb/infrun.c:5064
|
||||
#29 0x000055555ce7f0da in stop_waiting (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:8006
|
||||
#30 0x000055555ce67f5c in handle_signal_stop (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:6062
|
||||
#31 0x000055555ce63653 in handle_inferior_event (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:5727
|
||||
#32 0x000055555ce4f297 in fetch_inferior_event () at /home/simark/src/binutils-gdb/gdb/infrun.c:4105
|
||||
#33 0x000055555cdbe3bf in inferior_event_handler (event_type=INF_REG_EVENT) at /home/simark/src/binutils-gdb/gdb/inf-loop.c:42
|
||||
#34 0x000055555d018047 in handle_target_event (error=0, client_data=0x0) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:4060
|
||||
#35 0x000055555e5ea77e in handle_file_event (file_ptr=0x60600008b1c0, ready_mask=1) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:575
|
||||
#36 0x000055555e5eb09c in gdb_wait_for_event (block=0) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:701
|
||||
#37 0x000055555e5e8d19 in gdb_do_one_event () at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:212
|
||||
#38 0x000055555dd6e0d4 in wait_sync_command_done () at /home/simark/src/binutils-gdb/gdb/top.c:528
|
||||
#39 0x000055555dd6e372 in maybe_wait_sync_command_done (was_sync=0) at /home/simark/src/binutils-gdb/gdb/top.c:545
|
||||
#40 0x000055555d0ec7c8 in catch_command_errors (command=0x55555ce01bb8 <attach_command(char const*, int)>, arg=0x7fffffffe28d "1472010", from_tty=1, do_bp_actions=false) at /home/simark/src/binutils-gdb/gdb/main.c:452
|
||||
#41 0x000055555d0f03ad in captured_main_1 (context=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1149
|
||||
#42 0x000055555d0f1239 in captured_main (data=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1232
|
||||
#43 0x000055555d0f1315 in gdb_main (args=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1257
|
||||
#44 0x000055555bb70cf9 in main (argc=7, argv=0x7fffffffde88) at /home/simark/src/binutils-gdb/gdb/gdb.c:32
|
||||
|
||||
The exception is caught here:
|
||||
|
||||
#0 __cxxabiv1::__cxa_begin_catch (exc_obj_in=0x60e0000060e0) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_catch.cc:84
|
||||
#1 0x000055555d95fded in solib_read_symbols (so=0x6190000d8e80, flags=...) at /home/simark/src/binutils-gdb/gdb/solib.c:689
|
||||
#2 0x000055555d96233d in solib_add (pattern=0x0, from_tty=0, readsyms=1) at /home/simark/src/binutils-gdb/gdb/solib.c:987
|
||||
#3 0x000055555d93646e in enable_break (info=0x608000008f20, from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:2238
|
||||
#4 0x000055555d93cfc0 in svr4_solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:3049
|
||||
#5 0x000055555d96610d in solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib.c:1195
|
||||
#6 0x000055555cdee318 in post_create_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:318
|
||||
#7 0x000055555ce00e6e in setup_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:2439
|
||||
#8 0x000055555ce59c34 in handle_one (event=...) at /home/simark/src/binutils-gdb/gdb/infrun.c:4887
|
||||
#9 0x000055555ce5cd00 in stop_all_threads () at /home/simark/src/binutils-gdb/gdb/infrun.c:5064
|
||||
#10 0x000055555ce7f0da in stop_waiting (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:8006
|
||||
#11 0x000055555ce67f5c in handle_signal_stop (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:6062
|
||||
#12 0x000055555ce63653 in handle_inferior_event (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:5727
|
||||
#13 0x000055555ce4f297 in fetch_inferior_event () at /home/simark/src/binutils-gdb/gdb/infrun.c:4105
|
||||
#14 0x000055555cdbe3bf in inferior_event_handler (event_type=INF_REG_EVENT) at /home/simark/src/binutils-gdb/gdb/inf-loop.c:42
|
||||
#15 0x000055555d018047 in handle_target_event (error=0, client_data=0x0) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:4060
|
||||
#16 0x000055555e5ea77e in handle_file_event (file_ptr=0x60600008b1c0, ready_mask=1) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:575
|
||||
#17 0x000055555e5eb09c in gdb_wait_for_event (block=0) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:701
|
||||
#18 0x000055555e5e8d19 in gdb_do_one_event () at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:212
|
||||
#19 0x000055555dd6e0d4 in wait_sync_command_done () at /home/simark/src/binutils-gdb/gdb/top.c:528
|
||||
#20 0x000055555dd6e372 in maybe_wait_sync_command_done (was_sync=0) at /home/simark/src/binutils-gdb/gdb/top.c:545
|
||||
#21 0x000055555d0ec7c8 in catch_command_errors (command=0x55555ce01bb8 <attach_command(char const*, int)>, arg=0x7fffffffe28d "1472010", from_tty=1, do_bp_actions=false) at /home/simark/src/binutils-gdb/gdb/main.c:452
|
||||
#22 0x000055555d0f03ad in captured_main_1 (context=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1149
|
||||
#23 0x000055555d0f1239 in captured_main (data=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1232
|
||||
#24 0x000055555d0f1315 in gdb_main (args=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1257
|
||||
#25 0x000055555bb70cf9 in main (argc=7, argv=0x7fffffffde88) at /home/simark/src/binutils-gdb/gdb/gdb.c:32
|
||||
|
||||
Catching the exception at this point means that the thread_db_info
|
||||
object for this inferior will be left in place, despite the failure to
|
||||
load libthread_db. This means that there won't be further attempts at
|
||||
loading libthread_db, because thread_db_load will think that
|
||||
libthread_db is already loaded for this inferior and will always exit
|
||||
early. To fix this, add a try/catch around calling try_thread_db_load_1
|
||||
in try_thread_db_load, such that if some exception is thrown while
|
||||
trying to load libthread_db, we reset / delete the thread_db_info for
|
||||
that inferior. That alone makes attach work fine again, because
|
||||
check_for_thread_db is called again in the thread_db_inferior_created
|
||||
observer (that happens after we learned about all shared libraries and
|
||||
their symbols), and libthread_db is successfully loaded then.
|
||||
|
||||
When attaching, I think that the inferior_created observer is a good
|
||||
place to try to load libthread_db: it is called once everything has
|
||||
stabilized, when we learned about all shared libraries.
|
||||
|
||||
The only problem then is that when we first try (and fail) to load
|
||||
libthread_db, in reaction to learning about libpthread, we show this
|
||||
warning:
|
||||
|
||||
warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.
|
||||
|
||||
This is misleading, because we do succeed in loading it later. So when
|
||||
attaching, I think we shouldn't try to load libthread_db in reaction to
|
||||
the new_objfile events, we should wait until we have learned about all
|
||||
shared libraries (using the inferior_created observable). To do so, add
|
||||
an `in_initial_library_scan` flag to struct inferior. This flag is used
|
||||
to postpone loading libthread_db if we are attaching or handling a fork
|
||||
child.
|
||||
|
||||
When debugging remotely with GDBserver, the same problem happens, except
|
||||
that the qSymbol mechanism (allowing the remote side to ask GDB for
|
||||
symbols values) is involved. The fix there is the same idea, we make
|
||||
GDB wait until all shared libraries and their symbols are known before
|
||||
sending out a qSymbol packet. This way, we never present the remote
|
||||
side a state where libpthread.so's symbols are known but ld-linux's
|
||||
symbols aren't.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* inferior.h (class inferior) <in_initial_library_scan>: New.
|
||||
* infcmd.c (post_create_inferior): Set in_initial_library_scan.
|
||||
* infrun.c (follow_fork_inferior): Likewise.
|
||||
* linux-thread-db.c (try_thread_db_load): Catch exception thrown
|
||||
by try_thread_db_load_1
|
||||
(thread_db_load): Return early if in_initial_library_scan is
|
||||
set.
|
||||
* remote.c (remote_new_objfile): Return early if
|
||||
in_initial_library_scan is set.
|
||||
|
||||
Change-Id: I7a279836cfbb2b362b4fde11b196b4aab82f5efb
|
||||
|
||||
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
|
||||
--- a/gdb/infcmd.c
|
||||
+++ b/gdb/infcmd.c
|
||||
@@ -313,6 +313,10 @@ post_create_inferior (struct target_ops *target, int from_tty)
|
||||
const unsigned solib_add_generation
|
||||
= current_program_space->solib_add_generation;
|
||||
|
||||
+ scoped_restore restore_in_initial_library_scan
|
||||
+ = make_scoped_restore (¤t_inferior ()->in_initial_library_scan,
|
||||
+ true);
|
||||
+
|
||||
/* Create the hooks to handle shared library load and unload
|
||||
events. */
|
||||
solib_create_inferior_hook (from_tty);
|
||||
diff --git a/gdb/inferior.h b/gdb/inferior.h
|
||||
--- a/gdb/inferior.h
|
||||
+++ b/gdb/inferior.h
|
||||
@@ -511,6 +511,10 @@ class inferior : public refcounted_object
|
||||
architecture/description. */
|
||||
bool needs_setup = false;
|
||||
|
||||
+ /* True when we are reading the library list of the inferior during an
|
||||
+ attach or handling a fork child. */
|
||||
+ bool in_initial_library_scan = false;
|
||||
+
|
||||
/* Private data used by the target vector implementation. */
|
||||
std::unique_ptr<private_inferior> priv;
|
||||
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -540,6 +540,9 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
breakpoint. If a "cloned-VM" event was propagated
|
||||
better throughout the core, this wouldn't be
|
||||
required. */
|
||||
+ scoped_restore restore_in_initial_library_scan
|
||||
+ = make_scoped_restore (&child_inf->in_initial_library_scan,
|
||||
+ true);
|
||||
solib_create_inferior_hook (0);
|
||||
}
|
||||
}
|
||||
@@ -675,6 +678,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
shared libraries, and install the solib event breakpoint.
|
||||
If a "cloned-VM" event was propagated better throughout
|
||||
the core, this wouldn't be required. */
|
||||
+ scoped_restore restore_in_initial_library_scan
|
||||
+ = make_scoped_restore (&child_inf->in_initial_library_scan, true);
|
||||
solib_create_inferior_hook (0);
|
||||
}
|
||||
|
||||
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
|
||||
--- a/gdb/linux-thread-db.c
|
||||
+++ b/gdb/linux-thread-db.c
|
||||
@@ -1012,8 +1012,17 @@ try_thread_db_load (const char *library, bool check_auto_load_safe)
|
||||
if (strchr (library, '/') != NULL)
|
||||
info->filename = gdb_realpath (library).release ();
|
||||
|
||||
- if (try_thread_db_load_1 (info))
|
||||
- return true;
|
||||
+ try
|
||||
+ {
|
||||
+ if (try_thread_db_load_1 (info))
|
||||
+ return true;
|
||||
+ }
|
||||
+ catch (const gdb_exception_error &except)
|
||||
+ {
|
||||
+ if (libthread_db_debug)
|
||||
+ exception_fprintf (gdb_stdlog, except,
|
||||
+ "Warning: While trying to load libthread_db: ");
|
||||
+ }
|
||||
|
||||
/* This library "refused" to work on current inferior. */
|
||||
delete_thread_db_info (current_inferior ()->process_target (),
|
||||
@@ -1184,10 +1193,15 @@ has_libpthread (void)
|
||||
static bool
|
||||
thread_db_load (void)
|
||||
{
|
||||
- struct thread_db_info *info;
|
||||
+ inferior *inf = current_inferior ();
|
||||
|
||||
- info = get_thread_db_info (current_inferior ()->process_target (),
|
||||
- inferior_ptid.pid ());
|
||||
+ /* When attaching / handling fork child, don't try loading libthread_db
|
||||
+ until we know about all shared libraries. */
|
||||
+ if (inf->in_initial_library_scan)
|
||||
+ return false;
|
||||
+
|
||||
+ thread_db_info *info = get_thread_db_info (inf->process_target (),
|
||||
+ inferior_ptid.pid ());
|
||||
|
||||
if (info != NULL)
|
||||
return true;
|
||||
diff --git a/gdb/remote.c b/gdb/remote.c
|
||||
--- a/gdb/remote.c
|
||||
+++ b/gdb/remote.c
|
||||
@@ -14299,8 +14299,26 @@ remote_new_objfile (struct objfile *objfile)
|
||||
{
|
||||
remote_target *remote = get_current_remote_target ();
|
||||
|
||||
- if (remote != NULL) /* Have a remote connection. */
|
||||
- remote->remote_check_symbols ();
|
||||
+ /* First, check whether the current inferior's process target is a remote
|
||||
+ target. */
|
||||
+ if (remote == nullptr)
|
||||
+ return;
|
||||
+
|
||||
+ /* When we are attaching or handling a fork child and the shared library
|
||||
+ subsystem reads the list of loaded libraries, we receive new objfile
|
||||
+ events in between each found library. The libraries are read in an
|
||||
+ undefined order, so if we gave the remote side a chance to look up
|
||||
+ symbols between each objfile, we might give it an inconsistent picture
|
||||
+ of the inferior. It could appear that a library A appears loaded but
|
||||
+ a library B does not, even though library A requires library B. That
|
||||
+ would present a state that couldn't normally exist in the inferior.
|
||||
+
|
||||
+ So, skip these events, we'll give the remote a chance to look up symbols
|
||||
+ once all the loaded libraries and their symbols are known to GDB. */
|
||||
+ if (current_inferior ()->in_initial_library_scan)
|
||||
+ return;
|
||||
+
|
||||
+ remote->remote_check_symbols ();
|
||||
}
|
||||
|
||||
/* Pull all the tracepoints defined on the target and create local
|
@ -1,149 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 14 Jun 2021 19:20:07 -0700
|
||||
Subject: gdb-rhbz1971096-glibc2.34-2.patch
|
||||
|
||||
;; Backport patch fixing gdb on glibc-2.34 machines w/ regard to
|
||||
;; libthread_db initialization.
|
||||
|
||||
libthread_db initialization changes related to upcoming glibc-2.34
|
||||
|
||||
This commit makes some adjustments to accomodate the upcoming
|
||||
glibc-2.34 release. Beginning with glibc-2.34, functionality formerly
|
||||
contained in libpthread has been moved to libc. For the time being,
|
||||
libpthread.so still exists in the file system, but it won't show up in
|
||||
ldd output and therefore won't be able to trigger initialization of
|
||||
libthread_db related code. E.g...
|
||||
|
||||
Fedora 34 / glibc-2.33.9000:
|
||||
|
||||
[kev@f34-2 gdb]$ ldd testsuite/outputs/gdb.threads/tls/tls
|
||||
linux-vdso.so.1 (0x00007ffcf94fa000)
|
||||
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007ff0ba9af000)
|
||||
libm.so.6 => /lib64/libm.so.6 (0x00007ff0ba8d4000)
|
||||
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007ff0ba8b9000)
|
||||
libc.so.6 => /lib64/libc.so.6 (0x00007ff0ba6c6000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x00007ff0babf0000)
|
||||
|
||||
Fedora 34 / glibc-2.33:
|
||||
|
||||
[kev@f34-1 gdb]$ ldd testsuite/outputs/gdb.threads/tls/tls
|
||||
linux-vdso.so.1 (0x00007fff32dc0000)
|
||||
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f815f6de000)
|
||||
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f815f4bf000)
|
||||
libm.so.6 => /lib64/libm.so.6 (0x00007f815f37b000)
|
||||
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f815f360000)
|
||||
libc.so.6 => /lib64/libc.so.6 (0x00007f815f191000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x00007f815f721000)
|
||||
|
||||
Note that libpthread is missing from the ldd output for the
|
||||
glibc-2.33.9000 machine.
|
||||
|
||||
This means that (unless we happen to think of some entirely different
|
||||
mechanism), we'll now need to potentially match "libc" in addition to
|
||||
"libpthread" as libraries which might be thread libraries. This
|
||||
accounts for the change made in solib.c. Note that the new code
|
||||
attempts to match "/libc." via strstr(). That trailing dot (".")
|
||||
avoids inadvertently matching libraries such as libcrypt (and
|
||||
all the other many libraries which begin with "libc").
|
||||
|
||||
To avoid attempts to load libthread_db when encountering older
|
||||
versions of libc, we now attempt to find "pthread_create" (which is a
|
||||
symbol that we'd expect to be in any pthread library) in the
|
||||
associated objfile. This accounts for the changes in
|
||||
linux-thread-db.c.
|
||||
|
||||
I think that other small adjustments will need to be made elsewhere
|
||||
too. I've been working through regressions on my glibc-2.33.9000
|
||||
machine; I've fixed some fairly "obvious" changes in the testsuite
|
||||
(which are in other commits). For the rest, it's not yet clear to me
|
||||
whether the handful of remaining failures represent a problem in glibc
|
||||
or gdb. I'm still investigating, however, I'll note that these are
|
||||
problems that I only see on my glibc-2.33.9000 machine.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
* solib.c (libpthread_name_p): Match "libc" in addition
|
||||
to "libpthread".
|
||||
* linux-thread-db.c (libpthread_objfile_p): New function.
|
||||
(libpthread_name_p): Adjust preexisting callers to use
|
||||
libpthread_objfile_p().
|
||||
|
||||
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
|
||||
--- a/gdb/linux-thread-db.c
|
||||
+++ b/gdb/linux-thread-db.c
|
||||
@@ -800,6 +800,24 @@ check_thread_db (struct thread_db_info *info, bool log_progress)
|
||||
return test_passed;
|
||||
}
|
||||
|
||||
+/* Predicate which tests whether objfile OBJ refers to the library
|
||||
+ containing pthread related symbols. Historically, this library has
|
||||
+ been named in such a way that looking for "libpthread" in the name
|
||||
+ was sufficient to identify it. As of glibc-2.34, the C library
|
||||
+ (libc) contains the thread library symbols. Therefore we check
|
||||
+ that the name matches a possible thread library, but we also check
|
||||
+ that it contains at least one of the symbols (pthread_create) that
|
||||
+ we'd expect to find in the thread library. */
|
||||
+
|
||||
+static bool
|
||||
+libpthread_objfile_p (objfile *obj)
|
||||
+{
|
||||
+ return (libpthread_name_p (objfile_name (obj))
|
||||
+ && lookup_minimal_symbol ("pthread_create",
|
||||
+ NULL,
|
||||
+ obj).minsym != NULL);
|
||||
+}
|
||||
+
|
||||
/* Attempt to initialize dlopen()ed libthread_db, described by INFO.
|
||||
Return true on success.
|
||||
Failure could happen if libthread_db does not have symbols we expect,
|
||||
@@ -1072,7 +1090,7 @@ try_thread_db_load_from_pdir (const char *subdir)
|
||||
return false;
|
||||
|
||||
for (objfile *obj : current_program_space->objfiles ())
|
||||
- if (libpthread_name_p (objfile_name (obj)))
|
||||
+ if (libpthread_objfile_p (obj))
|
||||
{
|
||||
if (try_thread_db_load_from_pdir_1 (obj, subdir))
|
||||
return true;
|
||||
@@ -1181,7 +1199,7 @@ static bool
|
||||
has_libpthread (void)
|
||||
{
|
||||
for (objfile *obj : current_program_space->objfiles ())
|
||||
- if (libpthread_name_p (objfile_name (obj)))
|
||||
+ if (libpthread_objfile_p (obj))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -1295,7 +1313,7 @@ thread_db_new_objfile (struct objfile *objfile)
|
||||
of the list of shared libraries to load, and in an app of several
|
||||
thousand shared libraries, this can otherwise be painful. */
|
||||
&& ((objfile->flags & OBJF_MAINLINE) != 0
|
||||
- || libpthread_name_p (objfile_name (objfile))))
|
||||
+ || libpthread_objfile_p (objfile)))
|
||||
check_for_thread_db ();
|
||||
}
|
||||
|
||||
diff --git a/gdb/solib.c b/gdb/solib.c
|
||||
--- a/gdb/solib.c
|
||||
+++ b/gdb/solib.c
|
||||
@@ -906,12 +906,17 @@ Do you need \"set solib-search-path\" or \"set sysroot\"?"),
|
||||
|
||||
Uses a fairly simplistic heuristic approach where we check
|
||||
the file name against "/libpthread". This can lead to false
|
||||
- positives, but this should be good enough in practice. */
|
||||
+ positives, but this should be good enough in practice.
|
||||
+
|
||||
+ As of glibc-2.34, functions formerly residing in libpthread have
|
||||
+ been moved to libc, so "/libc." needs to be checked too. (Matching
|
||||
+ the "." will avoid matching libraries such as libcrypt.) */
|
||||
|
||||
bool
|
||||
libpthread_name_p (const char *name)
|
||||
{
|
||||
- return (strstr (name, "/libpthread") != NULL);
|
||||
+ return (strstr (name, "/libpthread") != NULL
|
||||
+ || strstr (name, "/libc.") != NULL );
|
||||
}
|
||||
|
||||
/* Return non-zero if SO is the libpthread shared library. */
|
@ -1,72 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 14 Jun 2021 19:24:41 -0700
|
||||
Subject: gdb-rhbz1971096-glibc2.34-3.patch
|
||||
|
||||
;; Backport testsuite patch for matching new libthread_db related output
|
||||
;; when testing gdb on glibc-2.34 matchines (RH BZ 1971096).
|
||||
|
||||
testsuite/glib-2.34: Match/consume optional libthread_db related output
|
||||
|
||||
When using glibc-2.34, we now see messages related to the loading of
|
||||
the thread library for non-thread programs. E.g. for the test case,
|
||||
gdb.base/execl-update-breakpoints.exp, we will see the following when
|
||||
starting the program:
|
||||
|
||||
(gdb) break -qualified main
|
||||
Breakpoint 1 at 0x100118c: file /ironwood1/sourceware-git/f34-2-glibc244_fix/bld/../../worktree-glibc244_fix/gdb/testsuite/gdb.base/execl-update-breakpoints.c, line 34.
|
||||
(gdb) run
|
||||
Starting program: [...]/execl-update-breakpoints1
|
||||
[Thread debugging using libthread_db enabled]
|
||||
Using host libthread_db library "/lib64/libthread_db.so.1".
|
||||
|
||||
The two lines of output related to libthread_db are new; we didn't see
|
||||
these in the past. This is a side effect of libc now containing the
|
||||
pthread API - we can no longer tell whether the program is
|
||||
multi-threaded by simply looking for libpthread.so. That said, I
|
||||
think that we now want to load libthread_db anyway since it's used to
|
||||
resolve TLS variables; i.e. we need it for correctly determining the
|
||||
value of errno.
|
||||
|
||||
This commit adds the necessary regular expressions to match this
|
||||
(optional) additional output in the two tests which were failing
|
||||
without it.
|
||||
|
||||
gdb/testsuite/ChangeLog:
|
||||
|
||||
* gdb.base/execl-update-breakpoints.exp: Add regular
|
||||
expression for optionally matching output related to
|
||||
libthread_db.
|
||||
* gdb.base/fork-print-inferior-events.exp: Likewise.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/execl-update-breakpoints.exp b/gdb/testsuite/gdb.base/execl-update-breakpoints.exp
|
||||
--- a/gdb/testsuite/gdb.base/execl-update-breakpoints.exp
|
||||
+++ b/gdb/testsuite/gdb.base/execl-update-breakpoints.exp
|
||||
@@ -132,6 +132,7 @@ proc test { always_inserted } {
|
||||
"Continuing\\.\r\n" \
|
||||
"${not_nl} is executing new program: ${not_nl}\r\n" \
|
||||
"(Reading ${not_nl} from remote target\\.\\.\\.\r\n)*" \
|
||||
+ "(?:.Thread debugging using .*? enabled.\r\nUsing .*? library .*?\\.\r\n)?" \
|
||||
"\r\n" \
|
||||
"Breakpoint 1, main.*$gdb_prompt $"
|
||||
set message "continue across exec"
|
||||
diff --git a/gdb/testsuite/gdb.base/fork-print-inferior-events.exp b/gdb/testsuite/gdb.base/fork-print-inferior-events.exp
|
||||
--- a/gdb/testsuite/gdb.base/fork-print-inferior-events.exp
|
||||
+++ b/gdb/testsuite/gdb.base/fork-print-inferior-events.exp
|
||||
@@ -59,6 +59,7 @@ set detach_child_re "${reading_re}\\\[Detaching after fork from child .*\\\]\r\n
|
||||
set detach_parent_re "${reading_re}\\\[Detaching after fork from parent .*\\\]\r\n"
|
||||
set new_inf_re "${reading_re}\\\[New inferior $decimal \\(.*\\)\\\]\r\n"
|
||||
set inf_detached_re "${reading_re}\\\[Inferior $decimal \\(.*\\) detached\\\]\r\n"
|
||||
+set thread_db_re "(?:\\\[Thread debugging using .*? enabled\\\]\r\nUsing .*? library .*?\\.\r\n)?"
|
||||
|
||||
set expected_output [list \
|
||||
"${attach_child_re}${new_inf_re}${detach_parent_re}${inf_detached_re}" \
|
||||
@@ -84,7 +85,7 @@ foreach_with_prefix print_inferior_events { "on" "off" } {
|
||||
set output [lindex $expected_output $i]
|
||||
# Always add the "Starting program..." string so that we
|
||||
# match exactly the lines we want.
|
||||
- set output "Starting program: $binfile\\s*\r\n${output}${exited_normally_re}"
|
||||
+ set output "Starting program: $binfile\\s*\r\n${thread_db_re}${output}${thread_db_re}${exited_normally_re}"
|
||||
set i [expr $i + 1]
|
||||
gdb_test "run" $output
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 14 Jun 2021 19:29:19 -0700
|
||||
Subject: gdb-rhbz1971096-glibc2.34-4.patch
|
||||
|
||||
;; Backport patch adjusting test gdb.base/print-symbol-loading.exp.
|
||||
;; (RH BZ 1971096).
|
||||
|
||||
print-symbol-loading.exp: Allow libc symbols to be already loaded
|
||||
|
||||
One consequence of changing libpthread_name_p() in solib.c to (also)
|
||||
match libc is that the symbols for libc will now be loaded by
|
||||
solib_add() in solib.c. I think this is mostly harmless because
|
||||
we'll likely want these symbols to be loaded anyway, but it did cause
|
||||
two failures in gdb.base/print-symbol-loading.exp.
|
||||
|
||||
Specifically...
|
||||
|
||||
1)
|
||||
|
||||
sharedlibrary .*
|
||||
(gdb) PASS: gdb.base/print-symbol-loading.exp: shlib off: load shared-lib
|
||||
|
||||
now looks like this:
|
||||
|
||||
sharedlibrary .*
|
||||
Symbols already loaded for /lib64/libc.so.6
|
||||
(gdb) PASS: gdb.base/print-symbol-loading.exp: shlib off: load shared-lib
|
||||
|
||||
2)
|
||||
|
||||
sharedlibrary .*
|
||||
Loading symbols for shared libraries: .*
|
||||
(gdb) PASS: gdb.base/print-symbol-loading.exp: shlib brief: load shared-lib
|
||||
|
||||
now looks like this:
|
||||
|
||||
sharedlibrary .*
|
||||
Loading symbols for shared libraries: .*
|
||||
Symbols already loaded for /lib64/libc.so.6
|
||||
(gdb) PASS: gdb.base/print-symbol-loading.exp: shlib brief: load shared-lib
|
||||
|
||||
Fixing case #2 ended up being easier than #1. #1 had been using
|
||||
gdb_test_no_output to correctly match this no-output case. I
|
||||
ended up replacing it with gdb_test_multiple, matching the exact
|
||||
expected output for each of the two now acceptable cases.
|
||||
|
||||
For case #2, I simply added an optional non-capturing group
|
||||
for the potential new output.
|
||||
|
||||
gdb/testsuite/ChangeLog:
|
||||
|
||||
* gdb.base/print-symbol-loading.exp (proc test_load_shlib):
|
||||
Allow "Symbols already loaded for..." messages.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/print-symbol-loading.exp b/gdb/testsuite/gdb.base/print-symbol-loading.exp
|
||||
--- a/gdb/testsuite/gdb.base/print-symbol-loading.exp
|
||||
+++ b/gdb/testsuite/gdb.base/print-symbol-loading.exp
|
||||
@@ -96,6 +96,7 @@ test_load_core full
|
||||
|
||||
proc test_load_shlib { print_symbol_loading } {
|
||||
global binfile
|
||||
+ global gdb_prompt
|
||||
with_test_prefix "shlib ${print_symbol_loading}" {
|
||||
clean_restart ${binfile}
|
||||
gdb_test_no_output "set auto-solib-add off"
|
||||
@@ -106,12 +107,20 @@ proc test_load_shlib { print_symbol_loading } {
|
||||
set test_name "load shared-lib"
|
||||
switch ${print_symbol_loading} {
|
||||
"off" {
|
||||
- gdb_test_no_output "sharedlibrary .*" \
|
||||
- ${test_name}
|
||||
+ set cmd "sharedlibrary .*"
|
||||
+ set cmd_regex [string_to_regexp $cmd]
|
||||
+ gdb_test_multiple $cmd $test_name {
|
||||
+ -re "^$cmd_regex\r\n$gdb_prompt $" {
|
||||
+ pass $test_name
|
||||
+ }
|
||||
+ -re "^$cmd_regex\r\nSymbols already loaded for\[^\r\n\]*\\/libc\\.\[^\r\n\]*\r\n$gdb_prompt $" {
|
||||
+ pass $test_name
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
"brief" {
|
||||
gdb_test "sharedlibrary .*" \
|
||||
- "Loading symbols for shared libraries: \\.\\*" \
|
||||
+ "Loading symbols for shared libraries: \\.\\*.*?(?:Symbols already loaded for .*?libc)?" \
|
||||
${test_name}
|
||||
}
|
||||
"full" {
|
@ -1,86 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 14 Jun 2021 19:32:12 -0700
|
||||
Subject: gdb-rhbz1971096-glibc2.34-5.patch
|
||||
|
||||
;; Backport patch adjusting test gdb.mi/mi-sym-info.exp (RH BZ 1971096).
|
||||
|
||||
mi-sym-info.exp: Increase timeout for 114-symbol-info-functions
|
||||
|
||||
Loading libc.so's symbols increased the amount of time needed for
|
||||
114-symbol-info-function to fetch symbols, causing a timeout during my
|
||||
testing. I enclosed the entire block with a "with_timeout_factor 4",
|
||||
which fixes the problem for me. (Using 2 also fixed it for me, but it
|
||||
might not be enough when running this test on slower machines.)
|
||||
|
||||
gdb/testsuite/ChangeLog:
|
||||
|
||||
* gdb.mi/mi-sym-info.exp (114-symbol-info-function test): Increase
|
||||
timeout.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.mi/mi-sym-info.exp b/gdb/testsuite/gdb.mi/mi-sym-info.exp
|
||||
--- a/gdb/testsuite/gdb.mi/mi-sym-info.exp
|
||||
+++ b/gdb/testsuite/gdb.mi/mi-sym-info.exp
|
||||
@@ -122,33 +122,35 @@ gdb_test_multiple $cmd $testname -prompt "${mi_gdb_prompt}$" {
|
||||
# (from the symbol table). There's often so much output output from
|
||||
# this command that we overflow expect's buffers, avoid this by
|
||||
# fetching the output piece by piece.
|
||||
-set testname "List all functions"
|
||||
-set cmd "114-symbol-info-functions --include-nondebug"
|
||||
-set state 0
|
||||
-gdb_test_multiple $cmd ${testname} -prompt "${mi_gdb_prompt}$" {
|
||||
- -re "114\\^done,symbols=\{" {
|
||||
- if { $state == 0 } { set state 1 }
|
||||
- exp_continue
|
||||
- }
|
||||
- -re "debug=\\\[${symtab_re}" {
|
||||
- if { $state == 1 } { set state 2 }
|
||||
- exp_continue
|
||||
- }
|
||||
- -re ",${symtab_re}" {
|
||||
- exp_continue
|
||||
- }
|
||||
- -re "\\\],nondebug=\\\[" {
|
||||
- if { $state == 2 } { set state 3 }
|
||||
- exp_continue
|
||||
- }
|
||||
- -re "\{address=${qstr},name=${qstr}\}," {
|
||||
- exp_continue
|
||||
- }
|
||||
- -re "\{address=${qstr},name=${qstr}\}\\\]\}\r\n${mi_gdb_prompt}$" {
|
||||
- if { $state == 3 } {
|
||||
- pass $gdb_test_name
|
||||
- } else {
|
||||
- fail $gdb_test_name
|
||||
+with_timeout_factor 4 {
|
||||
+ set testname "List all functions"
|
||||
+ set cmd "114-symbol-info-functions --include-nondebug"
|
||||
+ set state 0
|
||||
+ gdb_test_multiple $cmd ${testname} -prompt "${mi_gdb_prompt}$" {
|
||||
+ -re "114\\^done,symbols=\{" {
|
||||
+ if { $state == 0 } { set state 1 }
|
||||
+ exp_continue
|
||||
+ }
|
||||
+ -re "debug=\\\[${symtab_re}" {
|
||||
+ if { $state == 1 } { set state 2 }
|
||||
+ exp_continue
|
||||
+ }
|
||||
+ -re ",${symtab_re}" {
|
||||
+ exp_continue
|
||||
+ }
|
||||
+ -re "\\\],nondebug=\\\[" {
|
||||
+ if { $state == 2 } { set state 3 }
|
||||
+ exp_continue
|
||||
+ }
|
||||
+ -re "\{address=${qstr},name=${qstr}\}," {
|
||||
+ exp_continue
|
||||
+ }
|
||||
+ -re "\{address=${qstr},name=${qstr}\}\\\]\}\r\n${mi_gdb_prompt}$" {
|
||||
+ if { $state == 3 } {
|
||||
+ pass $gdb_test_name
|
||||
+ } else {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ Fixes bug 28030.
|
||||
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
|
||||
--- a/gdb/gdbtypes.c
|
||||
+++ b/gdb/gdbtypes.c
|
||||
@@ -5434,6 +5434,10 @@ copy_type_recursive (struct objfile *objfile,
|
||||
@@ -5571,6 +5571,10 @@ copy_type_recursive (struct objfile *objfile,
|
||||
xstrdup (TYPE_FIELD_STATIC_PHYSNAME (type,
|
||||
i)));
|
||||
break;
|
||||
|
185
gdb-rhbz2012976-paper-over-fortran-lex-problems.patch
Normal file
185
gdb-rhbz2012976-paper-over-fortran-lex-problems.patch
Normal file
@ -0,0 +1,185 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 11 Oct 2021 11:22:04 -0700
|
||||
Subject: gdb-rhbz2012976-paper-over-fortran-lex-problems.patch
|
||||
|
||||
;; Backport gdb.fortran testsuite changes in order to avoid Fortran
|
||||
;; lexical analyzer bug.
|
||||
|
||||
[gdb/testsuite] Fix FAIL in gdb.mi/mi-var-child-f.exp
|
||||
|
||||
When running test-case gdb.mi/mi-var-child-f.exp on openSUSE Tumbleweed
|
||||
(with glibc 2.34) I run into:
|
||||
...
|
||||
(gdb) ^M
|
||||
PASS: gdb.mi/mi-var-child-f.exp: mi runto prog_array
|
||||
Expecting: ^(-var-create array \* array[^M
|
||||
]+)?(\^done,name="array",numchild="[0-9]+",value=".*",type=.*,has_more="0"[^M
|
||||
]+[(]gdb[)] ^M
|
||||
[ ]*)
|
||||
-var-create array * array^M
|
||||
&"Attempt to use a type name as an expression.\n"^M
|
||||
^error,msg="-var-create: unable to create variable object"^M
|
||||
(gdb) ^M
|
||||
FAIL: gdb.mi/mi-var-child-f.exp: create local variable array (unexpected output)
|
||||
...
|
||||
|
||||
The problem is that the name array is used both:
|
||||
- as the name for a local variable
|
||||
- as the name of a type in glibc, in file malloc/dynarray-skeleton.c, as included
|
||||
by nss/nss_files/files-hosts.c.
|
||||
|
||||
Fix this by ignoring the shared lib symbols.
|
||||
|
||||
Likewise in a couple of other fortran tests.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.fortran/allocated.exp b/gdb/testsuite/gdb.fortran/allocated.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/allocated.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/allocated.exp
|
||||
@@ -25,11 +25,17 @@ if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
|
||||
return -1
|
||||
}
|
||||
|
||||
+# Avoid shared lib symbols.
|
||||
+gdb_test_no_output "set auto-solib-add off"
|
||||
+
|
||||
if ![fortran_runto_main] {
|
||||
untested "could not run to main"
|
||||
return -1
|
||||
}
|
||||
|
||||
+# Avoid libc symbols, in particular the 'array' type.
|
||||
+gdb_test_no_output "nosharedlibrary"
|
||||
+
|
||||
# Set all the breakpoints.
|
||||
for { set i 1 } { $i < 6 } { incr i } {
|
||||
gdb_breakpoint [gdb_get_line_number "Breakpoint $i"]
|
||||
diff --git a/gdb/testsuite/gdb.fortran/array-slices-bad.exp b/gdb/testsuite/gdb.fortran/array-slices-bad.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/array-slices-bad.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/array-slices-bad.exp
|
||||
@@ -25,11 +25,17 @@ if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
|
||||
return -1
|
||||
}
|
||||
|
||||
+# Avoid shared lib symbols.
|
||||
+gdb_test_no_output "set auto-solib-add off"
|
||||
+
|
||||
if ![fortran_runto_main] {
|
||||
untested "could not run to main"
|
||||
return -1
|
||||
}
|
||||
|
||||
+# Avoid libc symbols, in particular the 'array' type.
|
||||
+gdb_test_no_output "nosharedlibrary"
|
||||
+
|
||||
# gdb_breakpoint [gdb_get_line_number "Display Message Breakpoint"]
|
||||
gdb_breakpoint [gdb_get_line_number "First Breakpoint"]
|
||||
gdb_breakpoint [gdb_get_line_number "Second Breakpoint"]
|
||||
diff --git a/gdb/testsuite/gdb.fortran/array-slices-sub-slices.exp b/gdb/testsuite/gdb.fortran/array-slices-sub-slices.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/array-slices-sub-slices.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/array-slices-sub-slices.exp
|
||||
@@ -25,11 +25,17 @@ if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
|
||||
return -1
|
||||
}
|
||||
|
||||
+# Avoid shared lib symbols.
|
||||
+gdb_test_no_output "set auto-solib-add off"
|
||||
+
|
||||
if ![fortran_runto_main] {
|
||||
untested "could not run to main"
|
||||
return -1
|
||||
}
|
||||
|
||||
+# Avoid libc symbols, in particular the 'array' type.
|
||||
+gdb_test_no_output "nosharedlibrary"
|
||||
+
|
||||
# gdb_breakpoint [gdb_get_line_number "Display Message Breakpoint"]
|
||||
gdb_breakpoint [gdb_get_line_number "Stop Here"]
|
||||
gdb_breakpoint [gdb_get_line_number "Final Breakpoint"]
|
||||
diff --git a/gdb/testsuite/gdb.fortran/array-slices.exp b/gdb/testsuite/gdb.fortran/array-slices.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/array-slices.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/array-slices.exp
|
||||
@@ -55,11 +55,17 @@ proc run_test { repack } {
|
||||
|
||||
clean_restart ${binfile}
|
||||
|
||||
+ # Avoid shared lib symbols.
|
||||
+ gdb_test_no_output "set auto-solib-add off"
|
||||
+
|
||||
if ![fortran_runto_main] {
|
||||
untested "could not run to main"
|
||||
return -1
|
||||
}
|
||||
|
||||
+ # Avoid libc symbols, in particular the 'array' type.
|
||||
+ gdb_test_no_output "nosharedlibrary"
|
||||
+
|
||||
gdb_test_no_output "set fortran repack-array-slices $repack"
|
||||
|
||||
# gdb_breakpoint [gdb_get_line_number "Display Message Breakpoint"]
|
||||
diff --git a/gdb/testsuite/gdb.fortran/lbound-ubound.exp b/gdb/testsuite/gdb.fortran/lbound-ubound.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/lbound-ubound.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/lbound-ubound.exp
|
||||
@@ -25,12 +25,17 @@ if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
|
||||
return -1
|
||||
}
|
||||
|
||||
+# Avoid shared lib symbols.
|
||||
+gdb_test_no_output "set auto-solib-add off"
|
||||
|
||||
if ![fortran_runto_main] {
|
||||
untested "could not run to main"
|
||||
return -1
|
||||
}
|
||||
|
||||
+# Avoid libc symbols, in particular the 'array' type.
|
||||
+gdb_test_no_output "nosharedlibrary"
|
||||
+
|
||||
gdb_breakpoint [gdb_get_line_number "Test Breakpoint"]
|
||||
gdb_breakpoint [gdb_get_line_number "Final Breakpoint"]
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.fortran/subarray.exp b/gdb/testsuite/gdb.fortran/subarray.exp
|
||||
--- a/gdb/testsuite/gdb.fortran/subarray.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/subarray.exp
|
||||
@@ -27,16 +27,17 @@ if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug f90}]} {
|
||||
return -1
|
||||
}
|
||||
|
||||
-gdb_exit
|
||||
-gdb_start
|
||||
-gdb_reinitialize_dir $srcdir/$subdir
|
||||
-gdb_load ${binfile}
|
||||
+# Avoid shared lib symbols.
|
||||
+gdb_test_no_output "set auto-solib-add off"
|
||||
|
||||
if ![fortran_runto_main] then {
|
||||
perror "couldn't run to main"
|
||||
continue
|
||||
}
|
||||
|
||||
+# Avoid libc symbols, in particular the 'array' type.
|
||||
+gdb_test_no_output "nosharedlibrary"
|
||||
+
|
||||
# Try to set breakpoint at the last write statement.
|
||||
|
||||
set bp_location [gdb_get_line_number "str(:)"]
|
||||
diff --git a/gdb/testsuite/gdb.mi/mi-var-child-f.exp b/gdb/testsuite/gdb.mi/mi-var-child-f.exp
|
||||
--- a/gdb/testsuite/gdb.mi/mi-var-child-f.exp
|
||||
+++ b/gdb/testsuite/gdb.mi/mi-var-child-f.exp
|
||||
@@ -36,8 +36,14 @@ if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
|
||||
mi_gdb_reinitialize_dir $srcdir/$subdir
|
||||
mi_gdb_load ${binfile}
|
||||
|
||||
+# Avoid shared lib symbols.
|
||||
+mi_gdb_test "-gdb-set auto-solib-add off" "\\^done"
|
||||
+
|
||||
mi_runto prog_array
|
||||
|
||||
+# Avoid libc symbols, in particular the 'array' type.
|
||||
+mi_gdb_test "nosharedlibrary" ".*\\^done"
|
||||
+
|
||||
mi_create_varobj "array" "array" "create local variable array"
|
||||
|
||||
|
18
gdb.spec
18
gdb.spec
@ -31,13 +31,13 @@ Name: %{?scl_prefix}gdb
|
||||
# Freeze it when GDB gets branched
|
||||
%global snapsrc 20200208
|
||||
# See timestamp of source gnulib installed into gnulib/ .
|
||||
%global snapgnulib 20200630
|
||||
%global snapgnulib 20210105
|
||||
%global tarname gdb-%{version}
|
||||
Version: 10.2
|
||||
Version: 11.1
|
||||
|
||||
# The release always contains a leading reserved number, start it at 1.
|
||||
# `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
|
||||
Release: 9%{?dist}
|
||||
Release: 2%{?dist}
|
||||
|
||||
License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and LGPLv3+ and BSD and Public Domain and GFDL
|
||||
# Do not provide URL for snapshots as the file lasts there only for 2 days.
|
||||
@ -1143,7 +1143,17 @@ fi
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Wed Sep 24 2021 Alexandra Hájková <ahajkova@redhat.com> - 10.2-9
|
||||
* Mon Oct 11 2021 Kevin Buettner - 11.1-2
|
||||
- Backport upstream patch which papers over Fortran lexical analyzer
|
||||
bug (RHBZ 2012976, Tom de Vries).
|
||||
|
||||
* Mon Oct 04 2021 Kevin Buettner - 11.1-1
|
||||
- Rebase to FSF GDB 11.1.
|
||||
- Adjust build-id related patches.
|
||||
- Drop backported patches which are no longer relevant.
|
||||
- Bump 'snapgnulib' date.
|
||||
|
||||
* Wed Sep 29 2021 Alexandra Hájková <ahajkova@redhat.com> - 10.2-9
|
||||
- Backport test for RHBZ 1976887 (Kevin Buettner).
|
||||
|
||||
* Wed Sep 29 2021 Alexandra Hájková <ahajkova@redhat.com> - 10.2-9
|
||||
|
2
sources
2
sources
@ -1,3 +1,3 @@
|
||||
SHA512 (gdb-libstdc++-v3-python-8.1.1-20180626.tar.xz) = a8b1c54dd348cfeb37da73f968742896be3dd13a4215f8d8519870c2abea915f5176c3fa6989ddd10f20020a16f0fab20cbae68ee8d58a82234d8778023520f8
|
||||
SHA512 (v2.0.4.tar.gz) = 596d2dac25fdbd3e5660d7e1feeb7e8d5d359d1d0e19b62ef593449037df236db1d4d98820f0031061b5573ed67797a85a77fb9991e215abaabc4bfe16ceaec8
|
||||
SHA512 (gdb-10.2.tar.xz) = 3653762ac008e065c37cd641653184c9ff7ce51ee2222ade1122bec9d6cc64dffd4fb74888ef11ac1942064a08910e96b7865112ad37f4602eb0a16bed074caa
|
||||
SHA512 (gdb-11.1.tar.xz) = c40bf970e2f7c2107b29c5aa6a7150daa709d75ddadb73ac20742419d4637d158e3063a4c6ff6e47fae8ca8e1d36253973f85ea15445d004be6d5d7a2dd9bd46
|
||||
|
@ -1,52 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Keith Seitz <keiths@redhat.com>
|
||||
Date: Tue, 23 Mar 2021 09:32:37 -0700
|
||||
Subject: testing-custom-inputrc.patch
|
||||
|
||||
;; Backport "Disable bracketed paste mode in GDB tests"
|
||||
;; (Tom Tromey)
|
||||
|
||||
commit 1af4c9c4209c3478224f18dfb79dc09567b96705
|
||||
Author: Tom Tromey <tom@tromey.com>
|
||||
Date: Sat Jan 23 08:52:45 2021 -0700
|
||||
|
||||
Disable bracketed paste mode in GDB tests
|
||||
|
||||
I have a patch to import GNU readline 8.1 into GDB. However, when
|
||||
running the tests, there were a number of failures due to "bracketed
|
||||
paste mode". This is a terminal feature that readline 8.1 enables by
|
||||
default.
|
||||
|
||||
The simplest way to work around this was to always make a ".inputrc"
|
||||
for GDB tests that will tell readline to disable brackted paste mode.
|
||||
|
||||
gdb/testsuite/ChangeLog
|
||||
2021-01-23 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* lib/gdb.exp (default_gdb_init): Set INPUTRC to a cached file.
|
||||
|
||||
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
|
||||
--- a/gdb/testsuite/lib/gdb.exp
|
||||
+++ b/gdb/testsuite/lib/gdb.exp
|
||||
@@ -5135,13 +5135,14 @@ proc default_gdb_init { test_file_name } {
|
||||
setenv LC_CTYPE C
|
||||
setenv LANG C
|
||||
|
||||
- # Don't let a .inputrc file or an existing setting of INPUTRC mess up
|
||||
- # the test results. Even if /dev/null doesn't exist on the particular
|
||||
- # platform, the readline library will use the default setting just by
|
||||
- # failing to open the file. OTOH, opening /dev/null successfully will
|
||||
- # also result in the default settings being used since nothing will be
|
||||
- # read from this file.
|
||||
- setenv INPUTRC "/dev/null"
|
||||
+ # Don't let a .inputrc file or an existing setting of INPUTRC mess
|
||||
+ # up the test results. Certain tests (style tests and TUI tests)
|
||||
+ # want to set the terminal to a non-"dumb" value, and for those we
|
||||
+ # want to disable bracketed paste mode. Versions of Readline
|
||||
+ # before 8.0 will not understand this and will issue a warning.
|
||||
+ # We tried using a $if to guard it, but Readline 8.1 had a bug in
|
||||
+ # its version-comparison code that prevented this for working.
|
||||
+ setenv INPUTRC [cached_file inputrc "set enable-bracketed-paste off"]
|
||||
|
||||
# This disables style output, which would interfere with many
|
||||
# tests.
|
Loading…
Reference in New Issue
Block a user