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-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-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-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 2d5321a..c01f9fb 100644 --- a/elfutils.spec +++ b/elfutils.spec @@ -1,7 +1,7 @@ Name: elfutils Version: 0.189 -%global baserelease 1 -Release: %{baserelease}.1.riscv64%{?dist} +%global baserelease 3 +Release: %{baserelease}.0.riscv64%{?dist} URL: http://elfutils.org/ %global source_url ftp://sourceware.org/pub/elfutils/%{version}/ License: GPLv3+ and (GPLv2+ or LGPLv3+) and GFDL @@ -74,6 +74,14 @@ 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 @@ -446,12 +454,17 @@ exit 0 %systemd_postun_with_restart debuginfod.service %changelog -* Mon Mar 27 2023 David Abdurachmanov - 0.189-1.1.riscv64 -- Rebuild with a new GCC and binutils - -* Sun Mar 12 2023 David Abdurachmanov - 0.189-1.0.riscv64 +* Tue Jul 02 2023 David Abdurachmanov - 0.189-3.0.riscv64 - Ignore testsuite failures on riscv64 +* 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 +- Add elfutils-0.189-elfcompress.patch + * Fri Mar 3 2023 Mark Wielaard - 0.189-1 - Upgrade to upsteam elfutils 0.189. 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..f8b643a --- /dev/null +++ b/tests/Regression/eu-elfcompress-breaks-hard-links/bubble.c @@ -0,0 +1,4 @@ +int main() +{ + 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