From 76c03cbebdb9ae48eb1047ad9ed268e1e4ed7c67 Mon Sep 17 00:00:00 2001 From: Hubert Badocha Date: Fri, 1 Dec 2023 18:49:42 +0100 Subject: [PATCH 1/3] libphoenix: compile with FPIC by default JIRA: RTOS-664 --- Makefile | 3 +++ arch/arm/v7a/Makefile | 2 +- arch/arm/v7a/tls.S | 48 +++++++++++++++++++++++++++++++++++++++++++ arch/riscv64/Makefile | 2 +- arch/riscv64/tls.S | 39 +++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 arch/arm/v7a/tls.S create mode 100644 arch/riscv64/tls.S diff --git a/Makefile b/Makefile index 31e74b07..e7271548 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,9 @@ endif CFLAGS += -Iinclude -fno-builtin-malloc +ifneq ($(LIBPHOENIX_NOPIC), y) +CFLAGS += -fpic +endif OBJS := # crt0.o should have all necessary initialization + call to main() diff --git a/arch/arm/v7a/Makefile b/arch/arm/v7a/Makefile index ae752782..42ae98f8 100644 --- a/arch/arm/v7a/Makefile +++ b/arch/arm/v7a/Makefile @@ -5,4 +5,4 @@ # Author: Pawel Pisarczyk # -OBJS += $(addprefix $(PREFIX_O)arch/arm/v7a/, syscalls.o reboot.o) +OBJS += $(addprefix $(PREFIX_O)arch/arm/v7a/, syscalls.o reboot.o tls.o) diff --git a/arch/arm/v7a/tls.S b/arch/arm/v7a/tls.S new file mode 100644 index 00000000..d6116ec3 --- /dev/null +++ b/arch/arm/v7a/tls.S @@ -0,0 +1,48 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * tls access function + * + * Copyright 2023 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + + /* NOTE: + * When libphoenix is compiled as a PIC, even when linked into a static NOPIC binary, + * compiler generates accesses to TLS as calls to this function. + * This functions is simple version just for static binaries purposes, + * in dynamic binaries dynamic linker handles TLS accesses. */ + + +/* typedef struct { + * unsigned long ti_moduleid; + * unsigned long ti_tlsoffset; + * } TLS_index; + * + * void *__tls_get_addr(TLS_index *ti) */ +.thumb +.syntax unified + +.text + +.thumb_func +.globl __tls_get_addr; +.type __tls_get_addr, %function; +.align 2 +__tls_get_addr: + /* Access ti_tlsoffset. */ + ldr r0, [r0, #4] + /* Get thread pointer. */ + mrc p15, 0, r1, cr13, cr0, 3 + /* GCC expects that TLS block has 8 byte TCB pointer at the begging. */ + add r1, r1, #8 + add r0, r0, r1 + bx lr +.size __tls_get_addr, .-__tls_get_addr diff --git a/arch/riscv64/Makefile b/arch/riscv64/Makefile index 5674f637..cdd606cc 100644 --- a/arch/riscv64/Makefile +++ b/arch/riscv64/Makefile @@ -5,5 +5,5 @@ # Author: Pawel Pisarczyk # -OBJS += $(addprefix $(PREFIX_O)arch/riscv64/, syscalls.o string.o signal.o reboot.o jmp.o) +OBJS += $(addprefix $(PREFIX_O)arch/riscv64/, syscalls.o string.o signal.o reboot.o jmp.o tls.o) CRT0_OBJS += $(addprefix $(PREFIX_O)arch/riscv64/, crt0.o) diff --git a/arch/riscv64/tls.S b/arch/riscv64/tls.S new file mode 100644 index 00000000..765ead8e --- /dev/null +++ b/arch/riscv64/tls.S @@ -0,0 +1,39 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * tls access function + * + * Copyright 2023 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +/* NOTE: + * When libphoenix is compiled as a PIC, even when linked into a static NOPIC binary, + * compiler generates accesses to TLS as calls to this function. + * This functions is simple version just for static binaries purposes, + * in dynamic binaries dynamic linker handles TLS accesses. */ + + +/* typedef struct { + * unsigned long ti_moduleid; + * unsigned long ti_tlsoffset; + * } TLS_index; + * + * void *__tls_get_addr(TLS_index *ti) */ +.globl __tls_get_addr; +.type __tls_get_addr, %function; +__tls_get_addr: + /* Access ti_tlsoffset. */ + ld a0, 8(a0) + /* GCC expects that Dynamic Thread Vector pointer points at TLS block start + 0x800 */ + li t0, 0x800 + add a0, a0, t0 + add a0, a0, tp + ret +.size __tls_get_addr, .-__tls_get_addr From 3b0461179eced394d50a8d2b4bd7867f04f58e31 Mon Sep 17 00:00:00 2001 From: Hubert Badocha Date: Sun, 10 Dec 2023 22:41:09 +0100 Subject: [PATCH 2/3] ia32: support PIE in asm In PIE on ia32 function calls should be made using GOT. JIRA: RTOS-664 --- arch/ia32/jmp.S | 192 +++++++++++++++++++++++++-------------------- arch/ia32/signal.S | 27 +++++-- 2 files changed, 128 insertions(+), 91 deletions(-) diff --git a/arch/ia32/jmp.S b/arch/ia32/jmp.S index 13351d97..9efc42b2 100644 --- a/arch/ia32/jmp.S +++ b/arch/ia32/jmp.S @@ -5,127 +5,149 @@ * * 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_SAVE_REGS /* 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 +.align 4 +_setjmp: + SETJMP_SAVE_REGS + /* Set no mask indicator */ + movl $0, 24(%edx) + /* Store result (0) */ + xorl %eax, %eax ret .size _setjmp, .-_setjmp .globl setjmp .type setjmp, %function +.align 4 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_SAVE_REGS + /* 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 %eax, %eax ret .size setjmp, .-setjmp .globl _longjmp .type _longjmp, %function +.align 4 _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 - +.align 4 + 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..7f60e0f0 100644 --- a/arch/ia32/signal.S +++ b/arch/ia32/signal.S @@ -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. * @@ -19,14 +19,29 @@ .globl _signal_trampoline .type _signal_trampoline, %function +.align 4 _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 From 7bff04adb8e0a472cc76d7a226d32a6a0cdde704 Mon Sep 17 00:00:00 2001 From: Hubert Badocha Date: Wed, 11 Sep 2024 14:15:52 +0200 Subject: [PATCH 3/3] arch/riscv64: respect PIC in asm JIRA: RTOS-664 --- arch/riscv64/jmp.S | 14 +++++++++++++- arch/riscv64/syscalls.S | 5 +++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/riscv64/jmp.S b/arch/riscv64/jmp.S index 1537a4eb..abc7b99b 100644 --- a/arch/riscv64/jmp.S +++ b/arch/riscv64/jmp.S @@ -29,16 +29,28 @@ .globl _setjmp .type _setjmp, %function _setjmp: +#if __pic__ == 0 mv a1, zero j sigsetjmp +#else + auipc t0, %pcrel_hi(sigsetjmp) + mv a1, zero + jr t0, %pcrel_lo(setjmp) +#endif .size _setjmp, .-_setjmp .globl setjmp .type setjmp, %function setjmp: +#if __pic__ == 0 li a1, 1 - j sigsetjmp + j sigsetjmp +#else + auipc t0, %pcrel_hi(sigsetjmp) + li a1, 1 + jr t0, %pcrel_lo(setjmp) +#endif .size setjmp, .-setjmp diff --git a/arch/riscv64/syscalls.S b/arch/riscv64/syscalls.S index c518695e..8f66b565 100644 --- a/arch/riscv64/syscalls.S +++ b/arch/riscv64/syscalls.S @@ -54,7 +54,12 @@ sym: \ .globl vfork; .type vfork, %function; vfork: +#if __pic__ == 0 j vforksvc +#else + auipc t0, %pcrel_hi(vforksvc) + jr t0, %pcrel_lo(vfork) +#endif .size vfork, .-vfork