When building the Fedora 37 'gcc-12.1.1.1-fc37.src.rpm' on a Rocky Linux EL8 system, only modified by setting "%define _prefix /usr/local", renaming to 'gcc-12-local', and changing the Provides and sub-package Requires from 'gcc' to to 'gcc-12-local*' & removing the Obsoletes, AFTER building the binutils-2.38-14.1-fc37.src.rpm, similarly renamed 'binutils-local-2.38-14.1.el8', similarly relocated under /usr/local , with $PATH set to /usr/local/bin:/usr/bin , to build EVERY supported GCC language, including gnat, d, gccgo, and objc, the gccgo build fails on this command: ```<quote><lit> echo timestamp > s-zdefaultcc /home/jvd/rpmbuild/BUILD/gcc-12.1.1-20220507/obj-x86_64-redhat-linux/./gcc/gccgo -B/home/jvd/rpmbuild/BUILD/gcc-12.1.1-20220507/obj-x86_64-redhat-linux/./gcc/ -B/usr/local/x86_64-redhat-linux/bin/ -B/usr/local/x86_64-redhat-linux/lib/ -isystem /usr/local/x86_64-redhat-linux/include -isystem /usr/local/x86_64-redhat-linux/sys-include -O2 -fexceptions -g -grecord-gcc-switches -Wall -Wformat-security -Wp,-D_GLIBCXX_ASSERTIONS -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I ../x86_64-redhat-linux/libgo -static-libstdc++ -static-libgcc -Wl,-z,relro,-z,now -L ../x86_64-redhat-linux/libgo -L ../x86_64-redhat-linux/libgo/.libs -o cgo ../../gotools/../libgo/go/cmd/cgo/ast.go ../../gotools/../libgo/go/cmd/cgo/ast_go118.go ../../gotools/../libgo/go/cmd/cgo/doc.go ../../gotools/../libgo/go/cmd/cgo/gcc.go ../../gotools/../libgo/go/cmd/cgo/godefs.go ../../gotools/../libgo/go/cmd/cgo/main.go ../../gotools/../libgo/go/cmd/cgo/out.go ../../gotools/../libgo/go/cmd/cgo/util.go zdefaultcc.go ../x86_64-redhat-linux/libgo/libgotool.a go1: warning: command-line option '-Wformat-security' is valid for C/C++/ObjC/ObjC++ but not for Go /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 150 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 1e0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 220 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 260 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 2a0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 2e0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 320 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 360 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 3a0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 3e0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 420 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 460 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 4a0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 4e0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 520 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 560 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 5f0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 630 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 670 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 6b0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 6f0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 730 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 770 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 7b0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 7f0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 830 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 870 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 8b0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 8f0 /usr/local/bin/ld: error: /tmp/ccFdAbSm.o: failed to match split-stack sequence at section 4 offset 1130 collect2: error: ld returned 1 exit status make[2]: *** [Makefile:830: buildid] Error 1 make[2]: *** Waiting for unfinished jobs.... </lit></quote> Investigation shows that ONLY removing '-fcf-protection' flag allows the above command line to succeed with no errors or warnings. I guess this COULD be either a GCC 12 bug, with gcc somehow putting the wrong / incorrect information into objs for '-fcf-protection', OR binutils's 'ld' is somehow interpreting this information incorrectly. This is most annoying, as everything else about the build worked perfectly. I will investigate to see if I can pin down precisely what -fcf-protection information is being inserted and if / how it is incorrect or ld is mis-interpreting it, unless anyone might know and would please tell me ?
Also, doing this, as root, solves the problem: $ cd /usr/local/bin $ mv ld not-ld $ ln -s /opt/rh/gcc-toolset-11/root/usr/bin/ld ld So this is why I raised the bug against binutils 2.38 in the first instance - it DOES NOT happen with ld 2.35 , ie. WITH '-fcf-protection' ld 2.35 handles the same command line fine. So this IS a bug with ld v2.38, and a regression, OR the RedHat distro maintainers have somehow messed up ld v2.38 with their patches... Investigating ...
Does NOT happen when option is changed from '-fcf-protection' to '-fcf-protection=check' - '-fcf-protection=branch' and '-fcf-protection=full' also trigger the bug. So I COULD make GCC use this option instead, and rebuild, but it is a shame to have to do this to workaround this bug in ld 2.38 (I think it is using ld.gold for this under the hood - the '-fcf-protection' code only seems to be in the 'gold' source ?
OK, as root, if I install the binutils-local-debuginfo and binutils-local-gold debuginfo RPMs, I can do : $ cd /usr/local/bin $ mv ld ld.bin $ echo '#!/bin/bash /usr/bin/gdb -q --batch-silent -ex 'set breakpoint pending on' -ex 'b x86_64.cc:6113' -ex run --args /usr/local/bin/ld.bin "$@" To make gdb load debuginfo for 'ld' and break at the point in binutils' gold/x86_64.cc where it is about to log the error message: template<int size> void Target_x86_64<size>::do_calls_non_split(Relobj* object, unsigned int shndx, section_offset_type fnoffset, section_size_type fnsize, const unsigned char*, size_t, unsigned char* view, section_size_type view_size, std::string* from, std::string* to) const { const char* const cmp_insn = reinterpret_cast<const char*> (size == 32 ? cmp_insn_32 : cmp_insn_64); const char* const lea_r10_insn = reinterpret_cast<const char*> (size == 32 ? lea_r10_insn_32 : lea_r10_insn_64); const char* const lea_r11_insn = reinterpret_cast<const char*> (size == 32 ? lea_r11_insn_32 : lea_r11_insn_64); const size_t cmp_insn_len = (size == 32 ? sizeof(cmp_insn_32) : sizeof(cmp_insn_64)); const size_t lea_r10_insn_len = (size == 32 ? sizeof(lea_r10_insn_32) : sizeof(lea_r10_insn_64)); const size_t lea_r11_insn_len = (size == 32 ? sizeof(lea_r11_insn_32) : sizeof(lea_r11_insn_64)); const size_t nop_len = (size == 32 ? 7 : 8); // The function starts with a comparison of the stack pointer and a // field in the TCB. This is followed by a jump. // cmp %fs:NN,%rsp if (this->match_view(view, view_size, fnoffset, cmp_insn, cmp_insn_len) && fnsize > nop_len + 1) { // We will call __morestack if the carry flag is set after this // comparison. We turn the comparison into an stc instruction // and some nops. view[fnoffset] = '\xf9'; this->set_view_to_nop(view, view_size, fnoffset + 1, nop_len); } // lea NN(%rsp),%r10 // lea NN(%rsp),%r11 else if ((this->match_view(view, view_size, fnoffset, lea_r10_insn, lea_r10_insn_len) || this->match_view(view, view_size, fnoffset, lea_r11_insn, lea_r11_insn_len)) && fnsize > 8) { // This is loading an offset from the stack pointer for a // comparison. The offset is negative, so we decrease the // offset by the amount of space we need for the stack. This // means we will avoid calling __morestack if there happens to // be plenty of space on the stack already. unsigned char* pval = view + fnoffset + 4; uint32_t val = elfcpp::Swap_unaligned<32, false>::readval(pval); val -= parameters->options().split_stack_adjust_size(); elfcpp::Swap_unaligned<32, false>::writeval(pval, val); } else { if (!object->has_no_split_stack()) /*LINE #6113:*/object->error(_("failed to match split-stack sequence at " "section %u offset %0zx"), shndx, static_cast<size_t>(fnoffset)); return; } // We have to change the function so that it calls // __morestack_non_split instead of __morestack. The former will // allocate additional stack space. *from = "__morestack"; *to = "__morestack_non_split"; } AARGH ! The bug does NOT happen when I run ld this way under GDB - the command works ! That was most unexpected. I am now going to have to rebuild ld/gold with line 6113 modified to be: object->error(_("failed to match split-stack sequence at " "section %u offset %0zx - r10:%c r11:%c fnsize: %u"), shndx, static_cast<size_t>(fnoffset) , this->match_view(view, view_size, fnoffset, lea_r10_insn, lea_r10_insn_len ) ? '1' : '0' , this->match_view(view, view_size, fnoffset, lea_r11_insn, lea_r11_insn_len && fnsize > 8) );
Oops, had not finished editing last line of previous comment: gold/x86_64.c, line 6113 will become: object->error(_("failed to match split-stack sequence at " "section %u offset %0zx - r10:%c r11:%c fnsize: %u"), shndx, static_cast<size_t>(fnoffset) , this->match_view(view, view_size, fnoffset, lea_r10_insn, lea_r10_insn_len ) ? '1' : '0' , this->match_view(view, view_size, fnoffset, lea_r11_insn, lea_r11_insn_len ) ? '1' : '0' , static_cast<uint32_t>(fnsize) ); With ld/gold augmented to print that under those circumstances, then we should be a bit further forward in understanding what is going on here. The fact that it strangely WORKS when run under the old binutils-2.35 using gdb (I have not got round to building latest gdb yet, was going to do that with GCC 12), DOES indicate something rather strange and subtle is going on here.
OK, with binutils 's gold/ld-new and libbfd recompiled with the above error statement in gold/x86_64.cc, we get: /usr/local/bin/ld: Unlocking file "/home/jvd/rpmbuild/BUILD/gcc-12.1.1-20220507/obj-x86_64-redhat-linux/./gcc/libgcc.a" /usr/local/bin/ld: Closed descriptor 5 for "/home/jvd/rpmbuild/BUILD/gcc-12.1.1-20220507/obj-x86_64-redhat-linux/./gcc/libgcc_eh.a" /usr/local/bin/ld: Opened new descriptor 4 for "cgo" /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 540 r10:0 r11:0 115 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 660 r10:0 r11:0 93 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 7e0 r10:0 r11:0 204 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 8b0 r10:0 r11:0 191 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 970 r10:0 r11:0 177 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset a30 r10:0 r11:0 369 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset bb0 r10:0 r11:0 161 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset c60 r10:0 r11:0 118 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset ce0 r10:0 r11:0 132 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset d70 r10:0 r11:0 135 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset ec0 r10:0 r11:0 2625 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 1910 r10:0 r11:0 240 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 1a00 r10:0 r11:0 240 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 1af0 r10:0 r11:0 102 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 1c70 r10:0 r11:0 218 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 1d50 r10:0 r11:0 395 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 1ee0 r10:0 r11:0 277 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 2390 r10:0 r11:0 3519 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 3150 r10:0 r11:0 263 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 3260 r10:0 r11:0 204 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 3330 r10:0 r11:0 282 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 3450 r10:0 r11:0 296 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 3580 r10:0 r11:0 68 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 35d0 r10:0 r11:0 428 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 39f0 r10:0 r11:0 228 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 3b70 r10:0 r11:0 1496 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 4150 r10:0 r11:0 1421 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 4780 r10:0 r11:0 4649 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 59b0 r10:0 r11:0 304 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 5b90 r10:0 r11:0 1194 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 6040 r10:0 r11:0 469 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 6220 r10:0 r11:0 401 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 6480 r10:0 r11:0 1505 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 6a70 r10:0 r11:0 175 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 6b20 r10:0 r11:0 205 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 6bf0 r10:0 r11:0 4529 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 7db0 r10:0 r11:0 542 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 7fd0 r10:0 r11:0 344 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 8130 r10:0 r11:0 179 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 81f0 r10:0 r11:0 360 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 8360 r10:0 r11:0 1810 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 8a80 r10:0 r11:0 411 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 8c20 r10:0 r11:0 56 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 8c60 r10:0 r11:0 1838 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 938e r10:0 r11:0 68 /usr/local/bin/ld: error: /tmp/ccAgu0zM.o: failed to match split-stack sequence at section 265 offset 93d2 r10:0 r11:0 68 So yes, it is neither an lea_r10_insn nor an lea_r10_insn, and fnsize appears always to be > 8, so the logic there definitely needs improvement - lack masking out the register number in the instruction, so that ANY 'lea' instruction would trigger insertion of correct code ? I will try to get it to break there now and see if I can get it to print what the instruction actually is, in /home/jvd/rpmbuild/BUILD/gcc-12.1.1-20220507/obj-x86_64-redhat-linux/./gcc/libgcc_eh.a, that is causing this issue.
OK, now the error message printing code looks like this: { if (!object->has_no_split_stack()) { unsigned char ib[16]={0}; if ( view ) { ib[0] = *(((unsigned char*)view) + fnoffset); ib[1] = *(((unsigned char*)view) + fnoffset + 1); ib[2] = *(((unsigned char*)view) + fnoffset + 2); ib[3] = *(((unsigned char*)view) + fnoffset + 3); } object->error(_("failed to match split-stack sequence at " "section %u offset %0zx r10:%c r11:%c %u %2.2hhx.%2.2hhx.%2.2hhx.%2.2hhx"), shndx, static_cast<size_t>(fnoffset) , (this->match_view(view, view_size, fnoffset, lea_r10_insn, lea_r10_insn_len ) ? '1' : '0' ) , (this->match_view(view, view_size, fnoffset, lea_r11_insn, lea_r11_insn_len ) ? '1' : '0' ) , static_cast<uint32_t>(fnsize) , ib[0], ib[1], ib[2], ib[3] ); } return; So we will see what instruction is actually at 'view + fnoffset' in gcc 12's libgcc_eh.a : /usr/local/bin/ld: Unlocking file "/home/jvd/rpmbuild/BUILD/gcc-12.1.1-20220507/obj-x86_64-redhat-linux/./gcc/libgcc.a" /usr/local/bin/ld: Closed descriptor 5 for "/home/jvd/rpmbuild/BUILD/gcc-12.1.1-20220507/obj-x86_64-redhat-linux/./gcc/libgcc_eh.a" /usr/local/bin/ld: Opened new descriptor 4 for "cgo" /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 540 r10:0 r11:0 115 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 660 r10:0 r11:0 93 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 7e0 r10:0 r11:0 204 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 8b0 r10:0 r11:0 191 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 970 r10:0 r11:0 177 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset a30 r10:0 r11:0 369 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset bb0 r10:0 r11:0 161 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset c60 r10:0 r11:0 118 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset ce0 r10:0 r11:0 132 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset d70 r10:0 r11:0 135 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset ec0 r10:0 r11:0 2625 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 1910 r10:0 r11:0 240 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 1a00 r10:0 r11:0 240 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 1af0 r10:0 r11:0 102 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 1c70 r10:0 r11:0 218 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 1d50 r10:0 r11:0 395 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 1ee0 r10:0 r11:0 277 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 2390 r10:0 r11:0 3519 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 3150 r10:0 r11:0 263 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 3260 r10:0 r11:0 204 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 3330 r10:0 r11:0 282 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 3450 r10:0 r11:0 296 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 3580 r10:0 r11:0 68 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 35d0 r10:0 r11:0 428 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 39f0 r10:0 r11:0 228 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 3b70 r10:0 r11:0 1496 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 4150 r10:0 r11:0 1421 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 4780 r10:0 r11:0 4649 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 59b0 r10:0 r11:0 304 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 5b90 r10:0 r11:0 1194 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 6040 r10:0 r11:0 469 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 6220 r10:0 r11:0 401 f3.0f.1e.fa /usr/local/bin/ld: error: /tmp/ccGv8QZX.o: failed to match split-stack sequence at section 265 offset 6480 r10:0 r11:0 1505 f3.0f.1e.fa ... Aha, so the instruction that causes the problem is (in hex) 'f3.0f.1e.fa' ? I will look this up in my Intel SDM . Maybe ld should make an exception for this sequence ? it always appears to be the same in every occurrence of this issue.
Aha! Am I right in thinking 'f3.0f.1e.fa' (hex byte string) specifies x86_64 instruction 'RDSSPD/RDSSPQ' ? I think so ! : From Intel Software Developer's Manual (SDM), Book 2, Instructions, Chapter 3, Instruction Set Reference, page Vol-2B,4-553 (pp.1735) : " RDSSPD/RDSSPQ—Read Shadow Stack Pointer Opcode/ Op/ 64/32 CPUID F3 0F 1E /1 (mod=11) R V/V CET_SS Copy low 32 bits of shadow stack pointer (SSP) to r32. RDSSPD r32 F3 REX.W 0F 1E /1 (mod=11) R V/N.E. CET_SS Copies shadow stack pointer (SSP) to r64. RDSSPQ r64 " So, then maybe the code should take this as an indication that the job has been done OK and so NOT to raise an error here ?
So my best guess at a patch would currently be: $ diff -U1 x86_64.cc~ x86_64.cc --- x86_64.cc~ 2022-01-22 12:14:09.000000000 +0000 +++ x86_64.cc 2022-06-05 17:34:26.400079527 +0100 @@ -6050,2 +6050,3 @@ static const unsigned char lea_r11_insn_64[] = { 0x4c, 0x8d, 0x9c, 0x24 }; +static const unsigned char rdssp_insn_64[] = { 0xf3, 0x0f, 0x1e, 0xfa }; @@ -6077,3 +6078,3 @@ const size_t nop_len = (size == 32 ? 7 : 8); - + const size_t rdssp_insn_len = 4; // The function starts with a comparison of the stack pointer and a @@ -6111,7 +6112,28 @@ { - if (!object->has_no_split_stack()) + if ( (!object->has_no_split_stack()) + &&(!this_match_view( view, view_size, fnoffset, rdssp_insn, rdssp_insn_len)) + ) + { unsigned char ib[16]={0}; + if ( view ) + { ib[0] = *(((unsigned char*)view) + fnoffset); + ib[1] = *(((unsigned char*)view) + fnoffset + 1); + ib[2] = *(((unsigned char*)view) + fnoffset + 2); + ib[3] = *(((unsigned char*)view) + fnoffset + 3); + } object->error(_("failed to match split-stack sequence at " - "section %u offset %0zx"), - shndx, static_cast<size_t>(fnoffset)); - return; + "section %u offset %0zx r10:%c r11:%c %u %2.2hhx.%2.2hhx.%2.2hhx.%2.2hhx"), + shndx, static_cast<size_t>(fnoffset) + , (this->match_view(view, view_size, fnoffset, + lea_r10_insn, lea_r10_insn_len + ) ? '1' : '0' + ) + , (this->match_view(view, view_size, fnoffset, + lea_r11_insn, lea_r11_insn_len + ) ? '1' : '0' + ) + , static_cast<uint32_t>(fnsize) + , ib[0], ib[1], ib[2], ib[3] + ); + return; + } }
Oops, a better patch is given by : $ gendiff gold \~ --- BEGIN PATCH diff -up gold/i386.cc~ gold/i386.cc --- gold/i386.cc~ 2022-06-05 02:23:38.826984954 +0100 +++ gold/i386.cc 2022-06-05 17:44:30.359415929 +0100 @@ -4191,10 +4191,31 @@ Target_i386::do_calls_non_split(Relobj* } else { - if (!object->has_no_split_stack()) + if ((!object->has_no_split_stack()) && + (!this->match_view(view, view_size, fnoffset, "\xf3\x0f\x1e", 3)) + ) + { unsigned char ib[16]={0}; + if ( view ) + { ib[0] = *(((unsigned char*)view) + fnoffset); + ib[1] = *(((unsigned char*)view) + fnoffset + 1); + ib[2] = *(((unsigned char*)view) + fnoffset + 2); + ib[3] = *(((unsigned char*)view) + fnoffset + 3); + } object->error(_("failed to match split-stack sequence at " - "section %u offset %0zx"), - shndx, static_cast<size_t>(fnoffset)); + "section %u offset %0zx #1:%c #2:%c %u %2.2hhx.%2.2hhx.%2.2hhx.%2.2hhx"), + shndx, static_cast<size_t>(fnoffset) + , (this->match_view(view, view_size, fnoffset, + "\x8d\x8c\x24", 3 + ) ? '1' : '0' + ) + , (this->match_view(view, view_size, fnoffset, + "\x8d\x8c\x94", 3 + ) ? '1' : '0' + ) + , static_cast<uint32_t>(fnsize) + , ib[0], ib[1], ib[2], ib[3] + ); + } return; } diff -up gold/x86_64.cc~ gold/x86_64.cc --- gold/x86_64.cc~ 2022-01-22 12:14:09.000000000 +0000 +++ gold/x86_64.cc 2022-06-05 17:52:24.813322107 +0100 @@ -6044,10 +6044,12 @@ Target_x86_64<size>::do_ehframe_datarel_ static const unsigned char cmp_insn_32[] = { 0x64, 0x3b, 0x24, 0x25 }; static const unsigned char lea_r10_insn_32[] = { 0x44, 0x8d, 0x94, 0x24 }; static const unsigned char lea_r11_insn_32[] = { 0x44, 0x8d, 0x9c, 0x24 }; +static const unsigned char rdssp_insn_32[] = { 0xf3, 0x0f, 0x1e, 0xfa }; static const unsigned char cmp_insn_64[] = { 0x64, 0x48, 0x3b, 0x24, 0x25 }; static const unsigned char lea_r10_insn_64[] = { 0x4c, 0x8d, 0x94, 0x24 }; static const unsigned char lea_r11_insn_64[] = { 0x4c, 0x8d, 0x9c, 0x24 }; +static const unsigned char rdssp_insn_64[] = { 0xf3, 0x0f, 0x1e, 0xfa }; template<int size> void @@ -6067,7 +6069,9 @@ Target_x86_64<size>::do_calls_non_split( (size == 32 ? lea_r10_insn_32 : lea_r10_insn_64); const char* const lea_r11_insn = reinterpret_cast<const char*> (size == 32 ? lea_r11_insn_32 : lea_r11_insn_64); - + const char* const rdssp_insn = reinterpret_cast<const char*> + (size == 32 ? rdssp_insn_32 : rdssp_insn_64); + const size_t cmp_insn_len = (size == 32 ? sizeof(cmp_insn_32) : sizeof(cmp_insn_64)); const size_t lea_r10_insn_len = @@ -6075,6 +6079,7 @@ Target_x86_64<size>::do_calls_non_split( const size_t lea_r11_insn_len = (size == 32 ? sizeof(lea_r11_insn_32) : sizeof(lea_r11_insn_64)); const size_t nop_len = (size == 32 ? 7 : 8); + const size_t rdssp_insn_len = 4; // The function starts with a comparison of the stack pointer and a // field in the TCB. This is followed by a jump. @@ -6109,10 +6114,31 @@ Target_x86_64<size>::do_calls_non_split( } else { - if (!object->has_no_split_stack()) + if ( (!object->has_no_split_stack()) + &&(!this->match_view( view, view_size, fnoffset, rdssp_insn, rdssp_insn_len)) + ) + { unsigned char ib[16]={0}; + if ( view ) + { ib[0] = *(((unsigned char*)view) + fnoffset); + ib[1] = *(((unsigned char*)view) + fnoffset + 1); + ib[2] = *(((unsigned char*)view) + fnoffset + 2); + ib[3] = *(((unsigned char*)view) + fnoffset + 3); + } object->error(_("failed to match split-stack sequence at " - "section %u offset %0zx"), - shndx, static_cast<size_t>(fnoffset)); + "section %u offset %0zx r10:%c r11:%c %u %2.2hhx.%2.2hhx.%2.2hhx.%2.2hhx"), + shndx, static_cast<size_t>(fnoffset) + , (this->match_view(view, view_size, fnoffset, + lea_r10_insn, lea_r10_insn_len + ) ? '1' : '0' + ) + , (this->match_view(view, view_size, fnoffset, + lea_r11_insn, lea_r11_insn_len + ) ? '1' : '0' + ) + , static_cast<uint32_t>(fnsize) + , ib[0], ib[1], ib[2], ib[3] + ); + } return; } ---END PATCH
OK, I am now running the full binutils test suite with the above patch applied, which DOES at least make the gcc build now work OK.
Hmm, close but no cigar - the test suite now bombs out at : `echo g++ -W -Wall -Wstack-usage=262144 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fmerge-constants -O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fno-use-linker-plugin -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,--enable-new-dtags -o copy_test_2.so | sed -e 's/\([^ ]*\)\(.*\)/\1 -Bgcctestdir\/\2/' -e 's/-Wp,-D_FORTIFY_SOURCE=[0-9][0-9]*//'` -shared copy_test_2_pic.o CXXLD copy_test gcctestdir/collect-ld: error: /tmp/cch1aq9d.ltrans0.ltrans.o: cannot make copy relocation for protected symbol 'ip', defined in copy_test_2.so collect2: error: ld returned 1 exit status
I will try with the last 'return' INSIDE the clause: + ); + return; + } }
OK, I discovered the SAME test fails completely without either of my patches, but BOTH allow the particular GCC build I was trying to succeed - I'm going with the last one : ---BEGIN PATCH diff -up gold/i386.cc~ gold/i386.cc --- gold/i386.cc~ 2022-06-05 02:23:38.826984954 +0100 +++ gold/i386.cc 2022-06-05 18:16:55.215927752 +0100 @@ -4190,12 +4190,34 @@ Target_i386::do_calls_non_split(Relobj* elfcpp::Swap_unaligned<32, false>::writeval(pval, val); } else - { - if (!object->has_no_split_stack()) + { bool is_rdssp = this->match_view(view, view_size, fnoffset, "\xf3\x0f\x1e", 3); + if ((!object->has_no_split_stack()) && + !is_rdssp + ) + { unsigned char ib[16]={0}; + if ( view ) + { ib[0] = *(((unsigned char*)view) + fnoffset); + ib[1] = *(((unsigned char*)view) + fnoffset + 1); + ib[2] = *(((unsigned char*)view) + fnoffset + 2); + ib[3] = *(((unsigned char*)view) + fnoffset + 3); + } object->error(_("failed to match split-stack sequence at " - "section %u offset %0zx"), - shndx, static_cast<size_t>(fnoffset)); - return; + "section %u offset %0zx #1:%c #2:%c %u %2.2hhx.%2.2hhx.%2.2hhx.%2.2hhx"), + shndx, static_cast<size_t>(fnoffset) + , (this->match_view(view, view_size, fnoffset, + "\x8d\x8c\x24", 3 + ) ? '1' : '0' + ) + , (this->match_view(view, view_size, fnoffset, + "\x8d\x8c\x94", 3 + ) ? '1' : '0' + ) + , static_cast<uint32_t>(fnsize) + , ib[0], ib[1], ib[2], ib[3] + ); + } + if ( ! is_rdssp ) + return; } // We have to change the function so that it calls diff -up gold/x86_64.cc~ gold/x86_64.cc --- gold/x86_64.cc~ 2022-01-22 12:14:09.000000000 +0000 +++ gold/x86_64.cc 2022-06-05 18:13:08.085938171 +0100 @@ -6044,10 +6044,12 @@ Target_x86_64<size>::do_ehframe_datarel_ static const unsigned char cmp_insn_32[] = { 0x64, 0x3b, 0x24, 0x25 }; static const unsigned char lea_r10_insn_32[] = { 0x44, 0x8d, 0x94, 0x24 }; static const unsigned char lea_r11_insn_32[] = { 0x44, 0x8d, 0x9c, 0x24 }; +static const unsigned char rdssp_insn_32[] = { 0xf3, 0x0f, 0x1e, 0xfa }; static const unsigned char cmp_insn_64[] = { 0x64, 0x48, 0x3b, 0x24, 0x25 }; static const unsigned char lea_r10_insn_64[] = { 0x4c, 0x8d, 0x94, 0x24 }; static const unsigned char lea_r11_insn_64[] = { 0x4c, 0x8d, 0x9c, 0x24 }; +static const unsigned char rdssp_insn_64[] = { 0xf3, 0x0f, 0x1e, 0xfa }; template<int size> void @@ -6067,7 +6069,9 @@ Target_x86_64<size>::do_calls_non_split( (size == 32 ? lea_r10_insn_32 : lea_r10_insn_64); const char* const lea_r11_insn = reinterpret_cast<const char*> (size == 32 ? lea_r11_insn_32 : lea_r11_insn_64); - + const char* const rdssp_insn = reinterpret_cast<const char*> + (size == 32 ? rdssp_insn_32 : rdssp_insn_64); + const size_t cmp_insn_len = (size == 32 ? sizeof(cmp_insn_32) : sizeof(cmp_insn_64)); const size_t lea_r10_insn_len = @@ -6075,6 +6079,7 @@ Target_x86_64<size>::do_calls_non_split( const size_t lea_r11_insn_len = (size == 32 ? sizeof(lea_r11_insn_32) : sizeof(lea_r11_insn_64)); const size_t nop_len = (size == 32 ? 7 : 8); + const size_t rdssp_insn_len = 4; // The function starts with a comparison of the stack pointer and a // field in the TCB. This is followed by a jump. @@ -6108,12 +6113,34 @@ Target_x86_64<size>::do_calls_non_split( elfcpp::Swap_unaligned<32, false>::writeval(pval, val); } else - { - if (!object->has_no_split_stack()) + { bool is_rdssp = this->match_view( view, view_size, fnoffset, rdssp_insn, rdssp_insn_len); + if ( (!object->has_no_split_stack()) + && !is_rdssp + ) + { unsigned char ib[16]={0}; + if ( view ) + { ib[0] = *(((unsigned char*)view) + fnoffset); + ib[1] = *(((unsigned char*)view) + fnoffset + 1); + ib[2] = *(((unsigned char*)view) + fnoffset + 2); + ib[3] = *(((unsigned char*)view) + fnoffset + 3); + } object->error(_("failed to match split-stack sequence at " - "section %u offset %0zx"), - shndx, static_cast<size_t>(fnoffset)); - return; + "section %u offset %0zx r10:%c r11:%c %u %2.2hhx.%2.2hhx.%2.2hhx.%2.2hhx"), + shndx, static_cast<size_t>(fnoffset) + , (this->match_view(view, view_size, fnoffset, + lea_r10_insn, lea_r10_insn_len + ) ? '1' : '0' + ) + , (this->match_view(view, view_size, fnoffset, + lea_r11_insn, lea_r11_insn_len + ) ? '1' : '0' + ) + , static_cast<uint32_t>(fnsize) + , ib[0], ib[1], ib[2], ib[3] + ); + } + if( !is_rdssp ) + return; } // We have to change the function so that it calls ---END PATCH
Created attachment 14130 [details] binutils-local.spec OK, CC'ing the RedHat maintainer on this - I do think this is a bug, and it DOES appear to be fixed by the attached 'binutils-2.38-bug29226.patch', which was successfully applied by the modified binutils-2.38-14.fc37.src.rpm spec file , also attached : 'binutils-local.spec', which ran all its tests successfully with the patch applied, and 'gcc-local.spec', which finally was able to use the patched binutils 2.38 to build everything. Note also that the 'gcc12-libtool-no-rpath.patch' file is also owned by the gcc SRPM, so if both SRPMs are installed, one file gets overwritten by the other, which failed the binutils build after the gcc SRPM is installed - so I renamed the binutils version 'binutils-2.38-libtool-no-rpath.patch' (also attached). The problem was also that the install scripts get confused by presence of /usr/bin/ld, and do not install /usr/local/bin/ld, if /usr/bin/ld exists, so I mistakenly linked 'ld.gold' to ld, leading me to discover the bug in the first place . I am fixing that in my binutils-local spec file. Anyway, GCC now builds either with my patched ld.gold, or with the proper 'ld' binary produced by the same build. Please review the attached patch to gold/i386.cc and gold/x86_64.cc - should they be returning WITHOUT changing the strings, or WITH changing the strings, IFF we discover that the view+offset points to an 'rdssp' instruction ? Best Regards, Jason Vas Dias, a Software+Embedded Systems (VOIP) Engineer, West Cork, Ireland +353 84 874 9040 On 05/06/2022, jason.vas.dias at gmail dot com <sourceware-bugzilla@sourceware.org> wrote: > https://sourceware.org/bugzilla/show_bug.cgi?id=29226 > > Jason Vas Dias <jason.vas.dias at gmail dot com> changed: > > What |Removed |Added > ---------------------------------------------------------------------------- > Priority|P2 |P1 > CC| |jason.vas.dias at gmail dot > com > > --- Comment #13 from Jason Vas Dias <jason.vas.dias at gmail dot com> --- > OK, I discovered the SAME test fails completely without either of my > patches, but BOTH allow the particular GCC build I was trying to succeed - > I'm going with the last one : > > ---BEGIN PATCH > diff -up gold/i386.cc~ gold/i386.cc > --- gold/i386.cc~ 2022-06-05 02:23:38.826984954 +0100 > +++ gold/i386.cc 2022-06-05 18:16:55.215927752 +0100 > @@ -4190,12 +4190,34 @@ Target_i386::do_calls_non_split(Relobj* > elfcpp::Swap_unaligned<32, false>::writeval(pval, val); > } > else > - { > - if (!object->has_no_split_stack()) > + { bool is_rdssp = this->match_view(view, view_size, fnoffset, > "\xf3\x0f\x1e", 3); > + if ((!object->has_no_split_stack()) && > + !is_rdssp > + ) > + { unsigned char ib[16]={0}; > + if ( view ) > + { ib[0] = *(((unsigned char*)view) + fnoffset); > + ib[1] = *(((unsigned char*)view) + fnoffset + 1); > + ib[2] = *(((unsigned char*)view) + fnoffset + 2); > + ib[3] = *(((unsigned char*)view) + fnoffset + 3); > + } > object->error(_("failed to match split-stack sequence at " > - "section %u offset %0zx"), > - shndx, static_cast<size_t>(fnoffset)); > - return; > + "section %u offset %0zx #1:%c #2:%c %u > %2.2hhx.%2.2hhx.%2.2hhx.%2.2hhx"), > + shndx, static_cast<size_t>(fnoffset) > + , (this->match_view(view, view_size, fnoffset, > + "\x8d\x8c\x24", 3 > + ) ? '1' : '0' > + ) > + , (this->match_view(view, view_size, fnoffset, > + "\x8d\x8c\x94", 3 > + ) ? '1' : '0' > + ) > + , static_cast<uint32_t>(fnsize) > + , ib[0], ib[1], ib[2], ib[3] > + ); > + } > + if ( ! is_rdssp ) > + return; > } > > // We have to change the function so that it calls > diff -up gold/x86_64.cc~ gold/x86_64.cc > --- gold/x86_64.cc~ 2022-01-22 12:14:09.000000000 +0000 > +++ gold/x86_64.cc 2022-06-05 18:13:08.085938171 +0100 > @@ -6044,10 +6044,12 @@ Target_x86_64<size>::do_ehframe_datarel_ > static const unsigned char cmp_insn_32[] = { 0x64, 0x3b, 0x24, 0x25 }; > static const unsigned char lea_r10_insn_32[] = { 0x44, 0x8d, 0x94, 0x24 }; > static const unsigned char lea_r11_insn_32[] = { 0x44, 0x8d, 0x9c, 0x24 }; > +static const unsigned char rdssp_insn_32[] = { 0xf3, 0x0f, 0x1e, 0xfa }; > > static const unsigned char cmp_insn_64[] = { 0x64, 0x48, 0x3b, 0x24, 0x25 > }; > static const unsigned char lea_r10_insn_64[] = { 0x4c, 0x8d, 0x94, 0x24 }; > static const unsigned char lea_r11_insn_64[] = { 0x4c, 0x8d, 0x9c, 0x24 }; > +static const unsigned char rdssp_insn_64[] = { 0xf3, 0x0f, 0x1e, 0xfa }; > > template<int size> > void > @@ -6067,7 +6069,9 @@ Target_x86_64<size>::do_calls_non_split( > (size == 32 ? lea_r10_insn_32 : lea_r10_insn_64); > const char* const lea_r11_insn = reinterpret_cast<const char*> > (size == 32 ? lea_r11_insn_32 : lea_r11_insn_64); > - > + const char* const rdssp_insn = reinterpret_cast<const char*> > + (size == 32 ? rdssp_insn_32 : rdssp_insn_64); > + > const size_t cmp_insn_len = > (size == 32 ? sizeof(cmp_insn_32) : sizeof(cmp_insn_64)); > const size_t lea_r10_insn_len = > @@ -6075,6 +6079,7 @@ Target_x86_64<size>::do_calls_non_split( > const size_t lea_r11_insn_len = > (size == 32 ? sizeof(lea_r11_insn_32) : sizeof(lea_r11_insn_64)); > const size_t nop_len = (size == 32 ? 7 : 8); > + const size_t rdssp_insn_len = 4; > > // The function starts with a comparison of the stack pointer and a > // field in the TCB. This is followed by a jump. > @@ -6108,12 +6113,34 @@ Target_x86_64<size>::do_calls_non_split( > elfcpp::Swap_unaligned<32, false>::writeval(pval, val); > } > else > - { > - if (!object->has_no_split_stack()) > + { bool is_rdssp = this->match_view( view, view_size, fnoffset, > rdssp_insn, > rdssp_insn_len); > + if ( (!object->has_no_split_stack()) > + && !is_rdssp > + ) > + { unsigned char ib[16]={0}; > + if ( view ) > + { ib[0] = *(((unsigned char*)view) + fnoffset); > + ib[1] = *(((unsigned char*)view) + fnoffset + 1); > + ib[2] = *(((unsigned char*)view) + fnoffset + 2); > + ib[3] = *(((unsigned char*)view) + fnoffset + 3); > + } > object->error(_("failed to match split-stack sequence at " > - "section %u offset %0zx"), > - shndx, static_cast<size_t>(fnoffset)); > - return; > + "section %u offset %0zx r10:%c r11:%c %u > %2.2hhx.%2.2hhx.%2.2hhx.%2.2hhx"), > + shndx, static_cast<size_t>(fnoffset) > + , (this->match_view(view, view_size, fnoffset, > + lea_r10_insn, lea_r10_insn_len > + ) ? '1' : '0' > + ) > + , (this->match_view(view, view_size, fnoffset, > + lea_r11_insn, lea_r11_insn_len > + ) ? '1' : '0' > + ) > + , static_cast<uint32_t>(fnsize) > + , ib[0], ib[1], ib[2], ib[3] > + ); > + } > + if( !is_rdssp ) > + return; > } > > // We have to change the function so that it calls > ---END PATCH > > -- > You are receiving this mail because: > You are on the CC list for the bug. > You reported the bug.
Created attachment 14131 [details] gcc-12-local.spec
Created attachment 14132 [details] binutils-2.38-bug29226.patch
Created attachment 14133 [details] binutils-2.38-gcc12-libtool-no-rpath.patch
I don't really see what CET has to do with split stack, so I would guess that, with CET enabled, the RDSSPD/Q instruction gets generated before the CMP or LEA instruction that we're expecting as the start of the split stack sequence. I don't think it's safe to assume that the presence of the RDSSPD/Q means that the split stack check is already done. More likely, you'd need to look for the CMP or LEA instruction following the shadow stack pointer check. But I'm not familiar enough with either CET or split-stack to be sure. Ian, can you please take a look?