On Mon, 13 Oct 2025 15:53:16 +0200 Benjamin Drung <[email protected]> wrote: > Package: dpkg > Version: 1.22.21 > Severity: normal > Tags: patch > X-Debbugs-Cc: [email protected] > > Dear Maintainer, > > as discussed and agreed on at DebConf 25, please add ELF package note > metadata following the > https://systemd.io/PACKAGE_METADATA_FOR_EXECUTABLE_FILES/ specification.
> > A tested patch is attached. Here is an updated patch with following changes: * fix extra comma when DEB_BUILD_DEBUG_INFO_URL is set * fix scripts/t/mk.t test case (i.e. make debian/changelog accessible) -- Benjamin Drung Debian & Ubuntu Developer
From 322086638d888fc604fe29db86fa196d7deda70c Mon Sep 17 00:00:00 2001 From: Benjamin Drung <[email protected]> Date: Tue, 18 Nov 2025 19:01:53 +0100 Subject: [PATCH] dpkg-buildflags: enable ELF package note metadata Following the https://systemd.io/ELF_PACKAGE_METADATA/ add a new qa flag, enable by default, that adds this package metadata ELF note to every binary being built, to ease identification, especially in the case of a coredump. Since the ELF package note metadata changes the build ID, include only "static" data and exclude the package version (as agreed at DebConf 25). Closes: #1117999 LP: #2071468 --- man/dpkg-buildflags.pod | 8 +++++ scripts/Dpkg/Vendor/Debian.pm | 64 +++++++++++++++++++++++++++++++++++ scripts/t/Dpkg_BuildFlags.t | 12 ++++++- scripts/t/mk.t | 4 ++- 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/man/dpkg-buildflags.pod b/man/dpkg-buildflags.pod index 7a759eb7a..33be2555b 100644 --- a/man/dpkg-buildflags.pod +++ b/man/dpkg-buildflags.pod @@ -545,6 +545,14 @@ B<OBJCFLAGS>, B<CXXFLAGS> and B<OBJCXXFLAGS> with flags set to B<-D__DEB_CANARY_>I<flag>_I<random-id>B<__>, and B<LDFLAGS> set to B<-Wl,-z,deb-canary->I<random-id>. +=item B<elfpackagemetadata> + +This setting (since dpkg 1.23.0; enabled by default) adds an ELF +note containing package metadata to every ELF binary being built. If the +$DEB_BUILD_DEBUG_INFO_URL environment variable is defined, it will be +used to include the value as a debuginfod URL. This follows the specification +defined at: https://systemd.io/ELF_PACKAGE_METADATA/ + =back =head2 optimize diff --git a/scripts/Dpkg/Vendor/Debian.pm b/scripts/Dpkg/Vendor/Debian.pm index f7272ad61..a002d7a9f 100644 --- a/scripts/Dpkg/Vendor/Debian.pm +++ b/scripts/Dpkg/Vendor/Debian.pm @@ -136,6 +136,7 @@ sub set_build_features { bug => undef, 'bug-implicit-func' => undef, canary => 0, + elfpackagemetadata => 1, }, reproducible => { timeless => 1, @@ -516,6 +517,10 @@ sub add_build_flags { $flags->append('LDFLAGS', "-Wl,-z,deb-canary-${id}"); } + if ($flags->use_feature('qa', 'elfpackagemetadata')) { + add_elf_package_metadata($flags); + } + ## Area: reproducible # Warn when the __TIME__, __DATE__ and __TIMESTAMP__ macros are used. @@ -681,6 +686,65 @@ sub add_build_flags { } } +sub add_elf_package_metadata { + my ($flags) = @_; + my $arch; + my $pkgsrc; + + if (!defined $ENV{DEB_HOST_ARCH}) { + require Dpkg::Arch; + $arch = Dpkg::Arch::get_host_arch(); + } else { + $arch = $ENV{DEB_HOST_ARCH}; + } + + if (!defined $ENV{DEB_SOURCE}) { + if (! -r 'debian/changelog') { + warning(g_('debian/changelog not found. Not setting ELF package metadata parameter.')); + return; + } + + require Dpkg::Changelog::Debian; + my $pkgchangelog = Dpkg::Changelog::Debian->new(range => { "count" => 1 }); + $pkgchangelog->load('debian/changelog'); + my $chgentry = @{$pkgchangelog}[0]; + $pkgsrc = $chgentry->get_source(); + } else { + $pkgsrc = $ENV{DEB_SOURCE}; + } + + if (! -f '/usr/lib/os-release') { + warning(g_('/usr/lib/os-release not found. Not setting ELF package metadata parameter.')); + return; + } + my $os_id = ''; + open my $os_release, '<', '/usr/lib/os-release' + or syserr(g_('failed to read /usr/lib/os-release')); + while (<$os_release>) { + chomp; + # Ensure any quotes are removed, as we don't want to embed them in JSON + if (m/^ID=(.*)/) { + $os_id = $1; + $os_id =~ tr/"//d; + } + } + close $os_release or syserr(g_('failed to close /usr/lib/os-release')); + if ($os_id eq '') { + warning(g_('/usr/lib/os-release does not set ID. Not setting ELF package metadata parameter.')); + return; + } + + # Per https://systemd.io/ELF_PACKAGE_METADATA/ + my $package_metadata = "{%22type%22:%22deb%22%2C%22os%22:%22$os_id%22%2C%22name%22:%22$pkgsrc%22%2C%22architecture%22:%22$arch%22"; + # The debuginfod URL is optional, skip it if not available. + if ($ENV{DEB_BUILD_DEBUG_INFO_URL}) { + $package_metadata .= "%2C%22debugInfoUrl%22:%22$ENV{DEB_BUILD_DEBUG_INFO_URL}%22"; + } + $package_metadata .= "}"; + $flags->append('LDFLAGS', "-Wl,--package-metadata=$package_metadata"); + return; +} + sub _build_tainted_by { my $self = shift; my %tainted; diff --git a/scripts/t/Dpkg_BuildFlags.t b/scripts/t/Dpkg_BuildFlags.t index 011a50717..07d8a15d2 100644 --- a/scripts/t/Dpkg_BuildFlags.t +++ b/scripts/t/Dpkg_BuildFlags.t @@ -15,7 +15,7 @@ use v5.36; -use Test::More tests => 118; +use Test::More tests => 119; BEGIN { $ENV{DEB_BUILD_ARCH} = 'amd64'; @@ -121,6 +121,7 @@ my %known_features = ( bug bug-implicit-func canary + elfpackagemetadata ) ], reproducible => [ qw( fixdebugpath @@ -316,4 +317,13 @@ test_has_noflag($bf, 'CPPFLAGS', '-D_TIME_BITS=64'); test_has_noflag($bf, 'CPPFLAGS', '-U_TIME_BITS'); test_has_flag($bf, 'CFLAGS', '-Werror=implicit-function-declaration'); +# ELF package metadata +$bf = Dpkg::BuildFlags->new(); +my %qa_features = $bf->get_features('qa'); +if ($qa_features{'elfpackagemetadata'} && -r 'debian/changelog') { + test_has_flag($bf, 'LDFLAGS', '-Wl,--package-metadata=\{*'); +} else { + test_has_noflag($bf, 'LDFLAGS', '-Wl,--package-metadata*'); +} + # TODO: Add more test cases. diff --git a/scripts/t/mk.t b/scripts/t/mk.t index 811b7be7e..d77a5adba 100644 --- a/scripts/t/mk.t +++ b/scripts/t/mk.t @@ -26,7 +26,7 @@ use Dpkg::IPC; use Dpkg::Vendor; my $srcdir = rel2abs($ENV{srcdir} || '.'); -my $datadir = test_get_data_path(); +my $datadir = rel2abs(test_get_data_path()); # Turn these into absolute names so that we can safely switch to the test # directory with «make -C». @@ -74,6 +74,8 @@ sub cmd_get_vars { # Test makefiles. +chdir($ENV{DEB_BUILD_PATH}); + my %arch = cmd_get_vars($ENV{PERL}, "$srcdir/dpkg-architecture.pl", '-f'); while (my ($k, $v) = each %arch) { -- 2.51.0

