Skip to content

Commit

Permalink
ia32: support PIE in asm
Browse files Browse the repository at this point in the history
In PIE on ia32 function calls should be made using GOT.

JIRA: RTOS-664
  • Loading branch information
badochov committed Dec 11, 2023
1 parent 97a6012 commit 00a1625
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 91 deletions.
188 changes: 103 additions & 85 deletions arch/ia32/jmp.S
Original file line number Diff line number Diff line change
Expand Up @@ -5,127 +5,145 @@
*
* setjmp, longjmp
*
* Copyright 2018-2019 Phoenix Systems
* Author: Jan Sikorski, Andrzej Glowinski
* Copyright 2018-2019, 2023 Phoenix Systems
* Author: Jan Sikorski, Andrzej Glowinski, Hubert Badocha
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

/* jmp_buf layout:
* esi
* ebx
* 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 %esi, (%edx)
movl %ebx, 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


.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


.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 4(%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 (%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
26 changes: 20 additions & 6 deletions arch/ia32/signal.S
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
*
* Signal trampoline (ia32)
*
* Copyright 2019 Phoenix Systems
* Author: Jan Sikorski
* Copyright 2019, 2023 Phoenix Systems
* Author: Jan Sikorski, Hubert Badocha
*
* This file is part of Phoenix-RTOS.
*
Expand All @@ -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

0 comments on commit 00a1625

Please sign in to comment.