kaniini / libucontext

ucontext implementation featuring glibc-compatible ABI
Other
102 stars 41 forks source link

Stack pointer misaligned on x86 #61

Closed nmeum closed 1 month ago

nmeum commented 7 months ago

The x86 calling convention requires the stack pointer to be aligned on a 16-byte boundary. Otherwise, code using SSE instructions on x86 in conjunction with libucontext will just crash. This currently causes the gccgo runtime to crash on x86 Alpine Linux, see https://github.com/golang/go/issues/63935.

Independent of gccgo, we can reproduce this issue by inspecting SP values in the libucontext test suite:

$ env LD_LIBRARY_PATH="$(pwd)" gdb ./test_libucontext_posix
(gdb) break f2
Breakpoint 1 at 0x1410
(gdb) run
Breakpoint 1, 0x56556410 in f2 ()
(gdb) disassemble
Dump of assembler code for function f2:
…
   0x56556418 <+12>:    add    $0x2b8c,%ebx
   0x5655641e <+18>:    sub    $0xc,%esp
   0x56556421 <+21>:    lea    -0x1ef4(%ebx),%eax
   0x56556427 <+27>:    push   %eax
   0x56556428 <+28>:    call   0x56556030 <puts@plt>
   0x5655642d <+33>:    add    $0x10,%esp
   0x56556430 <+36>:    sub    $0xc,%esp
…
(gdb) break *0x56556428
(gdb) cont
Breakpoint 2, 0x56556428 in f2 ()
(gdb) disassemble
=> 0x56556428 <+28>:    call   0x56556030 <puts@plt>
(gdb) p $esp
$1 = (void *) 0xffffdbac

From this debugging session, we can deduce that the stack pointer ($esp) is not aligned before the first call to the puts(3) function in f2 (0xffffdbac % 16 == 12). I believe this to be non-conformant with the x86 calling convention which requires it to be 16-byte aligned when calling a function.

kaniini commented 7 months ago

Likely it is the code which aligns the stack pointer in makecontext.c which needs to be fixed here.

nmeum commented 7 months ago

Most definitely so, the initial SP value set in makecontext.c is not 16-byte aligned. However, one also needs to adjust the setcontext.S, swapcontext.S and FETCH_LINKPTR implementations to operate on the new SP value and my x86 assembly skills are a bit too rusty for that.

nmeum commented 1 month ago

Are we positive that the alignment issue has been fixed? gcc-go binaries still crash on x86. And the gdb instructions provided above still print an $esp value which is not 16-byte aligned.