From 68d36578e9a840c088e0f73c41416ff9b30cb79b Mon Sep 17 00:00:00 2001 From: Valerii Chernous Date: Thu, 28 Oct 2021 05:19:19 -0700 Subject: [PATCH] ignore build-id for linker inputs if new requested Issue description: building of glibc 2.32 and later with option "-Wl,--build-id" produce libc.so.6 with section ".note.gnu.build-id" that have invalid(double, 0x48) section size. It happens because glibc use sublibraries for linking libc.so.6 ld produce this sublibraries with build-id section and on last linking stage loads this sections as input for linking. ld should create new(valid) ".note.gnu.build-id" into function ldelf_setup_build_id on last linking stage but it skip creating because build-id section already exists. As result libc.so.6 contain ".note.gnu.build-id" with build-ids from sublibraries and without valid build-id Howto solved: Ignoring ".note.gnu.build-id" on linker input fix this problem. Linker input doesn't have invalid build-id sections on ldelf_setup_build_id stage and create new(proper) one for output library/binary Clang have it's own fix for this issue: https://reviews.llvm.org/D42823 https://bugs.llvm.org/show_bug.cgi?id=36203 howto reproduce: yocto: cd GLIBC_RECIPE_WORKDIR export CMD_PREFIX="./recipe-sysroot-native/usr/bin/x86_64-iosxe-linux/x86_64-iosxe-linux"; export GCC="$CMD_PREFIX-gcc"; export RELF="$CMD_PREFIX-readelf" echo "void f1(){}" >f1.c echo "void f2(){}" >f2.c $GCC f1.c -c -o f1.o $GCC f2.c -c -o f2.o $GCC f1.o -Wl,--build-id -nostdlib -nostartfiles -r -o f1 $GCC f2.o -Wl,--build-id -nostdlib -nostartfiles -r -o f2 $GCC ./f1 ./f2 -shared -Wl,--build-id -nostdlib -nostartfiles -o f.so $RELF -S f.so | grep -E -A1 "note.gnu.bu" ubuntu: echo "void f1(){}" >f1.c echo "void f2(){}" >f2.c gcc f1.c -c -o f1.o gcc f2.c -c -o f2.o gcc f1.o -Wl,--build-id -nostdlib -nostartfiles -r -o f1 gcc f2.o -Wl,--build-id -nostdlib -nostartfiles -r -o f2 gcc ./f1 ./f2 -shared -Wl,--build-id -nostdlib -nostartfiles -o f.so readelf -S f.so | grep -E -A1 "note.gnu.bu" output: without fix [ 1] .note.gnu.bu[...] NOTE 0000000000000238 00000238 0000000000000048 0000000000000000 A 0 0 4 with fix [ 1] .note.gnu.bu[...] NOTE 0000000000000238 00000238 0000000000000024 0000000000000000 A 0 0 4 Signed-off-by: Valerii Chernous --- bfd/bfd-in2.h | 2 ++ bfd/elf.c | 4 ++++ ld/ldfile.c | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 7b7a329cd62..5a91e14f6f9 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -6851,6 +6851,8 @@ struct bfd /* For input BFDs, the build ID, if the object has one. */ const struct bfd_build_id *build_id; + /* linker set this flag if create build-id requested by cmd line or default */ + int is_new_build_id_requested; }; static inline const char * diff --git a/bfd/elf.c b/bfd/elf.c index cfdb94922f3..24a1dc44731 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -2100,6 +2100,10 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) case SHT_PREINIT_ARRAY: /* .preinit_array section. */ case SHT_GNU_LIBLIST: /* .gnu.liblist section. */ case SHT_GNU_HASH: /* .gnu.hash section. */ + + /* skip .note.gnu.build-id section for linker input if create new one requested */ + if (hdr->sh_type == SHT_NOTE && abfd->is_linker_input == 1 && abfd->is_new_build_id_requested == 1 && strncmp(name, ".note.gnu.build-id", strlen(".note.gnu.build-id")) == 0 ) + goto success; ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); goto success; diff --git a/ld/ldfile.c b/ld/ldfile.c index 22271fd6810..e28cf297057 100644 --- a/ld/ldfile.c +++ b/ld/ldfile.c @@ -34,6 +34,7 @@ #include "ldemul.h" #include "libiberty.h" #include "filenames.h" +#include "ldelf.h" #if BFD_SUPPORTS_PLUGINS #include "plugin-api.h" #include "plugin.h" @@ -155,6 +156,10 @@ ldfile_try_open_bfd (const char *attempt, entry->the_bfd->lto_output = 1; #endif + /* if new build-id required, inform bfd/elf.c about it */ + if (ldelf_emit_note_gnu_build_id != NULL) + entry->the_bfd->is_new_build_id_requested = 1; + /* If we are searching for this file, see if the architecture is compatible with the output file. If it isn't, keep searching. If we can't open the file as an object file, stop the search -- 2.26.2.Cisco