Просмотр исходного кода

i386: add CFI to __libc_i386_syscall6 for cancellation unwinding

__libc_i386_syscall6 (the hand-written 6-argument syscall helper) carried
no CFI, hence no .eh_frame FDE.  A thread cancelled asynchronously while
blocked in the int $0x80 inside this helper could not be unwound -- the
forced unwind could not walk back through the helper to run the pthread
cleanup handlers.  This broke cancellation of every syscall routed through
it: pselect6 (-> select, pselect) and the ipc() multiplexer (-> msgrcv);
their cleanup handlers were not called (tst-cancelx4).

%ebp holds the 6th argument across the syscall, so the saved frame pointer
lives on the stack; the added CFI records that together with the
esp-relative CFA.  With the FDE in place tst-cancelx4 passes (full i686
suite: 476 passed, 0 failed).

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
Ramin Moussavi 1 неделя назад
Родитель
Сommit
7ec7f14b07
1 измененных файлов с 22 добавлено и 0 удалено
  1. 22 0
      libc/sysdeps/linux/i386/syscall6.S

+ 22 - 0
libc/sysdeps/linux/i386/syscall6.S

@@ -47,10 +47,23 @@
 	.globl	__libc_i386_syscall6
 	.type	__libc_i386_syscall6,@function
 __libc_i386_syscall6:
+	/* Emit CFI (DWARF reg numbers: ebx=3, ebp=5, esi=6, edi=7) so an
+	   async pthread cancellation can unwind through this helper when a
+	   thread is cancelled while blocked in the syscall; %ebp holds arg6
+	   here, so the saved frame pointer must be found on the stack. */
+	.cfi_startproc
 	push	ebp
+	.cfi_adjust_cfa_offset 4
+	.cfi_rel_offset 5, 0
 	push	ebx
+	.cfi_adjust_cfa_offset 4
+	.cfi_rel_offset 3, 0
 	push	esi
+	.cfi_adjust_cfa_offset 4
+	.cfi_rel_offset 6, 0
 	push	edi
+	.cfi_adjust_cfa_offset 4
+	.cfi_rel_offset 7, 0
 	mov	eax,[esp + 20]	/* nr */
 	mov	ebx,[esp + 24]	/* arg1 */
 	mov	ecx,[esp + 28]	/* arg2 */
@@ -60,8 +73,17 @@ __libc_i386_syscall6:
 	mov	ebp,[esp + 44]	/* arg6 */
 	int	0x80
 	pop	edi
+	.cfi_adjust_cfa_offset -4
+	.cfi_restore 7
 	pop	esi
+	.cfi_adjust_cfa_offset -4
+	.cfi_restore 6
 	pop	ebx
+	.cfi_adjust_cfa_offset -4
+	.cfi_restore 3
 	pop	ebp
+	.cfi_adjust_cfa_offset -4
+	.cfi_restore 5
 	ret
+	.cfi_endproc
 	.size	__libc_i386_syscall6,.-__libc_i386_syscall6