diff --git a/SOURCES/_gdb.spec.Patch.include b/SOURCES/_gdb.spec.Patch.include index 0b35c97..f9e20b1 100644 --- a/SOURCES/_gdb.spec.Patch.include +++ b/SOURCES/_gdb.spec.Patch.include @@ -674,3 +674,80 @@ Patch164: gdb-rhbz1768593-s390x-arch13-03.patch # Andreas Arnaz, RH BZ 1659535 Patch165: gdb-rhbz1659535-z15-record-replay.patch +# Fix terminal problems when error() is called +# Alan Hayward (RH BZ 1852580) +Patch166: gdb-rhbz1852580-terminal-woes.patch + +# Remove hack for GDB which sets the section size to 0 +# Kevin Buettner, RH BZ 1842691 +Patch167: gdb-rhbz1842691-corefile-mem-access-1of15.patch + +# Adjust corefile.exp test to show regression after bfd hack removal +# Kevin Buettner, RH BZ 1842691 +Patch168: gdb-rhbz1842691-corefile-mem-access-2of15.patch + +# section_table_xfer_memory: Replace section name with callback predicate +# Kevin Buettner, RH BZ 1842691 +Patch169: gdb-rhbz1842691-corefile-mem-access-3of15.patch + +# Provide access to non SEC_HAS_CONTENTS core file sections +# Kevin Buettner, RH BZ 1842961 +Patch170: gdb-rhbz1842691-corefile-mem-access-4of15.patch + +# Test ability to access unwritten-to mmap data in core file +# Kevin Buettner, RH BZ 1842961 +Patch171: gdb-rhbz1842691-corefile-mem-access-5of15.patch + +# Update binary_get_section_contents to seek using section's file position +# Kevin Buettner, RH BZ 1842961 +Patch172: gdb-rhbz1842691-corefile-mem-access-6of15.patch + +# Add new gdbarch method, read_core_file_mappings +# Kevin Buettner, RH BZ 1842961 +Patch173: gdb-rhbz1842691-corefile-mem-access-7of15.patch + +# Use NT_FILE note section for reading core target memory +# Kevin Buettner, RH BZ 1842961 +Patch174: gdb-rhbz1842691-corefile-mem-access-8of15.patch + +# Add test for accessing read-only mmapped data in a core file +# Kevin Buettner, RH BZ 1842691 +Patch175: gdb-rhbz1842691-corefile-mem-access-9of15.patch + +# gcore command: Place all file-backed mappings in NT_FILE note +# Kevin Buettner, RH BZ 1842961 +Patch176: gdb-rhbz1842691-corefile-mem-access-10of15.patch + +# Adjust coredump-filter.exp to account for NT_FILE note handling +# Kevin Buettner, RH BZ 1842961 +Patch177: gdb-rhbz1842691-corefile-mem-access-11of15.patch + +# Add new command "maint print core-file-backed-mappings" +# Kevin Buettner, RH BZ 1842961 +Patch178: gdb-rhbz1842691-corefile-mem-access-12of15.patch + +# Add documentation for "maint print core-file-backed-mappings" +# Kevin Buettner, RH BZ 1842961 +Patch179: gdb-rhbz1842691-corefile-mem-access-13of15.patch + +# New core file tests with mappings over existing program memory +# Kevin Buettner, RH BZ 1842961 +Patch180: gdb-rhbz1842691-corefile-mem-access-14of15.patch + +# Add period to help text for maint print core-file-backed-mappings +# Kevin Buettner, RH BZ 1842961 +Patch181: gdb-rhbz1842691-corefile-mem-access-15of15.patch + +# Backport "Stop the BFD library from issuing a warning message when +# processing allocated sections in debuginfo files that lie outside of +# Nick Clifton and Keith Seitz, RH BZ 1878810 +Patch182: gdb-rhbz1878810-bfd-suppress-loadable-section-outside-ELF-sections.patch + +# Backport "fortran dynamic type related fixes" +# Andrew Burgess (RH BZ 1905701) +Patch183: gdb-rhbz1905701-DWARF-data_location.patch + +# Backport of "Correct recording of 'store on condition' insns" +# Andreas Arnaz (RH BZ 1903374) +Patch184: gdb-rhbz1903374-s390x-store-on-condition.patch + diff --git a/SOURCES/_gdb.spec.patch.include b/SOURCES/_gdb.spec.patch.include index 526e285..f14d36a 100644 --- a/SOURCES/_gdb.spec.patch.include +++ b/SOURCES/_gdb.spec.patch.include @@ -163,3 +163,22 @@ %patch163 -p1 %patch164 -p1 %patch165 -p1 +%patch166 -p1 +%patch167 -p1 +%patch168 -p1 +%patch169 -p1 +%patch170 -p1 +%patch171 -p1 +%patch172 -p1 +%patch173 -p1 +%patch174 -p1 +%patch175 -p1 +%patch176 -p1 +%patch177 -p1 +%patch178 -p1 +%patch179 -p1 +%patch180 -p1 +%patch181 -p1 +%patch182 -p1 +%patch183 -p1 +%patch184 -p1 diff --git a/SOURCES/gdb-rhbz1659535-z15-record-replay.patch b/SOURCES/gdb-rhbz1659535-z15-record-replay.patch index 6385b36..e943646 100644 --- a/SOURCES/gdb-rhbz1659535-z15-record-replay.patch +++ b/SOURCES/gdb-rhbz1659535-z15-record-replay.patch @@ -1,10 +1,14 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Tue, 12 May 2020 15:38:27 -0400 +Subject: gdb-rhbz1659535-z15-record-replay.patch + ;; Backport z15 record/replay ;; Andreas Arnaz, RH BZ 1659535 -commit 6d9d6da48e84a65871a9d72fa785105d603990a6 -Author: Andreas Arnez -Date: Wed Oct 9 11:09:22 2019 +0200 - + commit 6d9d6da48e84a65871a9d72fa785105d603990a6 + Author: Andreas Arnez + Date: Wed Oct 9 11:09:22 2019 +0200 s390: Add record/replay support for arch13 instructions Enable recording most of the new "arch13" instructions on z/Architecture diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-10of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-10of15.patch new file mode 100644 index 0000000..806bdae --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-10of15.patch @@ -0,0 +1,114 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Mon, 27 Jul 2020 19:38:20 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-10of15.patch + +;; gcore command: Place all file-backed mappings in NT_FILE note +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Wed Jul 1 06:34:50 2020 -0700 + + gcore command: Place all file-backed mappings in NT_FILE note + + When making a core file with the GDB's gcore command on Linux, + the same criteria used for determining which mappings should be + dumped were also being used for determining which entries should + be placed in the NT_FILE note. This is wrong; we want to place + all file-backed mappings in this note. + + The predicate function, dump_mapping_p, was used to determine whether + or not to dump a mapping from within linux_find_memory_regions_full. + This commit leaves this predicate in place, but adds a new parameter, + should_dump_mapping_p, to linux_find_memory_regions_full. It then + calls should_dump_mapping_p instead of dump_mapping_p. dump_mapping_p + is passed to linux_find_memory_regions_full at one call site; at the + other call site, dump_note_entry_p is passed instead. + + gdb/ChangeLog: + + * linux-tdep.c (dump_note_entry_p): New function. + (linux_dump_mapping_p_ftype): New typedef. + (linux_find_memory_regions_full): Add new parameter, + should_dump_mapping_p. + (linux_find_memory_regions): Adjust call to + linux_find_memory_regions_full. + (linux_make_mappings_core_file_notes): Use dump_note_entry_p in + call to linux_find_memory_regions_full. + +diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c +--- a/gdb/linux-tdep.c ++++ b/gdb/linux-tdep.c +@@ -710,6 +710,25 @@ dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v, + } + } + ++/* As above, but return true only when we should dump the NT_FILE ++ entry. */ ++ ++static int ++dump_note_entry_p (filter_flags filterflags, const struct smaps_vmflags *v, ++ int maybe_private_p, int mapping_anon_p, int mapping_file_p, ++ const char *filename) ++{ ++ /* vDSO and vsyscall mappings will end up in the core file. Don't ++ put them in the NT_FILE note. */ ++ if (strcmp ("[vdso]", filename) == 0 ++ || strcmp ("[vsyscall]", filename) == 0) ++ return 0; ++ ++ /* Otherwise, any other file-based mapping should be placed in the ++ note. */ ++ return filename != nullptr; ++} ++ + /* Implement the "info proc" command. */ + + static void +@@ -1224,10 +1243,18 @@ typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size, + const char *filename, + void *data); + ++typedef int linux_dump_mapping_p_ftype (filter_flags filterflags, ++ const struct smaps_vmflags *v, ++ int maybe_private_p, ++ int mapping_anon_p, ++ int mapping_file_p, ++ const char *filename); ++ + /* List memory regions in the inferior for a corefile. */ + + static int + linux_find_memory_regions_full (struct gdbarch *gdbarch, ++ linux_dump_mapping_p_ftype *should_dump_mapping_p, + linux_find_memory_region_ftype *func, + void *obfd) + { +@@ -1378,7 +1405,7 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch, + } + + if (has_anonymous) +- should_dump_p = dump_mapping_p (filterflags, &v, priv, ++ should_dump_p = should_dump_mapping_p (filterflags, &v, priv, + mapping_anon_p, mapping_file_p, + filename); + else +@@ -1444,6 +1471,7 @@ linux_find_memory_regions (struct gdbarch *gdbarch, + data.obfd = obfd; + + return linux_find_memory_regions_full (gdbarch, ++ dump_mapping_p, + linux_find_memory_regions_thunk, + &data); + } +@@ -1606,7 +1634,9 @@ linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, + pack_long (buf, long_type, 1); + obstack_grow (&data_obstack, buf, TYPE_LENGTH (long_type)); + +- linux_find_memory_regions_full (gdbarch, linux_make_mappings_callback, ++ linux_find_memory_regions_full (gdbarch, ++ dump_note_entry_p, ++ linux_make_mappings_callback, + &mapping_data); + + if (mapping_data.file_count != 0) diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-11of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-11of15.patch new file mode 100644 index 0000000..6551038 --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-11of15.patch @@ -0,0 +1,87 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Tue, 28 Jul 2020 09:26:44 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-11of15.patch + +;; Adjust coredump-filter.exp to account for NT_FILE note handling +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Fri Jul 3 20:10:22 2020 -0700 + + Adjust coredump-filter.exp to account for NT_FILE note handling + + This commit makes adjustments to coredump-filter.exp to account + for the fact that NT_FILE file-backed mappings are now available + when a core file is loaded. Thus, a test which was expected + to PASS when a memory region was determined to be unavailable + (due to no file-backed mappings being available) will now FAIL + due to those mappings being available from having loaded the + NT_FILE note. + + I had originally marked the test as XFAIL, but Mihails Strasuns + suggested a much better approach: + + 1) First test that it still works if file is accessible in the + filesystem. + 2) Temporarily move / rename the file and test that disassembly + doesn't work anymore. + + That's what this commit implements. + + gdb/testsuite/ChangeLog: + + * gdb.base/coredump-filter.exp: Add second + non-Private-Shared-Anon-File test. + (test_disasm): Rename binfile for test which is expected + to fail. + +diff --git a/gdb/testsuite/gdb.base/coredump-filter.exp b/gdb/testsuite/gdb.base/coredump-filter.exp +--- a/gdb/testsuite/gdb.base/coredump-filter.exp ++++ b/gdb/testsuite/gdb.base/coredump-filter.exp +@@ -80,15 +80,26 @@ proc do_load_and_test_core { core var working_var working_value dump_excluded } + # disassemble of a function (i.e., the binary's .text section). GDB + # should fail in this case. However, it must succeed if the binary is + # provided along with the corefile. This is what we test here. ++# ++# A further complication is that Linux NT_FILE notes are now read from ++# the corefile. This note allows GDB to find the binary for file ++# backed mappings even though the binary wasn't loaded by GDB in the ++# conventional manner. In order to see the expected failure for this ++# case, we rename the binary in order to perform this test. + + proc test_disasm { core address should_fail } { +- global testfile hex ++ global testfile hex binfile + + # Restart GDB without loading the binary. + with_test_prefix "no binary" { + gdb_exit + gdb_start + ++ set hide_binfile [standard_output_file "${testfile}.hide"] ++ if { $should_fail == 1 } { ++ remote_exec host "mv -f $binfile $hide_binfile" ++ } ++ + set core_loaded [gdb_core_cmd "$core" "load core"] + if { $core_loaded == -1 } { + fail "loading $core" +@@ -96,6 +107,7 @@ proc test_disasm { core address should_fail } { + } + + if { $should_fail == 1 } { ++ remote_exec host "mv -f $hide_binfile $binfile" + gdb_test "x/i \$pc" "=> $hex:\tCannot access memory at address $hex" \ + "disassemble function with corefile and without a binary" + } else { +@@ -225,5 +237,9 @@ foreach item $all_anon_corefiles { + } + + with_test_prefix "loading and testing corefile for non-Private-Shared-Anon-File" { ++ test_disasm $non_private_shared_anon_file_core $main_addr 0 ++} ++ ++with_test_prefix "loading and testing corefile for non-Private-Shared-Anon-File with renamed binary" { + test_disasm $non_private_shared_anon_file_core $main_addr 1 + } diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-12of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-12of15.patch new file mode 100644 index 0000000..39f8bb4 --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-12of15.patch @@ -0,0 +1,169 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Tue, 28 Jul 2020 09:32:50 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-12of15.patch + +;; Add new command "maint print core-file-backed-mappings" +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Fri Jul 3 21:55:51 2020 -0700 + + Add new command "maint print core-file-backed-mappings" + + I wrote a read_core_file_mappings method for FreeBSD and then registered + this gdbarch method. I saw some strange behavior while testing it and + wanted a way to make sure that mappings were being correctly loaded + into corelow.c, so I wrote the new command which is the topic of this + commit. I think it might be occasionally useful for debugging strange + corefile behavior. + + With regard to FreeBSD, my work isn't ready yet. Unlike Linux, + FreeBSD puts all mappings into its core file note. And, unlike Linux, + it doesn't dump load segments which occupy no space in the file. So + my (perhaps naive) implementation of a FreeBSD read_core_file_mappings + didn't work all that well: I saw more failures in the corefile2.exp + tests than without it. I think it should be possible to make FreeBSD + work as well as Linux, but it will require doing something with all of + the mappings, not just the file based mappings that I was considering. + + In the v4 series, Pedro asked the following: + + I don't understand what this command provides that "info proc + mappings" doesn't? Can you give an example of when you'd use this + command over "info proc mappings" ? + + On Linux, "info proc mappings" and "maint print core-file-backed-mappings" + will produce similar, possibly identical, output. This need not be + the case for other OSes. E.g. on FreeBSD, had I finished the + implementation, the output from these commands would have been very + different. The FreeBSD "info proc mappings" command would show + additional (non-file-backed) mappings in addition to at least one + additional field (memory permissions) for each mapping. + + As noted earlier, I was seeing some unexpected behavior while working + on the FreeBSD implementation and wanted to be certain that the + mappings were being correctly loaded by corelow.c. "info proc + mappings" prints the core file mappings, but doesn't tell us anything + about whether they've been loaded by corelow.c This new maintenance + command directly interrogates the data structures and prints the + values found there. + + gdb/ChangeLog: + + * corelow.c (gdbcmd.h): Include. + (core_target::info_proc_mappings): New method. + (get_current_core_target): New function. + (maintenance_print_core_file_backed_mappings): New function. + (_initialize_corelow): Add core-file-backed-mappings to + "maint print" commands. + +diff --git a/gdb/corelow.c b/gdb/corelow.c +--- a/gdb/corelow.c ++++ b/gdb/corelow.c +@@ -118,6 +118,9 @@ public: + const char *human_name, + bool required); + ++ /* See definition. */ ++ void info_proc_mappings (struct gdbarch *gdbarch); ++ + private: /* per-core data */ + + /* The core's section table. Note that these target sections are +@@ -1292,6 +1295,86 @@ core_target::info_proc (const char *args, enum info_proc_what request) + return true; + } + ++/* Get a pointer to the current core target. If not connected to a ++ core target, return NULL. */ ++ ++static core_target * ++get_current_core_target () ++{ ++ target_ops *proc_target = find_target_at (process_stratum); ++ return dynamic_cast (proc_target); ++} ++ ++/* Display file backed mappings from core file. */ ++ ++void ++core_target::info_proc_mappings (struct gdbarch *gdbarch) ++{ ++ if (m_core_file_mappings.sections != m_core_file_mappings.sections_end) ++ { ++ printf_filtered (_("Mapped address spaces:\n\n")); ++ if (gdbarch_addr_bit (gdbarch) == 32) ++ { ++ printf_filtered ("\t%10s %10s %10s %10s %s\n", ++ "Start Addr", ++ " End Addr", ++ " Size", " Offset", "objfile"); ++ } ++ else ++ { ++ printf_filtered (" %18s %18s %10s %10s %s\n", ++ "Start Addr", ++ " End Addr", ++ " Size", " Offset", "objfile"); ++ } ++ } ++ ++ for (const struct target_section *tsp = m_core_file_mappings.sections; ++ tsp < m_core_file_mappings.sections_end; ++ tsp++) ++ { ++ ULONGEST start = tsp->addr; ++ ULONGEST end = tsp->endaddr; ++ ULONGEST file_ofs = tsp->the_bfd_section->filepos; ++ const char *filename = bfd_get_filename (tsp->the_bfd_section->owner); ++ ++ if (gdbarch_addr_bit (gdbarch) == 32) ++ printf_filtered ("\t%10s %10s %10s %10s %s\n", ++ paddress (gdbarch, start), ++ paddress (gdbarch, end), ++ hex_string (end - start), ++ hex_string (file_ofs), ++ filename); ++ else ++ printf_filtered (" %18s %18s %10s %10s %s\n", ++ paddress (gdbarch, start), ++ paddress (gdbarch, end), ++ hex_string (end - start), ++ hex_string (file_ofs), ++ filename); ++ } ++} ++ ++/* Implement "maintenance print core-file-backed-mappings" command. ++ ++ If mappings are loaded, the results should be similar to the ++ mappings shown by "info proc mappings". This command is mainly a ++ debugging tool for GDB developers to make sure that the expected ++ mappings are present after loading a core file. For Linux, the ++ output provided by this command will be very similar (if not ++ identical) to that provided by "info proc mappings". This is not ++ necessarily the case for other OSes which might provide ++ more/different information in the "info proc mappings" output. */ ++ ++static void ++maintenance_print_core_file_backed_mappings (const char *args, int from_tty) ++{ ++ core_target *targ = get_current_core_target (); ++ if (targ != nullptr) ++ targ->info_proc_mappings (targ->core_gdbarch ()); ++} ++ ++void _initialize_corelow (); + void + _initialize_corelow (void) + { +@@ -1303,4 +1386,8 @@ Set whether CORE-FILE loads the build-id associated files automatically."), _("\ + Show whether CORE-FILE loads the build-id associated files automatically."), + NULL, NULL, NULL, + &setlist, &showlist); ++ add_cmd ("core-file-backed-mappings", class_maintenance, ++ maintenance_print_core_file_backed_mappings, ++ _("Print core file's file-backed mappings"), ++ &maintenanceprintlist); + } diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-13of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-13of15.patch new file mode 100644 index 0000000..aef3ebc --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-13of15.patch @@ -0,0 +1,41 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Tue, 28 Jul 2020 09:44:04 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-13of15.patch + +;; Add documentation for "maint print core-file-backed-mappings" +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Fri Jul 3 22:09:20 2020 -0700 + + Add documentation for "maint print core-file-backed-mappings" + + gdb/ChangeLog: + + * NEWS (New commands): Mention new command + "maintenance print core-file-backed-mappings". + + gdb/doc/ChangeLog: + + * gdb.texinfo (Maintenance Commands): Add documentation for + new command "maintenance print core-file-backed-mappings". + +diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo +--- a/gdb/doc/gdb.texinfo ++++ b/gdb/doc/gdb.texinfo +@@ -35633,6 +35633,14 @@ library. This exercises all @code{libthread_db} functionality used by + @code{libthread_db} uses. Note that parts of the test may be skipped + on some platforms when debugging core files. + ++@kindex maint print core-file-backed-mappings ++@cindex memory address space mappings ++@item maint print core-file-backed-mappings ++Print the file-backed mappings which were loaded from a core file note. ++This output represents state internal to @value{GDBN} and should be ++similar to the mappings displayed by the @code{info proc mappings} ++command. ++ + @kindex maint print dummy-frames + @item maint print dummy-frames + Prints the contents of @value{GDBN}'s internal dummy-frame stack. diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-14of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-14of15.patch new file mode 100644 index 0000000..4a09679 --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-14of15.patch @@ -0,0 +1,439 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Tue, 28 Jul 2020 09:46:44 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-14of15.patch + +;; New core file tests with mappings over existing program memory +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Wed Jun 17 19:25:47 2020 -0700 + + New core file tests with mappings over existing program memory + + This test case was inspired by Pedro's demonstration of a problem + with my v2 patches. It can be found here: + + https://sourceware.org/pipermail/gdb-patches/2020-May/168826.html + + In a nutshell, my earlier patches could not handle the case in + which a read-only mapping created with mmap() was created at + an address used by other file-backed read-only memory in use by + the process. + + This problem has been fixed (for Linux, anyway) by the commit "Use + NT_FILE note section for reading core target memory". + + When I run this test without any of my recent corefile patches, + I see these failures: + + FAIL: gdb.base/corefile2.exp: kernel core: print/x mbuf_ro[0]@4 + FAIL: gdb.base/corefile2.exp: kernel core: print/x mbuf_ro[pagesize-4]@4 + FAIL: gdb.base/corefile2.exp: kernel core: print/x mbuf_ro[-3]@6 + FAIL: gdb.base/corefile2.exp: kernel core: print/x mbuf_rw[pagesize-3]@6 + FAIL: gdb.base/corefile2.exp: kernel core: print/x mbuf_ro[pagesize-3]@6 + FAIL: gdb.base/corefile2.exp: maint print core-file-backed-mappings + FAIL: gdb.base/corefile2.exp: gcore core: print/x mbuf_ro[-3]@6 + + The ones involving mbuf_ro will almost certainly fail when run on + non-Linux systems; I've used setup_xfail on those tests to prevent + them from outright FAILing when not run on Linux. For a time, I + had considered skipping these tests altogether when not run on + Linux, but I changed my mind due to this failure... + + FAIL: gdb.base/corefile2.exp: print/x mbuf_rw[pagesize-3]@6 + + I think it *should* pass without my recent corefile patches. The fact + that it doesn't is likely due to a bug in GDB. The following + interaction with GDB demonstrates the problem: + + (gdb) print/x mbuf_rw[pagesize-3]@6 + $1 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0} + (gdb) print/x mbuf_rw[pagesize]@3 + $2 = {0x6b, 0x6b, 0x6b} + + The last three values in display of $1 should be the same as those + shown by $2. Like this... + + (gdb) print/x mbuf_rw[pagesize-3]@6 + $1 = {0x0, 0x0, 0x0, 0x6b, 0x6b, 0x6b} + (gdb) print/x mbuf_rw[pagesize]@3 + $2 = {0x6b, 0x6b, 0x6b} + + That latter output was obtained with the use of all of my current + corefile patches. I see no failures on Linux when running this test + with my current set of corefile patches. I tested 3 architectures: + x86_64, s390x, and aarch64. + + I also tested on FreeBSD 12.1-RELEASE. I see the following results + both with and without the current set of core file patches: + + # of expected passes 26 + # of expected failures 8 + + Of particular interest is that I did *not* see the problematic mbuf_rw + failure noted earlier (both with and without the core file patches). + I still don't have an explanation for why this failure occurred on + Linux. Prior to running the tests, I had hypothesized that I'd see + this failure on FreeBSD too, but testing shows that this is not the + case. + + Also of importance is that we see no FAILs with this test on FreeBSD + which indicates that I XFAILed the correct tests. + + This version runs the interesting tests twice, once with a kernel + created core file and another time with a gcore created core file. + + It also does a very minimal test of the new command "maint print + core-file-backed-mappings". + + gdb/testsuite/ChangeLog: + + * gdb.base/corefile2.exp: New file. + * gdb.base/coremaker2.exp: New file. + +diff --git a/gdb/testsuite/gdb.base/corefile2.exp b/gdb/testsuite/gdb.base/corefile2.exp +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/corefile2.exp +@@ -0,0 +1,185 @@ ++# Copyright 2020 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 . ++ ++# Tests of core file memory accesses when mmap() has been used to ++# create a "hole" of zeroes over pre-existing memory regions. See ++# coremaker2.c for details. ++ ++# are we on a target board ++if ![isnative] then { ++ return ++} ++ ++# Some of these tests will only work on GNU/Linux due to the ++# fact that Linux core files includes a section describing ++# memory address to file mappings. We'll use set_up_xfail for the ++# affected tests. As other targets become supported, the condition ++# can be changed accordingly. ++ ++set xfail 0 ++if { ![istarget *-linux*] } { ++ set xfail 1 ++} ++ ++standard_testfile coremaker2.c ++ ++if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} { ++ untested "failed to compile" ++ return -1 ++} ++ ++set corefile [core_find $binfile {}] ++if {$corefile == ""} { ++ return 0 ++} ++ ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# Attempt to load the core file. ++ ++gdb_test_multiple "core-file $corefile" "core-file command" { ++ -re ".* program is being debugged already.*y or n. $" { ++ # gdb_load may connect us to a gdbserver. ++ send_gdb "y\n" ++ exp_continue ++ } ++ -re "Core was generated by .*corefile.*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" { ++ pass "core-file command" ++ } ++ -re "Core was generated by .*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" { ++ pass "core-file command (with bad program name)" ++ } ++ -re ".*registers from core file: File in wrong format.* $" { ++ fail "core-file command (could not read registers from core file)" ++ } ++} ++ ++# Perform the "interesting" tests which check the contents of certain ++# memory regions. ++ ++proc do_tests { } { ++ global xfail ++ ++ # Check contents of beginning of buf_rw and buf_ro. ++ ++ gdb_test {print/x buf_rw[0]@4} {\{0x6b, 0x6b, 0x6b, 0x6b\}} ++ gdb_test {print/x buf_ro[0]@4} {\{0xc5, 0xc5, 0xc5, 0xc5\}} ++ ++ # Check for correct contents at beginning of mbuf_rw and mbuf_ro. ++ ++ gdb_test {print/x mbuf_rw[0]@4} {\{0x0, 0x0, 0x0, 0x0\}} ++ ++ if { $xfail } { setup_xfail "*-*-*" } ++ gdb_test {print/x mbuf_ro[0]@4} {\{0x0, 0x0, 0x0, 0x0\}} ++ ++ # Check contents of mbuf_rw and mbuf_ro at the end of these regions. ++ ++ gdb_test {print/x mbuf_rw[pagesize-4]@4} {\{0x0, 0x0, 0x0, 0x0\}} ++ ++ if { $xfail } { setup_xfail "*-*-*" } ++ gdb_test {print/x mbuf_ro[pagesize-4]@4} {\{0x0, 0x0, 0x0, 0x0\}} ++ ++ # Check contents of mbuf_rw and mbuf_ro, right before the hole, ++ # overlapping into the beginning of these mmap'd regions. ++ ++ gdb_test {print/x mbuf_rw[-3]@6} {\{0x6b, 0x6b, 0x6b, 0x0, 0x0, 0x0\}} ++ ++ if { $xfail } { setup_xfail "*-*-*" } ++ gdb_test {print/x mbuf_ro[-3]@6} {\{0xc5, 0xc5, 0xc5, 0x0, 0x0, 0x0\}} ++ ++ # Likewise, at the end of the mbuf_rw and mbuf_ro, with overlap. ++ ++ # If this test FAILs, it's probably a genuine bug unrelated to whether ++ # the core file includes a section describing memory address to file ++ # mappings or not. (So don't xfail it!) ++ gdb_test {print/x mbuf_rw[pagesize-3]@6} {\{0x0, 0x0, 0x0, 0x6b, 0x6b, 0x6b\}} ++ ++ if { $xfail } { setup_xfail "*-*-*" } ++ gdb_test {print/x mbuf_ro[pagesize-3]@6} {\{0x0, 0x0, 0x0, 0xc5, 0xc5, 0xc5\}} ++ ++ # Check contents of (what should be) buf_rw and buf_ro immediately after ++ # mbuf_rw and mbuf_ro holes. ++ ++ gdb_test {print/x mbuf_rw[pagesize]@4} {\{0x6b, 0x6b, 0x6b, 0x6b\}} ++ gdb_test {print/x mbuf_ro[pagesize]@4} {\{0xc5, 0xc5, 0xc5, 0xc5\}} ++ ++ # Check contents at ends of buf_rw and buf_rw. ++ ++ gdb_test {print/x buf_rw[sizeof(buf_rw)-4]@4} {\{0x6b, 0x6b, 0x6b, 0x6b\}} ++ gdb_test {print/x buf_ro[sizeof(buf_ro)-4]@4} {\{0xc5, 0xc5, 0xc5, 0xc5\}} ++} ++ ++# Run tests with kernel-produced core file. ++ ++with_test_prefix "kernel core" { ++ do_tests ++} ++ ++# Verify that "maint print core-file-backed-mappings" exists and does ++# not crash GDB. If it produces any output at all, make sure that ++# that output at least mentions binfile. ++ ++set test "maint print core-file-backed-mappings" ++gdb_test_multiple $test "" { ++ -re ".*$binfile.*$gdb_prompt $" { ++ pass $test ++ } ++ -re "^$test\[\r\n\]*$gdb_prompt $" { ++ pass "$test (no output)" ++ } ++} ++ ++# Restart and run to the abort call. ++ ++clean_restart $binfile ++ ++if ![runto_main] then { ++ fail "can't run to main" ++ return ++} ++ ++gdb_breakpoint [gdb_get_line_number "abort"] ++gdb_continue_to_breakpoint "at abort" ++ ++# Do not execute abort call; instead, invoke gcore command to make a ++# gdb-produced core file. ++ ++set corefile [standard_output_file gcore.test] ++set core_supported [gdb_gcore_cmd "$corefile" "save a corefile"] ++if {!$core_supported} { ++ return ++} ++ ++# maint print-core-file-backed-mappings shouldn't produce any output ++# when not debugging a core file. ++ ++gdb_test_no_output "maint print core-file-backed-mappings" \ ++ "maint print core-file-backed-mapping with no core file" ++ ++clean_restart $binfile ++ ++set core_loaded [gdb_core_cmd "$corefile" "re-load generated corefile"] ++if { $core_loaded == -1 } { ++ # No use proceeding from here. ++ return ++} ++ ++# Run tests using gcore-produced core file. ++ ++with_test_prefix "gcore core" { ++ do_tests ++} +diff --git a/gdb/testsuite/gdb.base/coremaker2.c b/gdb/testsuite/gdb.base/coremaker2.c +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/coremaker2.c +@@ -0,0 +1,150 @@ ++/* Copyright 1992-2020 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++/* This test has two large memory areas buf_rw and buf_ro. ++ ++ buf_rw is written to by the program while buf_ro is initialized at ++ compile / load time. Thus, when a core file is created, buf_rw's ++ memory should reside in the core file, but buf_ro probably won't be. ++ Instead, the contents of buf_ro are available from the executable. ++ ++ Now, for the wrinkle: We create a one page read-only mapping over ++ both of these areas. This will create a one page "hole" of all ++ zeros in each area. ++ ++ Will GDB be able to correctly read memory from each of the four ++ (or six, if you count the regions on the other side of each hole) ++ memory regions? */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* These are globals so that we can find them easily when debugging ++ the core file. */ ++long pagesize; ++unsigned long long addr; ++char *mbuf_ro; ++char *mbuf_rw; ++ ++/* 24 KiB buffer. */ ++char buf_rw[24 * 1024]; ++ ++/* 24 KiB worth of data. For this test case, we can't allocate a ++ buffer and then fill it; we want GDB to have to read this data ++ from the executable; it should NOT find it in the core file. */ ++ ++#define C5_16 \ ++ 0xc5, 0xc5, 0xc5, 0xc5, \ ++ 0xc5, 0xc5, 0xc5, 0xc5, \ ++ 0xc5, 0xc5, 0xc5, 0xc5, \ ++ 0xc5, 0xc5, 0xc5, 0xc5 ++ ++#define C5_256 \ ++ C5_16, C5_16, C5_16, C5_16, \ ++ C5_16, C5_16, C5_16, C5_16, \ ++ C5_16, C5_16, C5_16, C5_16, \ ++ C5_16, C5_16, C5_16, C5_16 ++ ++#define C5_1k \ ++ C5_256, C5_256, C5_256, C5_256 ++ ++#define C5_24k \ ++ C5_1k, C5_1k, C5_1k, C5_1k, \ ++ C5_1k, C5_1k, C5_1k, C5_1k, \ ++ C5_1k, C5_1k, C5_1k, C5_1k, \ ++ C5_1k, C5_1k, C5_1k, C5_1k, \ ++ C5_1k, C5_1k, C5_1k, C5_1k, \ ++ C5_1k, C5_1k, C5_1k, C5_1k ++ ++const char buf_ro[] = { C5_24k }; ++ ++int ++main (int argc, char **argv) ++{ ++ int i, bitcount; ++ ++#ifdef _SC_PAGESIZE ++ pagesize = sysconf (_SC_PAGESIZE); ++#else ++ pagesize = 8192; ++#endif ++ ++ /* Verify that pagesize is a power of 2. */ ++ bitcount = 0; ++ for (i = 0; i < 4 * sizeof (pagesize); i++) ++ if (pagesize & (1 << i)) ++ bitcount++; ++ ++ if (bitcount != 1) ++ { ++ fprintf (stderr, "pagesize is not a power of 2.\n"); ++ exit (1); ++ } ++ ++ /* Compute an address that should be within buf_ro. Complain if not. */ ++ addr = ((unsigned long long) buf_ro + pagesize) & ~(pagesize - 1); ++ ++ if (addr <= (unsigned long long) buf_ro ++ || addr >= (unsigned long long) buf_ro + sizeof (buf_ro)) ++ { ++ fprintf (stderr, "Unable to compute a suitable address within buf_ro.\n"); ++ exit (1); ++ } ++ ++ mbuf_ro = mmap ((void *) addr, pagesize, PROT_READ, ++ MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); ++ ++ if (mbuf_ro == MAP_FAILED) ++ { ++ fprintf (stderr, "mmap #1 failed: %s.\n", strerror (errno)); ++ exit (1); ++ } ++ ++ /* Write (and fill) the R/W region. */ ++ for (i = 0; i < sizeof (buf_rw); i++) ++ buf_rw[i] = 0x6b; ++ ++ /* Compute an mmap address within buf_rw. Complain if it's somewhere ++ else. */ ++ addr = ((unsigned long long) buf_rw + pagesize) & ~(pagesize - 1); ++ ++ if (addr <= (unsigned long long) buf_rw ++ || addr >= (unsigned long long) buf_rw + sizeof (buf_rw)) ++ { ++ fprintf (stderr, "Unable to compute a suitable address within buf_rw.\n"); ++ exit (1); ++ } ++ ++ mbuf_rw = mmap ((void *) addr, pagesize, PROT_READ, ++ MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); ++ ++ if (mbuf_rw == MAP_FAILED) ++ { ++ fprintf (stderr, "mmap #2 failed: %s.\n", strerror (errno)); ++ exit (1); ++ } ++ ++ /* With correct ulimit, etc. this should cause a core dump. */ ++ abort (); ++} diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-15of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-15of15.patch new file mode 100644 index 0000000..89ab175 --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-15of15.patch @@ -0,0 +1,30 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Tue, 28 Jul 2020 09:49:56 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-15of15.patch + +;; Add period to help text for maint print core-file-backed-mappings +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Thu Jul 23 13:26:44 2020 -0700 + + Fix BZ 26294 - Add period to help text for maint print core-file-backed-mappings + + gdb/ChangeLog: + + PR corefiles/26294 + * corelow.c (_initialize_corelow): Add period to help text + for "maintenance print core-file-backed-mappings". + +diff --git a/gdb/corelow.c b/gdb/corelow.c +--- a/gdb/corelow.c ++++ b/gdb/corelow.c +@@ -1388,6 +1388,6 @@ Show whether CORE-FILE loads the build-id associated files automatically."), + &setlist, &showlist); + add_cmd ("core-file-backed-mappings", class_maintenance, + maintenance_print_core_file_backed_mappings, +- _("Print core file's file-backed mappings"), ++ _("Print core file's file-backed mappings."), + &maintenanceprintlist); + } diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-1of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-1of15.patch new file mode 100644 index 0000000..fbca53a --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-1of15.patch @@ -0,0 +1,60 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Mon, 27 Jul 2020 16:34:37 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-1of15.patch + +;; Remove hack for GDB which sets the section size to 0 +;; Kevin Buettner, RH BZ 1842691 + + Author: Kevin Buettner + + Remove hack for GDB which sets the section size to 0 + + This commit removes a hack for GDB which was introduced in 2007. + See: + + https://sourceware.org/ml/binutils/2007-08/msg00044.html + + That hack mostly allowed GDB's handling of core files to continue to + work without any changes to GDB. + + The problem with setting the section size to zero is that GDB won't + know how big that section is/was. Often, this doesn't matter because + the data in question are found in the exec file. But it can happen + that the section describes memory that had been allocated, but never + written to. In this instance, the contents of that memory region are + not written to the core file. Also, since the region in question was + dynamically allocated, it won't appear in the exec file. We don't + want these regions to appear as inaccessible to GDB (since they *were* + accessible when the process was live), so it's important that GDB know + the size of the region. + + I've made changes to GDB which correctly handles this case. When + attempting to access memory, GDB will first consider core file data + for which both SEC_ALLOC and SEC_HAS_CONTENTS is set. Next, if that + fails, GDB will attempt to find the data in the exec file. Finally, + if that also fails, GDB will attempt to access memory in the sections + which are flagged as SEC_ALLOC, but not SEC_HAS_CONTENTS. + + bfd/ChangeLog: + + * elf.c (_bfd_elf_make_section_from_phdr): Remove hack for GDB. + +diff --git a/bfd/elf.c b/bfd/elf.c +--- a/bfd/elf.c ++++ b/bfd/elf.c +@@ -2975,14 +2975,6 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, + newsect->alignment_power = bfd_log2 (align); + if (hdr->p_type == PT_LOAD) + { +- /* Hack for gdb. Segments that have not been modified do +- not have their contents written to a core file, on the +- assumption that a debugger can find the contents in the +- executable. We flag this case by setting the fake +- section size to zero. Note that "real" bss sections will +- always have their contents dumped to the core file. */ +- if (bfd_get_format (abfd) == bfd_core) +- newsect->size = 0; + newsect->flags |= SEC_ALLOC; + if (hdr->p_flags & PF_X) + newsect->flags |= SEC_CODE; diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-2of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-2of15.patch new file mode 100644 index 0000000..60f8e77 --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-2of15.patch @@ -0,0 +1,129 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Mon, 27 Jul 2020 16:47:19 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-2of15.patch + +;; Adjust corefile.exp test to show regression after bfd hack removal +;; Kevin Buettner, RH BZ 1842691 + + Author: Kevin Buettner + Date: Tue May 12 17:44:19 2020 -0700 + + Adjust corefile.exp test to show regression after bfd hack removal + + In his review of my BZ 25631 patch series, Pedro was unable to + reproduce the regression which should occur after patch #1, "Remove + hack for GDB which sets the section size to 0", is applied. + + Pedro was using an ld version older than 2.30. Version 2.30 + introduced the linker option -z separate-code. Here's what the man + page has to say about it: + + Create separate code "PT_LOAD" segment header in the object. This + specifies a memory segment that should contain only instructions + and must be in wholly disjoint pages from any other data. + + In ld version 2.31, use of separate-code became the default for + Linux/x86. So, really, 2.31 or later is required in order to see the + regression that occurs in recent Linux distributions when only the + bfd hack removal patch is applied. + + For the test case in question, use of the separate-code linker option + means that the global variable "coremaker_ro" ends up in a separate + load segment (though potentially with other read-only data). The + upshot of this is that when only patch #1 is applied, GDB won't be + able to correctly access coremaker_ro. The reason for this is due + to the fact that this section will now have a non-zero size, but + will not have contents from the core file to find this data. + So GDB will ask BFD for the contents and BFD will respond with + zeroes for anything from those sections. GDB should instead be + looking in the executable for this data. Failing that, it can + then ask BFD for a reasonable value. This is what a later patch + in this series does. + + When using ld versions earlier than 2.31 (or 2.30 w/ the + -z separate-code option explicitly provided to the linker), there is + the possibility that coremaker_ro ends up being placed near other data + which is recorded in the core file. That means that the correct value + will end up in the core file, simply because it resides on a page that + the kernel chooses to put in the core file. This is why Pedro wasn't + able to reproduce the regression that should occur after fixing the + BFD hack. + + This patch places a big chunk of memory, two pages worth on x86, in + front of "coremaker_ro" to attempt to force it onto another page + without requiring use of that new-fangled linker switch. + + Speaking of which, I considered changing the test to use + -z separate-code, but this won't work because it didn't + exist prior to version 2.30. The linker would probably complain + of an unrecognized switch. Also, it likely won't be available in + other linkers not based on current binutils. I.e. it probably won't + work in FreeBSD, NetBSD, etc. + + To make this more concrete, this is what *should* happen when + attempting to access coremaker_ro when only patch #1 is applied: + + Core was generated by `/mesquite2/sourceware-git/f28-coresegs/bld/gdb/testsuite/outputs/gdb.base/coref'. + Program terminated with signal SIGABRT, Aborted. + #0 0x00007f68205deefb in raise () from /lib64/libc.so.6 + (gdb) p coremaker_ro + $1 = 0 + + Note that this result is wrong; 201 should have been printed instead. + But that's the point of the rest of the patch series. + + However, without this commit, or when using an old Linux distro with + a pre-2.31 ld, this is what you might see instead: + + Core was generated by `/mesquite2/sourceware-git/f28-coresegs/bld/gdb/testsuite/outputs/gdb.base/coref'. + Program terminated with signal SIGABRT, Aborted. + #0 0x00007f63dd658efb in raise () from /lib64/libc.so.6 + (gdb) p coremaker_ro + $1 = 201 + + I.e. it prints the right answer, which sort of makes it seem like the + rest of the series isn't required. + + Now, back to the patch itself... what should be the size of the memory + chunk placed before coremaker_ro? + + It needs to be at least as big as the page size (PAGE_SIZE) from + the kernel. For x86 and several other architectures this value is + 4096. I used MAPSIZE which is defined to be 8192 in coremaker.c. + So it's twice as big as what's currently needed for most Linux + architectures. The constant PAGE_SIZE is available from , + but this isn't portable either. In the end, it seemed simpler to + just pick a value and hope that it's big enough. (Running a separate + program which finds the page size via sysconf(_SC_PAGESIZE) and then + passes it to the compilation via a -D switch seemed like overkill + for a case which is rendered moot by recent linker versions.) + + Further information can be found here: + + https://sourceware.org/pipermail/gdb-patches/2020-May/168168.html + https://sourceware.org/pipermail/gdb-patches/2020-May/168170.html + + Thanks to H.J. Lu for telling me about the '-z separate-code' linker + switch. + + gdb/testsuite/ChangeLog: + + * gdb.base/coremaker.c (filler_ro): New global constant. + +diff --git a/gdb/testsuite/gdb.base/coremaker.c b/gdb/testsuite/gdb.base/coremaker.c +--- a/gdb/testsuite/gdb.base/coremaker.c ++++ b/gdb/testsuite/gdb.base/coremaker.c +@@ -42,6 +42,12 @@ char *buf2; + int coremaker_data = 1; /* In Data section */ + int coremaker_bss; /* In BSS section */ + ++/* Place a chunk of memory before coremaker_ro to improve the chances ++ that coremaker_ro will end up on it's own page. See: ++ ++ https://sourceware.org/pipermail/gdb-patches/2020-May/168168.html ++ https://sourceware.org/pipermail/gdb-patches/2020-May/168170.html */ ++const unsigned char filler_ro[MAPSIZE] = {1, 2, 3, 4, 5, 6, 7, 8}; + const int coremaker_ro = 201; /* In Read-Only Data section */ + + /* Note that if the mapping fails for any reason, we set buf2 diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-3of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-3of15.patch new file mode 100644 index 0000000..7ddeebc --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-3of15.patch @@ -0,0 +1,174 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Mon, 27 Jul 2020 16:52:18 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-3of15.patch + +;; section_table_xfer_memory: Replace section name with callback predicate +;; Kevin Buettner, RH BZ 1842691 + + Author: Kevin Buettner + Date: Wed Mar 4 17:42:41 2020 -0700 + + section_table_xfer_memory: Replace section name with callback predicate + + This patch is motivated by the need to be able to select sections + that section_table_xfer_memory_partial should consider for memory + transfers. I'll use this facility in the next patch in this series. + + section_table_xfer_memory_partial() can currently be passed a section + name which may be used to make name-based selections. This is similar + to what I want to do, except that I want to be able to consider + section flags instead of the name. + + I'm replacing the section name parameter with a predicate that, + when passed a pointer to a target_section struct, will return + true if that section should be further considered, or false which + indicates that it shouldn't. + + I've converted the one existing use where a non-NULL section + name is passed to section_table_xfer_memory_partial(). Instead + of passing the section name, it now looks like this: + + auto match_cb = [=] (const struct target_section *s) + { + return (strcmp (section_name, s->the_bfd_section->name) == 0); + }; + + return section_table_xfer_memory_partial (readbuf, writebuf, + memaddr, len, xfered_len, + table->sections, + table->sections_end, + match_cb); + + The other callers all passed NULL; they've been simplified somewhat + in that they no longer need to pass NULL. + + gdb/ChangeLog: + + * exec.h (section_table_xfer_memory): Revise declaration, + replacing section name parameter with an optional callback + predicate. + * exec.c (section_table_xfer_memory): Likewise. + * bfd-target.c, exec.c, target.c, corelow.c: Adjust all callers + of section_table_xfer_memory. + +diff --git a/gdb/bfd-target.c b/gdb/bfd-target.c +--- a/gdb/bfd-target.c ++++ b/gdb/bfd-target.c +@@ -75,8 +75,7 @@ target_bfd::xfer_partial (target_object object, + return section_table_xfer_memory_partial (readbuf, writebuf, + offset, len, xfered_len, + m_table.sections, +- m_table.sections_end, +- NULL); ++ m_table.sections_end); + } + default: + return TARGET_XFER_E_IO; +diff --git a/gdb/corelow.c b/gdb/corelow.c +--- a/gdb/corelow.c ++++ b/gdb/corelow.c +@@ -820,8 +820,7 @@ core_target::xfer_partial (enum target_object object, const char *annex, + (readbuf, writebuf, + offset, len, xfered_len, + m_core_section_table.sections, +- m_core_section_table.sections_end, +- NULL)); ++ m_core_section_table.sections_end)); + + case TARGET_OBJECT_AUXV: + if (readbuf) +diff --git a/gdb/exec.c b/gdb/exec.c +--- a/gdb/exec.c ++++ b/gdb/exec.c +@@ -805,7 +805,8 @@ section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST *xfered_len, + struct target_section *sections, + struct target_section *sections_end, +- const char *section_name) ++ gdb::function_view match_cb) + { + int res; + struct target_section *p; +@@ -821,7 +822,7 @@ section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf, + struct bfd_section *asect = p->the_bfd_section; + bfd *abfd = asect->owner; + +- if (section_name && strcmp (section_name, asect->name) != 0) ++ if (match_cb != nullptr && !match_cb (p)) + continue; /* not the section we need. */ + if (memaddr >= p->addr) + { +@@ -894,8 +895,7 @@ exec_target::xfer_partial (enum target_object object, + return section_table_xfer_memory_partial (readbuf, writebuf, + offset, len, xfered_len, + table->sections, +- table->sections_end, +- NULL); ++ table->sections_end); + else + return TARGET_XFER_E_IO; + } +diff --git a/gdb/exec.h b/gdb/exec.h +--- a/gdb/exec.h ++++ b/gdb/exec.h +@@ -58,8 +58,13 @@ extern enum target_xfer_status + Request to transfer up to LEN 8-bit bytes of the target sections + defined by SECTIONS and SECTIONS_END. The OFFSET specifies the + starting address. +- If SECTION_NAME is not NULL, only access sections with that same +- name. ++ ++ The MATCH_CB predicate is optional; when provided it will be called ++ for each section under consideration. When MATCH_CB evaluates as ++ true, the section remains under consideration; a false result ++ removes it from consideration for performing the memory transfers ++ noted above. See memory_xfer_partial_1() in target.c for an ++ example. + + Return the number of bytes actually transfered, or zero when no + data is available for the requested range. +@@ -76,7 +81,9 @@ extern enum target_xfer_status + ULONGEST, ULONGEST, ULONGEST *, + struct target_section *, + struct target_section *, +- const char *); ++ gdb::function_view match_cb ++ = nullptr); + + /* Read from mappable read-only sections of BFD executable files. + Similar to exec_read_partial_read_only, but return +diff --git a/gdb/target.c b/gdb/target.c +--- a/gdb/target.c ++++ b/gdb/target.c +@@ -1098,11 +1098,17 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, + const char *section_name = section->the_bfd_section->name; + + memaddr = overlay_mapped_address (memaddr, section); ++ ++ auto match_cb = [=] (const struct target_section *s) ++ { ++ return (strcmp (section_name, s->the_bfd_section->name) == 0); ++ }; ++ + return section_table_xfer_memory_partial (readbuf, writebuf, + memaddr, len, xfered_len, + table->sections, + table->sections_end, +- section_name); ++ match_cb); + } + } + +@@ -1122,8 +1128,7 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, + return section_table_xfer_memory_partial (readbuf, writebuf, + memaddr, len, xfered_len, + table->sections, +- table->sections_end, +- NULL); ++ table->sections_end); + } + } + diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-4of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-4of15.patch new file mode 100644 index 0000000..2c09816 --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-4of15.patch @@ -0,0 +1,227 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Mon, 27 Jul 2020 17:11:49 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-4of15.patch + +;; Provide access to non SEC_HAS_CONTENTS core file sections +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Wed Mar 4 17:42:42 2020 -0700 + + Provide access to non SEC_HAS_CONTENTS core file sections + + Consider the following program: + + - - - mkmmapcore.c - - - + + static char *buf; + + int + main (int argc, char **argv) + { + buf = mmap (NULL, 8192, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + abort (); + } + - - - end mkmmapcore.c - - - + + Compile it like this: + + gcc -g -o mkmmapcore mkmmapcore.c + + Now let's run it from GDB. I've already placed a breakpoint on the + line with the abort() call and have run to that breakpoint. + + Breakpoint 1, main (argc=1, argv=0x7fffffffd678) at mkmmapcore.c:11 + 11 abort (); + (gdb) x/x buf + 0x7ffff7fcb000: 0x00000000 + + Note that we can examine the memory allocated via the call to mmap(). + + Now let's try debugging a core file created by running this program. + Depending on your system, in order to make a core file, you may have to + run the following as root (or using sudo): + + echo core > /proc/sys/kernel/core_pattern + + It may also be necessary to do: + + ulimit -c unlimited + + I'm using Fedora 31. YMMV if you're using one of the BSDs or some other + (non-Linux) system. + + This is what things look like when we debug the core file: + + [kev@f31-1 tmp]$ gdb -q ./mkmmapcore core.304767 + Reading symbols from ./mkmmapcore... + [New LWP 304767] + Core was generated by `/tmp/mkmmapcore'. + Program terminated with signal SIGABRT, Aborted. + #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 + 50 return ret; + (gdb) x/x buf + 0x7ffff7fcb000: Cannot access memory at address 0x7ffff7fcb000 + + Note that we can no longer access the memory region allocated by mmap(). + + Back in 2007, a hack for GDB was added to _bfd_elf_make_section_from_phdr() + in bfd/elf.c: + + /* Hack for gdb. Segments that have not been modified do + not have their contents written to a core file, on the + assumption that a debugger can find the contents in the + executable. We flag this case by setting the fake + section size to zero. Note that "real" bss sections will + always have their contents dumped to the core file. */ + if (bfd_get_format (abfd) == bfd_core) + newsect->size = 0; + + You can find the entire patch plus links to other discussion starting + here: + + https://sourceware.org/ml/binutils/2007-08/msg00047.html + + This hack sets the size of certain BFD sections to 0, which + effectively causes GDB to ignore them. I think it's likely that the + bug described above existed even before this hack was added, but I + have no easy way to test this now. + + The output from objdump -h shows the result of this hack: + + 25 load13 00000000 00007ffff7fcb000 0000000000000000 00013000 2**12 + ALLOC + + (The first field, after load13, shows the size of 0.) + + Once the hack is removed, the output from objdump -h shows the correct + size: + + 25 load13 00002000 00007ffff7fcb000 0000000000000000 00013000 2**12 + ALLOC + + (This is a digression, but I think it's good that objdump will now show + the correct size.) + + If we remove the hack from bfd/elf.c, but do nothing to GDB, we'll + see the following regression: + + FAIL: gdb.base/corefile.exp: print coremaker_ro + + The reason for this is that all sections which have the BFD flag + SEC_ALLOC set, but for which SEC_HAS_CONTENTS is not set no longer + have zero size. Some of these sections have data that can (and should) + be read from the executable. (Sections for which SEC_HAS_CONTENTS + is set should be read from the core file; sections which do not have + this flag set need to either be read from the executable or, failing + that, from the core file using whatever BFD decides is the best value + to present to the user - it uses zeros.) + + At present, due to the way that the target strata are traversed when + attempting to access memory, the non-SEC_HAS_CONTENTS sections will be + read as zeroes from the process_stratum (which in this case is the + core file stratum) without first checking the file stratum, which is + where the data might actually be found. + + What we should be doing is this: + + - Attempt to access core file data for SEC_HAS_CONTENTS sections. + - Attempt to access executable file data if the above fails. + - Attempt to access core file data for non SEC_HAS_CONTENTS sections, if + both of the above fail. + + This corresponds to the analysis of Daniel Jacobowitz back in 2007 + when the hack was added to BFD: + + https://sourceware.org/legacy-ml/binutils/2007-08/msg00045.html + + The difference, observed by Pedro in his review of my v1 patches, is + that I'm using "the section flags as proxy for the p_filesz/p_memsz + checks." + + gdb/ChangeLog: + + PR corefiles/25631 + * corelow.c (core_target:xfer_partial): Revise + TARGET_OBJECT_MEMORY case to consider non-SEC_HAS_CONTENTS + case after first checking the stratum beneath the core + target. + (has_all_memory): Return true. + * target.c (raw_memory_xfer_partial): Revise comment + regarding use of has_all_memory. + +diff --git a/gdb/corelow.c b/gdb/corelow.c +--- a/gdb/corelow.c ++++ b/gdb/corelow.c +@@ -816,12 +816,47 @@ core_target::xfer_partial (enum target_object object, const char *annex, + switch (object) + { + case TARGET_OBJECT_MEMORY: +- return (section_table_xfer_memory_partial +- (readbuf, writebuf, +- offset, len, xfered_len, +- m_core_section_table.sections, +- m_core_section_table.sections_end)); ++ { ++ enum target_xfer_status xfer_status; ++ ++ /* Try accessing memory contents from core file data, ++ restricting consideration to those sections for which ++ the BFD section flag SEC_HAS_CONTENTS is set. */ ++ auto has_contents_cb = [] (const struct target_section *s) ++ { ++ return ((s->the_bfd_section->flags & SEC_HAS_CONTENTS) != 0); ++ }; ++ xfer_status = section_table_xfer_memory_partial ++ (readbuf, writebuf, ++ offset, len, xfered_len, ++ m_core_section_table.sections, ++ m_core_section_table.sections_end, ++ has_contents_cb); ++ if (xfer_status == TARGET_XFER_OK) ++ return TARGET_XFER_OK; ++ ++ /* Now check the stratum beneath us; this should be file_stratum. */ ++ xfer_status = this->beneath ()->xfer_partial (object, annex, readbuf, ++ writebuf, offset, len, ++ xfered_len); ++ if (xfer_status == TARGET_XFER_OK) ++ return TARGET_XFER_OK; + ++ /* Finally, attempt to access data in core file sections with ++ no contents. These will typically read as all zero. */ ++ auto no_contents_cb = [&] (const struct target_section *s) ++ { ++ return !has_contents_cb (s); ++ }; ++ xfer_status = section_table_xfer_memory_partial ++ (readbuf, writebuf, ++ offset, len, xfered_len, ++ m_core_section_table.sections, ++ m_core_section_table.sections_end, ++ no_contents_cb); ++ ++ return xfer_status; ++ } + case TARGET_OBJECT_AUXV: + if (readbuf) + { +diff --git a/gdb/target.c b/gdb/target.c +--- a/gdb/target.c ++++ b/gdb/target.c +@@ -1043,8 +1043,11 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf, + if (res == TARGET_XFER_UNAVAILABLE) + break; + +- /* We want to continue past core files to executables, but not +- past a running target's memory. */ ++ /* Don't continue past targets which have all the memory. ++ At one time, this code was necessary to read data from ++ executables / shared libraries when data for the requested ++ addresses weren't available in the core file. But now the ++ core target handles this case itself. */ + if (ops->has_all_memory ()) + break; + diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-5of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-5of15.patch new file mode 100644 index 0000000..9b0a49f --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-5of15.patch @@ -0,0 +1,68 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Mon, 27 Jul 2020 17:27:39 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-5of15.patch + +;; Test ability to access unwritten-to mmap data in core file +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Wed Mar 4 17:42:43 2020 -0700 + + Test ability to access unwritten-to mmap data in core file + + gdb/testsuite/ChangeLog: + + PR corefiles/25631 + * gdb.base/corefile.exp (accessing anonymous, unwritten-to mmap data): + New test. + * gdb.base/coremaker.c (buf3): New global. + (mmapdata): Add mmap call which uses MAP_ANONYMOUS and MAP_PRIVATE + flags. + +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 +@@ -175,6 +175,15 @@ gdb_test_multiple "x/8bd buf2" "$test" { + } + } + ++# Test ability to read anonymous and, more importantly, unwritten-to ++# mmap'd data. ++ ++if { ![istarget *-linux*] } { ++ setup_xfail "*-*-*" ++} ++gdb_test "x/wx buf3" "$hex:\[ \t\]+0x00000000" \ ++ "accessing anonymous, unwritten-to mmap data" ++ + # test reinit_frame_cache + + gdb_load ${binfile} +diff --git a/gdb/testsuite/gdb.base/coremaker.c b/gdb/testsuite/gdb.base/coremaker.c +--- a/gdb/testsuite/gdb.base/coremaker.c ++++ b/gdb/testsuite/gdb.base/coremaker.c +@@ -38,6 +38,7 @@ + + char *buf1; + char *buf2; ++char *buf3; + + int coremaker_data = 1; /* In Data section */ + int coremaker_bss; /* In BSS section */ +@@ -104,6 +105,15 @@ mmapdata () + } + /* Touch buf2 so kernel writes it out into 'core'. */ + buf2[0] = buf1[0]; ++ ++ /* Create yet another region which is allocated, but not written to. */ ++ buf3 = mmap (NULL, MAPSIZE, PROT_READ | PROT_WRITE, ++ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ if (buf3 == (char *) -1) ++ { ++ perror ("mmap failed"); ++ return; ++ } + } + + void diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-6of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-6of15.patch new file mode 100644 index 0000000..0df6f68 --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-6of15.patch @@ -0,0 +1,62 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Mon, 27 Jul 2020 17:32:50 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-6of15.patch + +;; Update binary_get_section_contents to seek using section's file position +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Thu Jun 11 18:58:49 2020 -0700 + + Update binary_get_section_contents to seek using section's file position + + I have a patch for GDB which opens and reads from BFDs using the + "binary" target. However, for it to work, we need to be able to get a + section's contents based from the file position of that section. + + At the moment, reading a section's contents will always read from the + start of the file regardless of where that section is located. While + this was fine for the original use of the "binary" target, it won't + work for my use case. This change shouldn't impact any existing + callers due to the fact that the single .data section is initialized + with a filepos of 0. + + bfd/ChangeLog: + + * binary.c (binary_get_section_contents): Seek using offset + from section's file position. + +diff --git a/bfd/binary.c b/bfd/binary.c +--- a/bfd/binary.c ++++ b/bfd/binary.c +@@ -19,10 +19,10 @@ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +-/* This is a BFD backend which may be used to write binary objects. +- It may only be used for output, not input. The intention is that +- this may be used as an output format for objcopy in order to +- generate raw binary data. ++/* This is a BFD backend which may be used to read or write binary ++ objects. Historically, it was used as an output format for objcopy ++ in order to generate raw binary data, but is now used for other ++ purposes as well. + + This is very simple. The only complication is that the real data + will start at some address X, and in some cases we will not want to +@@ -97,12 +97,12 @@ binary_object_p (bfd *abfd) + + static bfd_boolean + binary_get_section_contents (bfd *abfd, +- asection *section ATTRIBUTE_UNUSED, ++ asection *section, + void * location, + file_ptr offset, + bfd_size_type count) + { +- if (bfd_seek (abfd, offset, SEEK_SET) != 0 ++ if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0 + || bfd_bread (location, count, abfd) != count) + return FALSE; + return TRUE; diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-7of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-7of15.patch new file mode 100644 index 0000000..b09feea --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-7of15.patch @@ -0,0 +1,180 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Mon, 27 Jul 2020 18:01:32 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-7of15.patch + +;; Add new gdbarch method, read_core_file_mappings +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Fri Jul 3 13:32:08 2020 -0700 + + Add new gdbarch method, read_core_file_mappings + + The new gdbarch method, read_core_file_mappings, will be used for + reading file-backed mappings from a core file. It'll be used + for two purposes: 1) to construct a table of file-backed mappings + in corelow.c, and 2) for display of core file mappings. + + For Linux, I tried a different approach in which knowledge of the note + format was placed directly in corelow.c. This seemed okay at first; + it was only one note format and the note format was fairly simple. + After looking at FreeBSD's note/mapping reading code, I concluded + that it's best to leave architecture specific details for decoding + the note in (architecture specific) tdep files. + + With regard to display of core file mappings, I experimented with + placing the mappings display code in corelow.c. It has access to the + file-backed mappings which were read in when the core file was loaded. + And, better, still common code could be used for all architectures. + But, again, the FreeBSD mapping code convinced me that this was not + the best approach since it has even more mapping info than Linux. + Display code which would work well for Linux will leave out mappings + as well as protection info for mappings. + + So, for these reasons, I'm introducing a new gdbarch method for + reading core file mappings. + + gdb/ChangeLog: + + * arch-utils.c (default_read_core_file_mappings): New function. + * arch-utils.c (default_read_core_file_mappings): Declare. + * gdbarch.sh (read_core_file_mappings): New gdbarch method. + * gdbarch.h, gdbarch.c: Regenerate. + +diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c +--- a/gdb/arch-utils.c ++++ b/gdb/arch-utils.c +@@ -997,6 +997,22 @@ default_type_align (struct gdbarch *gdbarch, struct type *type) + return type_length_units (check_typedef (type)); + } + ++/* See arch-utils.h. */ ++void ++default_read_core_file_mappings (struct gdbarch *gdbarch, ++ struct bfd *cbfd, ++ gdb::function_view ++ pre_loop_cb, ++ gdb::function_view ++ loop_cb) ++{ ++} ++ + void + _initialize_gdbarch_utils (void) + { +diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h +--- a/gdb/arch-utils.h ++++ b/gdb/arch-utils.h +@@ -271,4 +271,16 @@ extern bool default_in_indirect_branch_thunk (gdbarch *gdbarch, + extern ULONGEST default_type_align (struct gdbarch *gdbarch, + struct type *type); + ++/* Default implementation of gdbarch read_core_file_mappings method. */ ++extern void default_read_core_file_mappings (struct gdbarch *gdbarch, ++ struct bfd *cbfd, ++ gdb::function_view ++ pre_loop_cb, ++ gdb::function_view ++ loop_cb); + #endif +diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c +--- a/gdb/gdbarch.c ++++ b/gdb/gdbarch.c +@@ -354,6 +354,7 @@ struct gdbarch + char ** disassembler_options; + const disasm_options_and_args_t * valid_disassembler_options; + gdbarch_type_align_ftype *type_align; ++ gdbarch_read_core_file_mappings_ftype *read_core_file_mappings; + }; + + /* Create a new ``struct gdbarch'' based on information provided by +@@ -466,6 +467,7 @@ gdbarch_alloc (const struct gdbarch_info *info, + gdbarch->gnu_triplet_regexp = default_gnu_triplet_regexp; + gdbarch->addressable_memory_unit_size = default_addressable_memory_unit_size; + gdbarch->type_align = default_type_align; ++ gdbarch->read_core_file_mappings = default_read_core_file_mappings; + /* gdbarch_alloc() */ + + return gdbarch; +@@ -712,6 +714,7 @@ verify_gdbarch (struct gdbarch *gdbarch) + /* Skip verify of disassembler_options, invalid_p == 0 */ + /* Skip verify of valid_disassembler_options, invalid_p == 0 */ + /* Skip verify of type_align, invalid_p == 0 */ ++ /* Skip verify of read_core_file_mappings, invalid_p == 0 */ + if (!log.empty ()) + internal_error (__FILE__, __LINE__, + _("verify_gdbarch: the following are invalid ...%s"), +@@ -1275,6 +1278,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) + fprintf_unfiltered (file, + "gdbarch_dump: ravenscar_ops = %s\n", + host_address_to_string (gdbarch->ravenscar_ops)); ++ fprintf_unfiltered (file, ++ "gdbarch_dump: read_core_file_mappings = <%s>\n", ++ host_address_to_string (gdbarch->read_core_file_mappings)); + fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_read_pc_p() = %d\n", + gdbarch_read_pc_p (gdbarch)); +@@ -5117,6 +5123,23 @@ set_gdbarch_type_align (struct gdbarch *gdbarch, + gdbarch->type_align = type_align; + } + ++void ++gdbarch_read_core_file_mappings (struct gdbarch *gdbarch, struct bfd *cbfd,gdb::function_view pre_loop_cb,gdb::function_view loop_cb) ++{ ++ gdb_assert (gdbarch != NULL); ++ gdb_assert (gdbarch->read_core_file_mappings != NULL); ++ if (gdbarch_debug >= 2) ++ fprintf_unfiltered (gdb_stdlog, "gdbarch_read_core_file_mappings called\n"); ++ gdbarch->read_core_file_mappings (gdbarch, cbfd, pre_loop_cb, loop_cb); ++} ++ ++void ++set_gdbarch_read_core_file_mappings (struct gdbarch *gdbarch, ++ gdbarch_read_core_file_mappings_ftype read_core_file_mappings) ++{ ++ gdbarch->read_core_file_mappings = read_core_file_mappings; ++} ++ + + /* Keep a registry of per-architecture data-pointers required by GDB + modules. */ +diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h +--- a/gdb/gdbarch.h ++++ b/gdb/gdbarch.h +@@ -1566,6 +1566,12 @@ typedef ULONGEST (gdbarch_type_align_ftype) (struct gdbarch *gdbarch, struct typ + extern ULONGEST gdbarch_type_align (struct gdbarch *gdbarch, struct type *type); + extern void set_gdbarch_type_align (struct gdbarch *gdbarch, gdbarch_type_align_ftype *type_align); + ++/* Read core file mappings */ ++ ++typedef void (gdbarch_read_core_file_mappings_ftype) (struct gdbarch *gdbarch, struct bfd *cbfd,gdb::function_view pre_loop_cb,gdb::function_view loop_cb); ++extern void gdbarch_read_core_file_mappings (struct gdbarch *gdbarch, struct bfd *cbfd,gdb::function_view pre_loop_cb,gdb::function_view loop_cb); ++extern void set_gdbarch_read_core_file_mappings (struct gdbarch *gdbarch, gdbarch_read_core_file_mappings_ftype *read_core_file_mappings); ++ + /* Definition for an unknown syscall, used basically in error-cases. */ + #define UNKNOWN_SYSCALL (-1) + +diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh +--- a/gdb/gdbarch.sh ++++ b/gdb/gdbarch.sh +@@ -1164,6 +1164,9 @@ v;const disasm_options_and_args_t *;valid_disassembler_options;;;0;0;;0;host_add + # Type alignment. + m;ULONGEST;type_align;struct type *type;type;;default_type_align;;0 + ++# Read core file mappings ++m;void;read_core_file_mappings;struct bfd *cbfd,gdb::function_view pre_loop_cb,gdb::function_view loop_cb;cbfd, pre_loop_cb, loop_cb;;default_read_core_file_mappings;;0 ++ + EOF + } + diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-8of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-8of15.patch new file mode 100644 index 0000000..1470072 --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-8of15.patch @@ -0,0 +1,532 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Mon, 27 Jul 2020 18:51:07 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-8of15.patch + +;; Use NT_FILE note section for reading core target memory +;; Kevin Buettner, RH BZ 1842961 + + Author: Kevin Buettner + Date: Thu Jun 11 19:20:03 2020 -0700 + + Use NT_FILE note section for reading core target memory + + In his reviews of my v1 and v2 corefile related patches, Pedro + identified two cases which weren't handled by those patches. + + In https://sourceware.org/pipermail/gdb-patches/2020-May/168826.html, + Pedro showed that debugging a core file in which mmap() is used to + create a new mapping over an existing file-backed mapping will + produce incorrect results. I.e, for his example, GDB would + show: + + (gdb) disassemble main + Dump of assembler code for function main: + 0x00000000004004e6 <+0>: push %rbp + 0x00000000004004e7 <+1>: mov %rsp,%rbp + => 0x00000000004004ea <+4>: callq 0x4003f0 + End of assembler dump. + + This sort of looks like it might be correct, but is not due to the + fact that mmap(...MAP_FIXED...) was used to create a mapping (of all + zeros) on top of the .text section. So, the correct result should be: + + (gdb) disassemble main + Dump of assembler code for function main: + 0x00000000004004e6 <+0>: add %al,(%rax) + 0x00000000004004e8 <+2>: add %al,(%rax) + => 0x00000000004004ea <+4>: add %al,(%rax) + 0x00000000004004ec <+6>: add %al,(%rax) + 0x00000000004004ee <+8>: add %al,(%rax) + End of assembler dump. + + The other case that Pedro found involved an attempted examination of a + particular section in the test case from gdb.base/corefile.exp. On + Fedora 27 or 28, the following behavior may be observed: + + (gdb) info proc mappings + Mapped address spaces: + + Start Addr End Addr Size Offset objfile + ... + 0x7ffff7839000 0x7ffff7a38000 0x1ff000 0x1b5000 /usr/lib64/libc-2.27.so + ... + (gdb) x/4x 0x7ffff7839000 + 0x7ffff7839000: Cannot access memory at address 0x7ffff7839000 + + FYI, this section appears to be unrelocated vtable data. See + https://sourceware.org/pipermail/gdb-patches/2020-May/168331.html for + a detailed analysis. + + The important thing here is that GDB should be able to access this + address since it should be backed by the shared library. I.e. it + should do this: + + (gdb) x/4x 0x7ffff7839000 + 0x7ffff7839000: 0x0007ddf0 0x00000000 0x0007dba0 0x00000000 + + Both of these cases are fixed with this commit. + + In a nutshell, this commit opens a "binary" target BFD for each of the + files that are mentioned in an NT_FILE / .note.linuxcore.file note + section. It then uses these mappings instead of the file stratum + mappings that GDB has used in the past. + + If this note section doesn't exist or is mangled for some reason, then + GDB will use the file stratum as before. Should this happen, then + we can expect both of the above problems to again be present. + + See the code comments in the commit for other details. + + gdb/ChangeLog: + + * corelow.c (solist.h, unordered_map): Include. + (class core_target): Add field m_core_file_mappings and + method build_file_mappings. + (core_target::core_target): Call build_file_mappings. + (core_target::~core_target): Free memory associated with + m_core_file_mappings. + (core_target::build_file_mappings): New method. + (core_target::xfer_partial): Use m_core_file_mappings + for memory transfers. + * linux-tdep.c (linux_read_core_file_mappings): New + function. + (linux_core_info_proc_mappings): Rewrite to use + linux_read_core_file_mappings. + (linux_init_abi): Register linux_read_core_file_mappings. + +diff --git a/gdb/corelow.c b/gdb/corelow.c +--- a/gdb/corelow.c ++++ b/gdb/corelow.c +@@ -39,6 +39,7 @@ + #include "exec.h" + #include "readline/readline.h" + #include "solib.h" ++#include "solist.h" + #include "filenames.h" + #include "progspace.h" + #include "objfiles.h" +@@ -49,6 +50,8 @@ + #include "elf/common.h" + #include "gdbcmd.h" + #include "build-id.h" ++#include "common/pathstuff.h" ++#include + + #ifndef O_LARGEFILE + #define O_LARGEFILE 0 +@@ -129,6 +132,13 @@ private: /* per-core data */ + core file currently open on core_bfd. */ + core_fns *m_core_vec = NULL; + ++ /* File-backed address space mappings: some core files include ++ information about memory mapped files. */ ++ target_section_table m_core_file_mappings {}; ++ ++ /* Build m_core_file_mappings. Called from the constructor. */ ++ void build_file_mappings (); ++ + /* FIXME: kettenis/20031023: Eventually this field should + disappear. */ + struct gdbarch *m_core_gdbarch = NULL; +@@ -149,11 +159,120 @@ core_target::core_target () + &m_core_section_table.sections_end)) + error (_("\"%s\": Can't find sections: %s"), + bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ())); ++ ++ build_file_mappings (); + } + + core_target::~core_target () + { + xfree (m_core_section_table.sections); ++ xfree (m_core_file_mappings.sections); ++} ++ ++/* Construct the target_section_table for file-backed mappings if ++ they exist. ++ ++ For each unique path in the note, we'll open a BFD with a bfd ++ target of "binary". This is an unstructured bfd target upon which ++ we'll impose a structure from the mappings in the architecture-specific ++ mappings note. A BFD section is allocated and initialized for each ++ file-backed mapping. ++ ++ We take care to not share already open bfds with other parts of ++ GDB; in particular, we don't want to add new sections to existing ++ BFDs. We do, however, ensure that the BFDs that we allocate here ++ will go away (be deallocated) when the core target is detached. */ ++ ++void ++core_target::build_file_mappings () ++{ ++ std::unordered_map bfd_map; ++ ++ /* See linux_read_core_file_mappings() in linux-tdep.c for an example ++ read_core_file_mappings method. */ ++ gdbarch_read_core_file_mappings (m_core_gdbarch, core_bfd, ++ ++ /* After determining the number of mappings, read_core_file_mappings ++ will invoke this lambda which allocates target_section storage for ++ the mappings. */ ++ [&] (ULONGEST count) ++ { ++ m_core_file_mappings.sections = XNEWVEC (struct target_section, count); ++ m_core_file_mappings.sections_end = m_core_file_mappings.sections; ++ }, ++ ++ /* read_core_file_mappings will invoke this lambda for each mapping ++ that it finds. */ ++ [&] (int num, ULONGEST start, ULONGEST end, ULONGEST file_ofs, ++ const char *filename, const void *other) ++ { ++ /* Architecture-specific read_core_mapping methods are expected to ++ weed out non-file-backed mappings. */ ++ gdb_assert (filename != nullptr); ++ ++ struct bfd *bfd = bfd_map[filename]; ++ if (bfd == nullptr) ++ { ++ /* Use exec_file_find() to do sysroot expansion. It'll ++ also strip the potential sysroot "target:" prefix. If ++ there is no sysroot, an equivalent (possibly more ++ canonical) pathname will be provided. */ ++ gdb::unique_xmalloc_ptr expanded_fname ++ = exec_file_find (filename, NULL); ++ if (expanded_fname == nullptr) ++ { ++ warning (_("Can't open file %s during file-backed mapping " ++ "note processing"), ++ expanded_fname.get ()); ++ return; ++ } ++ ++ bfd = bfd_map[filename] = bfd_openr (expanded_fname.get (), ++ "binary"); ++ ++ if (bfd == nullptr || !bfd_check_format (bfd, bfd_object)) ++ { ++ /* If we get here, there's a good chance that it's due to ++ an internal error. We issue a warning instead of an ++ internal error because of the possibility that the ++ file was removed in between checking for its ++ existence during the expansion in exec_file_find() ++ and the calls to bfd_openr() / bfd_check_format(). ++ Output both the path from the core file note along ++ with its expansion to make debugging this problem ++ easier. */ ++ warning (_("Can't open file %s which was expanded to %s " ++ "during file-backed mapping note processing"), ++ filename, expanded_fname.get ()); ++ if (bfd != nullptr) ++ bfd_close (bfd); ++ return; ++ } ++ /* Ensure that the bfd will be closed when core_bfd is closed. ++ This can be checked before/after a core file detach via ++ "maint info bfds". */ ++ gdb_bfd_record_inclusion (core_bfd, bfd); ++ } ++ ++ /* Make new BFD section. All sections have the same name, ++ which is permitted by bfd_make_section_anyway(). */ ++ asection *sec = bfd_make_section_anyway (bfd, "load"); ++ if (sec == nullptr) ++ error (_("Can't make section")); ++ sec->filepos = file_ofs; ++ bfd_set_section_flags (sec->owner, sec, SEC_READONLY | SEC_HAS_CONTENTS); ++ bfd_set_section_size (sec->owner, sec, end - start); ++ bfd_set_section_vma (sec->owner, sec, start); ++ sec->lma = start; ++ bfd_set_section_alignment (sec->owner, sec, 2); ++ ++ /* Set target_section fields. */ ++ struct target_section *ts = m_core_file_mappings.sections_end++; ++ ts->addr = start; ++ ts->endaddr = end; ++ ts->owner = nullptr; ++ ts->the_bfd_section = sec; ++ }); + } + + /* List of all available core_fns. On gdb startup, each core file +@@ -835,10 +954,21 @@ core_target::xfer_partial (enum target_object object, const char *annex, + if (xfer_status == TARGET_XFER_OK) + return TARGET_XFER_OK; + +- /* Now check the stratum beneath us; this should be file_stratum. */ +- xfer_status = this->beneath ()->xfer_partial (object, annex, readbuf, +- writebuf, offset, len, +- xfered_len); ++ /* Check file backed mappings. If they're available, use ++ core file provided mappings (e.g. from .note.linuxcore.file ++ or the like) as this should provide a more accurate ++ result. If not, check the stratum beneath us, which should ++ be the file stratum. */ ++ if (m_core_file_mappings.sections != nullptr) ++ xfer_status = section_table_xfer_memory_partial ++ (readbuf, writebuf, ++ offset, len, xfered_len, ++ m_core_file_mappings.sections, ++ m_core_file_mappings.sections_end); ++ else ++ xfer_status = this->beneath ()->xfer_partial (object, annex, readbuf, ++ writebuf, offset, len, ++ xfered_len); + if (xfer_status == TARGET_XFER_OK) + return TARGET_XFER_OK; + +diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c +--- a/gdb/linux-tdep.c ++++ b/gdb/linux-tdep.c +@@ -1002,106 +1002,174 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args, + } + } + +-/* Implement "info proc mappings" for a corefile. */ ++/* Implementation of `gdbarch_read_core_file_mappings', as defined in ++ gdbarch.h. ++ ++ This function reads the NT_FILE note (which BFD turns into the ++ section ".note.linuxcore.file"). The format of this note / section ++ is described as follows in the Linux kernel sources in ++ fs/binfmt_elf.c: ++ ++ long count -- how many files are mapped ++ long page_size -- units for file_ofs ++ array of [COUNT] elements of ++ long start ++ long end ++ long file_ofs ++ followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL... ++ ++ CBFD is the BFD of the core file. ++ ++ PRE_LOOP_CB is the callback function to invoke prior to starting ++ the loop which processes individual entries. This callback will ++ only be executed after the note has been examined in enough ++ detail to verify that it's not malformed in some way. ++ ++ LOOP_CB is the callback function that will be executed once ++ for each mapping. */ + + static void +-linux_core_info_proc_mappings (struct gdbarch *gdbarch, const char *args) ++linux_read_core_file_mappings (struct gdbarch *gdbarch, ++ struct bfd *cbfd, ++ gdb::function_view ++ pre_loop_cb, ++ gdb::function_view ++ loop_cb) + { +- asection *section; +- ULONGEST count, page_size; +- unsigned char *descdata, *filenames, *descend; +- size_t note_size; +- unsigned int addr_size_bits, addr_size; +- struct gdbarch *core_gdbarch = gdbarch_from_bfd (core_bfd); +- /* We assume this for reading 64-bit core files. */ ++ /* Ensure that ULONGEST is big enough for reading 64-bit core files. */ + gdb_static_assert (sizeof (ULONGEST) >= 8); + +- section = bfd_get_section_by_name (core_bfd, ".note.linuxcore.file"); +- if (section == NULL) +- { +- warning (_("unable to find mappings in core file")); +- return; +- } ++ /* It's not required that the NT_FILE note exists, so return silently ++ if it's not found. Beyond this point though, we'll complain ++ if problems are found. */ ++ asection *section = bfd_get_section_by_name (cbfd, ".note.linuxcore.file"); ++ if (section == nullptr) ++ return; + +- addr_size_bits = gdbarch_addr_bit (core_gdbarch); +- addr_size = addr_size_bits / 8; +- note_size = bfd_get_section_size (section); ++ unsigned int addr_size_bits = gdbarch_addr_bit (gdbarch); ++ unsigned int addr_size = addr_size_bits / 8; ++ size_t note_size = bfd_section_size (section->abfd, section); + + if (note_size < 2 * addr_size) +- error (_("malformed core note - too short for header")); ++ { ++ warning (_("malformed core note - too short for header")); ++ return; ++ } + +- gdb::def_vector contents (note_size); ++ gdb::def_vector contents (note_size); + if (!bfd_get_section_contents (core_bfd, section, contents.data (), +- 0, note_size)) +- error (_("could not get core note contents")); ++ 0, note_size)) ++ { ++ warning (_("could not get core note contents")); ++ return; ++ } + +- descdata = contents.data (); +- descend = descdata + note_size; ++ gdb_byte *descdata = contents.data (); ++ char *descend = (char *) descdata + note_size; + + if (descdata[note_size - 1] != '\0') +- error (_("malformed note - does not end with \\0")); ++ { ++ warning (_("malformed note - does not end with \\0")); ++ return; ++ } + +- count = bfd_get (addr_size_bits, core_bfd, descdata); ++ ULONGEST count = bfd_get (addr_size_bits, core_bfd, descdata); + descdata += addr_size; + +- page_size = bfd_get (addr_size_bits, core_bfd, descdata); ++ ULONGEST page_size = bfd_get (addr_size_bits, core_bfd, descdata); + descdata += addr_size; + + if (note_size < 2 * addr_size + count * 3 * addr_size) +- error (_("malformed note - too short for supplied file count")); +- +- printf_filtered (_("Mapped address spaces:\n\n")); +- if (gdbarch_addr_bit (gdbarch) == 32) + { +- printf_filtered ("\t%10s %10s %10s %10s %s\n", +- "Start Addr", +- " End Addr", +- " Size", " Offset", "objfile"); +- } +- else +- { +- printf_filtered (" %18s %18s %10s %10s %s\n", +- "Start Addr", +- " End Addr", +- " Size", " Offset", "objfile"); ++ warning (_("malformed note - too short for supplied file count")); ++ return; + } + +- filenames = descdata + count * 3 * addr_size; +- while (--count > 0) ++ char *filenames = (char *) descdata + count * 3 * addr_size; ++ ++ /* Make sure that the correct number of filenames exist. Complain ++ if there aren't enough or are too many. */ ++ char *f = filenames; ++ for (int i = 0; i < count; i++) + { +- ULONGEST start, end, file_ofs; ++ if (f >= descend) ++ { ++ warning (_("malformed note - filename area is too small")); ++ return; ++ } ++ f += strnlen (f, descend - f) + 1; ++ } ++ /* Complain, but don't return early if the filename area is too big. */ ++ if (f != descend) ++ warning (_("malformed note - filename area is too big")); + +- if (filenames == descend) +- error (_("malformed note - filenames end too early")); ++ pre_loop_cb (count); + +- start = bfd_get (addr_size_bits, core_bfd, descdata); ++ for (int i = 0; i < count; i++) ++ { ++ ULONGEST start = bfd_get (addr_size_bits, core_bfd, descdata); + descdata += addr_size; +- end = bfd_get (addr_size_bits, core_bfd, descdata); ++ ULONGEST end = bfd_get (addr_size_bits, core_bfd, descdata); + descdata += addr_size; +- file_ofs = bfd_get (addr_size_bits, core_bfd, descdata); ++ ULONGEST file_ofs ++ = bfd_get (addr_size_bits, core_bfd, descdata) * page_size; + descdata += addr_size; ++ char * filename = filenames; ++ filenames += strlen ((char *) filenames) + 1; + +- file_ofs *= page_size; +- +- if (gdbarch_addr_bit (gdbarch) == 32) +- printf_filtered ("\t%10s %10s %10s %10s %s\n", +- paddress (gdbarch, start), +- paddress (gdbarch, end), +- hex_string (end - start), +- hex_string (file_ofs), +- filenames); +- else +- printf_filtered (" %18s %18s %10s %10s %s\n", +- paddress (gdbarch, start), +- paddress (gdbarch, end), +- hex_string (end - start), +- hex_string (file_ofs), +- filenames); +- +- filenames += 1 + strlen ((char *) filenames); ++ loop_cb (i, start, end, file_ofs, filename, nullptr); + } + } + ++/* Implement "info proc mappings" for a corefile. */ ++ ++static void ++linux_core_info_proc_mappings (struct gdbarch *gdbarch, const char *args) ++{ ++ linux_read_core_file_mappings (gdbarch, core_bfd, ++ [=] (ULONGEST count) ++ { ++ printf_filtered (_("Mapped address spaces:\n\n")); ++ if (gdbarch_addr_bit (gdbarch) == 32) ++ { ++ printf_filtered ("\t%10s %10s %10s %10s %s\n", ++ "Start Addr", ++ " End Addr", ++ " Size", " Offset", "objfile"); ++ } ++ else ++ { ++ printf_filtered (" %18s %18s %10s %10s %s\n", ++ "Start Addr", ++ " End Addr", ++ " Size", " Offset", "objfile"); ++ } ++ }, ++ [=] (int num, ULONGEST start, ULONGEST end, ULONGEST file_ofs, ++ const char *filename, const void *other) ++ { ++ if (gdbarch_addr_bit (gdbarch) == 32) ++ printf_filtered ("\t%10s %10s %10s %10s %s\n", ++ paddress (gdbarch, start), ++ paddress (gdbarch, end), ++ hex_string (end - start), ++ hex_string (file_ofs), ++ filename); ++ else ++ printf_filtered (" %18s %18s %10s %10s %s\n", ++ paddress (gdbarch, start), ++ paddress (gdbarch, end), ++ hex_string (end - start), ++ hex_string (file_ofs), ++ filename); ++ }); ++} ++ + /* Implement "info proc" for a corefile. */ + + static void +@@ -2501,6 +2569,7 @@ linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) + set_gdbarch_info_proc (gdbarch, linux_info_proc); + set_gdbarch_core_info_proc (gdbarch, linux_core_info_proc); + set_gdbarch_core_xfer_siginfo (gdbarch, linux_core_xfer_siginfo); ++ set_gdbarch_read_core_file_mappings (gdbarch, linux_read_core_file_mappings); + set_gdbarch_find_memory_regions (gdbarch, linux_find_memory_regions); + set_gdbarch_make_corefile_notes (gdbarch, linux_make_corefile_notes); + set_gdbarch_has_shared_address_space (gdbarch, diff --git a/SOURCES/gdb-rhbz1842691-corefile-mem-access-9of15.patch b/SOURCES/gdb-rhbz1842691-corefile-mem-access-9of15.patch new file mode 100644 index 0000000..5591b78 --- /dev/null +++ b/SOURCES/gdb-rhbz1842691-corefile-mem-access-9of15.patch @@ -0,0 +1,101 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Mon, 27 Jul 2020 19:21:54 -0400 +Subject: gdb-rhbz1842691-corefile-mem-access-9of15.patch + +;; Add test for accessing read-only mmapped data in a core file +;; Kevin Buettner, RH BZ 1842691 + + Author: Kevin Buettner + Date: Tue Jun 16 11:39:22 2020 -0700 + + Add test for accessing read-only mmapped data in a core file + + This test passes when run using a GDB with my corefile patches. When + run against a GDB without my patches, I see the following failures, + the first of which is due to the test added by this commit: + + FAIL: gdb.base/corefile.exp: accessing read-only mmapped data in core file ( + FAIL: gdb.base/corefile.exp: accessing anonymous, unwritten-to mmap data + + gdb/testsuite/ChangeLog: + + * gdb.base/corefile.exp: Add test "accessing read-only mmapped + data in core file". + * gdb.base/coremaker.c (buf2ro): New global. + (mmapdata): Add a read-only mmap mapping. + +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 +@@ -34,7 +34,10 @@ if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} { + return -1 + } + +-set corefile [core_find $binfile {coremmap.data}] ++# Do not delete coremap.data when calling core_find. This file is ++# required for GDB to find mmap'd data in the "accessing read-only ++# mmapped data in core file" test. ++set corefile [core_find $binfile {}] + if {$corefile == ""} { + return 0 + } +@@ -175,6 +178,19 @@ gdb_test_multiple "x/8bd buf2" "$test" { + } + } + ++set test "accessing read-only mmapped data in core file" ++gdb_test_multiple "x/8bd buf2ro" "$test" { ++ -re ".*:.*0.*1.*2.*3.*4.*5.*6.*7.*$gdb_prompt $" { ++ pass "$test" ++ } ++ -re "0x\[f\]*:.*Cannot access memory at address 0x\[f\]*.*$gdb_prompt $" { ++ fail "$test (mapping failed at runtime)" ++ } ++ -re "0x.*:.*Cannot access memory at address 0x.*$gdb_prompt $" { ++ fail "$test (mapping address not found in core file)" ++ } ++} ++ + # Test ability to read anonymous and, more importantly, unwritten-to + # mmap'd data. + +diff --git a/gdb/testsuite/gdb.base/coremaker.c b/gdb/testsuite/gdb.base/coremaker.c +--- a/gdb/testsuite/gdb.base/coremaker.c ++++ b/gdb/testsuite/gdb.base/coremaker.c +@@ -38,6 +38,7 @@ + + char *buf1; + char *buf2; ++char *buf2ro; + char *buf3; + + int coremaker_data = 1; /* In Data section */ +@@ -90,16 +91,25 @@ mmapdata () + return; + } + ++ /* Map in another copy, read-only. We won't write to this copy so it ++ will likely not end up in the core file. */ ++ buf2ro = (char *) mmap (0, MAPSIZE, PROT_READ, MAP_PRIVATE, fd, 0); ++ if (buf2ro == (char *) -1) ++ { ++ perror ("mmap failed"); ++ return; ++ } ++ + /* Verify that the original data and the mapped data are identical. + If not, we'd rather fail now than when trying to access the mapped + data from the core file. */ + + for (j = 0; j < MAPSIZE; ++j) + { +- if (buf1[j] != buf2[j]) ++ if (buf1[j] != buf2[j] || buf1[j] != buf2ro[j]) + { + fprintf (stderr, "mapped data is incorrect"); +- buf2 = (char *) -1; ++ buf2 = buf2ro = (char *) -1; + return; + } + } diff --git a/SOURCES/gdb-rhbz1852580-terminal-woes.patch b/SOURCES/gdb-rhbz1852580-terminal-woes.patch new file mode 100644 index 0000000..9ba19ff --- /dev/null +++ b/SOURCES/gdb-rhbz1852580-terminal-woes.patch @@ -0,0 +1,164 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Alan Hayward +Date: Tue, 28 May 2019 10:07:54 +0100 +Subject: gdb-rhbz1852580-terminal-woes.patch + +;; Fix terminal problems when error() is called +;; Alan Hayward (RH BZ 1852580) + +Suppress SIGTTOU when handling errors + +Calls to error () can cause SIGTTOU to send gdb to the background. + +For example, on an Arm build: + (gdb) b main + Breakpoint 1 at 0x10774: file /build/gdb/testsuite/../../../src/binutils-gdb/gdb/testsuite/gdb.base/watchpoint.c, line 174. + (gdb) r + Starting program: /build/gdb/testsuite/outputs/gdb.base/watchpoint/watchpoint + + [1]+ Stopped ../gdb ./outputs/gdb.base/watchpoint/watchpoint + localhost$ fg + ../gdb ./outputs/gdb.base/watchpoint/watchpoint + Cannot parse expression `.L1199 4@r4'. + warning: Probes-based dynamic linker interface failed. + Reverting to original interface. + +The SIGTTOU is raised whilst inside a syscall during the call to tcdrain. +Fix is to use scoped_ignore_sigttou to ensure SIGTTOU is blocked. + +In addition fix include comments - job_control is not included via terminal.h + +gdb/ChangeLog: + + * event-top.c: Remove include comment. + * inflow.c (class scoped_ignore_sigttou): Move from here... + * inflow.h (class scoped_ignore_sigttou): ...to here. + * ser-unix.c (hardwire_drain_output): Block SIGTTOU during drain. + * top.c: Remove include comment. + +diff --git a/gdb/event-top.c b/gdb/event-top.c +--- a/gdb/event-top.c ++++ b/gdb/event-top.c +@@ -24,7 +24,7 @@ + #include "inferior.h" + #include "infrun.h" + #include "target.h" +-#include "terminal.h" /* for job_control */ ++#include "terminal.h" + #include "event-loop.h" + #include "event-top.h" + #include "interps.h" +diff --git a/gdb/inflow.c b/gdb/inflow.c +--- a/gdb/inflow.c ++++ b/gdb/inflow.c +@@ -103,35 +103,6 @@ static serial_ttystate initial_gdb_ttystate; + + static struct terminal_info *get_inflow_inferior_data (struct inferior *); + +-/* RAII class used to ignore SIGTTOU in a scope. */ +- +-class scoped_ignore_sigttou +-{ +-public: +- scoped_ignore_sigttou () +- { +-#ifdef SIGTTOU +- if (job_control) +- m_osigttou = signal (SIGTTOU, SIG_IGN); +-#endif +- } +- +- ~scoped_ignore_sigttou () +- { +-#ifdef SIGTTOU +- if (job_control) +- signal (SIGTTOU, m_osigttou); +-#endif +- } +- +- DISABLE_COPY_AND_ASSIGN (scoped_ignore_sigttou); +- +-private: +-#ifdef SIGTTOU +- sighandler_t m_osigttou = NULL; +-#endif +-}; +- + /* While the inferior is running, we want SIGINT and SIGQUIT to go to the + inferior only. If we have job control, that takes care of it. If not, + we save our handlers in these two variables and set SIGINT and SIGQUIT +diff --git a/gdb/inflow.h b/gdb/inflow.h +--- a/gdb/inflow.h ++++ b/gdb/inflow.h +@@ -21,5 +21,36 @@ + #define INFLOW_H + + #include ++#include ++#include "common/job-control.h" ++ ++/* RAII class used to ignore SIGTTOU in a scope. */ ++ ++class scoped_ignore_sigttou ++{ ++public: ++ scoped_ignore_sigttou () ++ { ++#ifdef SIGTTOU ++ if (job_control) ++ m_osigttou = signal (SIGTTOU, SIG_IGN); ++#endif ++ } ++ ++ ~scoped_ignore_sigttou () ++ { ++#ifdef SIGTTOU ++ if (job_control) ++ signal (SIGTTOU, m_osigttou); ++#endif ++ } ++ ++ DISABLE_COPY_AND_ASSIGN (scoped_ignore_sigttou); ++ ++private: ++#ifdef SIGTTOU ++ sighandler_t m_osigttou = NULL; ++#endif ++}; + + #endif /* inflow.h */ +diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c +--- a/gdb/ser-unix.c ++++ b/gdb/ser-unix.c +@@ -32,6 +32,7 @@ + #include "gdbcmd.h" + #include "filestuff.h" + #include ++#include "inflow.h" + + struct hardwire_ttystate + { +@@ -164,6 +165,9 @@ hardwire_print_tty_state (struct serial *scb, + static int + hardwire_drain_output (struct serial *scb) + { ++ /* Ignore SIGTTOU which may occur during the drain. */ ++ scoped_ignore_sigttou ignore_sigttou; ++ + return tcdrain (scb->fd); + } + +diff --git a/gdb/top.c b/gdb/top.c +--- a/gdb/top.c ++++ b/gdb/top.c +@@ -34,8 +34,8 @@ + #include "expression.h" + #include "value.h" + #include "language.h" +-#include "terminal.h" /* For job_control. */ +-#include "job-control.h" ++#include "terminal.h" ++#include "common/job-control.h" + #include "annotate.h" + #include "completer.h" + #include "top.h" diff --git a/SOURCES/gdb-rhbz1878810-bfd-suppress-loadable-section-outside-ELF-sections.patch b/SOURCES/gdb-rhbz1878810-bfd-suppress-loadable-section-outside-ELF-sections.patch new file mode 100644 index 0000000..30a5ab5 --- /dev/null +++ b/SOURCES/gdb-rhbz1878810-bfd-suppress-loadable-section-outside-ELF-sections.patch @@ -0,0 +1,108 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Fri, 23 Oct 2020 17:12:26 -0400 +Subject: + gdb-rhbz1878810-bfd-suppress-loadable-section-outside-ELF-sections.patch + +;; Backport "Stop the BFD library from issuing a warning message when +;; processing allocated sections in debuginfo files that lie outside of +;; Nick Clifton and Keith Seitz, RH BZ 1878810 + + Stop the BFD library from issuing a warning message when processing allocated sections in debuginfo files that lie outside of any loadable segment. + + bfd/ChangeLog + PR 24717 + * elf.c (is_debuginfo_file): New function. + (assign_file_positions_for_non_load_sections): Do not warn about + allocated sections outside of loadable segments if they are found + in a debuginfo file. + * elf-bfd.h (is_debuginfo_file): Prototype. + + gdb/ChangeLog + 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/bfd/elf-bfd.h b/bfd/elf-bfd.h +--- a/bfd/elf-bfd.h ++++ b/bfd/elf-bfd.h +@@ -2740,6 +2740,8 @@ extern bfd_vma elf64_r_sym (bfd_vma); + extern bfd_vma elf32_r_info (bfd_vma, bfd_vma); + extern bfd_vma elf32_r_sym (bfd_vma); + ++extern bfd_boolean is_debuginfo_file (bfd *); ++ + /* Large common section. */ + extern asection _bfd_elf_large_com_section; + +diff --git a/bfd/elf.c b/bfd/elf.c +--- a/bfd/elf.c ++++ b/bfd/elf.c +@@ -5725,6 +5725,35 @@ assign_file_positions_for_load_sections (bfd *abfd, + return TRUE; + } + ++/* Determine if a bfd is a debuginfo file. Unfortunately there ++ is no defined method for detecting such files, so we have to ++ use heuristics instead. */ ++ ++bfd_boolean ++is_debuginfo_file (bfd *abfd) ++{ ++ if (abfd == NULL || bfd_get_flavour (abfd) != bfd_target_elf_flavour) ++ return FALSE; ++ ++ Elf_Internal_Shdr **start_headers = elf_elfsections (abfd); ++ Elf_Internal_Shdr **end_headers = start_headers + elf_numsections (abfd); ++ Elf_Internal_Shdr **headerp; ++ ++ for (headerp = start_headers; headerp < end_headers; headerp ++) ++ { ++ Elf_Internal_Shdr *header = * headerp; ++ ++ /* Debuginfo files do not have any allocated SHT_PROGBITS sections. ++ The only allocated sections are SHT_NOBITS or SHT_NOTES. */ ++ if ((header->sh_flags & SHF_ALLOC) == SHF_ALLOC ++ && header->sh_type != SHT_NOBITS ++ && header->sh_type != SHT_NOTE) ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ + /* Assign file positions for the other sections. */ + + static bfd_boolean +@@ -5758,7 +5787,13 @@ assign_file_positions_for_non_load_sections (bfd *abfd, + BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos); + else if ((hdr->sh_flags & SHF_ALLOC) != 0) + { +- if (hdr->sh_size != 0) ++ if (hdr->sh_size != 0 ++ /* PR 24717 - debuginfo files are known to be not strictly ++ compliant with the ELF standard. In particular they often ++ have .note.gnu.property sections that are outside of any ++ loadable segment. This is not a problem for such files, ++ so do not warn about them. */ ++ && ! is_debuginfo_file (abfd)) + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: warning: allocated section `%s' not in segment"), +diff --git a/gdb/elfread.c b/gdb/elfread.c +--- a/gdb/elfread.c ++++ b/gdb/elfread.c +@@ -143,7 +143,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_get_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_get_section_size (sect) > 0 && j == num_segments + && (bfd_get_section_flags (abfd, sect) & SEC_LOAD) != 0) + warning (_("Loadable section \"%s\" outside of ELF segments"), + bfd_section_name (abfd, sect)); diff --git a/SOURCES/gdb-rhbz1903374-s390x-store-on-condition.patch b/SOURCES/gdb-rhbz1903374-s390x-store-on-condition.patch new file mode 100644 index 0000000..b132391 --- /dev/null +++ b/SOURCES/gdb-rhbz1903374-s390x-store-on-condition.patch @@ -0,0 +1,64 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Andreas Arnez +Date: Thu, 19 Nov 2020 19:10:58 +0100 +Subject: gdb-rhbz1903374-s390x-store-on-condition.patch + +;; Backport of "Correct recording of 'store on condition' insns" +;; Andreas Arnaz (RH BZ 1903374) + +gdb/s390: Correct recording of "store on condition" insns + +The "store on condition" instructions STOC, STOCG, and STOCFH are recorded +as if their instruction formats resembled that of STG. This is wrong, +usually resulting in "failed to record execution log" errors when trying +to record code with any of these instructions. + +This patch fixes the recording of these instructions. + +gdb/ChangeLog: + + PR tdep/26916 + * s390-tdep.c (s390_process_record): Fix recording of STOC, STOCG, + and STOCFH. + +diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c +--- a/gdb/s390-tdep.c ++++ b/gdb/s390-tdep.c +@@ -5332,7 +5332,6 @@ ex: + case 0xe325: /* NTSTG - nontransactional store */ + case 0xe326: /* CVDY - convert to decimal */ + case 0xe32f: /* STRVG - store reversed */ +- case 0xebe3: /* STOCG - store on condition */ + case 0xed67: /* STDY - store */ + oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], ibyte[4]); + if (record_full_arch_list_add_mem (oaddr, 8)) +@@ -5361,8 +5360,6 @@ ex: + case 0xe33e: /* STRV - store reversed */ + case 0xe350: /* STY - store */ + case 0xe3cb: /* STFH - store high */ +- case 0xebe1: /* STOCFH - store high on condition */ +- case 0xebf3: /* STOC - store on condition */ + case 0xed66: /* STEY - store */ + oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], ibyte[4]); + if (record_full_arch_list_add_mem (oaddr, 4)) +@@ -6075,6 +6072,20 @@ ex: + + /* 0xeb9c-0xebbf undefined */ + /* 0xebc1-0xebdb undefined */ ++ ++ case 0xebe1: /* STOCFH - store high on condition */ ++ case 0xebf3: /* STOC - store on condition */ ++ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], ibyte[4]); ++ if (record_full_arch_list_add_mem (oaddr, 4)) ++ return -1; ++ break; ++ ++ case 0xebe3: /* STOCG - store on condition */ ++ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], ibyte[4]); ++ if (record_full_arch_list_add_mem (oaddr, 8)) ++ return -1; ++ break; ++ + /* 0xebe5 undefined */ + /* 0xebe9 undefined */ + /* 0xebeb-0xebf1 undefined */ diff --git a/SOURCES/gdb-rhbz1905701-DWARF-data_location.patch b/SOURCES/gdb-rhbz1905701-DWARF-data_location.patch new file mode 100644 index 0000000..3c74a9e --- /dev/null +++ b/SOURCES/gdb-rhbz1905701-DWARF-data_location.patch @@ -0,0 +1,573 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Wed, 2 Dec 2020 17:39:33 -0500 +Subject: gdb-rhbz1905701-DWARF-data_location.patch + +;; Backport "fortran dynamic type related fixes" +;; Andrew Burgess (RH BZ 1905701) + + commit e79eb02f2f09baecffb144bac6804f975065466f + + gdb/fortran: resolve dynamic types when readjusting after an indirection + + After dereferencing a pointer (in value_ind) or following a + reference (in coerce_ref) we call readjust_indirect_value_type to + "fixup" the type of the resulting value object. + + This fixup handles cases relating to the type of the resulting object + being different (a sub-class) of the original pointers target type. + + If we encounter a pointer to a dynamic type then after dereferencing a + pointer (in value_ind) the type of the object created will have had + its dynamic type resolved. However, in readjust_indirect_value_type, + we use the target type of the original pointer to "fixup" the type of + the resulting value. In this case, the target type will be a dynamic + type, so the resulting value object, once again has a dynamic type. + + This then triggers an assertion later within GDB. + + The solution I propose here is that we call resolve_dynamic_type on + the pointer's target type (within readjust_indirect_value_type) so + that the resulting value is not converted back to a dynamic type. + + The test case is based on the original test in the bug report. + + gdb/ChangeLog: + + PR fortran/23051 + PR fortran/26139 + * valops.c (value_ind): Pass address to + readjust_indirect_value_type. + * value.c (readjust_indirect_value_type): Make parameter + non-const, and add extra address parameter. Resolve original type + before using it. + * value.h (readjust_indirect_value_type): Update function + signature and comment. + + gdb/testsuite/ChangeLog: + + PR fortran/23051 + PR fortran/26139 + * gdb.fortran/class-allocatable-array.exp: New file. + * gdb.fortran/class-allocatable-array.f90: New file. + * gdb.fortran/pointer-to-pointer.exp: New file. + * gdb.fortran/pointer-to-pointer.f90: New file. + +diff --git a/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.c b/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.c +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.c +@@ -0,0 +1,63 @@ ++/* Copyright 2014-2020 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++/* This C file simulates the implementation of object pointers in ++ GraalVM Java native images where the object data is not addressed ++ directly. It serves as a regression test for a bug where printing ++ of such redirected data structures suffers from a gdb exception. ++ ++ Debugging information on how to decode an object pointer to ++ identify the address of the underlying data will be generated ++ separately by the testcase using that file. */ ++ ++#include ++#include ++ ++struct Object { ++ struct Object *next; ++ int val; ++}; ++ ++struct Object *testOop; ++ ++extern int debugMe() { ++ return 0; ++} ++ ++struct Object *newObject() { ++ char *bytes = malloc(sizeof(struct Object)); ++ return (struct Object *)bytes; ++} ++ ++int ++main (void) ++{ ++ struct Object *obj1 = newObject(); ++ struct Object *obj2 = newObject(); ++ struct Object *obj3 = newObject(); ++ obj1->val = 0; ++ obj2->val = 1; ++ obj3->val = 2; ++ ++ obj1->next = obj2; ++ obj2->next = obj3; ++ obj3->next = obj1; ++ ++ testOop = obj1; ++ ++ return debugMe(); ++} +diff --git a/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.exp b/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.exp +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.exp +@@ -0,0 +1,122 @@ ++# Copyright 2014-2020 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 . ++load_lib dwarf.exp ++ ++# This test can only be run on targets which support DWARF-2 and use gas. ++if {![dwarf2_support]} { ++ return 0 ++} ++ ++standard_testfile .c -dw.S ++ ++if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { ++ return -1 ++} ++ ++# Make some DWARF for the test. ++set asm_file [standard_output_file $srcfile2] ++Dwarf::assemble $asm_file { ++ ++ cu {} { ++ DW_TAG_compile_unit { ++ {DW_AT_language @DW_LANG_C99} ++ {DW_AT_name data-loc2.c} ++ {DW_AT_comp_dir /tmp} ++ } { ++ declare_labels integer_label struct_label pointer_label ++ ++ integer_label: DW_TAG_base_type { ++ {DW_AT_byte_size 4 DW_FORM_sdata} ++ {DW_AT_encoding @DW_ATE_signed} ++ {DW_AT_name integer} ++ } ++ ++ struct_label: DW_TAG_structure_type { ++ {DW_AT_name "Object"} ++ {DW_AT_byte_size 20 DW_FORM_sdata} ++ {DW_AT_data_location { ++ DW_OP_push_object_address ++ } SPECIAL_expr} ++ } { ++ member { ++ {name next} ++ {type :$pointer_label} ++ {data_member_location 0 data1} ++ } ++ member { ++ {name val} ++ {type :$integer_label} ++ {data_member_location 8 data1} ++ } ++ } ++ pointer_label: DW_TAG_pointer_type { ++ {DW_AT_byte_size 4 DW_FORM_sdata} ++ {DW_AT_type :$struct_label} ++ } ++ DW_TAG_variable { ++ {DW_AT_name testOop} ++ {DW_AT_type :$pointer_label} ++ {DW_AT_location { ++ DW_OP_addr [gdb_target_symbol testOop] ++ } SPECIAL_expr} ++ {external 1 flag} ++ } ++ } ++ } ++} ++ ++# Now that we've generated the DWARF debugging info, rebuild our ++# program using our debug info instead of the info generated by ++# the compiler. ++ ++if { [prepare_for_testing "failed to prepare" ${testfile} \ ++ [list $srcfile $asm_file] {nodebug}] } { ++ return -1 ++} ++ ++if ![runto_main] { ++ return -1 ++} ++ ++# ensure the object network is set up as expected and check that ++# printing of structs which employ the data_location does not ++# fail with a gdb exception ++ ++gdb_test "break debugMe" \ ++ "Breakpoint .*" \ ++ "set breakpoint at debugMe" ++ ++gdb_continue_to_breakpoint "continue to debugMe" ++ ++gdb_test "print testOop->val" \ ++ ".* = 0" ++ ++gdb_test "print testOop->next->val" \ ++ ".* = 1" ++ ++gdb_test "print testOop->next->next->val" \ ++ ".* = 2" ++ ++gdb_test "print *testOop" \ ++ ".* = {next = .*, val = 0}" \ ++ "print contents of struct" ++ ++gdb_test "print *testOop->next" \ ++ ".* = {next = .*, val = 1}" \ ++ "print contents of an indirect struct" ++ ++gdb_test "print *testOop->next->next" \ ++ ".* = {next = .*, val = 2}" \ ++ "print contents of a double indirect struct" +diff --git a/gdb/testsuite/gdb.fortran/class-allocatable-array.exp b/gdb/testsuite/gdb.fortran/class-allocatable-array.exp +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/class-allocatable-array.exp +@@ -0,0 +1,43 @@ ++# Copyright 2020 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 . ++ ++# Test that GDB can print an allocatable array that is a data field ++# within a class like type. ++ ++if {[skip_fortran_tests]} { return -1 } ++ ++standard_testfile ".f90" ++load_lib fortran.exp ++ ++if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \ ++ {debug f90}]} { ++ return -1 ++} ++ ++if {![runto MAIN__]} { ++ untested main"could not run to main" ++ return -1 ++} ++ ++gdb_breakpoint [gdb_get_line_number "Break Here"] ++gdb_continue_to_breakpoint "Break Here" ++ ++# If this first test fails then the Fortran compiler being used uses ++# different names, or maybe a completely different approach, for ++# representing class like structures. The following tests are ++# 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\\) \\)" +diff --git a/gdb/testsuite/gdb.fortran/class-allocatable-array.f90 b/gdb/testsuite/gdb.fortran/class-allocatable-array.f90 +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/class-allocatable-array.f90 +@@ -0,0 +1,54 @@ ++! Copyright 2020 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 . ++ ++module test_module ++ type test_type ++ integer a ++ real, allocatable :: b (:, :) ++ contains ++ procedure :: test_proc ++ end type test_type ++ ++contains ++ ++ subroutine test_proc (this) ++ class(test_type), intent (inout) :: this ++ allocate (this%b (3, 2)) ++ call fill_array_2d (this%b) ++ print *, "" ! Break Here ++ contains ++ ! Helper subroutine to fill 2-dimensional array with unique ++ ! values. ++ subroutine fill_array_2d (array) ++ real, dimension (:,:) :: array ++ real :: counter ++ ++ counter = 1.0 ++ do i=LBOUND (array, 2), UBOUND (array, 2), 1 ++ do j=LBOUND (array, 1), UBOUND (array, 1), 1 ++ array (j,i) = counter ++ counter = counter + 1 ++ end do ++ end do ++ end subroutine fill_array_2d ++ end subroutine test_proc ++end module ++ ++program test ++ use test_module ++ implicit none ++ type(test_type) :: t ++ call t%test_proc () ++end program test +diff --git a/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp b/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp +@@ -0,0 +1,46 @@ ++# Copyright 2020 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 . ++ ++# Test for GDB printing a pointer to a type containing a buffer. ++ ++if {[skip_fortran_tests]} { return -1 } ++ ++standard_testfile ".f90" ++load_lib fortran.exp ++ ++if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \ ++ {debug f90}]} { ++ return -1 ++} ++ ++if {![runto MAIN__]} { ++ untested "could not run to main" ++ return -1 ++} ++ ++gdb_breakpoint [gdb_get_line_number "Break Here"] ++gdb_continue_to_breakpoint "Break Here" ++ ++gdb_test "print *buffer" \ ++ " = \\( alpha = \\(1\\.5, 2\\.5, 3\\.5, 4\\.5, 5\\.5\\) \\)" ++ ++set l_buffer_type [multi_line \ ++ "Type l_buffer" \ ++ " real\\(kind=4\\) :: alpha\\(.\\)" \ ++ "End Type l_buffer" ] ++ ++gdb_test "ptype buffer" "type = PTR TO -> \\( ${l_buffer_type} \\)" ++gdb_test "ptype *buffer" "type = ${l_buffer_type}" ++gdb_test "ptype buffer%alpha" "type = real\\(kind=4\\) \\(5\\)" +diff --git a/gdb/testsuite/gdb.fortran/pointer-to-pointer.f90 b/gdb/testsuite/gdb.fortran/pointer-to-pointer.f90 +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/pointer-to-pointer.f90 +@@ -0,0 +1,34 @@ ++! Copyright 2020 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 . ++ ++program allocate_array ++ ++ type l_buffer ++ real, dimension(:), pointer :: alpha ++ end type l_buffer ++ type(l_buffer), pointer :: buffer ++ ++ allocate (buffer) ++ allocate (buffer%alpha (5)) ++ ++ buffer%alpha (1) = 1.5 ++ buffer%alpha (2) = 2.5 ++ buffer%alpha (3) = 3.5 ++ buffer%alpha (4) = 4.5 ++ buffer%alpha (5) = 5.5 ++ ++ print *, buffer%alpha ! Break Here. ++ ++end program allocate_array +diff --git a/gdb/valops.c b/gdb/valops.c +--- a/gdb/valops.c ++++ b/gdb/valops.c +@@ -1573,42 +1573,34 @@ value_ind (struct value *arg1) + if (TYPE_CODE (base_type) == TYPE_CODE_PTR) + { + struct type *enc_type; +- CORE_ADDR addr; +- +- if (type_not_associated (base_type)) +- error (_("Attempt to take contents of a not associated pointer.")); +- +- if (NULL != TYPE_DATA_LOCATION (TYPE_TARGET_TYPE (base_type))) +- addr = value_address (arg1); +- else +- addr = value_as_address (arg1); +- +- if (addr != 0) +- TYPE_TARGET_TYPE (base_type) = +- resolve_dynamic_type (TYPE_TARGET_TYPE (base_type), NULL, addr); + + /* We may be pointing to something embedded in a larger object. + Get the real type of the enclosing object. */ + enc_type = check_typedef (value_enclosing_type (arg1)); + enc_type = TYPE_TARGET_TYPE (enc_type); + ++ CORE_ADDR base_addr; + if (TYPE_CODE (check_typedef (enc_type)) == TYPE_CODE_FUNC + || TYPE_CODE (check_typedef (enc_type)) == TYPE_CODE_METHOD) +- /* For functions, go through find_function_addr, which knows +- how to handle function descriptors. */ +- arg2 = value_at_lazy (enc_type, +- find_function_addr (arg1, NULL)); ++ { ++ /* For functions, go through find_function_addr, which knows ++ how to handle function descriptors. */ ++ base_addr = find_function_addr (arg1, NULL); ++ } + else +- /* Retrieve the enclosing object pointed to. */ +- arg2 = value_at_lazy (enc_type, +- (addr - value_pointed_to_offset (arg1))); ++ { ++ /* Retrieve the enclosing object pointed to. */ ++ base_addr = (value_as_address (arg1) ++ - value_pointed_to_offset (arg1)); ++ } + ++ arg2 = value_at_lazy (enc_type, base_addr); + enc_type = value_type (arg2); +- return readjust_indirect_value_type (arg2, enc_type, base_type, arg1); ++ return readjust_indirect_value_type (arg2, enc_type, base_type, ++ arg1, base_addr); + } + + error (_("Attempt to take contents of a non-pointer value.")); +- return 0; /* For lint -- never reached. */ + } + + /* Create a value for an array by allocating space in GDB, copying the +diff --git a/gdb/value.c b/gdb/value.c +--- a/gdb/value.c ++++ b/gdb/value.c +@@ -3611,10 +3611,19 @@ coerce_ref_if_computed (const struct value *arg) + struct value * + readjust_indirect_value_type (struct value *value, struct type *enc_type, + const struct type *original_type, +- const struct value *original_value) ++ struct value *original_value, ++ CORE_ADDR original_value_address) + { ++ gdb_assert (TYPE_CODE (original_type) == TYPE_CODE_PTR ++ || TYPE_IS_REFERENCE (original_type)); ++ ++ struct type *original_target_type = TYPE_TARGET_TYPE (original_type); ++ struct type *resolved_original_target_type ++ = resolve_dynamic_type (original_target_type, NULL, ++ original_value_address); ++ + /* Re-adjust type. */ +- deprecated_set_value_type (value, TYPE_TARGET_TYPE (original_type)); ++ deprecated_set_value_type (value, resolved_original_target_type); + + /* Add embedding info. */ + set_value_enclosing_type (value, enc_type); +@@ -3641,12 +3650,11 @@ coerce_ref (struct value *arg) + enc_type = check_typedef (value_enclosing_type (arg)); + enc_type = TYPE_TARGET_TYPE (enc_type); + +- retval = value_at_lazy (enc_type, +- unpack_pointer (value_type (arg), +- value_contents (arg))); ++ CORE_ADDR addr = unpack_pointer (value_type (arg), value_contents (arg)); ++ retval = value_at_lazy (enc_type, addr); + enc_type = value_type (retval); +- return readjust_indirect_value_type (retval, enc_type, +- value_type_arg_tmp, arg); ++ return readjust_indirect_value_type (retval, enc_type, value_type_arg_tmp, ++ arg, addr); + } + + struct value * +diff --git a/gdb/value.h b/gdb/value.h +--- a/gdb/value.h ++++ b/gdb/value.h +@@ -487,7 +487,9 @@ extern struct value *coerce_ref_if_computed (const struct value *arg); + + /* Setup a new value type and enclosing value type for dereferenced value VALUE. + ENC_TYPE is the new enclosing type that should be set. ORIGINAL_TYPE and +- ORIGINAL_VAL are the type and value of the original reference or pointer. ++ ORIGINAL_VAL are the type and value of the original reference or ++ pointer. ORIGINAL_VALUE_ADDRESS is the address within VALUE, that is ++ the address that was dereferenced. + + Note, that VALUE is modified by this function. + +@@ -496,7 +498,8 @@ extern struct value *coerce_ref_if_computed (const struct value *arg); + extern struct value * readjust_indirect_value_type (struct value *value, + struct type *enc_type, + const struct type *original_type, +- const struct value *original_val); ++ struct value *original_val, ++ CORE_ADDR original_value_address); + + /* Convert a REF to the object referenced. */ + diff --git a/SPECS/gdb.spec b/SPECS/gdb.spec index 41ef67d..ed26b1e 100644 --- a/SPECS/gdb.spec +++ b/SPECS/gdb.spec @@ -26,7 +26,7 @@ Version: 8.2 # 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: 12%{?dist} +Release: 15%{?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 Group: Development/Debuggers @@ -57,8 +57,21 @@ Recommends: dnf-command(debuginfo-install) # below, but it cannot hurt either -- rdieter Conflicts: gdb-headless < 7.12-29 +# Do not permit installations of 32-bit package. RH BZ 1853140 +%ifarch %{ix86} +Conflicts: libc.so.6()(64bit) +%endif + Summary: A stub package for GNU source-level debugger Requires: gdb-headless%{?_isa} = %{version}-%{release} +# Obsolete previous versions with this version, which should force users +# of the i686 package to update/install the x86_64 version. +# RH BZ 1853140 +%ifarch x86_64 +Provides: gdb = %{version}-%{release} +Obsoletes: gdb < %{version}-%{release} +%endif +%endif %description 'gdb' package is only a stub to install gcc-gdb-plugin for 'compile' commands. @@ -66,6 +79,13 @@ See package 'gdb-headless'. %package headless Group: Development/Debuggers + +# Obsolete previous versions with this version, which should force users +# of the i686 package to update/install the x86_64 version. +# RH BZ 1853140 +%ifarch x86_64 +Provides: gdb-headless = %{version}-%{release} +Obsoletes: gdb-headless < %{version}-%{release} %endif Summary: A GNU source-level debugger for C, C++, Fortran, Go and other languages @@ -379,6 +399,14 @@ and printing their data. Summary: A standalone server for GDB (the GNU source-level debugger) Group: Development/Debuggers +# Obsolete previous versions with this version, which should force users +# of the i686 package to update/install the x86_64 version. +# RH BZ 1853140 +%ifarch x86_64 +Provides: gdb-gdbserver = %{version}-%{release} +Obsoletes: gdb-gdbserver < %{version}-%{release} +%endif + %description gdbserver GDB, the GNU debugger, allows you to debug programs written in C, C++, Java, and other languages, by executing them in a controlled fashion @@ -1034,6 +1062,25 @@ fi %endif %changelog +* Fri Dec 11 2020 Keith Seitz - 8.2-15.el8 +- Backport "Correct recording of 'store on condition' insns" + (Andreas Arnaz, RH BZ 1903374) +- Backport "Fortran dynamic type related fixes" + (Andrew Burgess, RH BZ 1905701) + +* Fri Nov 13 2020 Keith Seitz - 8.2-14.el8 +- Obsolete earlier versions on x86_64 and conflict with 64-bit + glibc on ix86. (Keith Seitz, RH BZ 1853140) +- Really fix 1878810 (Keith Seitz, RH BZ 1878810) + +* Wed Nov 4 2020 Keith Seitz - 8.2-13.el8 +- Backport "Fix terminal problems when error() is called." + (Alan Hayward RH BZ 1852580) +- Backport "core file memory access problem." + (Kevin Buettner, RH BZ 1785126) +- Backport "Stop the BFD library from issuing a warning message..." + (Nick Clifton, RH BZ 1878810) + * Tue May 12 2020 Keith Seitz - 8.2-12.el8 - Include support for z15 record/replay (RH BZ 1659535)