https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128136

            Bug ID: 128136
           Summary: x86-64: wrong code at -O1 and above: a __seg_gs load
                    returns the value just stored through __seg_fs at the
                    same offset
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kyuwoncho18 at gmail dot com
  Target Milestone: ---
            Target: x86_64-pc-linux-gnu

#include <asm/prctl.h>
#include <sys/syscall.h>
#include <unistd.h>

int x, y = 2;

__attribute__((noinline)) int f(unsigned long p)
{
  *(int __seg_fs *)p = 1;
  return *(int __seg_gs *)p;
}

int main(void)
{
  unsigned long fs;
  syscall(SYS_arch_prctl, ARCH_GET_FS, &fs);
  unsigned long p = (unsigned long)&x - fs;
  syscall(SYS_arch_prctl, ARCH_SET_GS, (unsigned long)&y - p);
  if (f(p) != 2)
    __builtin_abort();
}

godbolt: https://godbolt.org/z/Ef8cb71TP

The store writes FS base + p, which is x, and the load reads GS base + p, which
is y (the GS base is installed with arch_prctl), so f must return 2 and the
program must exit normally, as it does at -O0 and with -O2 -fno-dse. At -O1,
-O2, -O3 and -Os the load is replaced by the stored constant (f is movl $1,
%fs:(%rdi); movl $1, %eax; ret), f returns 1, and the program aborts.
  • [Bug rtl-optimization/128136] Ne... kyuwoncho18 at gmail dot com via Gcc-bugs

Reply via email to