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

            Bug ID: 128015
           Summary: [x86] sgxintrin.h: __enclv_generic binds "=c" to b
                    instead of c
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: 220245569 at seu dot edu.cn
                CC: jianhao.xu at seu dot edu.cn
  Target Milestone: ---

Summary
-------
In `gcc/config/i386/sgxintrin.h:106`, the `__enclv_generic` macro has a typo
in its extended asm output constraints:

#define __enclv_generic(leaf, b, c, d, retval)          \
  __asm__ __volatile__("enclv\n\t"                      \
           : "=a" (retval), "=b" (b), "=c" (b), "=d" (d)\
           : "a" (leaf), "b" (b), "c" (c), "d" (d)      \
           : "cc")

The third output constraint is written as `"=c" (b)` instead of `"=c" (c)`.
Comparing with `__encls_generic` (line 58) and `__enclu_generic` (line 88),
both correctly bind `"=c"` to `(c)`.

Because both `"=b"` and `"=c"` are bound to the same lvalue `b` (the `D[0]`
slot), the compiler emits code storing `%rcx` into `D[0]`, clobbering the
value from `%rbx`. Meanwhile, `c` (`D[1]`) receives no store at all.
When calling `_enclv_u32` with a non-constant leaf or a generic leaf, this
silently corrupts `D[0]` and fails to return `D[1]`.

Reproducer
----------
$ cat trigger.c
#include <x86intrin.h>

extern unsigned int leaf;

unsigned long f(void) {
    size_t d[3] = { 0x1111UL, 0x2222UL, 0x3333UL };
    _enclv_u32(leaf, d);
    return d[0]; /* Expects 0x1111 (or RBX output), returns 0x2222 (RCX) */
}

Compile flag: -O2 -msgx -S trigger.c

$ cat trigger.s
        movq    $4369, %rbx
        movq    $8738, %rcx
        movq    $13107, %rdx
#APP
        enclv
#NO_APP
        movq    %rcx, %rax    # returns %rcx instead of %rbx
        popq    %rbx
        ret

Reply via email to