From c5d4b997830939a7172fd1b1d19c44f19d6bc11f Mon Sep 17 00:00:00 2001 From: Hubert Badocha Date: Sun, 10 Dec 2023 22:41:09 +0100 Subject: [PATCH] ia32: support PIE in asm In PIE on ia32 function calls should be made using GOT. JIRA: RTOS-664 --- arch/ia32/jmp.S | 184 +++++++++++++++++++++++++-------------------- arch/ia32/signal.S | 22 +++++- 2 files changed, 119 insertions(+), 87 deletions(-) diff --git a/arch/ia32/jmp.S b/arch/ia32/jmp.S index 13351d97..da0cad86 100644 --- a/arch/ia32/jmp.S +++ b/arch/ia32/jmp.S @@ -13,35 +13,47 @@ * %LICENSE% */ + /* jmp_buf layout: + * ebx + * esi + * edi + * ebp + * esp + 4 + * return address + * signal mask indicator (0 - not saved, otherwise saved(GOT addr on PIC)) + * signal mask (if saved) + */ + #define __ASSEMBLY__ .text -.globl _setjmp -.type _setjmp, %function -_setjmp: + +.macro __SETJMP /* Store registers into jmpbuf */ - movl 4(%esp), %edx - movl %ebx, (%edx) - movl %esi, 4(%edx) - movl %edi, 8(%edx) - movl %ebp, 12(%edx) + leal 4(%esp), %ecx + movl (%ecx), %edx + movl %ebx, (%edx) + movl %esi, 4(%edx) + movl %edi, 8(%edx) + movl %ebp, 12(%edx) /* Store stack pointer pointing before return address */ - leal 4(%esp), %ecx - movl %ecx, 16(%edx) - /* Store jump address */ - leal (1f), %ecx - movl %ecx, 20(%edx) + movl %ecx, 16(%edx) /* Store return address */ - movl (%esp), %ecx - movl %ecx, 24(%edx) - /* Store result */ - movl $0, %eax - ret -1: - /* Jump point. Push return address to stack */ - pushl 24(%edx) + movl (%esp), %ecx + movl %ecx, 20(%edx) +.endm + + +.globl _setjmp +.type _setjmp, %function +_setjmp: + __SETJMP + /* Set no mask indicator */ + movl $0, 24(%edx) + /* Store result (0) */ + xorl %eax, %eax ret .size _setjmp, .-_setjmp @@ -49,44 +61,36 @@ _setjmp: .globl setjmp .type setjmp, %function setjmp: - /* Get signal mask */ - pushl $0 - pushl $0 - call signalMask - addl $8, %esp - /* Store registers into jmpbuf */ - movl 4(%esp), %edx - movl %ebx, (%edx) - movl %esi, 4(%edx) - movl %edi, 8(%edx) - movl %ebp, 12(%edx) - /* Store stack pointer pointing before return address */ - leal 4(%esp), %ecx - movl %ecx, 16(%edx) - /* Store jump address */ - leal (1f), %ecx - movl %ecx, 20(%edx) - /* Store return address */ - movl (%esp), %ecx - movl %ecx, 24(%edx) - /* Store signal mask */ - movl %eax, 28(%edx) - /* Store result */ - movl $0, %eax - ret -1: - /* Jump point. Push return address to stack */ - pushl 24(%edx) - /* Store longjmp return value */ - pushl %eax - /* Restore signal mask */ - movl 28(%edx), %ecx - pushl $0xffffffff - pushl %ecx + __SETJMP + /* Get signal mask */ +#if __pic__ == 0 + pushl $0 + pushl $0 call signalMask - addl $8, %esp - /* Restore longjmp return value */ - popl %eax + addl $8, %esp + /* Store signal mask indicator */ + movl $1, 24(%edx) +#else + pushl %ebx + + call .l1 +.l1: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+(.-.l1), %ebx + + pushl $0 + pushl $0 + call signalMask@got(%ebx) + addl $8, %esp + /* Save GOT address as an indicator as it will not be 0 */ + movl %ebx, 24(%edx) + + popl %ebx +#endif + /* Store signal mask */ + movl %eax, 28(%edx) + /* Store result (0) */ + xorl $0, %eax ret .size setjmp, .-setjmp @@ -94,38 +98,52 @@ setjmp: .globl _longjmp .type _longjmp, %function _longjmp: - movl 4(%esp), %edx - movl 8(%esp), %eax - test %eax, %eax - jnz 1f - inc %eax + /* Since esi will be restored later it can be used as a scratch register */ + /* Using it allows to safely call signalMask */ + movl 4(%esp), %esi + /* Check mask indicator */ + /* Since ebx will be restored later it can be used as a scratch register */ + /* ebx as the mask indicator is a GOT address in PIC */ + movl 24(%esi), %ebx + test %ebx, %ebx + jz 1f + /* Restore signal mask */ + pushl $0xffffffff + pushl 28(%esi) + +#if __pic__ == 0 + call signalMask +#else + call signalMask@got(%ebx) +#endif + + addl $8, %esp 1: + /* Get second argument */ + movl 8(%esp), %eax + /* _longjmp shall return 1 if 0 is provided as the second argument */ + movl $1, %ecx + test %eax, %eax + cmove %ecx, %eax /* Restore registers from jmpbuf */ - movl (%edx), %ebx - movl 4(%edx), %esi - movl 8(%edx), %edi - movl 12(%edx), %ebp - movl 16(%edx), %esp - /* Restore jump address */ - movl 20(%edx), %ecx - /* Jump */ - jmp *%ecx + movl (%esi), %ebx + movl 8(%esi), %edi + movl 12(%esi), %ebp + movl 16(%esi), %esp + /* Jump point. Push return address to stack */ + pushl 20(%esi) + /* At last restore esi */ + movl 4(%esi), %esi + ret .size _longjmp, .-_longjmp .globl sigsetjmp .type sigsetjmp, %function sigsetjmp: - /* Modify stack frame to skip this function when returning from setjmp */ - movl 8(%esp), %edx - movl 4(%esp), %ecx - movl (%esp), %eax - addl $8, %esp - pushl %ecx - pushl %eax - + movl 8(%esp), %edx /* Call proper setjmp */ - test %edx, %edx - jne setjmp - jmp _setjmp + test %edx, %edx + jz _setjmp + jmp setjmp .size sigsetjmp, .-sigsetjmp diff --git a/arch/ia32/signal.S b/arch/ia32/signal.S index 38131c99..6ad449b6 100644 --- a/arch/ia32/signal.S +++ b/arch/ia32/signal.S @@ -21,12 +21,26 @@ .type _signal_trampoline, %function _signal_trampoline: /* Signal number on stack */ - call _signal_handler +#if __pic__ == 0 + call _signal_handler +#else + /* ebx will be restored by sigreturn */ + call .l1 +.l1: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+(.-.l1), %ebx - addl $4, %esp + call _signal_handler@got(%ebx) +#endif + + addl $4, %esp /* Put old mask on stack */ - push %eax + pushl %eax /* cpu context *, eip, esp on stack */ - call sigreturn +#if __pic__ == 0 + call sigreturn +#else + call sigreturn@got(%ebx) +#endif .size _signal_trampoline, .-_signal_trampoline