Bug#1117999: dpkg-buildflags: enable ELF package note metadata

Benjamin Drung <[email protected]>
Newsgroups gmane.linux.debian.devel.dpkg.bugs
Message-ID <176036359611.970514.9620085692494184542.reportbug__7994.36026006646$1760363737$gmane$org@curves>
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.

--
Benjamin Drung
Debian & Ubuntu Developer
0001-dpkg-buildflags-enable-ELF-package-note-metadata.patch (application/mbox, 5.5 KB)
From 244073ac87fc934cd299be76b7da950b9817f725 Mon Sep 17 00:00:00 2001
From: Benjamin Drung <[email protected]>
Date: Mon, 13 Oct 2025 15:38:22 +0200
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).
---
 man/dpkg-buildflags.pod       |  8 +++++
 scripts/Dpkg/Vendor/Debian.pm | 64 +++++++++++++++++++++++++++++++++++
 scripts/t/Dpkg_BuildFlags.t   | 12 ++++++-
 3 files changed, 83 insertions(+), 1 deletion(-)

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..11d1da413 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.
-- 
2.51.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.