···20202121static volatile bool am_i_ptraced = false;
2222static void handle_rt_signal(int signum);
2323+static void sigexc_fake_suspend(struct linux_ucontext* ctxt);
2324extern void sig_restorer(void);
2425extern int getpid(void);
2526···170171 // If >0, process the signal
171172 // If <0, introduce a new signal
172173 int sig = info->si_value;
173173- if (sig < 0)
174174+ if (sig == SIGNAL_THREAD_SUSPEND)
175175+ {
176176+ kern_printf("sigexc: SIGNAL_THREAD_SUSPEND");
177177+ sigexc_fake_suspend(ctxt);
178178+ }
179179+ else if (sig == SIGNAL_THREAD_RESUME)
180180+ {
181181+ kern_printf("sigexc: SIGNAL_THREAD_RESUME");
182182+ }
183183+ else if (sig < 0)
174184 {
175185 // This is only used to pass a SIGSTOP to the traced process (from the debugger)
176186 // and have it passed back through the sigexc mechanism.
177177- // See sys_wait4().
187187+ // See sys_kill().
178188 sigexc_handler(-sig, NULL, (struct linux_ucontext*) ctxt);
179189 }
180190 else
···273283 return 0;
274284}
275285286286+static void state_to_kernel(struct linux_ucontext* ctxt, thread_t thread)
287287+{
288288+#if defined(__x86_64__)
289289+ x86_thread_state64_t tstate;
290290+ x86_float_state64_t fstate;
291291+292292+ if (ctxt != NULL)
293293+ {
294294+ mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, &tstate);
295295+ mcontext_to_float_state(ctxt->uc_mcontext.fpregs, &fstate);
296296+ /*
297297+#ifdef __x86_64__
298298+ if (bsd_signum == SIGTRAP)
299299+ {
300300+ uint8_t* rip = (uint8_t*) ctxt->uc_mcontext.gregs.rip;
301301+ kern_printf("rip is %p\n", rip);
302302+ kern_printf("Value at rip-1 on suspend: 0x%x\n", *(rip-1));
303303+ }
304304+#endif
305305+ */
306306+ }
307307+ else
308308+ {
309309+ memset(&tstate, 0, sizeof(tstate));
310310+ memset(&fstate, 0, sizeof(fstate));
311311+ }
312312+313313+ thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t) &tstate, x86_THREAD_STATE64_COUNT);
314314+ thread_set_state(thread, x86_FLOAT_STATE64, (thread_state_t) &fstate, x86_FLOAT_STATE64_COUNT);
315315+#elif defined(__i386__)
316316+ x86_thread_state32_t tstate;
317317+ x86_float_state32_t fstate;
318318+319319+ if (ctxt != NULL)
320320+ {
321321+ mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, &tstate);
322322+ mcontext_to_float_state(ctxt->uc_mcontext.fpregs, &fstate);
323323+ }
324324+ else
325325+ {
326326+ memset(&tstate, 0, sizeof(tstate));
327327+ memset(&fstate, 0, sizeof(fstate));
328328+ }
329329+330330+ thread_set_state(thread, x86_THREAD_STATE32, (thread_state_t) &tstate, x86_THREAD_STATE32_COUNT);
331331+ thread_set_state(thread, x86_FLOAT_STATE32, (thread_state_t) &fstate, x86_FLOAT_STATE32_COUNT);
332332+#endif
333333+334334+}
335335+336336+static void state_from_kernel(struct linux_ucontext* ctxt, thread_t thread)
337337+{
338338+#if defined(__x86_64__)
339339+ x86_thread_state64_t tstate;
340340+ x86_float_state64_t fstate;
341341+ mach_msg_type_number_t count;
342342+343343+ count = x86_THREAD_STATE64_COUNT;
344344+ thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t) &tstate, &count);
345345+ count = x86_FLOAT_STATE64_COUNT;
346346+ thread_get_state(thread, x86_FLOAT_STATE64, (thread_state_t) &fstate, &count);
347347+348348+ thread_state_to_mcontext(&tstate, &ctxt->uc_mcontext.gregs);
349349+ float_state_to_mcontext(&fstate, ctxt->uc_mcontext.fpregs);
350350+351351+#elif defined(__i386__)
352352+ x86_thread_state32_t tstate;
353353+ x86_float_state32_t fstate;
354354+ mach_msg_type_number_t count;
355355+356356+ count = x86_THREAD_STATE32_COUNT;
357357+ thread_get_state(thread, x86_THREAD_STATE32, (thread_state_t) &tstate, &count);
358358+ count = x86_FLOAT_STATE32_COUNT;
359359+ thread_get_state(thread, x86_FLOAT_STATE32, (thread_state_t) &fstate, &count);
360360+361361+ thread_state_to_mcontext(&tstate, &ctxt->uc_mcontext.gregs);
362362+ float_state_to_mcontext(&fstate, ctxt->uc_mcontext.fpregs);
363363+#endif
364364+}
365365+366366+void sigexc_fake_suspend(struct linux_ucontext* ctxt)
367367+{
368368+ if (_pthread_getspecific_direct(SIGEXC_TSD_KEY) != 0)
369369+ return;
370370+ thread_t thread = mach_thread_self();
371371+372372+ kern_printf("sigexc_fake_suspend -> state_to_kernel\n");
373373+ state_to_kernel(ctxt, thread);
374374+375375+ linux_sigset_t set = -1ll;
376376+ set &= ~(1ull << (SIGNAL_SIGEXC_THUPDATE-1));
377377+378378+ LINUX_SYSCALL(__NR_rt_sigsuspend, &set, 8);
379379+380380+ kern_printf("sigexc_fake_suspend -> state_from_kernel\n");
381381+ state_from_kernel(ctxt, thread);
382382+}
276383277384// syscall tracking
278385#define LINUX_TRAP_BRKPT 1
···318425 // SIGILL -> EXC_BAD_INSTRUCTION
319426 // SIGFPE -> EXC_ARITHMETIC
320427 // * -> EXC_SOFTWARE with EXC_SOFT_SIGNAL (e.g. SIGSTOP)
321321- kern_printf("sigexc_handler #2\n");
322428323429 // Only real exceptions produced by the CPU get translated to these
324430 // Mach exceptions. The rest comes as EXC_SOFTWARE.
···373479 port = get_exc_port(mach_exception, &behavior);
374480375481 // Pass register states to LKM
376376-#if defined(__x86_64__)
377377- x86_thread_state64_t tstate;
378378- x86_float_state64_t fstate;
379379-380380- if (ctxt != NULL)
381381- {
382382- mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, &tstate);
383383- mcontext_to_float_state(ctxt->uc_mcontext.fpregs, &fstate);
384384- /*
385385-#ifdef __x86_64__
386386- if (bsd_signum == SIGTRAP)
387387- {
388388- uint8_t* rip = (uint8_t*) ctxt->uc_mcontext.gregs.rip;
389389- kern_printf("rip is %p\n", rip);
390390- kern_printf("Value at rip-1 on suspend: 0x%x\n", *(rip-1));
391391- }
392392-#endif
393393- */
394394- }
395395- else
396396- {
397397- memset(&tstate, 0, sizeof(tstate));
398398- memset(&fstate, 0, sizeof(fstate));
399399- }
400400-401401- thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t) &tstate, x86_THREAD_STATE64_COUNT);
402402- thread_set_state(thread, x86_FLOAT_STATE64, (thread_state_t) &fstate, x86_FLOAT_STATE64_COUNT);
403403-#elif defined(__i386__)
404404- x86_thread_state32_t tstate;
405405- x86_float_state32_t fstate;
406406-407407- if (ctxt != NULL)
408408- {
409409- mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, &tstate);
410410- mcontext_to_float_state(ctxt->uc_mcontext.fpregs, &fstate);
411411- }
412412- else
413413- {
414414- memset(&tstate, 0, sizeof(tstate));
415415- memset(&fstate, 0, sizeof(fstate));
416416- }
417417-418418- thread_set_state(thread, x86_THREAD_STATE32, (thread_state_t) &tstate, x86_THREAD_STATE32_COUNT);
419419- thread_set_state(thread, x86_FLOAT_STATE32, (thread_state_t) &fstate, x86_FLOAT_STATE32_COUNT);
420420-#endif
482482+ state_to_kernel(ctxt, thread);
421483422484 // __simple_printf("Passing Mach exception to port %d\n", port);
423485 if (port != 0)
···443505 }
444506445507 bsd_signum = _pthread_getspecific_direct(SIGEXC_TSD_KEY);
508508+ _pthread_setspecific_direct(SIGEXC_TSD_KEY, 0);
446509 }
447510448511 // Get (possibly updated by GDB) register states from LKM
449512 if (ctxt != NULL)
450450- {
451451-#if defined(__x86_64__)
452452- mach_msg_type_number_t count;
453453-454454- count = x86_THREAD_STATE64_COUNT;
455455- thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t) &tstate, &count);
456456- count = x86_FLOAT_STATE64_COUNT;
457457- thread_get_state(thread, x86_FLOAT_STATE64, (thread_state_t) &fstate, &count);
458458-459459- thread_state_to_mcontext(&tstate, &ctxt->uc_mcontext.gregs);
460460- float_state_to_mcontext(&fstate, ctxt->uc_mcontext.fpregs);
461461-462462-#elif defined(__i386__)
463463- mach_msg_type_number_t count;
464464-465465- count = x86_THREAD_STATE32_COUNT;
466466- thread_get_state(thread, x86_THREAD_STATE32, (thread_state_t) &tstate, &count);
467467- count = x86_FLOAT_STATE32_COUNT;
468468- thread_get_state(thread, x86_FLOAT_STATE32, (thread_state_t) &fstate, &count);
469469-470470- thread_state_to_mcontext(&tstate, &ctxt->uc_mcontext.gregs);
471471- float_state_to_mcontext(&fstate, ctxt->uc_mcontext.fpregs);
472472-#endif
473473- }
513513+ state_from_kernel(ctxt, thread);
474514475515 // Pass the signal to the application handler or emulate the effects of the signal if SIG_DFL is set.
476516 if (bsd_signum)
+3
src/kernel/emulation/linux/signal/sigexc.h
···1111// A BSD signal number is passed as value
1212#define SIGNAL_SIGEXC_THUPDATE (LINUX_SIGRTMIN + 1)
13131414+#define SIGNAL_THREAD_SUSPEND -100
1515+#define SIGNAL_THREAD_RESUME -101
1616+1417#define SIGRT_MAGIC_ENABLE_SIGEXC 0xdebdeb01
1518#define SIGRT_MAGIC_DISABLE_SIGEXC 0xdebdeb00
1619