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