From ea8d0bf5ce729fc88ad78dd4442d47078661344b Mon Sep 17 00:00:00 2001 From: Martin Cermak Date: Wed, 8 Mar 2023 12:44:48 +0100 Subject: [PATCH 01/10] CI Tests: Fix the debuginfod URL --- tests/Regression/GNU-Attribute-notes-not-recognized/runtest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Regression/GNU-Attribute-notes-not-recognized/runtest.sh b/tests/Regression/GNU-Attribute-notes-not-recognized/runtest.sh index 7b6e187..aaa6c89 100755 --- a/tests/Regression/GNU-Attribute-notes-not-recognized/runtest.sh +++ b/tests/Regression/GNU-Attribute-notes-not-recognized/runtest.sh @@ -43,7 +43,7 @@ rlJournalStart # Let's see if we can chase down needed debuginfo somewhere... # Attempt getting the needed file using debuginfod - export DEBUGINFOD_URLS=http://debuginfod.usersys.redhat.com:3632/ + export DEBUGINFOD_URLS=https://debuginfod.fedoraproject.org/ rlRun "f=\"$f $(debuginfod-find debuginfo /bin/bash)\"" # Attempt getting the needed file by traditional means From fda83a73f8b3c2d3743fa2ee67cb40f79cc26ef3 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 22 Apr 2023 22:23:26 +0200 Subject: [PATCH 02/10] Add elfutils-0.189-c99-compat.patch --- elfutils-0.189-c99-compat.patch | 31 +++++++++++++++++++++++++++++++ elfutils.spec | 5 +++++ 2 files changed, 36 insertions(+) create mode 100644 elfutils-0.189-c99-compat.patch diff --git a/elfutils-0.189-c99-compat.patch b/elfutils-0.189-c99-compat.patch new file mode 100644 index 0000000..4932c2c --- /dev/null +++ b/elfutils-0.189-c99-compat.patch @@ -0,0 +1,31 @@ +From 6e7ac623674242628c9e54892a532d55d3288bb8 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Sat, 22 Apr 2023 21:37:09 +0200 +Subject: [PATCH] testsuite: Avoid C99 compatibility issues in + run-native-test.sh + +Include for the pause function, and add the return type +of main. Avoids an implicit function declaration and implicit int. + +Signed-off-by: Florian Weimer +--- + tests/run-native-test.sh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tests/run-native-test.sh b/tests/run-native-test.sh +index d19007f2..042a51c6 100755 +--- a/tests/run-native-test.sh ++++ b/tests/run-native-test.sh +@@ -27,7 +27,8 @@ + # in all builds. + + tempfiles native.c native +-echo 'main () { while (1) pause (); }' > native.c ++printf '#include \nint main (void) { while (1) pause (); }\n' \ ++ > native.c + + native=0 + kill_native() +-- +2.31.1 + diff --git a/elfutils.spec b/elfutils.spec index 8d2b05b..8de0442 100644 --- a/elfutils.spec +++ b/elfutils.spec @@ -74,6 +74,8 @@ BuildRequires: gettext-devel # For s390x... FDO package notes are bogus. Patch1: elfutils-0.186-fdo-swap.patch +# testsuite: Avoid C99 compatibility issues in run-native-test.sh +Patch2: elfutils-0.189-c99-compat.patch %description Elfutils is a collection of utilities, including stack (to show @@ -442,6 +444,9 @@ exit 0 %systemd_postun_with_restart debuginfod.service %changelog +* Sat Apr 22 2023 Mark Wielaard +- Add elfutils-0.189-c99-compat.patch + * Fri Mar 3 2023 Mark Wielaard - 0.189-1 - Upgrade to upsteam elfutils 0.189. From 8bb416f87082dfe271e2efd85b2c08da1f81b8bc Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 22 Apr 2023 22:28:38 +0200 Subject: [PATCH 03/10] Add elfutils-0.189-elfcompress.patch --- elfutils-0.189-elfcompress.patch | 95 ++++++++++++++++++++++++++++++++ elfutils.spec | 3 + 2 files changed, 98 insertions(+) create mode 100644 elfutils-0.189-elfcompress.patch diff --git a/elfutils-0.189-elfcompress.patch b/elfutils-0.189-elfcompress.patch new file mode 100644 index 0000000..5f0d681 --- /dev/null +++ b/elfutils-0.189-elfcompress.patch @@ -0,0 +1,95 @@ +From ef9164520c81ea61efe88777a8ad61bf17a54201 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Sat, 22 Apr 2023 01:26:17 +0200 +Subject: [PATCH] elfcompress: Don't compress if section already compressed + unless forced + +Before commit a5b07cdf9 "support ZSTD compression algorithm" +elfcompress would not try to compress a section if it already +had the requested compression type (or was already uncompressed) +unless the --force flag was given. An else if construct was changed +to an if in the commit causing elfcompress to warn (in verbose mode) +but then still try to (re)compress the section. + +Add an explicit check so if nothing needs (un)compressing, the file +isn't changed. + +The diff looks large, but git diff -b -w is just: + ++ if (force || type != schtype) ++ { + if (shdr->sh_type != SHT_NOBITS + && (shdr->sh_flags & SHF_ALLOC) == 0) + { +@@ -554,6 +556,7 @@ process_file (const char *fname) + printf ("[%zd] %s ignoring %s section\n", ndx, sname, + (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated")); + } ++ } + +Signed-off-by: Mark Wielaard +--- + src/elfcompress.c | 43 +++++++++++++++++++++++-------------------- + 1 file changed, 23 insertions(+), 20 deletions(-) + +diff --git a/src/elfcompress.c b/src/elfcompress.c +index 18ade66f..f771b92a 100644 +--- a/src/elfcompress.c ++++ b/src/elfcompress.c +@@ -529,30 +529,33 @@ process_file (const char *fname) + } + } + +- if (shdr->sh_type != SHT_NOBITS +- && (shdr->sh_flags & SHF_ALLOC) == 0) ++ if (force || type != schtype) + { +- set_section (sections, ndx); +- /* Check if we might want to change this section name. */ +- if (! adjust_names +- && ((type != ZLIB_GNU +- && startswith (sname, ".zdebug")) +- || (type == ZLIB_GNU +- && startswith (sname, ".debug")))) +- adjust_names = true; +- +- /* We need a buffer this large if we change the names. */ +- if (adjust_names) ++ if (shdr->sh_type != SHT_NOBITS ++ && (shdr->sh_flags & SHF_ALLOC) == 0) + { +- size_t slen = strlen (sname); +- if (slen > maxnamelen) +- maxnamelen = slen; ++ set_section (sections, ndx); ++ /* Check if we might want to change this section name. */ ++ if (! adjust_names ++ && ((type != ZLIB_GNU ++ && startswith (sname, ".zdebug")) ++ || (type == ZLIB_GNU ++ && startswith (sname, ".debug")))) ++ adjust_names = true; ++ ++ /* We need a buffer this large if we change the names. */ ++ if (adjust_names) ++ { ++ size_t slen = strlen (sname); ++ if (slen > maxnamelen) ++ maxnamelen = slen; ++ } + } ++ else ++ if (verbose >= 0) ++ printf ("[%zd] %s ignoring %s section\n", ndx, sname, ++ (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated")); + } +- else +- if (verbose >= 0) +- printf ("[%zd] %s ignoring %s section\n", ndx, sname, +- (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated")); + } + + if (shdr->sh_type == SHT_SYMTAB) +-- +2.31.1 + diff --git a/elfutils.spec b/elfutils.spec index 8de0442..f18aea2 100644 --- a/elfutils.spec +++ b/elfutils.spec @@ -76,6 +76,8 @@ BuildRequires: gettext-devel Patch1: elfutils-0.186-fdo-swap.patch # testsuite: Avoid C99 compatibility issues in run-native-test.sh Patch2: elfutils-0.189-c99-compat.patch +# elfcompress: Don't compress if section already compressed unless forced +Patch3: elfutils-0.189-elfcompress.patch %description Elfutils is a collection of utilities, including stack (to show @@ -446,6 +448,7 @@ exit 0 %changelog * Sat Apr 22 2023 Mark Wielaard - Add elfutils-0.189-c99-compat.patch +- Add elfutils-0.189-elfcompress.patch * Fri Mar 3 2023 Mark Wielaard - 0.189-1 - Upgrade to upsteam elfutils 0.189. From 76ba0b256c1314cc24943253fdf78a923d6f5d2d Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 22 Apr 2023 22:29:20 +0200 Subject: [PATCH 04/10] 0.189-2 --- elfutils.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elfutils.spec b/elfutils.spec index f18aea2..86f3b34 100644 --- a/elfutils.spec +++ b/elfutils.spec @@ -1,6 +1,6 @@ Name: elfutils Version: 0.189 -%global baserelease 1 +%global baserelease 2 Release: %{baserelease}%{?dist} URL: http://elfutils.org/ %global source_url ftp://sourceware.org/pub/elfutils/%{version}/ @@ -446,7 +446,7 @@ exit 0 %systemd_postun_with_restart debuginfod.service %changelog -* Sat Apr 22 2023 Mark Wielaard +* Sat Apr 22 2023 Mark Wielaard - 0.189-2 - Add elfutils-0.189-c99-compat.patch - Add elfutils-0.189-elfcompress.patch From 0d0a9de97880490a32c82934407f03f02bc98ea6 Mon Sep 17 00:00:00 2001 From: Martin Cermak Date: Tue, 25 Apr 2023 12:40:59 +0200 Subject: [PATCH 05/10] CI Tests: Test cover rhbz2188064 --- .../eu-elfcompress-breaks-hard-links/bubble.c | 36 ++++++++++++ .../eu-elfcompress-breaks-hard-links/main.fmf | 15 +++++ .../runtest.sh | 55 +++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 tests/Regression/eu-elfcompress-breaks-hard-links/bubble.c create mode 100644 tests/Regression/eu-elfcompress-breaks-hard-links/main.fmf create mode 100755 tests/Regression/eu-elfcompress-breaks-hard-links/runtest.sh diff --git a/tests/Regression/eu-elfcompress-breaks-hard-links/bubble.c b/tests/Regression/eu-elfcompress-breaks-hard-links/bubble.c new file mode 100644 index 0000000..9ec3260 --- /dev/null +++ b/tests/Regression/eu-elfcompress-breaks-hard-links/bubble.c @@ -0,0 +1,36 @@ +/* Bubble sort code */ + +#include + +int main() +{ + int array[100], n, c, d, swap; + + printf("Enter number of elements\n"); + scanf("%d", &n); + + printf("Enter %d integers\n", n); + + for (c = 0; c < n; c++) + scanf("%d", &array[c]); + + for (c = 0 ; c < n - 1; c++) + { + for (d = 0 ; d < n - c - 1; d++) + { + if (array[d] > array[d+1]) /* For decreasing order use '<' instead of '>' */ + { + swap = array[d]; + array[d] = array[d+1]; + array[d+1] = swap; + } + } + } + + printf("Sorted list in ascending order:\n"); + + for (c = 0; c < n; c++) + printf("%d\n", array[c]); + + return 0; +} diff --git a/tests/Regression/eu-elfcompress-breaks-hard-links/main.fmf b/tests/Regression/eu-elfcompress-breaks-hard-links/main.fmf new file mode 100644 index 0000000..a34c573 --- /dev/null +++ b/tests/Regression/eu-elfcompress-breaks-hard-links/main.fmf @@ -0,0 +1,15 @@ +summary: eu-elfcompress-breaks-hard-links +description: '' +link: + - relates: https://bugzilla.redhat.com/show_bug.cgi?id=2188064 +contact: Martin Cermak +component: + - elfutils +test: ./runtest.sh +framework: beakerlib +recommend: + - elfutils + - gcc +duration: 1h +extra-summary: /tools/elfutils/Regression/eu-elfcompress-breaks-hard-links +extra-task: /tools/elfutils/Regression/eu-elfcompress-breaks-hard-links diff --git a/tests/Regression/eu-elfcompress-breaks-hard-links/runtest.sh b/tests/Regression/eu-elfcompress-breaks-hard-links/runtest.sh new file mode 100755 index 0000000..7709a74 --- /dev/null +++ b/tests/Regression/eu-elfcompress-breaks-hard-links/runtest.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# runtest.sh of /tools/elfutils/Regression/eu-elfcompress-breaks-hard-links +# Description: eu-elfcompress-breaks-hard-links +# Author: Martin Cermak +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2023 Red Hat, Inc. +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation, either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Include Beaker environment +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +PACKAGE="elfutils" + +rlJournalStart + rlPhaseStartSetup + rlAssertRpm $PACKAGE + rlRun "TMP=$(mktemp -d)" + rlRun "cp bubble.c $TMP/" + rlRun "pushd $TMP" + rlPhaseEnd + + rlPhaseStartTest + rlRun "gcc -o a.out -g bubble.c" + rlRun "ln a.out a.lnk" + rlRun "eu-elfcompress -q -p -t none a.lnk" + rlRun "i0=$(stat -c '%i' a.out)" + rlRun "i1=$(stat -c '%i' a.lnk)" + rlRun "test $i0 -eq $i1" + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -r $TMP" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd From fb3a116370bc9cb43ea28f31821bfa34f309f3f0 Mon Sep 17 00:00:00 2001 From: Martin Cermak Date: Tue, 25 Apr 2023 12:50:10 +0200 Subject: [PATCH 06/10] CI Tests: Simplify test for rhbz2188064 --- .../eu-elfcompress-breaks-hard-links/bubble.c | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/tests/Regression/eu-elfcompress-breaks-hard-links/bubble.c b/tests/Regression/eu-elfcompress-breaks-hard-links/bubble.c index 9ec3260..f8b643a 100644 --- a/tests/Regression/eu-elfcompress-breaks-hard-links/bubble.c +++ b/tests/Regression/eu-elfcompress-breaks-hard-links/bubble.c @@ -1,36 +1,4 @@ -/* Bubble sort code */ - -#include - int main() { - int array[100], n, c, d, swap; - - printf("Enter number of elements\n"); - scanf("%d", &n); - - printf("Enter %d integers\n", n); - - for (c = 0; c < n; c++) - scanf("%d", &array[c]); - - for (c = 0 ; c < n - 1; c++) - { - for (d = 0 ; d < n - c - 1; d++) - { - if (array[d] > array[d+1]) /* For decreasing order use '<' instead of '>' */ - { - swap = array[d]; - array[d] = array[d+1]; - array[d+1] = swap; - } - } - } - - printf("Sorted list in ascending order:\n"); - - for (c = 0; c < n; c++) - printf("%d\n", array[c]); - return 0; } From e719860fcd58764575dad76c12a3addf64577275 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 22 Jun 2023 15:08:31 +0200 Subject: [PATCH 07/10] Add elfutils-0.189-elf_getdata_rawchunk.patch --- elfutils-0.189-elf_getdata_rawchunk.patch | 224 ++++++++++++++++++++++ elfutils.spec | 5 + 2 files changed, 229 insertions(+) create mode 100644 elfutils-0.189-elf_getdata_rawchunk.patch diff --git a/elfutils-0.189-elf_getdata_rawchunk.patch b/elfutils-0.189-elf_getdata_rawchunk.patch new file mode 100644 index 0000000..7ce6695 --- /dev/null +++ b/elfutils-0.189-elf_getdata_rawchunk.patch @@ -0,0 +1,224 @@ +From 3aca5b5f1f1617db2220022d9061dcaf129e54c4 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Wed, 21 Jun 2023 18:05:12 +0200 +Subject: [PATCH] libelf: Replace list of elf_getdata_rawchunk results with a + tree + +elf_getdata_rawchunks did a linear search to see if a chunk was +already fetched. Replace this list with a binary search tree to make +lookup faster when a lot of Elf_Data_Chunk were created. + + * libelf/libelfP.h (Elf_Data_Chunk): Remove next field. + (struct Elf): Change the rawchunks type from Elf_Data_Chunk * + to void *. + * elf_getdata_rawchunk.c (chunk_compare): New static function. + (elf_getdata_rawchunk): Use tsearch instead of a manual linked + list. + * elf_end.c (free_chunk): New static function. + (elf_end): Call tdestroy instead of walking linked list. + +Signed-off-by: Mark Wielaard +--- + libelf/elf_end.c | 22 +++++++++------- + libelf/elf_getdata_rawchunk.c | 47 +++++++++++++++++++++++++---------- + libelf/libelfP.h | 13 ++++------ + 3 files changed, 52 insertions(+), 30 deletions(-) + +diff --git a/libelf/elf_end.c b/libelf/elf_end.c +index 5c451f36..3e5d4c86 100644 +--- a/libelf/elf_end.c ++++ b/libelf/elf_end.c +@@ -1,5 +1,6 @@ + /* Free resources associated with Elf descriptor. + Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007,2015,2016 Red Hat, Inc. ++ Copyright (C) 2023 Mark J. Wielaard + This file is part of elfutils. + Written by Ulrich Drepper , 1998. + +@@ -32,12 +33,22 @@ + #endif + + #include ++#include + #include + #include + + #include "libelfP.h" + + ++static void ++free_chunk (void *n) ++{ ++ Elf_Data_Chunk *rawchunk = (Elf_Data_Chunk *)n; ++ if (rawchunk->dummy_scn.flags & ELF_F_MALLOCED) ++ free (rawchunk->data.d.d_buf); ++ free (rawchunk); ++} ++ + int + elf_end (Elf *elf) + { +@@ -112,20 +123,13 @@ elf_end (Elf *elf) + + case ELF_K_ELF: + { +- Elf_Data_Chunk *rawchunks ++ void *rawchunks + = (elf->class == ELFCLASS32 + || (offsetof (struct Elf, state.elf32.rawchunks) + == offsetof (struct Elf, state.elf64.rawchunks)) + ? elf->state.elf32.rawchunks + : elf->state.elf64.rawchunks); +- while (rawchunks != NULL) +- { +- Elf_Data_Chunk *next = rawchunks->next; +- if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED) +- free (rawchunks->data.d.d_buf); +- free (rawchunks); +- rawchunks = next; +- } ++ tdestroy (rawchunks, free_chunk); + + Elf_ScnList *list = (elf->class == ELFCLASS32 + || (offsetof (struct Elf, state.elf32.scns) +diff --git a/libelf/elf_getdata_rawchunk.c b/libelf/elf_getdata_rawchunk.c +index 5a35ccdc..cfd40396 100644 +--- a/libelf/elf_getdata_rawchunk.c ++++ b/libelf/elf_getdata_rawchunk.c +@@ -1,6 +1,6 @@ + /* Return converted data from raw chunk of ELF file. + Copyright (C) 2007, 2014, 2015 Red Hat, Inc. +- Copyright (C) 2022 Mark J. Wielaard ++ Copyright (C) 2022, 2023 Mark J. Wielaard + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify +@@ -33,12 +33,28 @@ + + #include + #include ++#include + #include + #include + + #include "libelfP.h" + #include "common.h" + ++static int ++chunk_compare (const void *a, const void *b) ++{ ++ Elf_Data_Chunk *da = (Elf_Data_Chunk *)a; ++ Elf_Data_Chunk *db = (Elf_Data_Chunk *)b; ++ ++ if (da->offset != db->offset) ++ return da->offset - db->offset; ++ ++ if (da->data.d.d_size != db->data.d.d_size) ++ return da->data.d.d_size - db->data.d.d_size; ++ ++ return da->data.d.d_type - db->data.d.d_type; ++} ++ + Elf_Data * + elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) + { +@@ -75,19 +91,25 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) + rwlock_rdlock (elf->lock); + + /* Maybe we already got this chunk? */ +- Elf_Data_Chunk *rawchunks = elf->state.elf.rawchunks; +- while (rawchunks != NULL) ++ Elf_Data_Chunk key; ++ key.offset = offset; ++ key.data.d.d_size = size; ++ key.data.d.d_type = type; ++ Elf_Data_Chunk **found = tsearch (&key, &elf->state.elf.rawchunks, ++ &chunk_compare); ++ if (found == NULL) ++ goto nomem; ++ ++ /* Existing entry. */ ++ if (*found != &key && *found != NULL) + { +- if ((rawchunks->offset == offset || size == 0) +- && rawchunks->data.d.d_size == size +- && rawchunks->data.d.d_type == type) +- { +- result = &rawchunks->data.d; +- goto out; +- } +- rawchunks = rawchunks->next; ++ result = &(*found)->data.d; ++ goto out; + } + ++ /* New entry. */ ++ *found = NULL; ++ + size_t align = __libelf_type_align (elf->class, type); + if (elf->map_address != NULL) + { +@@ -189,8 +211,7 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) + rwlock_unlock (elf->lock); + rwlock_wrlock (elf->lock); + +- chunk->next = elf->state.elf.rawchunks; +- elf->state.elf.rawchunks = chunk; ++ *found = chunk; + result = &chunk->data.d; + + out: +diff --git a/libelf/libelfP.h b/libelf/libelfP.h +index 6624f38a..d3c241e5 100644 +--- a/libelf/libelfP.h ++++ b/libelf/libelfP.h +@@ -1,5 +1,6 @@ + /* Internal interfaces for libelf. + Copyright (C) 1998-2010, 2015, 2016 Red Hat, Inc. ++ Copyright (C) 2023 Mark J. Wielaard + This file is part of elfutils. + Contributed by Ulrich Drepper , 1998. + +@@ -262,11 +263,7 @@ typedef struct Elf_ScnList + typedef struct Elf_Data_Chunk + { + Elf_Data_Scn data; +- union +- { +- Elf_Scn dummy_scn; +- struct Elf_Data_Chunk *next; +- }; ++ Elf_Scn dummy_scn; + int64_t offset; /* The original raw offset in the Elf image. */ + } Elf_Data_Chunk; + +@@ -324,7 +321,7 @@ struct Elf + Elf_ScnList *scns_last; /* Last element in the section list. + If NULL the data has not yet been + read from the file. */ +- Elf_Data_Chunk *rawchunks; /* List of elf_getdata_rawchunk results. */ ++ void *rawchunks; /* Tree of elf_getdata_rawchunk results. */ + unsigned int scnincr; /* Number of sections allocate the last + time. */ + int ehdr_flags; /* Flags (dirty) for ELF header. */ +@@ -343,7 +340,7 @@ struct Elf + Elf_ScnList *scns_last; /* Last element in the section list. + If NULL the data has not yet been + read from the file. */ +- Elf_Data_Chunk *rawchunks; /* List of elf_getdata_rawchunk results. */ ++ void *rawchunks; /* Tree of elf_getdata_rawchunk results. */ + unsigned int scnincr; /* Number of sections allocate the last + time. */ + int ehdr_flags; /* Flags (dirty) for ELF header. */ +@@ -368,7 +365,7 @@ struct Elf + Elf_ScnList *scns_last; /* Last element in the section list. + If NULL the data has not yet been + read from the file. */ +- Elf_Data_Chunk *rawchunks; /* List of elf_getdata_rawchunk results. */ ++ void *rawchunks; /* Tree of elf_getdata_rawchunk results. */ + unsigned int scnincr; /* Number of sections allocate the last + time. */ + int ehdr_flags; /* Flags (dirty) for ELF header. */ +-- +2.40.1 + diff --git a/elfutils.spec b/elfutils.spec index 86f3b34..7955ff1 100644 --- a/elfutils.spec +++ b/elfutils.spec @@ -78,6 +78,8 @@ Patch1: elfutils-0.186-fdo-swap.patch Patch2: elfutils-0.189-c99-compat.patch # elfcompress: Don't compress if section already compressed unless forced Patch3: elfutils-0.189-elfcompress.patch +# libelf: Replace list of elf_getdata_rawchunk results with a tree +Patch4: elfutils-0.189-elf_getdata_rawchunk.patch %description Elfutils is a collection of utilities, including stack (to show @@ -446,6 +448,9 @@ exit 0 %systemd_postun_with_restart debuginfod.service %changelog +* Thu Jun 22 2023 Mark Wielaard +- Add elfutils-0.189-elf_getdata_rawchunk.patch + * Sat Apr 22 2023 Mark Wielaard - 0.189-2 - Add elfutils-0.189-c99-compat.patch - Add elfutils-0.189-elfcompress.patch From dc22742a6111d91a6c0a50e6587cc158cb73a6cd Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 22 Jun 2023 15:10:49 +0200 Subject: [PATCH 08/10] 0.189-3 - Add elfutils-0.189-debuginfod_config_cache-double-close.patch --- ...debuginfod_config_cache-double-close.patch | 73 +++++++++++++++++++ elfutils.spec | 7 +- 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 elfutils-0.189-debuginfod_config_cache-double-close.patch diff --git a/elfutils-0.189-debuginfod_config_cache-double-close.patch b/elfutils-0.189-debuginfod_config_cache-double-close.patch new file mode 100644 index 0000000..3380b71 --- /dev/null +++ b/elfutils-0.189-debuginfod_config_cache-double-close.patch @@ -0,0 +1,73 @@ +diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c +index ef4d47e3..d92d8d62 100644 +--- a/debuginfod/debuginfod-client.c ++++ b/debuginfod/debuginfod-client.c +@@ -248,7 +248,7 @@ debuginfod_write_callback (char *ptr, size_t size, size_t nmemb, void *data) + + /* handle config file read and write */ + static int +-debuginfod_config_cache(char *config_path, ++debuginfod_config_cache(debuginfod_client *c, char *config_path, + long cache_config_default_s, + struct stat *st) + { +@@ -277,17 +277,27 @@ debuginfod_config_cache(char *config_path, + } + + long cache_config; ++ /* PR29696 - NB: When using fdopen, the file descriptor is NOT ++ dup'ed and will be closed when the stream is closed. Manually ++ closing fd after fclose is called will lead to a race condition ++ where, if reused, the file descriptor will compete for its ++ regular use before being incorrectly closed here. */ + FILE *config_file = fdopen(fd, "r"); + if (config_file) + { + if (fscanf(config_file, "%ld", &cache_config) != 1) +- cache_config = cache_config_default_s; +- fclose(config_file); ++ cache_config = cache_config_default_s; ++ if (0 != fclose (config_file) && c->verbose_fd >= 0) ++ dprintf (c->verbose_fd, "fclose failed with %s (err=%d)\n", ++ strerror (errno), errno); + } + else +- cache_config = cache_config_default_s; +- +- close (fd); ++ { ++ cache_config = cache_config_default_s; ++ if (0 != close (fd) && c->verbose_fd >= 0) ++ dprintf (c->verbose_fd, "close failed with %s (err=%d)\n", ++ strerror (errno), errno); ++ } + return cache_config; + } + +@@ -303,7 +313,7 @@ debuginfod_clean_cache(debuginfod_client *c, + struct stat st; + + /* Create new interval file. */ +- rc = debuginfod_config_cache(interval_path, ++ rc = debuginfod_config_cache(c, interval_path, + cache_clean_default_interval_s, &st); + if (rc < 0) + return rc; +@@ -320,7 +330,7 @@ debuginfod_clean_cache(debuginfod_client *c, + utime (interval_path, NULL); + + /* Read max unused age value from config file. */ +- rc = debuginfod_config_cache(max_unused_path, ++ rc = debuginfod_config_cache(c, max_unused_path, + cache_default_max_unused_age_s, &st); + if (rc < 0) + return rc; +@@ -1110,7 +1135,7 @@ debuginfod_query_server (debuginfod_client *c, + + close(fd); /* no need to hold onto the negative-hit file descriptor */ + +- rc = debuginfod_config_cache(cache_miss_path, ++ rc = debuginfod_config_cache(c, cache_miss_path, + cache_miss_default_s, &st); + if (rc < 0) + goto out; diff --git a/elfutils.spec b/elfutils.spec index 7955ff1..c27e88f 100644 --- a/elfutils.spec +++ b/elfutils.spec @@ -1,6 +1,6 @@ Name: elfutils Version: 0.189 -%global baserelease 2 +%global baserelease 3 Release: %{baserelease}%{?dist} URL: http://elfutils.org/ %global source_url ftp://sourceware.org/pub/elfutils/%{version}/ @@ -80,6 +80,8 @@ Patch2: elfutils-0.189-c99-compat.patch Patch3: elfutils-0.189-elfcompress.patch # libelf: Replace list of elf_getdata_rawchunk results with a tree Patch4: elfutils-0.189-elf_getdata_rawchunk.patch +# PR29696: Removed secondary fd close in cache config causing race condition +Patch5: elfutils-0.189-debuginfod_config_cache-double-close.patch %description Elfutils is a collection of utilities, including stack (to show @@ -448,8 +450,9 @@ exit 0 %systemd_postun_with_restart debuginfod.service %changelog -* Thu Jun 22 2023 Mark Wielaard +* Thu Jun 22 2023 Mark Wielaard - 0.189-3 - Add elfutils-0.189-elf_getdata_rawchunk.patch +- Add elfutils-0.189-debuginfod_config_cache-double-close.patch * Sat Apr 22 2023 Mark Wielaard - 0.189-2 - Add elfutils-0.189-c99-compat.patch From 6a0f0e45c4e51b1ab87d82e899ba90d85eca0dc3 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 3 Nov 2023 21:11:40 +0100 Subject: [PATCH 09/10] 0.190-1 - Upgrade to upstream elfutils 0.190 - Add eu-srcfiles - Drop upstreamed patches elfutils-0.189-debuginfod_config_cache-double-close.patch elfutils-0.189-elf_getdata_rawchunk.patch elfutils-0.189-elfcompress.patch elfutils-0.189-c99-compat.patch - Only package debuginfod-client-config.7 manpage for debuginfod-client --- .gitignore | 1 + elfutils-0.189-c99-compat.patch | 31 --- ...debuginfod_config_cache-double-close.patch | 73 ------ elfutils-0.189-elf_getdata_rawchunk.patch | 224 ------------------ elfutils-0.189-elfcompress.patch | 95 -------- elfutils.spec | 24 +- sources | 2 +- 7 files changed, 15 insertions(+), 435 deletions(-) delete mode 100644 elfutils-0.189-c99-compat.patch delete mode 100644 elfutils-0.189-debuginfod_config_cache-double-close.patch delete mode 100644 elfutils-0.189-elf_getdata_rawchunk.patch delete mode 100644 elfutils-0.189-elfcompress.patch diff --git a/.gitignore b/.gitignore index 9d73fa8..eb85273 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ /elfutils-0.187.tar.bz2 /elfutils-0.188.tar.bz2 /elfutils-0.189.tar.bz2 +/elfutils-0.190.tar.bz2 diff --git a/elfutils-0.189-c99-compat.patch b/elfutils-0.189-c99-compat.patch deleted file mode 100644 index 4932c2c..0000000 --- a/elfutils-0.189-c99-compat.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 6e7ac623674242628c9e54892a532d55d3288bb8 Mon Sep 17 00:00:00 2001 -From: Florian Weimer -Date: Sat, 22 Apr 2023 21:37:09 +0200 -Subject: [PATCH] testsuite: Avoid C99 compatibility issues in - run-native-test.sh - -Include for the pause function, and add the return type -of main. Avoids an implicit function declaration and implicit int. - -Signed-off-by: Florian Weimer ---- - tests/run-native-test.sh | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/tests/run-native-test.sh b/tests/run-native-test.sh -index d19007f2..042a51c6 100755 ---- a/tests/run-native-test.sh -+++ b/tests/run-native-test.sh -@@ -27,7 +27,8 @@ - # in all builds. - - tempfiles native.c native --echo 'main () { while (1) pause (); }' > native.c -+printf '#include \nint main (void) { while (1) pause (); }\n' \ -+ > native.c - - native=0 - kill_native() --- -2.31.1 - diff --git a/elfutils-0.189-debuginfod_config_cache-double-close.patch b/elfutils-0.189-debuginfod_config_cache-double-close.patch deleted file mode 100644 index 3380b71..0000000 --- a/elfutils-0.189-debuginfod_config_cache-double-close.patch +++ /dev/null @@ -1,73 +0,0 @@ -diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c -index ef4d47e3..d92d8d62 100644 ---- a/debuginfod/debuginfod-client.c -+++ b/debuginfod/debuginfod-client.c -@@ -248,7 +248,7 @@ debuginfod_write_callback (char *ptr, size_t size, size_t nmemb, void *data) - - /* handle config file read and write */ - static int --debuginfod_config_cache(char *config_path, -+debuginfod_config_cache(debuginfod_client *c, char *config_path, - long cache_config_default_s, - struct stat *st) - { -@@ -277,17 +277,27 @@ debuginfod_config_cache(char *config_path, - } - - long cache_config; -+ /* PR29696 - NB: When using fdopen, the file descriptor is NOT -+ dup'ed and will be closed when the stream is closed. Manually -+ closing fd after fclose is called will lead to a race condition -+ where, if reused, the file descriptor will compete for its -+ regular use before being incorrectly closed here. */ - FILE *config_file = fdopen(fd, "r"); - if (config_file) - { - if (fscanf(config_file, "%ld", &cache_config) != 1) -- cache_config = cache_config_default_s; -- fclose(config_file); -+ cache_config = cache_config_default_s; -+ if (0 != fclose (config_file) && c->verbose_fd >= 0) -+ dprintf (c->verbose_fd, "fclose failed with %s (err=%d)\n", -+ strerror (errno), errno); - } - else -- cache_config = cache_config_default_s; -- -- close (fd); -+ { -+ cache_config = cache_config_default_s; -+ if (0 != close (fd) && c->verbose_fd >= 0) -+ dprintf (c->verbose_fd, "close failed with %s (err=%d)\n", -+ strerror (errno), errno); -+ } - return cache_config; - } - -@@ -303,7 +313,7 @@ debuginfod_clean_cache(debuginfod_client *c, - struct stat st; - - /* Create new interval file. */ -- rc = debuginfod_config_cache(interval_path, -+ rc = debuginfod_config_cache(c, interval_path, - cache_clean_default_interval_s, &st); - if (rc < 0) - return rc; -@@ -320,7 +330,7 @@ debuginfod_clean_cache(debuginfod_client *c, - utime (interval_path, NULL); - - /* Read max unused age value from config file. */ -- rc = debuginfod_config_cache(max_unused_path, -+ rc = debuginfod_config_cache(c, max_unused_path, - cache_default_max_unused_age_s, &st); - if (rc < 0) - return rc; -@@ -1110,7 +1135,7 @@ debuginfod_query_server (debuginfod_client *c, - - close(fd); /* no need to hold onto the negative-hit file descriptor */ - -- rc = debuginfod_config_cache(cache_miss_path, -+ rc = debuginfod_config_cache(c, cache_miss_path, - cache_miss_default_s, &st); - if (rc < 0) - goto out; diff --git a/elfutils-0.189-elf_getdata_rawchunk.patch b/elfutils-0.189-elf_getdata_rawchunk.patch deleted file mode 100644 index 7ce6695..0000000 --- a/elfutils-0.189-elf_getdata_rawchunk.patch +++ /dev/null @@ -1,224 +0,0 @@ -From 3aca5b5f1f1617db2220022d9061dcaf129e54c4 Mon Sep 17 00:00:00 2001 -From: Mark Wielaard -Date: Wed, 21 Jun 2023 18:05:12 +0200 -Subject: [PATCH] libelf: Replace list of elf_getdata_rawchunk results with a - tree - -elf_getdata_rawchunks did a linear search to see if a chunk was -already fetched. Replace this list with a binary search tree to make -lookup faster when a lot of Elf_Data_Chunk were created. - - * libelf/libelfP.h (Elf_Data_Chunk): Remove next field. - (struct Elf): Change the rawchunks type from Elf_Data_Chunk * - to void *. - * elf_getdata_rawchunk.c (chunk_compare): New static function. - (elf_getdata_rawchunk): Use tsearch instead of a manual linked - list. - * elf_end.c (free_chunk): New static function. - (elf_end): Call tdestroy instead of walking linked list. - -Signed-off-by: Mark Wielaard ---- - libelf/elf_end.c | 22 +++++++++------- - libelf/elf_getdata_rawchunk.c | 47 +++++++++++++++++++++++++---------- - libelf/libelfP.h | 13 ++++------ - 3 files changed, 52 insertions(+), 30 deletions(-) - -diff --git a/libelf/elf_end.c b/libelf/elf_end.c -index 5c451f36..3e5d4c86 100644 ---- a/libelf/elf_end.c -+++ b/libelf/elf_end.c -@@ -1,5 +1,6 @@ - /* Free resources associated with Elf descriptor. - Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007,2015,2016 Red Hat, Inc. -+ Copyright (C) 2023 Mark J. Wielaard - This file is part of elfutils. - Written by Ulrich Drepper , 1998. - -@@ -32,12 +33,22 @@ - #endif - - #include -+#include - #include - #include - - #include "libelfP.h" - - -+static void -+free_chunk (void *n) -+{ -+ Elf_Data_Chunk *rawchunk = (Elf_Data_Chunk *)n; -+ if (rawchunk->dummy_scn.flags & ELF_F_MALLOCED) -+ free (rawchunk->data.d.d_buf); -+ free (rawchunk); -+} -+ - int - elf_end (Elf *elf) - { -@@ -112,20 +123,13 @@ elf_end (Elf *elf) - - case ELF_K_ELF: - { -- Elf_Data_Chunk *rawchunks -+ void *rawchunks - = (elf->class == ELFCLASS32 - || (offsetof (struct Elf, state.elf32.rawchunks) - == offsetof (struct Elf, state.elf64.rawchunks)) - ? elf->state.elf32.rawchunks - : elf->state.elf64.rawchunks); -- while (rawchunks != NULL) -- { -- Elf_Data_Chunk *next = rawchunks->next; -- if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED) -- free (rawchunks->data.d.d_buf); -- free (rawchunks); -- rawchunks = next; -- } -+ tdestroy (rawchunks, free_chunk); - - Elf_ScnList *list = (elf->class == ELFCLASS32 - || (offsetof (struct Elf, state.elf32.scns) -diff --git a/libelf/elf_getdata_rawchunk.c b/libelf/elf_getdata_rawchunk.c -index 5a35ccdc..cfd40396 100644 ---- a/libelf/elf_getdata_rawchunk.c -+++ b/libelf/elf_getdata_rawchunk.c -@@ -1,6 +1,6 @@ - /* Return converted data from raw chunk of ELF file. - Copyright (C) 2007, 2014, 2015 Red Hat, Inc. -- Copyright (C) 2022 Mark J. Wielaard -+ Copyright (C) 2022, 2023 Mark J. Wielaard - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify -@@ -33,12 +33,28 @@ - - #include - #include -+#include - #include - #include - - #include "libelfP.h" - #include "common.h" - -+static int -+chunk_compare (const void *a, const void *b) -+{ -+ Elf_Data_Chunk *da = (Elf_Data_Chunk *)a; -+ Elf_Data_Chunk *db = (Elf_Data_Chunk *)b; -+ -+ if (da->offset != db->offset) -+ return da->offset - db->offset; -+ -+ if (da->data.d.d_size != db->data.d.d_size) -+ return da->data.d.d_size - db->data.d.d_size; -+ -+ return da->data.d.d_type - db->data.d.d_type; -+} -+ - Elf_Data * - elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) - { -@@ -75,19 +91,25 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) - rwlock_rdlock (elf->lock); - - /* Maybe we already got this chunk? */ -- Elf_Data_Chunk *rawchunks = elf->state.elf.rawchunks; -- while (rawchunks != NULL) -+ Elf_Data_Chunk key; -+ key.offset = offset; -+ key.data.d.d_size = size; -+ key.data.d.d_type = type; -+ Elf_Data_Chunk **found = tsearch (&key, &elf->state.elf.rawchunks, -+ &chunk_compare); -+ if (found == NULL) -+ goto nomem; -+ -+ /* Existing entry. */ -+ if (*found != &key && *found != NULL) - { -- if ((rawchunks->offset == offset || size == 0) -- && rawchunks->data.d.d_size == size -- && rawchunks->data.d.d_type == type) -- { -- result = &rawchunks->data.d; -- goto out; -- } -- rawchunks = rawchunks->next; -+ result = &(*found)->data.d; -+ goto out; - } - -+ /* New entry. */ -+ *found = NULL; -+ - size_t align = __libelf_type_align (elf->class, type); - if (elf->map_address != NULL) - { -@@ -189,8 +211,7 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) - rwlock_unlock (elf->lock); - rwlock_wrlock (elf->lock); - -- chunk->next = elf->state.elf.rawchunks; -- elf->state.elf.rawchunks = chunk; -+ *found = chunk; - result = &chunk->data.d; - - out: -diff --git a/libelf/libelfP.h b/libelf/libelfP.h -index 6624f38a..d3c241e5 100644 ---- a/libelf/libelfP.h -+++ b/libelf/libelfP.h -@@ -1,5 +1,6 @@ - /* Internal interfaces for libelf. - Copyright (C) 1998-2010, 2015, 2016 Red Hat, Inc. -+ Copyright (C) 2023 Mark J. Wielaard - This file is part of elfutils. - Contributed by Ulrich Drepper , 1998. - -@@ -262,11 +263,7 @@ typedef struct Elf_ScnList - typedef struct Elf_Data_Chunk - { - Elf_Data_Scn data; -- union -- { -- Elf_Scn dummy_scn; -- struct Elf_Data_Chunk *next; -- }; -+ Elf_Scn dummy_scn; - int64_t offset; /* The original raw offset in the Elf image. */ - } Elf_Data_Chunk; - -@@ -324,7 +321,7 @@ struct Elf - Elf_ScnList *scns_last; /* Last element in the section list. - If NULL the data has not yet been - read from the file. */ -- Elf_Data_Chunk *rawchunks; /* List of elf_getdata_rawchunk results. */ -+ void *rawchunks; /* Tree of elf_getdata_rawchunk results. */ - unsigned int scnincr; /* Number of sections allocate the last - time. */ - int ehdr_flags; /* Flags (dirty) for ELF header. */ -@@ -343,7 +340,7 @@ struct Elf - Elf_ScnList *scns_last; /* Last element in the section list. - If NULL the data has not yet been - read from the file. */ -- Elf_Data_Chunk *rawchunks; /* List of elf_getdata_rawchunk results. */ -+ void *rawchunks; /* Tree of elf_getdata_rawchunk results. */ - unsigned int scnincr; /* Number of sections allocate the last - time. */ - int ehdr_flags; /* Flags (dirty) for ELF header. */ -@@ -368,7 +365,7 @@ struct Elf - Elf_ScnList *scns_last; /* Last element in the section list. - If NULL the data has not yet been - read from the file. */ -- Elf_Data_Chunk *rawchunks; /* List of elf_getdata_rawchunk results. */ -+ void *rawchunks; /* Tree of elf_getdata_rawchunk results. */ - unsigned int scnincr; /* Number of sections allocate the last - time. */ - int ehdr_flags; /* Flags (dirty) for ELF header. */ --- -2.40.1 - diff --git a/elfutils-0.189-elfcompress.patch b/elfutils-0.189-elfcompress.patch deleted file mode 100644 index 5f0d681..0000000 --- a/elfutils-0.189-elfcompress.patch +++ /dev/null @@ -1,95 +0,0 @@ -From ef9164520c81ea61efe88777a8ad61bf17a54201 Mon Sep 17 00:00:00 2001 -From: Mark Wielaard -Date: Sat, 22 Apr 2023 01:26:17 +0200 -Subject: [PATCH] elfcompress: Don't compress if section already compressed - unless forced - -Before commit a5b07cdf9 "support ZSTD compression algorithm" -elfcompress would not try to compress a section if it already -had the requested compression type (or was already uncompressed) -unless the --force flag was given. An else if construct was changed -to an if in the commit causing elfcompress to warn (in verbose mode) -but then still try to (re)compress the section. - -Add an explicit check so if nothing needs (un)compressing, the file -isn't changed. - -The diff looks large, but git diff -b -w is just: - -+ if (force || type != schtype) -+ { - if (shdr->sh_type != SHT_NOBITS - && (shdr->sh_flags & SHF_ALLOC) == 0) - { -@@ -554,6 +556,7 @@ process_file (const char *fname) - printf ("[%zd] %s ignoring %s section\n", ndx, sname, - (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated")); - } -+ } - -Signed-off-by: Mark Wielaard ---- - src/elfcompress.c | 43 +++++++++++++++++++++++-------------------- - 1 file changed, 23 insertions(+), 20 deletions(-) - -diff --git a/src/elfcompress.c b/src/elfcompress.c -index 18ade66f..f771b92a 100644 ---- a/src/elfcompress.c -+++ b/src/elfcompress.c -@@ -529,30 +529,33 @@ process_file (const char *fname) - } - } - -- if (shdr->sh_type != SHT_NOBITS -- && (shdr->sh_flags & SHF_ALLOC) == 0) -+ if (force || type != schtype) - { -- set_section (sections, ndx); -- /* Check if we might want to change this section name. */ -- if (! adjust_names -- && ((type != ZLIB_GNU -- && startswith (sname, ".zdebug")) -- || (type == ZLIB_GNU -- && startswith (sname, ".debug")))) -- adjust_names = true; -- -- /* We need a buffer this large if we change the names. */ -- if (adjust_names) -+ if (shdr->sh_type != SHT_NOBITS -+ && (shdr->sh_flags & SHF_ALLOC) == 0) - { -- size_t slen = strlen (sname); -- if (slen > maxnamelen) -- maxnamelen = slen; -+ set_section (sections, ndx); -+ /* Check if we might want to change this section name. */ -+ if (! adjust_names -+ && ((type != ZLIB_GNU -+ && startswith (sname, ".zdebug")) -+ || (type == ZLIB_GNU -+ && startswith (sname, ".debug")))) -+ adjust_names = true; -+ -+ /* We need a buffer this large if we change the names. */ -+ if (adjust_names) -+ { -+ size_t slen = strlen (sname); -+ if (slen > maxnamelen) -+ maxnamelen = slen; -+ } - } -+ else -+ if (verbose >= 0) -+ printf ("[%zd] %s ignoring %s section\n", ndx, sname, -+ (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated")); - } -- else -- if (verbose >= 0) -- printf ("[%zd] %s ignoring %s section\n", ndx, sname, -- (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated")); - } - - if (shdr->sh_type == SHT_SYMTAB) --- -2.31.1 - diff --git a/elfutils.spec b/elfutils.spec index c27e88f..87484c5 100644 --- a/elfutils.spec +++ b/elfutils.spec @@ -1,6 +1,6 @@ Name: elfutils -Version: 0.189 -%global baserelease 3 +Version: 0.190 +%global baserelease 1 Release: %{baserelease}%{?dist} URL: http://elfutils.org/ %global source_url ftp://sourceware.org/pub/elfutils/%{version}/ @@ -74,14 +74,6 @@ BuildRequires: gettext-devel # For s390x... FDO package notes are bogus. Patch1: elfutils-0.186-fdo-swap.patch -# testsuite: Avoid C99 compatibility issues in run-native-test.sh -Patch2: elfutils-0.189-c99-compat.patch -# elfcompress: Don't compress if section already compressed unless forced -Patch3: elfutils-0.189-elfcompress.patch -# libelf: Replace list of elf_getdata_rawchunk results with a tree -Patch4: elfutils-0.189-elf_getdata_rawchunk.patch -# PR29696: Removed secondary fd close in cache config causing race condition -Patch5: elfutils-0.189-debuginfod_config_cache-double-close.patch %description Elfutils is a collection of utilities, including stack (to show @@ -356,6 +348,7 @@ fi %{_bindir}/eu-ranlib %{_bindir}/eu-readelf %{_bindir}/eu-size +%{_bindir}/eu-srcfiles %{_bindir}/eu-stack %{_bindir}/eu-strings %{_bindir}/eu-strip @@ -426,7 +419,6 @@ fi %{_sysusersdir}/elfutils-debuginfod.conf %endif %{_mandir}/man8/debuginfod*.8* -%{_mandir}/man7/debuginfod*.7* %dir %attr(0700,debuginfod,debuginfod) %{_localstatedir}/cache/debuginfod @@ -450,6 +442,16 @@ exit 0 %systemd_postun_with_restart debuginfod.service %changelog +* Fri Nov 10 2023 Mark Wielaard - 0.190-1 +- Upgrade to upstream elfutils 0.190 +- Add eu-srcfiles +- Drop upstreamed patches + elfutils-0.189-debuginfod_config_cache-double-close.patch + elfutils-0.189-elf_getdata_rawchunk.patch + elfutils-0.189-elfcompress.patch + elfutils-0.189-c99-compat.patch +- Only package debuginfod-client-config.7 manpage for debuginfod-client + * Thu Jun 22 2023 Mark Wielaard - 0.189-3 - Add elfutils-0.189-elf_getdata_rawchunk.patch - Add elfutils-0.189-debuginfod_config_cache-double-close.patch diff --git a/sources b/sources index 57e5577..658148d 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (elfutils-0.189.tar.bz2) = 93a877e34db93e5498581d0ab2d702b08c0d87e4cafd9cec9d6636dfa85a168095c305c11583a5b0fb79374dd93bc8d0e9ce6016e6c172764bcea12861605b71 +SHA512 (elfutils-0.190.tar.bz2) = 9c4f5328097e028286c42f29e39dc3d80914b656cdfbbe05b639e91bc787ae8ae64dd4d69a6e317ce30c01648ded10281b86a51e718295f4c589df1225a48102 From d5f93720bbbbce8fa9ab2d2eb850af432344abdb Mon Sep 17 00:00:00 2001 From: Aaron Merey Date: Wed, 29 Nov 2023 14:14:47 -0500 Subject: [PATCH 10/10] 0.190-2 - Update Fedora license tags to spdx license tags - Add elfutils-0.190-fix-core-noncontig.patch - Add elfutils-0.190-remove-ET_REL-unstrip-test.patch --- elfutils-0.190-fix-core-noncontig.patch | 329 ++++++++++++++++++ ...ils-0.190-remove-ET_REL-unstrip-test.patch | 32 ++ elfutils.spec | 32 +- testcore-noncontig.bz2 | Bin 0 -> 54684 bytes 4 files changed, 383 insertions(+), 10 deletions(-) create mode 100644 elfutils-0.190-fix-core-noncontig.patch create mode 100644 elfutils-0.190-remove-ET_REL-unstrip-test.patch create mode 100644 testcore-noncontig.bz2 diff --git a/elfutils-0.190-fix-core-noncontig.patch b/elfutils-0.190-fix-core-noncontig.patch new file mode 100644 index 0000000..e8a7f07 --- /dev/null +++ b/elfutils-0.190-fix-core-noncontig.patch @@ -0,0 +1,329 @@ +From 0fba72fed595f77ca19a57553096ce3cc81cf8f3 Mon Sep 17 00:00:00 2001 +From: Aaron Merey +Date: Fri, 24 Nov 2023 14:52:38 -0500 +Subject: [PATCH] libdwfl: Correctly handle corefile non-contiguous segments + +It is possible for segments of different shared libaries to be interleaved +in memory such that the segments of one library are located in between +non-contiguous segments of another library. + +For example, this can be seen with firefox on RHEL 7.9 where multiple +shared libraries could be mapped in between ld-2.17.so segments: + + [...] + 7f0972082000-7f09720a4000 00000000 139264 /usr/lib64/ld-2.17.so + 7f09720a4000-7f09720a5000 00000000 4096 /memfd:mozilla-ipc (deleted) + 7f09720a5000-7f09720a7000 00000000 8192 /memfd:mozilla-ipc (deleted) + 7f09720a7000-7f09720a9000 00000000 8192 /memfd:mozilla-ipc (deleted) + 7f0972134000-7f0972136000 00000000 8192 /usr/lib64/firefox/libmozwayland.so + 7f0972136000-7f0972137000 00002000 4096 /usr/lib64/firefox/libmozwayland.so + 7f0972137000-7f0972138000 00003000 4096 /usr/lib64/firefox/libmozwayland.so + 7f0972138000-7f0972139000 00003000 4096 /usr/lib64/firefox/libmozwayland.so + 7f097213a000-7f0972147000 00000000 53248 /usr/lib64/firefox/libmozsqlite3.so + 7f0972147000-7f097221e000 0000d000 880640 /usr/lib64/firefox/libmozsqlite3.so + 7f097221e000-7f0972248000 000e4000 172032 /usr/lib64/firefox/libmozsqlite3.so + 7f0972248000-7f0972249000 0010e000 4096 /usr/lib64/firefox/libmozsqlite3.so + 7f0972249000-7f097224c000 0010e000 12288 /usr/lib64/firefox/libmozsqlite3.so + 7f097224c000-7f0972250000 00111000 16384 /usr/lib64/firefox/libmozsqlite3.so + 7f0972250000-7f0972253000 00000000 12288 /usr/lib64/firefox/liblgpllibs.so + [...] + 7f09722a3000-7f09722a4000 00021000 4096 /usr/lib64/ld-2.17.so + 7f09722a4000-7f09722a5000 00022000 4096 /usr/lib64/ld-2.17.so + +dwfl_segment_report_module did not account for the possibility of +interleaving non-contiguous segments, resulting in premature closure +of modules as well as failing to report modules. + +Fix this by removing segment skipping in dwfl_segment_report_module. +When dwfl_segment_report_module reported a module, it would return +the index of the segment immediately following the end address of the +current module. Since there's a chance that other modules might fall +within this address range, dwfl_segment_report_module instead returns +the index of the next segment. + +This patch also fixes premature module closure that can occur in +dwfl_segment_report_module when interleaving non-contiguous segments +are found. Previously modules with start and end addresses that overlap +with the current segment would have their build-ids compared with the +current segment's build-id. If there was a mismatch, that module would +be closed. Avoid closing modules in this case when mismatching build-ids +correspond to distinct modules. + +https://sourceware.org/bugzilla/show_bug.cgi?id=30975 + +Signed-off-by: Aaron Merey +--- + libdwfl/dwfl_segment_report_module.c | 37 ++++++++---- + tests/Makefile.am | 8 ++- + tests/dwfl-core-noncontig.c | 82 +++++++++++++++++++++++++++ + tests/run-dwfl-core-noncontig.sh | 63 ++++++++++++++++++++ + 4 files changed, 177 insertions(+), 14 deletions(-) + create mode 100644 tests/dwfl-core-noncontig.c + create mode 100755 tests/run-dwfl-core-noncontig.sh + +diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c +index 3ef62a7d..09ee37b3 100644 +--- a/libdwfl/dwfl_segment_report_module.c ++++ b/libdwfl/dwfl_segment_report_module.c +@@ -737,17 +737,34 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, + && invalid_elf (module->elf, module->disk_file_has_build_id, + &build_id)) + { +- elf_end (module->elf); +- close (module->fd); +- module->elf = NULL; +- module->fd = -1; ++ /* If MODULE's build-id doesn't match the disk file's ++ build-id, close ELF only if MODULE and ELF refer to ++ different builds of files with the same name. This ++ prevents premature closure of the correct ELF in cases ++ where segments of a module are non-contiguous in memory. */ ++ if (name != NULL && module->name[0] != '\0' ++ && strcmp (basename (module->name), basename (name)) == 0) ++ { ++ elf_end (module->elf); ++ close (module->fd); ++ module->elf = NULL; ++ module->fd = -1; ++ } + } +- if (module->elf != NULL) ++ else if (module->elf != NULL) + { +- /* Ignore this found module if it would conflict in address +- space with any already existing module of DWFL. */ ++ /* This module has already been reported. */ + skip_this_module = true; + } ++ else ++ { ++ /* Only report this module if we haven't already done so. */ ++ for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; ++ mod = mod->next) ++ if (mod->low_addr == module_start ++ && mod->high_addr == module_end) ++ skip_this_module = true; ++ } + } + if (skip_this_module) + goto out; +@@ -781,10 +798,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, + } + } + +- /* Our return value now says to skip the segments contained +- within the module. */ +- ndx = addr_segndx (dwfl, segment, module_end, true); +- + /* Examine its .dynamic section to get more interesting details. + If it has DT_SONAME, we'll use that as the module name. + If it has a DT_DEBUG, then it's actually a PIE rather than a DSO. +@@ -929,6 +942,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, + ndx = -1; + goto out; + } ++ else ++ ndx++; + + /* We have reported the module. Now let the caller decide whether we + should read the whole thing in right now. */ +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 7fb8efb1..9f8f7698 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -42,7 +42,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ + dwfl-bug-addr-overflow arls dwfl-bug-fd-leak \ + dwfl-addr-sect dwfl-bug-report early-offscn \ + dwfl-bug-getmodules dwarf-getmacros dwarf-ranges addrcfi \ +- dwarfcfi \ ++ dwfl-core-noncontig dwarfcfi \ + test-flag-nobits dwarf-getstring rerequest_tag \ + alldts typeiter typeiter2 low_high_pc \ + test-elf_cntl_gelf_getshdr dwflsyms dwfllines \ +@@ -212,7 +212,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ + $(asm_TESTS) run-disasm-bpf.sh run-low_high_pc-dw-form-indirect.sh \ + run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \ + run-readelf-dw-form-indirect.sh run-strip-largealign.sh \ +- run-readelf-Dd.sh ++ run-readelf-Dd.sh run-dwfl-core-noncontig.sh + + if !BIARCH + export ELFUTILS_DISABLE_BIARCH = 1 +@@ -632,7 +632,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ + run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \ + testfile_nvidia_linemap.bz2 \ + testfile-largealign.o.bz2 run-strip-largealign.sh \ +- run-funcretval++11.sh ++ run-funcretval++11.sh \ ++ run-dwfl-core-noncontig.sh testcore-noncontig.bz2 + + + if USE_VALGRIND +@@ -738,6 +739,7 @@ dwfl_bug_fd_leak_LDADD = $(libeu) $(libdw) $(libebl) $(libelf) + dwfl_bug_report_LDADD = $(libdw) $(libebl) $(libelf) + dwfl_bug_getmodules_LDADD = $(libeu) $(libdw) $(libebl) $(libelf) + dwfl_addr_sect_LDADD = $(libeu) $(libdw) $(libebl) $(libelf) $(argp_LDADD) ++dwfl_core_noncontig_LDADD = $(libdw) $(libelf) + dwarf_getmacros_LDADD = $(libdw) + dwarf_ranges_LDADD = $(libdw) + dwarf_getstring_LDADD = $(libdw) +diff --git a/tests/dwfl-core-noncontig.c b/tests/dwfl-core-noncontig.c +new file mode 100644 +index 00000000..04558e28 +--- /dev/null ++++ b/tests/dwfl-core-noncontig.c +@@ -0,0 +1,82 @@ ++/* Test program for dwfl_getmodules bug. ++ Copyright (C) 2008 Red Hat, Inc. ++ This file is part of elfutils. ++ ++ This file is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ elfutils is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#include ++#include ++#include ++#include ++#include ELFUTILS_HEADER(dwfl) ++#include ELFUTILS_HEADER(elf) ++ ++static const Dwfl_Callbacks cb = ++{ ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++}; ++ ++int ++main (int argc, char **argv) ++{ ++ assert (argc == 2); ++ ++ Dwfl *dwfl = dwfl_begin (&cb); ++ ++ int fd = open (argv[1], O_RDONLY); ++ assert (fd != -1); ++ ++ Elf *elf = elf_begin (fd, ELF_C_READ, NULL); ++ (void) dwfl_core_file_report (dwfl, elf, argv[0]); ++ ++ /* testcore-noncontig contains a shared library mapped between ++ non-contiguous segments of another shared library: ++ ++ [...] ++ 7f14e458c000-7f14e45ae000 00000000 139264 /usr/lib64/ld-2.17.so (1) ++ 7f14e4795000-7f14e4798000 00000000 12288 /usr/lib64/firefox/liblgpllibs.so (2) ++ 7f14e4798000-7f14e479d000 00003000 20480 /usr/lib64/firefox/liblgpllibs.so ++ 7f14e479d000-7f14e479f000 00008000 8192 /usr/lib64/firefox/liblgpllibs.so ++ 7f14e479f000-7f14e47a0000 00009000 4096 /usr/lib64/firefox/liblgpllibs.so ++ 7f14e47a0000-7f14e47a1000 0000a000 4096 /usr/lib64/firefox/liblgpllibs.so (3) ++ 7f14e47ad000-7f14e47ae000 00021000 4096 /usr/lib64/ld-2.17.so (4) ++ 7f14e47ae000-7f14e47af000 00022000 4096 /usr/lib64/ld-2.17.so */ ++ ++ /* First segment of the non-contiguous module (1). */ ++ int seg = dwfl_addrsegment (dwfl, 0x7f14e458c000, NULL); ++ assert (seg == 32); ++ ++ /* First segment of the module within the non-contiguous module's address ++ range (2). */ ++ seg = dwfl_addrsegment (dwfl, 0x7f14e4795000, NULL); ++ assert (seg == 33); ++ ++ /* Last segment of the module within the non-contiguous module's ++ address range (3). */ ++ seg = dwfl_addrsegment (dwfl, 0x7f14e47a0000, NULL); ++ assert (seg == 37); ++ ++ /* First segment of non-contiguous module following its address space ++ gap (4). */ ++ seg = dwfl_addrsegment (dwfl, 0x7f14e47ad000, NULL); ++ assert (seg == 40); ++ ++ dwfl_end (dwfl); ++ elf_end (elf); ++ ++ return 0; ++} +diff --git a/tests/run-dwfl-core-noncontig.sh b/tests/run-dwfl-core-noncontig.sh +new file mode 100755 +index 00000000..1245b67f +--- /dev/null ++++ b/tests/run-dwfl-core-noncontig.sh +@@ -0,0 +1,63 @@ ++#! /bin/sh ++# Copyright (C) 2023 Red Hat, Inc. ++# This file is part of elfutils. ++# ++# This file is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# elfutils is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++. $srcdir/test-subr.sh ++ ++# Test whether libdwfl can handle corefiles containing non-contiguous ++# segments where multiple modules are contained within the address ++# space of some other module. ++ ++# testcore-noncontig was generated from the following program with ++# systemd-coredump on RHEL 7.9 Workstation, kernel ++# 3.10.0-1160.105.1.el7.x86_64. liblgpllibs.so was packaged with ++# firefox-115.4.0-1.el7_9.x86_64.rpm. ++ ++# #include ++# #include ++# ++# int main () { ++# dlopen ("/usr/lib64/firefox/liblgpllibs.so", RTLD_GLOBAL | RTLD_NOW); ++# sleep (60); ++# return 0; ++# } ++# ++# gcc -ldl -o test test.c ++ ++tempfiles out ++testfiles testcore-noncontig ++ ++testrun ${abs_builddir}/dwfl-core-noncontig testcore-noncontig ++ ++# Remove parts of the output that could change depending on which ++# libraries are locally installed. ++testrun ${abs_top_builddir}/src/unstrip -n --core testcore-noncontig \ ++ | sed 's/+/ /g' | cut -d " " -f1,3 | sort > out ++ ++testrun_compare cat out <<\EOF ++0x400000 3a1748a544b40a38b3be3d2d13ffa34a2a5a71c0@0x400284 ++0x7f14e357e000 edf51350c7f71496149d064aa8b1441f786df88a@0x7f14e357e1d8 ++0x7f14e3794000 7615604eaf4a068dfae5085444d15c0dee93dfbd@0x7f14e37941d8 ++0x7f14e3a96000 09cfb171310110bc7ea9f4476c9fa044d85baff4@0x7f14e3a96210 ++0x7f14e3d9e000 e10cc8f2b932fc3daeda22f8dac5ebb969524e5b@0x7f14e3d9e248 ++0x7f14e3fba000 fc4fa58e47a5acc137eadb7689bce4357c557a96@0x7f14e3fba280 ++0x7f14e4388000 7f2e9cb0769d7e57bd669b485a74b537b63a57c4@0x7f14e43881d8 ++0x7f14e458c000 62c449974331341bb08dcce3859560a22af1e172@0x7f14e458c1d8 ++0x7f14e4795000 175efdcef445455872a86a6fbee7567ca16a513e@0x7f14e4795248 ++0x7ffcfe59f000 80d79b32785868a2dc10047b39a80d1daec8923d@0x7ffcfe59f328 ++EOF ++ ++exit 0 +-- +2.41.0 + diff --git a/elfutils-0.190-remove-ET_REL-unstrip-test.patch b/elfutils-0.190-remove-ET_REL-unstrip-test.patch new file mode 100644 index 0000000..0f5599e --- /dev/null +++ b/elfutils-0.190-remove-ET_REL-unstrip-test.patch @@ -0,0 +1,32 @@ +From 010cacd89b847659b3c666ac963269b06a8c5058 Mon Sep 17 00:00:00 2001 +From: Aaron Merey +Date: Tue, 28 Nov 2023 16:41:35 -0500 +Subject: [PATCH] tests/run-strip-strmerge.sh: remove ET_REL unstrip and + elflint tests + +These tests can fail on i386. Remove them for now since stripping and +unstripping an ET_REL file is obscure. + +--- + tests/run-strip-strmerge.sh | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/tests/run-strip-strmerge.sh b/tests/run-strip-strmerge.sh +index aa9c1eb..67543eb 100755 +--- a/tests/run-strip-strmerge.sh ++++ b/tests/run-strip-strmerge.sh +@@ -69,11 +69,5 @@ echo elflint $stripped + testrun ${abs_top_builddir}/src/elflint --gnu $stripped + echo elflint $debugfile + testrun ${abs_top_builddir}/src/elflint --gnu -d $debugfile +-echo unstrip +-testrun ${abs_top_builddir}/src/unstrip -o $remerged $stripped $debugfile +-echo elflint $remerged +-testrun ${abs_top_builddir}/src/elflint --gnu $remerged +-echo elfcmp +-testrun ${abs_top_builddir}/src/elfcmp $merged $remerged + + exit 0 +-- +2.41.0 + diff --git a/elfutils.spec b/elfutils.spec index 87484c5..79a206a 100644 --- a/elfutils.spec +++ b/elfutils.spec @@ -1,12 +1,13 @@ Name: elfutils Version: 0.190 -%global baserelease 1 +%global baserelease 2 Release: %{baserelease}%{?dist} URL: http://elfutils.org/ %global source_url ftp://sourceware.org/pub/elfutils/%{version}/ -License: GPLv3+ and (GPLv2+ or LGPLv3+) and GFDL +License: GPL-3.0-or-later and (GPL-2.0-or-later or LGPL-3.0-or-later) and GFDL-1.3-no-invariants-or-later Source: %{?source_url}%{name}-%{version}.tar.bz2 Source1: elfutils-debuginfod.sysusers +Source2: testcore-noncontig.bz2 Summary: A collection of utilities and DSOs to handle ELF files and DWARF data # Needed for isa specific Provides and Requires. @@ -74,6 +75,10 @@ BuildRequires: gettext-devel # For s390x... FDO package notes are bogus. Patch1: elfutils-0.186-fdo-swap.patch +# PR30975: Fix handling of corefiles with non-contiguous .so segments. +Patch2: elfutils-0.190-fix-core-noncontig.patch +# Remove obscure tests that can fail on i386. +Patch3: elfutils-0.190-remove-ET_REL-unstrip-test.patch %description Elfutils is a collection of utilities, including stack (to show @@ -85,7 +90,7 @@ elfcompress (to compress or decompress ELF sections). %package libs Summary: Libraries to handle compiled objects -License: GPLv2+ or LGPLv3+ +License: GPL-2.0-or-later or LGPL-3.0-or-later %if 0%{!?_isa:1} Provides: elfutils-libs%{depsuffix} = %{version}-%{release} %endif @@ -108,7 +113,7 @@ libraries. %package devel Summary: Development libraries to handle compiled objects -License: GPLv2+ or LGPLv3+ +License: GPL-2.0-or-later or LGPL-3.0-or-later %if 0%{!?_isa:1} Provides: elfutils-devel%{depsuffix} = %{version}-%{release} %endif @@ -129,7 +134,7 @@ assembler interface. %package libelf Summary: Library to read and write ELF files -License: GPLv2+ or LGPLv3+ +License: GPL-2.0-or-later or LGPL-3.0-or-later %if 0%{!?_isa:1} Provides: elfutils-libelf%{depsuffix} = %{version}-%{release} %endif @@ -143,7 +148,7 @@ elfutils package use it also to generate new ELF files. %package libelf-devel Summary: Development support for libelf -License: GPLv2+ or LGPLv3+ +License: GPL-2.0-or-later or LGPL-3.0-or-later %if 0%{!?_isa:1} Provides: elfutils-libelf-devel%{depsuffix} = %{version}-%{release} %endif @@ -160,7 +165,7 @@ different sections of an ELF file. %if %{provide_yama_scope} %package default-yama-scope Summary: Default yama attach scope sysctl setting -License: GPLv2+ or LGPLv3+ +License: GPL-2.0-or-later or LGPL-3.0-or-later Provides: default-yama-scope BuildArch: noarch # For the sysctl_apply macro we need systemd as build requires. @@ -194,7 +199,7 @@ profiling) of processes. %package debuginfod-client Summary: Library and command line client for build-id HTTP ELF/DWARF server -License: GPLv3+ and (GPLv2+ or LGPLv3+) +License: GPL-3.0-or-later and (GPL-2.0-or-later or LGPL-3.0-or-later) %if 0%{!?_isa:1} Provides: elfutils-debuginfod-client%{depsuffix} = %{version}-%{release} %endif @@ -204,7 +209,7 @@ Requires: elfutils-libelf%{depsuffix} = %{version}-%{release} %package debuginfod-client-devel Summary: Libraries and headers to build debuginfod client applications -License: GPLv2+ or LGPLv3+ +License: GPL-2.0-or-later or LGPL-3.0-or-later %if 0%{!?_isa:1} Provides: elfutils-debuginfod-client-devel%{depsuffix} = %{version}-%{release} %endif @@ -212,7 +217,7 @@ Requires: elfutils-debuginfod-client%{depsuffix} = %{version}-%{release} %package debuginfod Summary: HTTP ELF/DWARF file server addressed by build-id -License: GPLv3+ +License: GPL-3.0-or-later Requires: elfutils-libs%{depsuffix} = %{version}-%{release} Requires: elfutils-libelf%{depsuffix} = %{version}-%{release} Requires: elfutils-debuginfod-client%{depsuffix} = %{version}-%{release} @@ -258,6 +263,8 @@ autoreconf -f -v -i # are executable. find . -name \*.sh ! -perm -0100 -print | xargs chmod +x +cp %{SOURCE2} tests + %build # Remove -Wall from default flags. The makefiles enable enough warnings # themselves, and they use -Werror. Appending -Wall defeats the cases where @@ -442,6 +449,11 @@ exit 0 %systemd_postun_with_restart debuginfod.service %changelog +* Wed Nov 29 2023 Aaron Merey - 0.190-2 +- Update Fedora license tags to spdx license tags +- Add elfutils-0.190-fix-core-noncontig.patch +- Add elfutils-0.190-remove-ET_REL-unstrip-test.patch + * Fri Nov 10 2023 Mark Wielaard - 0.190-1 - Upgrade to upstream elfutils 0.190 - Add eu-srcfiles diff --git a/testcore-noncontig.bz2 b/testcore-noncontig.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..514ad010e00499b9a75a98800aa20ec61596d491 GIT binary patch literal 54684 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 literal 0 HcmV?d00001