diff --git a/Makefile b/Makefile index 2eb7b30..51baeab 100644 --- a/Makefile +++ b/Makefile @@ -108,6 +108,8 @@ $(NOSSP_SRCS:%.c=%.o) $(NOSSP_SRCS:%.c=%.lo): CFLAGS += $(CFLAGS_NOSSP) $(CRT_LIBS:lib/%=crt/%): CFLAGS += -DCRT +$(patsubst %.c,%.o,$(wildcard src/complex/*.c)): CFLAGS += -fno-PIC -fno-PIE + # This incantation ensures that changes to any subarch asm files will # force the corresponding object file to be rebuilt, even if the implicit # rule below goes indirectly through a .sub file. diff --git a/arch/sh/pthread_arch.h b/arch/sh/pthread_arch.h index 65c389f..0960422 100644 --- a/arch/sh/pthread_arch.h +++ b/arch/sh/pthread_arch.h @@ -9,3 +9,14 @@ static inline struct pthread *__pthread_self() #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8) #define CANCEL_REG_IP 17 + +#ifdef SHARED +__attribute__((__visibility__("hidden"))) +#endif +extern const char __cp_begin[1], __cp_end[1], + __cp2_begin[1], __cp2_end[1]; + +#define IN_CP(ip) ((uintptr_t)(ip)-(uintptr_t)__cp_begin \ + < (uintptr_t)__cp_end-(uintptr_t)__cp_begin \ + || (uintptr_t)(ip)-(uintptr_t)__cp2_begin \ + < (uintptr_t)__cp2_end-(uintptr_t)__cp2_begin) diff --git a/arch/sh/src/__set_thread_area.c b/arch/sh/src/__set_thread_area.c index e69de29..a723ff2 100644 --- a/arch/sh/src/__set_thread_area.c +++ b/arch/sh/src/__set_thread_area.c @@ -0,0 +1,21 @@ +#include "pthread_impl.h" +#include "libc.h" +#include + +/* Also perform sh-specific init */ + +__attribute__((__visibility__("hidden"))) int __sh2_abi; + +int __set_thread_area(void *p) +{ + size_t *aux; + __asm__ __volatile__ ( "ldc %0, gbr" : : "r"(p) : "memory" ); + for (aux=libc.auxv; *aux; aux+=2) { + if (*aux != AT_PLATFORM) continue; + const char *s = (void *)aux[1]; + if (s[0]!='s' || s[1]!='h' || s[2]!='2' || s[3]-'0'<10u) break; + __sh2_abi = 1; + break; + } + return 0; +} diff --git a/arch/sh/src/atomic.c b/arch/sh/src/atomic.c index f8c615f..b3a8968 100644 --- a/arch/sh/src/atomic.c +++ b/arch/sh/src/atomic.c @@ -27,6 +27,8 @@ #define CPU_HAS_LLSC 0x0040 +#define __hwcap 0 + int __sh_cas(volatile int *p, int t, int s) { if (__hwcap & CPU_HAS_LLSC) return __sh_cas_llsc(p, t, s); diff --git a/arch/sh/src/sh/sh_syscall.s b/arch/sh/src/sh/sh_syscall.s index e69de29..546ae07 100644 --- a/arch/sh/src/sh/sh_syscall.s +++ b/arch/sh/src/sh/sh_syscall.s @@ -0,0 +1,38 @@ +.hidden __sh_syscall +.global __sh_syscall +.type __sh_syscall,@function +__sh_syscall: + mov.l r0,@-r15 + mov.l r2,@-r15 + + mova 1f, r0 + mov.l 1f, r2 + add r0, r2 + mov.l @r2, r2 + tst r2, r2 + + mov.l @r15+, r2 + mov.l @r15+, r0 + + bt 3f + bra 2f + nop + .align 2 + .hidden __sh2_abi +1: .long __sh2_abi@PCREL + +2: trapa #38 + bra 1f + nop + +3: trapa #22 + or r0, r0 + or r0, r0 + or r0, r0 + or r0, r0 + or r0, r0 + +1: neg r2, r2 + add #__sh_syscall-9f, r2 +9: braf r2 + nop diff --git a/arch/sh/syscall_arch.h b/arch/sh/syscall_arch.h index 7ee21a5..b56dfbf 100644 --- a/arch/sh/syscall_arch.h +++ b/arch/sh/syscall_arch.h @@ -3,26 +3,25 @@ ((union { long long ll; long l[2]; }){ .ll = x }).l[1] #define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) -/* The extra OR instructions are to work around a hardware bug: - * http://documentation.renesas.com/doc/products/mpumcu/tu/tnsh7456ae.pdf - */ -#define __asm_syscall(trapno, ...) do { \ - __asm__ __volatile__ ( \ - "trapa #" #trapno "\n" \ - "or r0, r0\n" \ - "or r0, r0\n" \ - "or r0, r0\n" \ - "or r0, r0\n" \ - "or r0, r0\n" \ - : "=r"(r0) : __VA_ARGS__ : "memory"); \ - return r0; \ - } while (0) +#define __SYSCALL_ASM "\n" \ +" mov.l 1f, r2\n" \ +" .align 2\n" \ +"2: braf r2\n" \ +" nop\n" \ +" .hidden __sh_syscall\n" \ +"1: .long __sh_syscall@PCREL\n" \ +"3: \n" + +#define __asm_syscall(...) \ + __asm__ __volatile__ ( __SYSCALL_ASM \ + : "=r"(r0) : __VA_ARGS__ : "memory", "r2", "t" ) static inline long __syscall0(long n) { register long r3 __asm__("r3") = n; register long r0 __asm__("r0"); - __asm_syscall(16, "r"(r3)); + __asm_syscall("r"(r3)); + return r0; } static inline long __syscall1(long n, long a) @@ -30,7 +29,8 @@ static inline long __syscall1(long n, long a) register long r3 __asm__("r3") = n; register long r4 __asm__("r4") = a; register long r0 __asm__("r0"); - __asm_syscall(17, "r"(r3), "r"(r4)); + __asm_syscall("r"(r3), "r"(r4)); + return r0; } static inline long __syscall2(long n, long a, long b) @@ -39,7 +39,8 @@ static inline long __syscall2(long n, long a, long b) register long r4 __asm__("r4") = a; register long r5 __asm__("r5") = b; register long r0 __asm__("r0"); - __asm_syscall(18, "r"(r3), "r"(r4), "r"(r5)); + __asm_syscall("r"(r3), "r"(r4), "r"(r5)); + return r0; } static inline long __syscall3(long n, long a, long b, long c) @@ -49,7 +50,8 @@ static inline long __syscall3(long n, long a, long b, long c) register long r5 __asm__("r5") = b; register long r6 __asm__("r6") = c; register long r0 __asm__("r0"); - __asm_syscall(19, "r"(r3), "r"(r4), "r"(r5), "r"(r6)); + __asm_syscall("r"(r3), "r"(r4), "r"(r5), "r"(r6)); + return r0; } static inline long __syscall4(long n, long a, long b, long c, long d) @@ -60,7 +62,8 @@ static inline long __syscall4(long n, long a, long b, long c, long d) register long r6 __asm__("r6") = c; register long r7 __asm__("r7") = d; register long r0 __asm__("r0"); - __asm_syscall(20, "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7)); + __asm_syscall("r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7)); + return r0; } static inline long __syscall5(long n, long a, long b, long c, long d, long e) @@ -71,7 +74,8 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e) register long r6 __asm__("r6") = c; register long r7 __asm__("r7") = d; register long r0 __asm__("r0") = e; - __asm_syscall(21, "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "0"(r0)); + __asm_syscall("r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "0"(r0)); + return r0; } static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) @@ -83,5 +87,6 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo register long r7 __asm__("r7") = d; register long r0 __asm__("r0") = e; register long r1 __asm__("r1") = f; - __asm_syscall(22, "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "0"(r0), "r"(r1)); + __asm_syscall("r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "0"(r0), "r"(r1)); + return r0; } diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c index f6f3b14..0ab80e2 100644 --- a/src/env/__libc_start_main.c +++ b/src/env/__libc_start_main.c @@ -42,6 +42,8 @@ void __init_libc(char **envp, char *pn) __init_tls(aux); __init_ssp((void *)aux[AT_RANDOM]); + if (__syscall(SYS_personality, 0) == -1) a_crash(); + if (aux[AT_UID]==aux[AT_EUID] && aux[AT_GID]==aux[AT_EGID] && !aux[AT_SECURE]) return; diff --git a/src/internal/sh/syscall.s b/src/internal/sh/syscall.s index d00712a..23feb32 100644 --- a/src/internal/sh/syscall.s +++ b/src/internal/sh/syscall.s @@ -2,10 +2,6 @@ .hidden __syscall .type __syscall, @function __syscall: - ! The kernel syscall entry point documents that the trap number indicates - ! the number of arguments being passed, but it then ignores that information. - ! Since we do not actually know how many arguments are being passed, we will - ! say there are six, since that is the maximum we support here. mov r4, r3 mov r5, r4 mov r6, r5 @@ -13,11 +9,13 @@ __syscall: mov.l @r15, r7 mov.l @(4,r15), r0 mov.l @(8,r15), r1 - trapa #22 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 + + mov.l 1f, r2 + .align 2 +2: braf r2 + nop + .hidden __sh_syscall +1: .long __sh_syscall@PCREL + rts nop diff --git a/src/process/sh/vfork.s b/src/process/sh/vfork.s index e69de29..9c61d03 100644 --- a/src/process/sh/vfork.s +++ b/src/process/sh/vfork.s @@ -0,0 +1,23 @@ +.global __vfork +.weak vfork +.type __vfork,@function +.type vfork,@function +__vfork: +vfork: + mov #95, r3 + add r3, r3 + + mov.l 1f, r2 + .align 2 +2: braf r2 + nop + .hidden __sh_syscall +1: .long __sh_syscall@PCREL + + mov r0, r4 + mov.l 1f, r0 +2: braf r0 + nop + .align 2 + .hidden __syscall_ret +1: .long __syscall_ret@PLT-(2b+4-.) diff --git a/src/signal/sh/restore.s b/src/signal/sh/restore.s index ab26034..f1b462c 100644 --- a/src/signal/sh/restore.s +++ b/src/signal/sh/restore.s @@ -2,23 +2,18 @@ .type __restore, @function __restore: mov #119, r3 !__NR_sigreturn - trapa #16 - - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 + bra 1f + nop .global __restore_rt .type __restore_rt, @function __restore_rt: mov #100, r3 !__NR_rt_sigreturn add #73, r3 - trapa #16 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 +1: mov.l 1f, r2 + .align 2 +2: braf r2 + nop + .hidden __sh_syscall +1: .long __sh_syscall@PCREL diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c index 0151a1a..5ddd304 100644 --- a/src/thread/pthread_cancel.c +++ b/src/thread/pthread_cancel.c @@ -57,6 +57,11 @@ __attribute__((__visibility__("hidden"))) #endif extern const char __cp_begin[1], __cp_end[1]; +#ifndef IN_CP +#define IN_CP(ip) ((uintptr_t)(ip)-(uintptr_t)__cp_begin \ + < (uintptr_t)__cp_end-(uintptr_t)__cp_begin) +#endif + static void cancel_handler(int sig, siginfo_t *si, void *ctx) { pthread_t self = __pthread_self(); @@ -68,7 +73,7 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx) _sigaddset(&uc->uc_sigmask, SIGCANCEL); - if (self->cancelasync || ip >= __cp_begin && ip < __cp_end) { + if (self->cancelasync || IN_CP(ip)) { ((char **)&uc->uc_mcontext)[CANCEL_REG_IP] = (char *)__cp_cancel; return; } diff --git a/src/thread/sh/__set_thread_area.s b/src/thread/sh/__set_thread_area.s index d9f1181..e69de29 100644 --- a/src/thread/sh/__set_thread_area.s +++ b/src/thread/sh/__set_thread_area.s @@ -1,6 +0,0 @@ -.global __set_thread_area -.type __set_thread_area, @function -__set_thread_area: - ldc r4, gbr - rts - mov #0, r0 diff --git a/src/thread/sh/__unmapself.s b/src/thread/sh/__unmapself.s deleted file mode 100644 index b34c3c8..0000000 --- a/src/thread/sh/__unmapself.s +++ /dev/null @@ -1,22 +0,0 @@ -.text -.global __unmapself -.type __unmapself, @function -__unmapself: - mov #91, r3 ! SYS_munmap - trapa #18 - - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 - - mov #1, r3 ! SYS_exit - mov #0, r4 - trapa #17 - - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 diff --git a/src/thread/sh/clone.s b/src/thread/sh/clone.s index d6c9184..5fc97fc 100644 --- a/src/thread/sh/clone.s +++ b/src/thread/sh/clone.s @@ -9,7 +9,7 @@ __clone: and r0, r5 mov r4, r1 ! r1 = fn - mov r7, r2 ! r2 = arg + mov.l r7, @-r5 ! (r5) = arg mov #120, r3 ! r3 = __NR_clone mov r6, r4 ! r4 = flags @@ -17,13 +17,13 @@ __clone: mov.l @r15, r6 ! r6 = ptid mov.l @(8,r15), r7 ! r7 = ctid mov.l @(4,r15), r0 ! r0 = tls - trapa #21 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 +3: mov.l 1f, r2 + .align 2 +2: braf r2 + nop + .hidden __sh_syscall +1: .long __sh_syscall@PCREL cmp/eq #0, r0 bt 1f @@ -34,14 +34,9 @@ __clone: 1: ! we are the child, call fn(arg) jsr @r1 - mov r2, r4 + mov.l @r15+, r4 mov #1, r3 ! __NR_exit mov r0, r4 - trapa #17 - - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 + bra 3b + nop diff --git a/src/thread/sh/syscall_cp.s b/src/thread/sh/syscall_cp.s index 6b28ddf..f8bb607 100644 --- a/src/thread/sh/syscall_cp.s +++ b/src/thread/sh/syscall_cp.s @@ -1,4 +1,8 @@ .text +.global __cp2_begin +.hidden __cp2_begin +.global __cp2_end +.hidden __cp2_end .global __cp_begin .hidden __cp_begin .global __cp_end @@ -11,28 +15,58 @@ .type __syscall_cp_asm, @function __syscall_cp_asm: -__cp_begin: - mov.l @r4, r4 - tst r4, r4 - bt 2f - - mov.l L1, r0 - braf r0 - nop -1: - -.align 2 -L1: .long __cancel@PLT-(1b-.) + mova 1f, r0 + mov.l 1f, r2 + add r0, r2 + mov.l @r1, r2 + tst r2, r2 -2: mov r5, r3 + ! setup syscall args + mov r4, r2 + mov r5, r3 mov r6, r4 mov r7, r5 mov.l @r15, r6 mov.l @(4,r15), r7 mov.l @(8,r15), r0 mov.l @(12,r15), r1 - trapa #22 + bt __cp_begin + bra __cp2_begin + nop + .align 2 + .hidden __sh2_abi +1: .long __sh2_abi@PCREL + +2: +__cp2_begin: + mov.l @r2, r2 + tst r2, r2 + bt 2f + + mov.l 1f, r0 + .align 2 + braf r0 + nop +1: .long __cancel@PCREL + +2: trapa #38 +__cp2_end: + rts + nop + +__cp_begin: + mov.l @r2, r2 + tst r2, r2 + bt 2f + + mov.l 1f, r0 + .align 2 + braf r0 + nop +1: .long __cancel@PCREL + +2: trapa #22 __cp_end: ! work around hardware bug or r0, r0 @@ -40,6 +74,5 @@ __cp_end: or r0, r0 or r0, r0 or r0, r0 - rts nop diff --git a/src/unistd/sh/pipe.s b/src/unistd/sh/pipe.s index d865ae3..ba3ea10 100644 --- a/src/unistd/sh/pipe.s +++ b/src/unistd/sh/pipe.s @@ -2,14 +2,13 @@ .type pipe, @function pipe: mov #42, r3 - trapa #17 - ! work around hardware bug - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 - or r0, r0 + mov.l 1f, r2 + .align 2 +2: braf r2 + nop + .hidden __sh_syscall +1: .long __sh_syscall@PCREL cmp/pz r0 bt 1f