From fe5a66122c2bfbdccb7ebf202a23666df4607f2b Mon Sep 17 00:00:00 2001 From: oreo639 Date: Fri, 22 Mar 2024 16:47:54 -0700 Subject: [PATCH] gobject-introspection: use elfutils lldwraper instead of prelink-cross Replace lldwraper with one maintained by Debian using elfutils. elfutils is already a dependency of glib. Also, always use this lldwrapper by default for both native and cross. https://salsa.debian.org/gnome-team/gobject-introspection/-/blob/debian/latest/debian/elf-get-needed.c https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/482 --- .../files/elf-get-needed.c | 156 ++++++++++++++++++ .../files/g-ir-scanner-wrapper | 2 +- ...-error-return-codes-from-ldd-wrapper.patch | 27 --- ...a6d482eab44da9d58b7eebf6dddc6cdf2912.patch | 108 ++++++++++++ srcpkgs/gobject-introspection/template | 14 +- 5 files changed, 274 insertions(+), 33 deletions(-) create mode 100644 srcpkgs/gobject-introspection/files/elf-get-needed.c delete mode 100644 srcpkgs/gobject-introspection/patches/0006-giscanner-ignore-error-return-codes-from-ldd-wrapper.patch create mode 100644 srcpkgs/gobject-introspection/patches/401ca6d482eab44da9d58b7eebf6dddc6cdf2912.patch diff --git a/srcpkgs/gobject-introspection/files/elf-get-needed.c b/srcpkgs/gobject-introspection/files/elf-get-needed.c new file mode 100644 index 00000000000000..be78f3bdf2a925 --- /dev/null +++ b/srcpkgs/gobject-introspection/files/elf-get-needed.c @@ -0,0 +1,156 @@ +/* + * Copyright © 2019-2023 Collabora Ltd. + * SPDX-License-Identifier: MIT + * + * Use libelf to parse ELF headers for DT_NEEDED, and fake the output + * format of ldd closely enough that GObject-Introspection can parse it. + * + * Limitations when compared with real ldd: + * - Only direct dependencies are output: unlike ldd, this is not recursive. + * For GObject-Introspection this is what we ideally want anyway. + * - Only bare SONAMEs are output, no paths or other extraneous information. + * + * https://salsa.debian.org/gnome-team/gobject-introspection/-/blob/debian/latest/debian/elf-get-needed.c + * https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/482 + */ + +#include +#include +#include +#include + +#include +#include + +#if 0 +#define trace(...) fprintf(stderr, __VA_ARGS__) +#else +#define trace(...) do {} while (0) +#endif + +int +main (int argc, + char **argv) +{ + const char *library; + Elf *elf = NULL; + Elf_Scn *scn = NULL; + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = NULL; + size_t phnum; + size_t i; + Elf_Data *data; + uintptr_t needed_offset = (uintptr_t) -1; + const char *needed; + size_t sh_entsize; + int fd; + + if (argc != 2) + { + fprintf (stderr, "Usage: %s LIBRARY\n", argv[0]); + return 2; + } + + library = argv[1]; + + if (elf_version (EV_CURRENT) == EV_NONE) + { + perror ("elf_version(EV_CURRENT)"); + return 1; + } + + if ((fd = open (library, O_RDONLY | O_CLOEXEC, 0)) < 0) + { + perror (library); + return 1; + } + + if ((elf = elf_begin (fd, ELF_C_READ, NULL)) == NULL) + { + fprintf (stderr, "Error reading library %s: %s", + library, elf_errmsg (elf_errno ())); + return 1; + } + + if (elf_getphdrnum (elf, &phnum) < 0) + { + + fprintf (stderr, "Unable to determine the number of program headers: %s\n", + elf_errmsg (elf_errno ())); + + return 1; + } + + trace ("phnum=%zu\n", phnum); + + for (i = 0; i < phnum; i++) + { + GElf_Phdr phdr_mem; + GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); + + if (phdr != NULL && phdr->p_type == PT_DYNAMIC) + { + scn = gelf_offscn (elf, phdr->p_offset); + trace ("scn=%p\n", scn); + + if (scn == NULL) + { + fprintf (stderr, "Unable to get the section: %s\n", + + elf_errmsg (elf_errno ())); + + return 1; + } + + shdr = gelf_getshdr (scn, &shdr_mem); + trace ("shdr=%p, shdr_mem=%p\n", shdr, &shdr_mem); + + if (shdr == NULL) + { + fprintf (stderr, "Unable to get the section header: %s\n", + + elf_errmsg (elf_errno ())); + + return 1; + } + break; + } + } + + if (shdr == NULL) + { + fprintf (stderr, "Unable to find the section header\n"); + return 1; + } + + data = elf_getdata (scn, NULL); + + if (data == NULL) + { + fprintf (stderr, "Unable to get the dynamic section data: %s\n", + elf_errmsg (elf_errno ())); + + return 1; + } + + trace ("data=%p\n", data); + + sh_entsize = gelf_fsize (elf, ELF_T_DYN, 1, EV_CURRENT); + trace ("sh_entsize=%zu\n", sh_entsize); + + for (i = 0; i < shdr->sh_size / sh_entsize; i++) + { + GElf_Dyn dyn_mem; + GElf_Dyn *dyn = gelf_getdyn (data, i, &dyn_mem); + + if (dyn == NULL) + break; + + if (dyn->d_tag == DT_NEEDED) + printf ("%s\n", elf_strptr (elf, shdr->sh_link, dyn->d_un.d_ptr)); + } + + elf_end (elf); + close (fd); + return 0; +} diff --git a/srcpkgs/gobject-introspection/files/g-ir-scanner-wrapper b/srcpkgs/gobject-introspection/files/g-ir-scanner-wrapper index d5c426d3cc2e2b..23a66d03655490 100644 --- a/srcpkgs/gobject-introspection/files/g-ir-scanner-wrapper +++ b/srcpkgs/gobject-introspection/files/g-ir-scanner-wrapper @@ -15,4 +15,4 @@ if [ -n "$XBPS_CROSS_BASE" -a -n "$XBPS_TARGET_MACHINE" -a -n "$XBPS_VERSION" ]; "${@//-I\/usr\/include/-I${XBPS_CROSS_BASE}\/usr\/include}" fi -exec /usr/bin/g-ir-scanner.wrapped "$@" +exec /usr/bin/g-ir-scanner.wrapped --use-ldd-wrapper=/usr/bin/g-ir-scanner-lddwrapper "$@" diff --git a/srcpkgs/gobject-introspection/patches/0006-giscanner-ignore-error-return-codes-from-ldd-wrapper.patch b/srcpkgs/gobject-introspection/patches/0006-giscanner-ignore-error-return-codes-from-ldd-wrapper.patch deleted file mode 100644 index 9167f042e5b4e4..00000000000000 --- a/srcpkgs/gobject-introspection/patches/0006-giscanner-ignore-error-return-codes-from-ldd-wrapper.patch +++ /dev/null @@ -1,27 +0,0 @@ -From f128cbeead687bfc6532cc1f2cc3e2dc5a2b5b30 Mon Sep 17 00:00:00 2001 -From: Alexander Kanavin -Date: Wed, 5 Sep 2018 16:46:52 +0200 -Subject: [PATCH] giscanner: ignore error return codes from ldd-wrapper - -prelink-rtld, which we use instead of ldd returns 127 when it can't find a library. -It is not an error per se, but it breaks subprocess.check_output(). - -Upstream-Status: Inappropriate [oe-core specific] -Signed-off-by: Alexander Kanavin ---- - giscanner/shlibs.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/giscanner/shlibs.py b/giscanner/shlibs.py -index 01d21a3..3bd3250 100644 ---- a/giscanner/shlibs.py -+++ b/giscanner/shlibs.py -@@ -108,7 +108,7 @@ def _resolve_non_libtool(options, binary, libraries): - args.extend(['otool', '-L', binary.args[0]]) - else: - args.extend(['ldd', binary.args[0]]) -- output = subprocess.check_output(args) -+ output = subprocess.run(args, check=False, stdout=subprocess.PIPE).stdout - if isinstance(output, bytes): - output = output.decode("utf-8", "replace") - diff --git a/srcpkgs/gobject-introspection/patches/401ca6d482eab44da9d58b7eebf6dddc6cdf2912.patch b/srcpkgs/gobject-introspection/patches/401ca6d482eab44da9d58b7eebf6dddc6cdf2912.patch new file mode 100644 index 00000000000000..4dfd02614ff085 --- /dev/null +++ b/srcpkgs/gobject-introspection/patches/401ca6d482eab44da9d58b7eebf6dddc6cdf2912.patch @@ -0,0 +1,108 @@ +From 401ca6d482eab44da9d58b7eebf6dddc6cdf2912 Mon Sep 17 00:00:00 2001 +From: Simon McVittie +Date: Sun, 12 May 2024 18:03:17 +0100 +Subject: [PATCH] giscanner: Be more thorough about applying -Wl,--no-as-needed + option + +Some Linux distributions routinely build all executables and libraries +with -Wl,--as-needed, either by adding it to LDFLAGS or by making it the +compiler or linker default. + +For installed executables and libraries this is a desirable way to +drop unnecessary transitive dependencies, minimizing the number of +rebuilds required if a lower-level library breaks ABI, but for our +dump executable it's counterproductive and can prevent us from finding +the SONAMEs of libraries that were passed as explicit -l arguments, +especially if we use a ldd replacement that is not recursive +(like the one in gobject-introspection#482). + +We already had a special case to add -Wl,--no-as-needed to the linker +arguments, but only for "internal" libraries and only when not using +libtool. Extend that to cover "external" libraries and libtool as well, +and filter out any -Wl,--as-needed from LDFLAGS to avoid it from being +defeated. + +Resolves: GNOME/gobject-introspection#505 +Signed-off-by: Simon McVittie +--- + giscanner/ccompiler.py | 28 ++++++++++++++++++++++------ + giscanner/dumper.py | 3 ++- + 2 files changed, 24 insertions(+), 7 deletions(-) + +diff --git a/giscanner/ccompiler.py b/giscanner/ccompiler.py +index d0ed70a3c..1938a842c 100644 +--- a/giscanner/ccompiler.py ++++ b/giscanner/ccompiler.py +@@ -35,6 +35,17 @@ from distutils.sysconfig import customize_compiler as orig_customize_compiler + from . import utils + + ++def no_as_needed(linker): ++ """\ ++ Filter out -Wl,--as-needed from the shell-quoted arguments in linker. ++ """ ++ return ' '.join( ++ [shlex.quote(arg) ++ for arg in shlex.split(linker) ++ if arg != '-Wl,--as-needed'] ++ ) ++ ++ + def customize_compiler(compiler): + """This is a version of distutils.sysconfig.customize_compiler, without + any macOS specific bits and which tries to avoid using any Python specific +@@ -88,8 +99,8 @@ def customize_compiler(compiler): + compiler=cc_cmd, + compiler_so=cc_cmd, + compiler_cxx=cxx, +- linker_so=ldshared, +- linker_exe=cc, ++ linker_so=no_as_needed(ldshared), ++ linker_exe=no_as_needed(cc), + archiver=archiver) + + compiler.shared_lib_extension = shlib_suffix +@@ -230,10 +241,10 @@ class CCompiler(object): + # https://bugzilla.gnome.org/show_bug.cgi?id=625195 + args.append('-Wl,-rpath,.') + +- # Ensure libraries are always linked as we are going to use ldd to work +- # out their names later +- if sys.platform != 'darwin': +- args.append('-Wl,--no-as-needed') ++ # Ensure libraries are always linked as we are going to use ldd to work ++ # out their names later ++ if sys.platform != 'darwin': ++ args.append('-Wl,--no-as-needed') + + for library_path in libpaths: + # The dumper program needs to look for dynamic libraries +@@ -279,6 +290,11 @@ class CCompiler(object): + # is installed on the system; this case is used for the scanning + # of GLib in gobject-introspection itself. + ++ # Ensure libraries are always linked as we are going to use ldd to work ++ # out their names later ++ if os.name != 'nt' and sys.platform != 'darwin': ++ args.append('-Wl,--no-as-needed') ++ + for library in libraries: + if os.path.isfile(library): + # If we get a real filename, just use it as-is +diff --git a/giscanner/dumper.py b/giscanner/dumper.py +index 74a494b8b..e2e7eeed0 100644 +--- a/giscanner/dumper.py ++++ b/giscanner/dumper.py +@@ -254,7 +254,8 @@ class DumpCompiler(object): + + if not self._compiler.check_is_msvc(): + for ldflag in shlex.split(os.environ.get('LDFLAGS', '')): +- args.append(ldflag) ++ if ldflag != '-Wl,--as-needed': ++ args.append(ldflag) + + dll_dirs = utils.dll_dirs() + dll_dirs.add_dll_dirs(self._packages) +-- +GitLab + diff --git a/srcpkgs/gobject-introspection/template b/srcpkgs/gobject-introspection/template index 60b4b05178e227..1e6aa8e6ef2b9d 100644 --- a/srcpkgs/gobject-introspection/template +++ b/srcpkgs/gobject-introspection/template @@ -2,13 +2,13 @@ # keep in sync with gobject-introspection-bootstrap pkgname=gobject-introspection version=1.80.1 -revision=1 +revision=2 build_style=meson pycompile_dirs="usr/lib/gobject-introspection/giscanner" hostmakedepends="flex pkg-config" # won't run tests with cairo to avoid cyclical deps -makedepends="libffi-devel libglib-devel python3-devel python3-Mako - python3-Markdown" +makedepends="libffi-devel libglib-devel python3-devel elfutils-devel + python3-Mako python3-Markdown" depends="libgirepository-devel python3-Mako python3-Markdown python3-setuptools" short_desc="Introspection system for GObject-based libraries" maintainer="Enno Boland " @@ -20,20 +20,24 @@ checksum=a1df7c424e15bda1ab639c00e9051b9adf5cea1a9e512f8a603b53cd199bc6d8 python_version=3 if [ "$CROSS_BUILD" ]; then - hostmakedepends+=" gobject-introspection qemu-user-static prelink-cross" + hostmakedepends+=" gobject-introspection qemu-user-static" configure_args+=" -Dgi_cross_use_prebuilt_gi=true -Dgi_cross_binary_wrapper=/usr/bin/g-ir-scanner-qemuwrapper -Dgi_cross_ldd_wrapper=/usr/bin/g-ir-scanner-lddwrapper -Dgi_cross_pkgconfig_sysroot_path=${XBPS_CROSS_BASE}" fi +post_build() { + $CC $CFLAGS $LDFLAGS ${FILESDIR}/elf-get-needed.c -lelf -o elf-get-needed +} + post_install() { rm ${DESTDIR}/usr/lib/gobject-introspection/giscanner/doctemplates/*/meson.build # Install our wrappers system-wide, they are required for building all other # gobject-based packages. vbin ${FILESDIR}/g-ir-scanner-qemuwrapper - vbin ${FILESDIR}/g-ir-scanner-lddwrapper + vbin elf-get-needed g-ir-scanner-lddwrapper # Install g-ir-scanner-wrapper as g-ir-scanner, we need it with that name since # we can't expect people to just not hardcode /usr/bin/g-ir-scanner, some packages