[binutils-gdb] gdb/corelow: mark bytes unavailable when reading from unavailable mapping
Simon Marchi via Gdb-cvs <[email protected]>
| Newsgroups | gmane.comp.gdb.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ad47afb11b1fff3d5d0631844c565d4d7f19033e commit ad47afb11b1fff3d5d0631844c565d4d7f19033e Author: Simon Marchi <[email protected]> Date: Sun Mar 1 22:23:05 2026 -0500 gdb/corelow: mark bytes unavailable when reading from unavailable mapping The main motivation for this change is to nicely support "lightweight" core files on ROCm (more on this below), but I think that the change also makes sense for regular core files. When handling a file mappings from a core file, the core target attempts to open the referenced file. If successful, the mappings from this file end up in the m_core_file_mappings vector. Otherwise, they end up in the m_core_unavailable_mappings vector. When trying to read from an address within an unavailable mapping, unless the executable target beneath is able to fulfill the request, the core target returns an error (TARGET_XFER_E_IO). This is from gdb.base/corefile.exp before the patch: (gdb) PASS: gdb.base/corefile.exp: accessing mmapped data in core file with coremmap.data removed x/8bd buf2ro 0x7f095a517000: Cannot access memory at address 0x7f095a517000 I think that this would be a good use case for the "unavailable" status. We know the memory was there at runtime, it's just not available during post-mortem debugging. That is the definition of "unavailable". After changing core_target::xfer_partial to report the bytes as unavailable, which this patch does, the same test now shows: (gdb) PASS: gdb.base/corefile.exp: accessing mmapped data in core file with coremmap.data removed x/8bd buf2ro 0x7f0250f52000: <unavailable> <unavailable> <unavailable> <unavailable> <unavailable> <unavailable> <unavailable> <unavailable> I would say that the output of the x command isn't great, but that is just a presentation issue. The original motivation for me to do this change is that we are working on lightweight GPU core dump support in ROCm. By default, the ROC runtime will dump all the memory allocated in the context of the crashing wave. This can result in absurdly big core dumps. With lightweight core dumps, the runtime only dumps a certain subset of the information that is considered essential. When trying to read a value from a segment of memory that was not dumped, I believe that it is natural to use the "unavailable" status. That is handled by this patch. In the following example, `d` is a kernel parameter of type `int *`. Its value was collected in the core dump, but the memory it points to, allocated with hipMalloc, was not. Before: (gdb) p data $1 = (int *) 0x78bf26e00000 (gdb) p data[5] ❌️ Cannot access memory at address 0x78bf26e00014 After: (gdb) p data $1 = (int *) 0x78bf26e00000 (gdb) p data[5] $2 = <unavailable> Note that the same concept exists on Linux with the minicoredumper project [1]. We could adjust the core target to act the same way when dealing with minicoredumps. [1] https://www.linutronix.de/minicoredumper/ Change-Id: I4df82ba4116e87545691facec0cb662c4b2b7797 Approved-By: Tom Tromey <[email protected]> Diff: --- gdb/corelow.c | 5 +++-- gdb/testsuite/gdb.base/coredump-filter.exp | 2 +- gdb/testsuite/gdb.base/corefile.exp | 2 +- gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/gdb/corelow.c b/gdb/corelow.c index 84f44bc680e..f6e8179d1f4 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -1450,7 +1450,7 @@ core_target::xfer_partial (enum target_object object, const char *annex, resolve the access from there. If that fails, but the access is within an unavailable region, - then the access itself should fail. */ + then report the bytes as unavailable. */ for (const auto &mr : m_core_unavailable_mappings) { if (mr.contains (offset)) @@ -1466,7 +1466,8 @@ core_target::xfer_partial (enum target_object object, const char *annex, if (xfer_status == TARGET_XFER_OK) return TARGET_XFER_OK; - return TARGET_XFER_E_IO; + *xfered_len = len; + return TARGET_XFER_UNAVAILABLE; } } diff --git a/gdb/testsuite/gdb.base/coredump-filter.exp b/gdb/testsuite/gdb.base/coredump-filter.exp index c35a0334ff3..e2ce86d48e8 100644 --- a/gdb/testsuite/gdb.base/coredump-filter.exp +++ b/gdb/testsuite/gdb.base/coredump-filter.exp @@ -62,7 +62,7 @@ proc do_load_and_test_core { core var working_var working_value dump_excluded } # Access the memory the addresses point to. if { $dump_excluded == 0 } { - gdb_test "print/x *(char *) $coredump_var_addr($var)" "\(${::valnum_re} = <error: \)?Cannot access memory at address $hex\(>\)?" \ + gdb_test "print/x *(char *) $coredump_var_addr($var)" "(Cannot access memory at address $hex|${::valnum_re} = <unavailable>)" \ "printing $var when core is loaded (should not work)" gdb_test "print/x *(char *) $coredump_var_addr($working_var)" " = $working_value.*" \ "print/x *$working_var ( = $working_value)" diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp index 957bccf43a4..f6a0a7a1eca 100644 --- a/gdb/testsuite/gdb.base/corefile.exp +++ b/gdb/testsuite/gdb.base/corefile.exp @@ -229,7 +229,7 @@ gdb_test "x/8bd buf2" \ "accessing mmapped data in core file with coremmap.data removed" gdb_test "x/8bd buf2ro" \ - "$hex\[^:\]*:\\s+Cannot access memory at address $hex" \ + "$hex\[^:\]*:(\\s+<unavailable>){8}" \ "accessing read-only mmapped data in core file with coremmap.data removed" # Restore the coremmap.data file so later tests don't give warnings diff --git a/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp index 784762c2057..b1934c6b7e4 100644 --- a/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp +++ b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp @@ -144,7 +144,7 @@ proc read_ptr_value { } { -re -wrap "^${::hex}(?:\\s+<\[^>\]+>)?:\\s+($::hex)" { set value $expect_out(1,string) } - -re -wrap "^${::hex}(?:\\s+<\[^>\]+>)?:\\s+Cannot access memory at address ${::hex}" { + -re -wrap "^${::hex}(?:\\s+<\[^>\]+>)?:\\s+<unavailable>" { set value "unavailable" } }