[PATCH] ld: ensure build-id is placed near ELF headers
Andrew Burgess
aburgess@redhat.com
Mon Aug 12 14:21:23 GMT 2024
After the commit:
commit e8e10743f7b207b21a1efb0cc9e42487080db013
Date: Thu Jun 13 15:10:15 2024 +0100
Add --rosegment option to BFD linker to stop the '-z separate-code' from generating two read-only segments.
When an executable is built with the --rosegment option GDB is no
longer able to find the build-id of the executable from a core file.
The problem is that GDB depends on what I guess was a lucky
coincidence; that the build-id was placed close to the ELF headers.
When a Linux kernel produces a core file there is specific support in
place so that the kernel will emit the first page of any private file
mapping that looks like it might contain ELF headers. If the build-id
is placed close to the ELF headers then it will be included in this
first page and GDB can find it. Using the build-id GDB can then
validate that it has the correct executable loaded to debug the core
file, or in some cases GDB can use the build-id to find the executable
that matches the core file automatically.
The Linux kernel support for this feature has existed since 2007, see
this (kernel) commit:
commit 82df39738ba9e02c057fa99b7461a56117d36119
Date: Tue Oct 16 23:27:02 2007 -0700
Add MMF_DUMP_ELF_HEADERS
I ran into this issue while testing on the latest Fedora Rawhide
build, currently the linker on this system enables --rosegment by
default and as a result GDB is not able to find the build-id for any
core file.
What's happening is that with --rosegment the linker merges the
.note.gnu.build-id sections with all the other data content and places
this after the executable content. Without the --rosegment the
.note.gnu.build-id section is placed pretty much first before the
executable and data sections.
As a consequence, without --rosegment the build-id will usually be on
the same page as the ELF headers while with --rosegment on the
executable content is first and this often fills the rest of the page
after the ELF headers.
This patch aims to fix this by placing the build-id first. The
build-id will then be included within the same LOAD-able segment as
the executable content, just as the ELF headers are. With this patch
in place GDB is once again able to find the build-id from a core
file.
---
ld/scripttempl/elf.sc | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index 54716110b61..17184037753 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -425,7 +425,6 @@ emit_early_ro()
{
cat <<EOF
${INITIAL_READONLY_SECTIONS}
- .note.gnu.build-id ${RELOCATING-0}: { *(.note.gnu.build-id) }
EOF
}
@@ -436,6 +435,11 @@ cat <<EOF
${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+PROVIDE (__executable_start = ${TEXT_START_ADDR}); . = ${TEXT_BASE_ADDRESS};}}}
${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}}
${CREATE_PIE+${RELOCATING+PROVIDE (__executable_start = ${SHLIB_TEXT_START_ADDR}); . = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}}
+
+ /* Place build-id as close to the ELF headers as possible. This
+ maximises the chance the build-id will be present in core files,
+ which GDB can use to improve the debug experience. */
+ .note.gnu.build-id ${RELOCATING-0}: { *(.note.gnu.build-id) }
EOF
}
base-commit: 49e607f511c1fab82a0116990a72d1915c74bb4a
--
2.25.4
More information about the Binutils
mailing list