diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7aadd870423..4840de8591a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2020-08-31 Kevin Buettner + + * corelow.c (unordered_set): Include. + (class core_target): Add field 'm_core_unavailable_mappings'. + (core_target::build_file_mappings): Print only one warning + per inaccessible file. Add unavailable/broken mappings + to m_core_unavailable_mappings. + (core_target::xfer_partial): Call... + (core_target::xfer_memory_via_mappings): New method. + 2020-08-31 Simon Marchi * dwarf2/read.c (struct field_info) : Change diff --git a/gdb/corelow.c b/gdb/corelow.c index b6ee219f57c..96ec739c62f 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -47,6 +47,7 @@ #include "build-id.h" #include "gdbsupport/pathstuff.h" #include +#include #include "gdbcmd.h" #ifndef O_LARGEFILE @@ -131,9 +132,21 @@ private: /* per-core data */ information about memory mapped files. */ target_section_table m_core_file_mappings {}; + /* Unavailable mappings. These correspond to pathnames which either + weren't found or could not be opened. Knowing these addresses can + still be useful. */ + std::vector m_core_unavailable_mappings; + /* Build m_core_file_mappings. Called from the constructor. */ void build_file_mappings (); + /* Helper method for xfer_partial. */ + enum target_xfer_status xfer_memory_via_mappings (gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, + ULONGEST len, + ULONGEST *xfered_len); + /* FIXME: kettenis/20031023: Eventually this field should disappear. */ struct gdbarch *m_core_gdbarch = NULL; @@ -182,6 +195,7 @@ void core_target::build_file_mappings () { std::unordered_map bfd_map; + std::unordered_set unavailable_paths; /* See linux_read_core_file_mappings() in linux-tdep.c for an example read_core_file_mappings method. */ @@ -216,9 +230,12 @@ core_target::build_file_mappings () = exec_file_find (filename, NULL); if (expanded_fname == nullptr) { - warning (_("Can't open file %s during file-backed mapping " - "note processing"), - filename); + m_core_unavailable_mappings.emplace_back (start, end - start); + /* Print just one warning per path. */ + if (unavailable_paths.insert (filename).second) + warning (_("Can't open file %s during file-backed mapping " + "note processing"), + filename); return; } @@ -227,6 +244,7 @@ core_target::build_file_mappings () if (bfd == nullptr || !bfd_check_format (bfd, bfd_object)) { + m_core_unavailable_mappings.emplace_back (start, end - start); /* 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 @@ -268,6 +286,8 @@ core_target::build_file_mappings () ts->owner = nullptr; ts->the_bfd_section = sec; }); + + normalize_mem_ranges (&m_core_unavailable_mappings); } static void add_to_thread_list (bfd *, asection *, void *); @@ -728,6 +748,57 @@ core_target::files_info () print_section_info (&m_core_section_table, core_bfd); } +/* Helper method for core_target::xfer_partial. */ + +enum target_xfer_status +core_target::xfer_memory_via_mappings (gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, ULONGEST len, + ULONGEST *xfered_len) +{ + enum target_xfer_status xfer_status; + + xfer_status = (section_table_xfer_memory_partial + (readbuf, writebuf, + offset, len, xfered_len, + m_core_file_mappings.sections, + m_core_file_mappings.sections_end)); + + if (xfer_status == TARGET_XFER_OK || m_core_unavailable_mappings.empty ()) + return xfer_status; + + /* There are instances - e.g. when debugging within a docker + container using the AUFS storage driver - where the pathnames + obtained from the note section are incorrect. Despite the path + being wrong, just knowing the start and end addresses of the + mappings is still useful; we can attempt an access of the file + stratum constrained to the address ranges corresponding to the + unavailable mappings. */ + + ULONGEST memaddr = offset; + ULONGEST memend = offset + len; + + for (const auto &mr : m_core_unavailable_mappings) + { + if (address_in_mem_range (memaddr, &mr)) + { + if (!address_in_mem_range (memend, &mr)) + len = mr.start + mr.length - memaddr; + + xfer_status = this->beneath ()->xfer_partial (TARGET_OBJECT_MEMORY, + NULL, + readbuf, + writebuf, + offset, + len, + xfered_len); + break; + } + } + + return xfer_status; +} + enum target_xfer_status core_target::xfer_partial (enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, @@ -761,11 +832,8 @@ core_target::xfer_partial (enum target_object object, const char *annex, 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); + xfer_status = xfer_memory_via_mappings (readbuf, writebuf, offset, + len, xfered_len); else xfer_status = this->beneath ()->xfer_partial (object, annex, readbuf, writebuf, offset, len, diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 148f31d26dd..e50b2352d9f 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-08-31 Kevin Buettner + + * gdb.base/corefile2.exp (renamed binfile): New tests. + 2020-08-31 Simon Marchi * gdb.dwarf2/dw2-reg-undefined.exp: Remove spurious #. diff --git a/gdb/testsuite/gdb.base/corefile2.exp b/gdb/testsuite/gdb.base/corefile2.exp index 5de7ead4d44..38b8eb770bd 100644 --- a/gdb/testsuite/gdb.base/corefile2.exp +++ b/gdb/testsuite/gdb.base/corefile2.exp @@ -143,6 +143,33 @@ gdb_test_multiple $test "" { } } +# Test again with executable renamed during loading of core file. + +with_test_prefix "renamed binfile" { + # Don't load $binfile in this call to clean_restart. (BFD will + # complain that $binfile has disappeared after the rename if it's + # loaded first.) + clean_restart + + # Rename $binfile so that it won't be found during loading of + # the core file. + set hide_binfile [standard_output_file "${testfile}.hide"] + remote_exec host "mv -f $binfile $hide_binfile" + + # Load core file - check that a warning is printed. + global xfail + if { $xfail } { setup_xfail "*-*-*" } + gdb_test "core-file $corefile" \ + "warning: Can't open file.*during.* note processing.*Core was generated by .*\#0 .*\(\)" \ + "load core file without having first loaded binfile" + + # Restore $binfile and then load it. + remote_exec host "mv -f $hide_binfile $binfile" + gdb_load ${binfile} + + do_tests +} + # Restart and run to the abort call. clean_restart $binfile