fix async thread cancellation on sh-fdpic
authorRich Felker <dalias@aerifal.cx>
Wed, 29 Aug 2018 18:01:46 +0000 (14:01 -0400)
committerRich Felker <dalias@aerifal.cx>
Wed, 29 Aug 2018 18:01:46 +0000 (14:01 -0400)
if __cp_cancel was reached via __syscall_cp, r12 will necessarily
still contain a GOT pointer (for libc.so or for the static-linked main
program) valid for entering __cancel. however, in the case of async
cancellation, r12 may contain any scratch value; it's not necessarily
even a valid GOT pointer for the code that was interrupted.

unlike in commit 0ec49dab6794166d67fae4764ce7fdea42ea6103 where the
corresponding issue was fixed for powerpc64, there is fundamentally no
way for fdpic code to recompute its GOT pointer. so a new mechanism is
introduced for cancel_handler to write a GOT register value into the
interrupted context on archs where it is needed.

arch/sh/pthread_arch.h
src/thread/pthread_cancel.c

index 41fefacfcf0377c64d5fddfef84222b99faabff8..a7dd27a6c43a3705c30170ab694f3cb4721082f4 100644 (file)
@@ -10,3 +10,8 @@ static inline struct pthread *__pthread_self()
 #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
 
 #define MC_PC sc_pc
+
+#ifdef __FDPIC__
+#define MC_GOT sc_regs[12]
+#define CANCEL_GOT (*(uintptr_t *)((char *)__syscall_cp_asm+sizeof(uintptr_t)))
+#endif
index bf07dbebd691778f25e16d824ecb92d7850518f6..5d458af2227dcdbe6474710ca26d8325be434e16 100644 (file)
@@ -61,6 +61,9 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
 
        if (self->cancelasync || pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) {
                uc->uc_mcontext.MC_PC = (uintptr_t)__cp_cancel;
+#ifdef CANCEL_GOT
+               uc->uc_mcontext.MC_GOT = CANCEL_GOT;
+#endif
                return;
        }