bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/29226] gcc -fcf-protection option causes GCC 12 gccgo build to f


From: jason.vas.dias at gmail dot com
Subject: [Bug ld/29226] gcc -fcf-protection option causes GCC 12 gccgo build to fail : "failed to match split-stack sequence"
Date: Sun, 05 Jun 2022 14:29:12 +0000

https://sourceware.org/bugzilla/show_bug.cgi?id=29226

--- Comment #3 from Jason Vas Dias <jason.vas.dias at gmail dot com> ---
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)
             );

-- 
You are receiving this mail because:
You are on the CC list for the bug.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]