simple static linking with is broken with 2.31 ld because it does not put program headers into a load section unless there is some other read only loaded section. $ ld --version GNU ld (GNU Binutils) 2.31.1.20180718 Copyright (C) 2018 Free Software Foundation, Inc. This program is free software; you may redistribute it under the terms of the GNU General Public License version 3 or (at your option) a later version. This program has absolutely no warranty. $ cat t.s .globl _start _start: xor %rdi,%rdi mov $0xe7,%eax syscall $ as -o t.o t.s $ ld -static t.o $ readelf -aW a.out ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x401000 Start of program headers: 64 (bytes into file) Start of section headers: 4320 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 1 Size of section headers: 64 (bytes) Number of section headers: 5 Section header string table index: 4 Section Headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 0000000000401000 001000 00000a 00 AX 0 0 1 [ 2] .symtab SYMTAB 0000000000000000 001010 000090 18 3 2 8 [ 3] .strtab STRTAB 0000000000000000 0010a0 000019 00 0 0 1 [ 4] .shstrtab STRTAB 0000000000000000 0010b9 000021 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x001000 0x0000000000401000 0x0000000000401000 0x00000a 0x00000a R E 0x1000 Section to Segment mapping: Segment Sections... 00 .text There is no dynamic section in this file. There are no relocations in this file. The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. Symbol table '.symtab' contains 6 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000401000 0 SECTION LOCAL DEFAULT 1 2: 0000000000401000 0 NOTYPE GLOBAL DEFAULT 1 _start 3: 0000000000402000 0 NOTYPE GLOBAL DEFAULT 1 __bss_start 4: 0000000000402000 0 NOTYPE GLOBAL DEFAULT 1 _edata 5: 0000000000402000 0 NOTYPE GLOBAL DEFAULT 1 _end No version information found in this file. $ ./a.out $ Note that the program headers (starting at 0x400000 + 64) are not in a load segment, so if the executable tries to access it (based on the program header address the kernel passed in auxv) then it will be a runtime fault. (reading program headers is e.g. needed to support tls in static executables) if i add a readonly note section then program headers are correctly loaded: $ ld --build-id -static t.o $ readelf -lW a.out Elf file type is EXEC (Executable file) Entry point 0x401000 There are 3 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x00010c 0x00010c R 0x1000 LOAD 0x001000 0x0000000000401000 0x0000000000401000 0x00000a 0x00000a R E 0x1000 NOTE 0x0000e8 0x00000000004000e8 0x00000000004000e8 0x000024 0x000024 R 0x4 Section to Segment mapping: Segment Sections... 00 .note.gnu.build-id 01 .text 02 .note.gnu.build-id $ with a 2.30 ld, the program headers are part of the same segment as .text so it is loaded (and executable): $ readelf -lW a.out Elf file type is EXEC (Executable file) Entry point 0x400078 There is 1 program header, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x000082 0x000082 R E 0x200000 Section to Segment mapping: Segment Sections... 00 .text $
pr23428 branch: https://github.com/hjl-tools/simple-linux/tree/pr23428 has a small run-time testcase: [hjl@gnu-tools-1 simple-linux]$ make gcc -g -O0 -fno-asynchronous-unwind-tables -c -o test.o test.c gcc -g -c -o start.o start.S gcc -g -c -o syscall.o syscall.S ld -z separate-code -o test test.o start.o syscall.o ./test; echo $? /bin/sh: line 1: 16441 Segmentation fault (core dumped) ./test 139 [hjl@gnu-tools-1 simple-linux]$ gcc test.o [hjl@gnu-tools-1 simple-linux]$ ./a.out [hjl@gnu-tools-1 simple-linux]$ echo $? 0 [hjl@gnu-tools-1 simple-linux]$
A patch is posted at https://sourceware.org/ml/binutils/2018-07/msg00321.html
I don't object to the patch as-is, but wouldn't it make more sense to make the program headers a first-class section with attribute alloc, so that they're semantically forced to be visible at runtime rather than just happening to fall into a load segment that exists due to other sections? This fix would be target-agnostic and would prevent the issue from ever arising for other targets.
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=241e64e3b42cd9eba514b8e0ad2ef39a337f10a5 commit 241e64e3b42cd9eba514b8e0ad2ef39a337f10a5 Author: H.J. Lu <hjl.tools@gmail.com> Date: Fri Jul 20 09:18:47 2018 -0700 x86: Add a GNU_PROPERTY_X86_ISA_1_USED note if needed When -z separate-code, which is enabled by default for Linux/x86, is used to create executable, ld won't place any data in the code-only PT_LOAD segment. If there are no data sections placed before the code-only PT_LOAD segment, the program headers won't be mapped into any PT_LOAD segment. When the executable tries to access it (based on the program header address passed in AT_PHDR), it will lead to segfault. This patch inserts a GNU_PROPERTY_X86_ISA_1_USED note if there may be no data sections before the text section so that the first PT_LOAD segment won't be code-only and will contain the program header. Testcases are adjusted to either pass "-z noseparate-code" to ld or discard the .note.gnu.property section. A Linux/x86 run-time test is added. bfd/ PR ld/23428 * elfxx-x86.c (_bfd_x86_elf_link_setup_gnu_properties): If the separate code program header is needed, make sure that the first read-only PT_LOAD segment has no code by adding a GNU_PROPERTY_X86_ISA_1_USED note. ld/ PR ld/23428 * testsuite/ld-elf/linux-x86.S: New file. * testsuite/ld-elf/linux-x86.exp: Likewise. * testsuite/ld-elf/pr23428.c: Likewise. * testsuite/ld-elf/sec64k.exp: Pass "-z noseparate-code" to ld for Linux/x86 targets. * testsuite/ld-i386/abs-iamcu.d: Likewise. * testsuite/ld-i386/abs.d: Likewise. * testsuite/ld-i386/pr12718.d: Likewise. * testsuite/ld-i386/pr12921.d: Likewise. * testsuite/ld-x86-64/abs-k1om.d: Likewise. * testsuite/ld-x86-64/abs-l1om.d: Likewise. * testsuite/ld-x86-64/abs.d: Likewise. * testsuite/ld-x86-64/pr12718.d: Likewise. * testsuite/ld-x86-64/pr12921.d: Likewise. * testsuite/ld-linkonce/zeroeh.ld: Discard .note.gnu.property section. * testsuite/ld-scripts/print-memory-usage.t: Likewise. * testsuite/ld-scripts/size-2.t: Likewise. * testsuite/lib/ld-lib.exp (run_ld_link_exec_tests): Use ld to create executable if language is "asm".
The binutils-2_31-branch branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6737a6b34f4823deb7142f27b4074831a37ac1e1 commit 6737a6b34f4823deb7142f27b4074831a37ac1e1 Author: H.J. Lu <hjl.tools@gmail.com> Date: Fri Jul 20 09:18:47 2018 -0700 x86: Add a GNU_PROPERTY_X86_ISA_1_USED note if needed When -z separate-code, which is enabled by default for Linux/x86, is used to create executable, ld won't place any data in the code-only PT_LOAD segment. If there are no data sections placed before the code-only PT_LOAD segment, the program headers won't be mapped into any PT_LOAD segment. When the executable tries to access it (based on the program header address passed in AT_PHDR), it will lead to segfault. This patch inserts a GNU_PROPERTY_X86_ISA_1_USED note if there may be no data sections before the text section so that the first PT_LOAD segment won't be code-only and will contain the program header. Testcases are adjusted to either pass "-z noseparate-code" to ld or discard the .note.gnu.property section. A Linux/x86 run-time test is added. bfd/ PR ld/23428 * elfxx-x86.c (_bfd_x86_elf_link_setup_gnu_properties): If the separate code program header is needed, make sure that the first read-only PT_LOAD segment has no code by adding a GNU_PROPERTY_X86_ISA_1_USED note. ld/ PR ld/23428 * testsuite/ld-elf/linux-x86.S: New file. * testsuite/ld-elf/linux-x86.exp: Likewise. * testsuite/ld-elf/pr23428.c: Likewise. * testsuite/ld-elf/sec64k.exp: Pass "-z noseparate-code" to ld for Linux/x86 targets. * testsuite/ld-i386/abs-iamcu.d: Likewise. * testsuite/ld-i386/abs.d: Likewise. * testsuite/ld-i386/pr12718.d: Likewise. * testsuite/ld-i386/pr12921.d: Likewise. * testsuite/ld-x86-64/abs-k1om.d: Likewise. * testsuite/ld-x86-64/abs-l1om.d: Likewise. * testsuite/ld-x86-64/abs.d: Likewise. * testsuite/ld-x86-64/pr12718.d: Likewise. * testsuite/ld-x86-64/pr12921.d: Likewise. * testsuite/ld-linkonce/zeroeh.ld: Discard .note.gnu.property section. * testsuite/ld-scripts/print-memory-usage.t: Likewise. * testsuite/ld-scripts/size-2.t: Likewise. * testsuite/lib/ld-lib.exp (run_ld_link_exec_tests): Use ld to create executable if language is "asm". (cherry picked from commit 241e64e3b42cd9eba514b8e0ad2ef39a337f10a5)
Fixed for 2.32 and on 2.31 branch.
@Szabolcs, Rich: Is the musl-gcc issue fixed for you guys? [1] I'm still getting a segfault with current binutils master (6404ab9937): $ ld -v GNU ld (GNU Binutils) 2.31.51.20180809 $ musl-gcc -ggdb3 -O0 -static -xc - <<<"int main() { return 0; }" $ gdb -q --batch -ex run -ex bt ./a.out Program received signal SIGSEGV, Segmentation fault. 0x000000000040140f in static_init_tls () #0 0x000000000040140f in static_init_tls () #1 0x0000000000000000 in ?? () [1] http://www.openwall.com/lists/musl/2018/07/18/5
* evangelos at foutrelis dot com <sourceware-bugzilla@sourceware.org> [2018-08-09 07:37:19 +0000]: > @Szabolcs, Rich: Is the musl-gcc issue fixed for you guys? [1] > > I'm still getting a segfault with current binutils master (6404ab9937): > > $ ld -v > GNU ld (GNU Binutils) 2.31.51.20180809 > > $ musl-gcc -ggdb3 -O0 -static -xc - <<<"int main() { return 0; }" > $ gdb -q --batch -ex run -ex bt ./a.out > > Program received signal SIGSEGV, Segmentation fault. > 0x000000000040140f in static_init_tls () > #0 0x000000000040140f in static_init_tls () > #1 0x0000000000000000 in ?? () it works for me, please post the readelf -aW ./a.out somewhere (e.g. musl list) (you should see a .note.gnu.property section and an appropriate NOTE program header.)
(In reply to nsz from comment #8) > it works for me, please post the readelf -aW ./a.out somewhere (e.g. musl > list) https://paste.xinu.at/igNNdz/ -- but as mentioned below, it's the same as unpatched binutils. > (you should see a .note.gnu.property section and an appropriate NOTE program > header.) This is really weird and I'm not sure what's going on: The output from 'readelf -aW' is exactly the same with both patched and unpatched binutils 2.31 when using the musl-gcc example. However, it does change when using your original example of linking t.o; with patched binutils I see a .note.gnu.property section and a NOTE program header. I also checked on Debian testing and the musl-gcc command produces a working binary there (even after removing the --build-id workaround from musl-gcc.specs). For some weird reason though, it still segfaults on Arch with patched binutils. :|
* evangelos at foutrelis dot com <sourceware-bugzilla@sourceware.org> [2018-08-10 02:14:57 +0000]: > I also checked on Debian testing and the musl-gcc command produces a working > binary there (even after removing the --build-id workaround from > musl-gcc.specs). For some weird reason though, it still segfaults on Arch with > patched binutils. :| i'd try to verify that the right ld is used (e.g. strace -f -e execve musl-gcc ...) then i'd try to reproduce the issue outside of musl-gcc (e.g. manually invoking ld with the options seen in the strace and look for the NOTE program header)
Created attachment 11174 [details] Test case with Arch's and Debian's GCC-provided crt{begin,end}.o (In reply to nsz from comment #10) > i'd try to verify that the right ld is used (e.g. strace -f -e execve > musl-gcc ...) > then i'd try to reproduce the issue outside of musl-gcc (e.g. manually > invoking > ld with the options seen in the strace and look for the NOTE program header) Thanks for the suggestion. I was able to reduce my test case to something that is reproducible on both Arch and Debian. The attached test case indicates that it's some difference between Debian's and Arch's crt{begin,end}.o (as provided by GCC) that's causing ld to add the NOTE program header and .note.gnu.property section to the produced binary. Comparing them using 'objdump -h', I notice that Arch's crt{begin,end}.o have a .note.gnu.property section and Debian's don't. If I use 'objcopy -R .note.gnu.property' on the Arch ones, then those produce a working executable too! Does the above indicate that the fix to binutils needs to be tweaked? ================================= [pr23428-test]$ make cc -c -o test.o test.c ld -static -o test-arch arch-crts/* arch-musl/* test.o ld -static -o test-debian debian-crts/* arch-musl/* test.o pr23428-test$ grep gnu.property test-* Binary file test-debian matches [pr23428-test]$ ./test-debian [pr23428-test]$ ./test-arch Segmentation fault (core dumped) [pr23428-test]$ objcopy -R .note.gnu.property arch-crts/crtbegin.o [pr23428-test]$ objcopy -R .note.gnu.property arch-crts/crtend.o [pr23428-test]$ make -Bs test-arch [pr23428-test]$ gdb -q -ex run ./test-arch Reading symbols from ./test-arch...(no debugging symbols found)...done. Starting program: /home/../desktop/pr23428-test/test-arch [Inferior 1 (process 17284) exited normally] =================================
(In reply to Evangelos Foutras from comment #11) > > Does the above indicate that the fix to binutils needs to be tweaked? > Please provide a small and host-independent testcase.
Created attachment 11177 [details] libgcc-8-dev rebuilt with --enable-cet=auto (for Debian testing) (In reply to H.J. Lu from comment #12) > Please provide a small and host-independent testcase. I have not been able to further reduce my findings from comment #11. I was hoping someone else might be able to figure out what's going on. ------------------ @Szabolcs: If you rebuild gcc-8 on Debian testing with "--enable-cet=auto" added to CONFARGS in debian/rules2, then you should be able to reproduce the musl-gcc crash (after removing the --build-id workaround from musl-gcc.specs!). (It appears that "--enable-cet=auto" is the important difference between Arch's and Debian's GCC packages.) Since gcc-8 takes several hours to build, I have attached libgcc-8-dev which contains the relevant crt{begin,end}.o files. With this I'm able to reproduce the crash in a new Debian testing VM as follows: # apt install ./libgcc-8-dev_8.2.0-3_amd64.deb # sed -i 's/--build-id //' /usr/lib/x86_64-linux-musl/musl-gcc.specs $ musl-gcc -static -xc - <<<"int main() { return 0; }" $ gdb -q --batch -ex run -ex bt ./a.out Program received signal SIGSEGV, Segmentation fault. 0x000000000040158d in static_init_tls () #0 0x000000000040158d in static_init_tls () #1 0x0000000000000000 in ?? ()
> @Szabolcs: If you rebuild gcc-8 on Debian testing with "--enable-cet=auto" > added to CONFARGS in debian/rules2, then you should be able to reproduce the > musl-gcc crash (after removing the --build-id workaround from musl-gcc.specs!). > > (It appears that "--enable-cet=auto" is the important difference between Arch's > and Debian's GCC packages.) thanks, i could reproduce the issue: it seems ld tries to add a dummy .note.gnu.property to force the program headers into a load segment, but if there is already a .note.gnu.property in some of the input object files then it just tries to merge those and don't add a dummy note at all, however the merging rules may produce an empty note in the end and then the note section is dropped. # cat i.c int i; # gcc -fcf-protection=full -c i.c # readelf -n i.o Displaying notes found in: .note.gnu.property Owner Data size Description GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 Properties: x86 feature: IBT, SHSTK # cat t.s .globl _start _start: ret # gcc -c t.s # ld t.o # readelf -ln a.out Elf file type is EXEC (Executable file) Entry point 0x401000 There are 3 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x0000000000000108 0x0000000000000108 R 0x1000 LOAD 0x0000000000001000 0x0000000000401000 0x0000000000401000 0x0000000000000001 0x0000000000000001 R E 0x1000 NOTE 0x00000000000000e8 0x00000000004000e8 0x00000000004000e8 0x0000000000000020 0x0000000000000020 R 0x8 Section to Segment mapping: Segment Sections... 00 .note.gnu.property 01 .text 02 .note.gnu.property Displaying notes found in: .note.gnu.property Owner Data size Description GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 Properties: x86 ISA used: i486 # ld t.o i.o # readelf -ln a.out Elf file type is EXEC (Executable file) Entry point 0x401000 There are 3 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000001000 0x0000000000401000 0x0000000000401000 0x0000000000000001 0x0000000000000001 R E 0x1000 LOAD 0x0000000000002000 0x0000000000402000 0x0000000000402000 0x0000000000000000 0x0000000000000008 RW 0x1000 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RWE 0x10 Section to Segment mapping: Segment Sections... 00 .text 01 .bss 02
(In reply to nsz from comment #14) > > @Szabolcs: If you rebuild gcc-8 on Debian testing with "--enable-cet=auto" > > added to CONFARGS in debian/rules2, then you should be able to reproduce the > > musl-gcc crash (after removing the --build-id workaround from musl-gcc.specs!). > > > > (It appears that "--enable-cet=auto" is the important difference between Arch's > > and Debian's GCC packages.) > > thanks, i could reproduce the issue: > > it seems ld tries to add a dummy .note.gnu.property to force the > program headers into a load segment, but if there is already a > .note.gnu.property in some of the input object files then it just > tries to merge those and don't add a dummy note at all, however > the merging rules may produce an empty note in the end and then > the note section is dropped. Please try binutils master branch with commit f7309df20c4e787041cedc4a6aced89c15259e54 Author: H.J. Lu <hjl.tools@gmail.com> Date: Wed Aug 8 06:09:15 2018 -0700 x86: Properly merge GNU_PROPERTY_X86_ISA_1_USED Without the GNU_PROPERTY_X86_ISA_1_USED property, all ISAs may be used. If a bit in the GNU_PROPERTY_X86_ISA_1_USED property is unset, the corresponding x86 instruction set isn\u2019t used. When merging properties from 2 input files and one input file doesn't have the GNU_PROPERTY_X86_ISA_1_USED property, the output file shouldn't have it neither. This patch removes the GNU_PROPERTY_X86_ISA_1_USED property if an input file doesn't have it. This patch replaces the GNU_PROPERTY_X86_ISA_1_USED property with the GNU_PROPERTY_X86_ISA_1_NEEDED property which is the minimum ISA requirement.
The test case from comment #14 is still reproducible for me with both binutils master (1dc9e2d6) and binutils-2_31-branch (6ee91b1e). No change at all in the resulting binary, compared to just the patch from comment #4.
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ab9e342807d132182892de1be1a92d6e91a5c1da commit ab9e342807d132182892de1be1a92d6e91a5c1da Author: H.J. Lu <hjl.tools@gmail.com> Date: Sat Aug 11 06:41:33 2018 -0700 x86: Properly add X86_ISA_1_NEEDED property Existing properties may be removed during property merging. We avoid adding X86_ISA_1_NEEDED property only if existing properties won't be removed. bfd/ PR ld/23428 * elfxx-x86.c (_bfd_x86_elf_link_setup_gnu_properties): Don't add X86_ISA_1_NEEDED property only if existing properties won't be removed. ld/ PR ld/23428 * testsuite/ld-elf/dummy.s: New file. * testsuite/ld-elf/linux-x86.S: Add X86_FEATURE_1_AND property. * testsuite/ld-elf/linux-x86.exp: Add dummy.s to pr23428.
(In reply to Evangelos Foutras from comment #16) > The test case from comment #14 is still reproducible for me with both > binutils master (1dc9e2d6) and binutils-2_31-branch (6ee91b1e). No change at > all in the resulting binary, compared to just the patch from comment #4. Please try master branch again.
(In reply to H.J. Lu from comment #18) > (In reply to Evangelos Foutras from comment #16) > > The test case from comment #14 is still reproducible for me with both > > binutils master (1dc9e2d6) and binutils-2_31-branch (6ee91b1e). No change at > > all in the resulting binary, compared to just the patch from comment #4. > > Please try master branch again. Your latest commit fixes the issue I was experiencing. Thanks!
The binutils-2_31-branch branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=28a27bdbb9500797e6767f80c8128b09112aeed5 commit 28a27bdbb9500797e6767f80c8128b09112aeed5 Author: H.J. Lu <hjl.tools@gmail.com> Date: Sat Aug 11 06:41:33 2018 -0700 x86: Properly add X86_ISA_1_NEEDED property Existing properties may be removed during property merging. We avoid adding X86_ISA_1_NEEDED property only if existing properties won't be removed. bfd/ PR ld/23428 * elfxx-x86.c (_bfd_x86_elf_link_setup_gnu_properties): Don't add X86_ISA_1_NEEDED property only if existing properties won't be removed. ld/ PR ld/23428 * testsuite/ld-elf/dummy.s: New file. * testsuite/ld-elf/linux-x86.S: Add X86_FEATURE_1_AND property. * testsuite/ld-elf/linux-x86.exp: Add dummy.s to pr23428. (cherry picked from commit ab9e342807d132182892de1be1a92d6e91a5c1da)
*** Bug 23561 has been marked as a duplicate of this bug. ***
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=80f3ac5d61a5d01d7cf951de0e24ecdc71c545cb commit 80f3ac5d61a5d01d7cf951de0e24ecdc71c545cb Author: H.J. Lu <hjl.tools@gmail.com> Date: Mon Oct 8 05:14:02 2018 -0700 x86: Don't add GNU_PROPERTY_X86_FEATURE_2_NEEDED for -z separate-code With commit 64029e93683a266c38d19789e780f3748bd6a188 Author: Alan Modra <amodra@gmail.com> Date: Fri Oct 5 11:40:54 2018 +0930 Separate header PT_LOAD for -z separate-code there is no need to add a GNU_PROPERTY_X86_ISA_1_USED note to force program header in in non-code PT_LOAD segment when -z separate-code is used. bfd/ PR ld/23428 * elfxx-x86.c (_bfd_x86_elf_link_setup_gnu_properties): Don't add GNU_PROPERTY_X86_FEATURE_2_NEEDED to force program header in non-code PT_LOAD segment. ld/ PR ld/23428 * testsuite/ld-i386/property-x86-4a.d: Updated. * testsuite/ld-x86-64/property-x86-4a-x32.d: Likewise. * testsuite/ld-x86-64/property-x86-4a.d: Likewise.