From 26fdff8f7404ee0f9ae957fd5640d43eb6d86820 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Mon, 13 Oct 2025 20:54:43 +0200 Subject: [PATCH 04/25] [gdb/testsuite] Use expect_build_id_in_core_file a bit more Recent commit c1950dcc04c ("gdb/testsuite: fix failure from gdb.python/py-corefile.exp") introduced proc expect_build_id_in_core_file, which detects the problem that: ... ... some versions of the linker didn't place the build-id within the first page of an ELF. As a result, the Linux kernel would not include the build-id in the generated core file, ... ... Use this proc in a few more test-cases, to deal with the same problem. Tested on x86_64-linux, openSUSE Tumbleweed with ld 2.43.1. Approved-By: Andrew Burgess PR testsuite/33528 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33528 --- .../gdb.debuginfod/corefile-mapped-file.exp | 3 + .../gdb.debuginfod/solib-with-soname.exp | 4 ++ .../gdb.python/py-missing-objfile.exp | 5 ++ gdb/testsuite/lib/gdb.exp | 58 +++++++++++++++++++ 4 files changed, 70 insertions(+) diff --git a/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp index f02876e1453..af143b7d506 100644 --- a/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp +++ b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp @@ -81,6 +81,9 @@ if {[prepare_for_testing_full "build exec which loads the shared library" \ return } +require {expect_build_id_in_core_file $binfile2} +require {expect_build_id_in_core_file $library_filename} + if {![runto_main]} { return } diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp b/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp index 98c4535fca7..07f0a0f170b 100644 --- a/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp +++ b/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp @@ -96,6 +96,10 @@ if { [build_executable "build executable" ${binfile} ${srcfile2} \ return } +require {expect_build_id_in_core_file $library_1_filename} +require {expect_build_id_in_core_file $library_2_filename} +require {expect_build_id_in_core_file $binfile} + # If the board file is automatically splitting the debug information # into a separate file (e.g. the cc-with-gnu-debuglink.exp board) then # this test isn't going to work. diff --git a/gdb/testsuite/gdb.python/py-missing-objfile.exp b/gdb/testsuite/gdb.python/py-missing-objfile.exp index 8488047d105..2786bdfb2ed 100644 --- a/gdb/testsuite/gdb.python/py-missing-objfile.exp +++ b/gdb/testsuite/gdb.python/py-missing-objfile.exp @@ -183,6 +183,11 @@ with_test_prefix "no objfiles available" { check_loaded_debug false false } +# The following tests assume that the build-ids of binfile and libfile can be +# found in the core file. +require {expect_build_id_in_core_file $binfile} +require {expect_build_id_in_core_file $libfile} + with_test_prefix "all objfiles available" { # Another sanity check that GDB can find the files via the # debug-file-directory. diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index b103c117258..47cff389a41 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -11044,5 +11044,63 @@ gdb_caching_proc root_user {} { return [expr $uid == 0] } +# Return true if we expect the build-id from FILENAME to be included +# in a core file. +# +# On GNU/Linux, when creating a core file, the kernel places the first +# page of an ELF into the core file. If the build-id is within that +# page then GDB can find the build-id from the core file. +# +# This proc checks that the target is GNU/Linux, and then uses readelf +# to find the offset of the build-id within the ELF. If there is a +# build-id, and it is within the first page, then return true. +# Otherwise, return false. + +proc expect_build_id_in_core_file { filename } { + # I'm not sure if other kernels take care to add the first page of + # each ELF into the core file. If they do then this test can be + # relaxed. + if {![istarget *-*-linux*]} { + return false + } + + # Use readelf to find the build-id note in FILENAME. + set readelf_program [gdb_find_readelf] + set cmd [list $readelf_program -WS $filename | grep ".note.gnu.build-id"] + set res [catch {exec {*}$cmd} output] + verbose -log "running: $cmd" + verbose -log "result: $res" + verbose -log "output: $output" + if { $res != 0 } { + return false + } + + # Extract the OFFSET from the readelf output. + set res [regexp {NOTE[ \t]+([0-9a-f]+)[ \t]+([0-9a-f]+)} \ + $output dummy addr offset] + if { $res != 1 } { + return false + } + + # Convert OFFSET to decimal. + set offset [expr {[subst 0x$offset]}] + + # Now figure out the page size. This should be fine for Linux + # hosts, see the istarget check above. + if {[catch {exec getconf PAGESIZE} page_size]} { + # Failed to fetch page size. + return false + } + + # If the build-id is within the first page, then we expect the + # kernel to include it in the core file. There is actually a + # kernel setting (see coredump_filter) that could prevent this, + # but the default behaviour is to include the first page of the + # ELF, so for now, we just assume this is on. + verbose -log "Page size is $page_size, Offset is $offset" + return [expr {$offset < $page_size}] +} + + # Always load compatibility stuff. load_lib future.exp -- 2.51.0