···6262 return SIGUSR1;
6363 case LINUX_SIGUSR2:
6464 return SIGUSR2;
6565+ // Hack! This is what we send instead of SIGSTOP to allow the target process to receive the signal
6666+ // and pass it through the LKM.
6767+ case LINUX_SIGSTKFLT:
6868+ return SIGSTOP;
6569 default:
6670 return 0;
6771 }
···102106 case SIGURG:
103107 return LINUX_SIGURG;
104108 case SIGSTOP:
105105- return LINUX_SIGSTOP;
109109+ // Hack! See above.
110110+ //return LINUX_SIGSTOP;
111111+ return LINUX_SIGSTKFLT;
106112 case SIGTSTP:
107113 return LINUX_SIGTSTP;
108114 case SIGCONT:
+2-2
src/kernel/emulation/linux/signal/kill.c
···16161717 // If we're stopping a process we're debugging, do an emulated SIGSTOP
1818 // so that the tracee has a chance to talk to us before stopping.
1919- if (signum == SIGSTOP && pid > 0)
1919+ /*if (signum == SIGSTOP && pid > 0)
2020 {
2121 int tracer = lkm_call(NR_get_tracer, (void*)(long)pid);
2222 if (tracer == getpid())
···2424 linux_sigqueue(pid, SIGNAL_SIGEXC_THUPDATE, -LINUX_SIGSTOP);
2525 return 0;
2626 }
2727- }
2727+ }*/
28282929 linux_signum = signum_bsd_to_linux(signum);
3030 if (!linux_signum)
+100-4
src/kernel/emulation/linux/signal/sigaction.c
···17171818// Libc uses only one trampoline
1919void (*sa_tramp)(void*, int, int, struct bsd_siginfo*, void*) = 0;
2020-bsd_sig_handler* sig_handlers[32];
2020+bsd_sig_handler* sig_handlers[32] = {
2121+ [LINUX_SIGWINCH] = (bsd_sig_handler*) SIG_IGN,
2222+ [LINUX_SIGCHLD] = (bsd_sig_handler*) SIG_IGN,
2323+ [LINUX_SIGURG] = (bsd_sig_handler*) SIG_IGN,
2424+};
2125int sig_flags[32];
2226unsigned int sig_masks[32];
2327···4145 return 0;
4246 }
43474848+ if (nsa != NULL && linux_signum == LINUX_SIGCHLD)
4949+ {
5050+ sa_tramp = nsa->sa_tramp;
5151+ if (nsa->sa_sigaction != SIG_DFL && nsa->sa_sigaction != SIG_IGN
5252+ && nsa->sa_sigaction != SIG_ERR)
5353+ {
5454+ sa.sa_sigaction = &handler_linux_to_bsd;
5555+ }
5656+ else
5757+ sa.sa_sigaction = (linux_sig_handler*) nsa->sa_sigaction;
5858+5959+ sigset_bsd_to_linux(&nsa->sa_mask, &sa.sa_mask);
6060+ sa.sa_flags = sigflags_bsd_to_linux(nsa->sa_flags) | LINUX_SA_RESTORER;
6161+ sa.sa_restorer = sig_restorer;
6262+6363+ ret = LINUX_SYSCALL(__NR_rt_sigaction, linux_signum,
6464+ (nsa != NULL) ? &sa : NULL, &olsa,
6565+ sizeof(sa.sa_mask));
6666+6767+ if (ret < 0)
6868+ return errno_linux_to_bsd(ret);
6969+7070+ if (osa != NULL)
7171+ {
7272+ if (olsa.sa_sigaction == handler_linux_to_bsd)
7373+ osa->sa_sigaction = sig_handlers[linux_signum];
7474+ else // values such as SIG_DFL
7575+ osa->sa_sigaction = (bsd_sig_handler*) olsa.sa_sigaction;
7676+ sigset_linux_to_bsd(&olsa.sa_mask, &osa->sa_mask);
7777+ osa->sa_flags = sigflags_linux_to_bsd(olsa.sa_flags);
7878+ }
7979+ }
8080+ else
8181+ {
8282+ ret = 0;
8383+8484+ if (osa != NULL)
8585+ {
8686+ osa->sa_sigaction = sig_handlers[linux_signum];
8787+ osa->sa_flags = sig_flags[linux_signum];
8888+ osa->sa_mask = sig_masks[linux_signum];
8989+ }
9090+ }
9191+9292+ if (nsa != NULL && ret >= 0)
9393+ {
9494+ // __simple_printf("Saving handler for signal %d: %p\n", linux_signum, nsa->sa_sigaction);
9595+ sig_handlers[linux_signum] = nsa->sa_sigaction;
9696+ sig_flags[linux_signum] = nsa->sa_flags;
9797+ sig_masks[linux_signum] = nsa->sa_mask;
9898+ }
9999+100100+ return 0;
101101+}
102102+103103+#if 0
104104+long sys_sigaction(int signum, const struct bsd___sigaction* nsa, struct bsd_sigaction* osa)
105105+{
106106+ int ret, linux_signum;
107107+ struct linux_sigaction sa, olsa;
108108+109109+ linux_signum = signum_bsd_to_linux(signum);
110110+ if (linux_signum == 0)
111111+ {
112112+ // Some software (e.g. Node.js) tries to set up handlers for all signals by
113113+ // walking through all signal numbers incrementally. They end up hitting
114114+ // signals that don't exist on Linux and then bail out if they receive
115115+ // an error.
116116+ // Fake that everyting is all right.
117117+118118+ if (osa != NULL)
119119+ memset(osa, 0, sizeof(*osa));
120120+121121+ return 0;
122122+ }
123123+44124 if (nsa != NULL)
45125 {
46126 sa_tramp = nsa->sa_tramp;
4747- if (darling_am_i_ptraced())
127127+ /*if (darling_am_i_ptraced())
48128 {
49129 sa.sa_sigaction = &sigexc_handler;
50130 }
5151- else if (nsa->sa_sigaction != SIG_DFL && nsa->sa_sigaction != SIG_IGN
131131+ else*/ if (nsa->sa_sigaction != SIG_DFL && nsa->sa_sigaction != SIG_IGN
52132 && nsa->sa_sigaction != SIG_ERR)
53133 {
54134 sa.sa_sigaction = &handler_linux_to_bsd;
···8716788168 return 0;
89169}
170170+#endif
9017191172static void ucontext_linux_to_bsd(const struct linux_ucontext* lc, struct bsd_ucontext* bc, struct bsd_mcontext* bm)
92173{
···193274194275 // __simple_printf("Handling signal %d\n", linux_signum);
195276196196- sig_handlers[linux_signum](bsd_signum, info ? &binfo : NULL, (lc != NULL) ? &bc : NULL);
277277+ bsd_sig_handler* handler = sig_handlers[linux_signum];
278278+ if (sig_flags[linux_signum] & LINUX_SA_RESETHAND)
279279+ {
280280+ switch (linux_signum)
281281+ {
282282+ case LINUX_SIGWINCH:
283283+ case LINUX_SIGCHLD:
284284+ case LINUX_SIGURG:
285285+ sig_handlers[linux_signum] = (bsd_sig_handler*) SIG_IGN;
286286+ break;
287287+ default:
288288+ sig_handlers[linux_signum] = NULL; // SIG_DFL
289289+ }
290290+ }
291291+292292+ handler(bsd_signum, info ? &binfo : NULL, (lc != NULL) ? &bc : NULL);
197293198294 if (lc != NULL)
199295 {
+162-427
src/kernel/emulation/linux/signal/sigexc.c
···11+#include "sigaction.h"
12#include "sigexc.h"
23#include "../base.h"
34#include "../unistd/exit.h"
45#include <stddef.h>
56#include <sys/signal.h>
67#include <linux-syscalls/linux.h>
77-#include <pthread/tsd_private.h>
88-#include "signal/mach_exc.h"
99-#include "signal/exc.h"
108#include "sigaltstack.h"
119#include "../mach/lkm.h"
1210#include "../../../../external/lkm/api.h"
1311#include "../../../libsyscall/wrappers/_libkernel_init.h"
1212+#include "../../../../../platform-include/sys/mman.h"
1313+#include "../mman/mman.h"
1414#include "kill.h"
1515#include "../simple.h"
1616···2929void darling_sigexc_uninstall(void);
3030void sigrt_handler(int signum, struct linux_siginfo* info, void* ctxt);
31313232-#define SIGEXC_TSD_KEY 102
3333-#define SIGEXC_CONTEXT_TSD_KEY 103
3434-static char sigexc_altstack[8192];
3535-static struct bsd_stack orig_stack;
3232+static char sigexc_altstack[8*1024];
36333734#if defined(__x86_64__)
3835static void mcontext_to_thread_state(const struct linux_gregset* regs, x86_thread_state64_t* s);
···4643static void float_state_to_mcontext(const x86_float_state32_t* s, linux_fpregset_t fx);
4744#endif
48454949-static void state_to_kernel(struct linux_ucontext* ctxt, thread_t thread);
4646+static void state_from_kernel(struct linux_ucontext* ctxt, const struct thread_state* kernel_state);
4747+static void state_to_kernel(struct linux_ucontext* ctxt, struct thread_state* kernel_state);
50485149#define DEBUG_SIGEXC
5250#ifdef DEBUG_SIGEXC
···57555856void sigexc_setup1(void)
5957{
6060- kern_printf("sigexc_setup1()");
6161- // Setup handler for SIGNAL_SIGEXC_TOGGLE and SIGNAL_SIGEXC_THUPDATE
6262- handle_rt_signal(SIGNAL_SIGEXC_TOGGLE);
6363- handle_rt_signal(SIGNAL_SIGEXC_THUPDATE);
5858+ handle_rt_signal(SIGNAL_SIGEXC_SUSPEND);
6459}
65606661void sigexc_setup2(void)
6762{
6868- kern_printf("sigexc_setup2()\n");
6969-7063 linux_sigset_t set;
7171- set = (1ull << (SIGNAL_SIGEXC_TOGGLE-1));
7272- set |= (1ull << (SIGNAL_SIGEXC_THUPDATE-1));
6464+ set = (1ull << (SIGNAL_SIGEXC_SUSPEND-1));
6565+ //set |= (1ull << (SIGNAL_SIGEXC_THUPDATE-1));
73667467 LINUX_SYSCALL(__NR_rt_sigprocmask, 1 /* LINUX_SIG_UNBLOCK */,
7568 &set, NULL, sizeof(linux_sigset_t));
7676-7777- // If we have a tracer (i.e. we are a new process after execve),
7878- // enable sigexc handling and send SIGTRAP to self to allow
7979- // the debugger to handle this situation.
8080- if (!am_i_ptraced && lkm_call(NR_get_tracer, NULL) != 0)
8181- {
8282- kern_printf("sigexc: the parent is traced\n");
8383- darling_sigexc_self();
8484- sigexc_handler(LINUX_SIGTRAP, NULL, NULL);
8585- }
8669}
87708888-void sigexc_setup(void)
7171+static void dump_gregs(const struct linux_gregset* regs)
8972{
9090-#ifdef VARIANT_DYLD
9191- sigexc_setup1();
9292- if (lkm_call(NR_started_suspended, 0))
7373+ unsigned long long* p = (unsigned long long*) regs;
7474+ for (int i = 0; i < 23; i++)
9375 {
9494- kern_printf("sigexc: waiting for signal\n");
9595-9696- // sigsuspend until resumed or debugger attached
9797- linux_sigset_t set = -1ll;
9898- set &= ~(1ull << (LINUX_SIGCONT-1));
9999- set &= ~(1ull << (SIGNAL_SIGEXC_TOGGLE-1));
100100- set &= ~(1ull << (SIGNAL_SIGEXC_THUPDATE-1));
101101-102102- LINUX_SYSCALL(__NR_rt_sigsuspend, &set, 8);
103103-104104- kern_printf("sigexc: done waiting for signal\n");
7676+ kern_printf("sigexc: gregs 0x%x\n", p[i]);
10577 }
106106- sigexc_setup2();
107107-#else
108108- sigexc_setup1();
109109-110110- // get am_i_ptraced value from dyld
111111- bool (*is_traced)(void);
112112- _libkernel_functions->dyld_func_lookup("__dyld_am_i_ptraced", (void**) &is_traced);
113113- am_i_ptraced = is_traced();
114114-115115- if (am_i_ptraced)
116116- {
117117- // We have to take over from dyld's build of this file, because
118118- // we rely on having accurate signal handler information of the running application.
119119- kern_printf("sigexc: taking over sigexc handling\n");
120120- darling_sigexc_self();
121121- }
122122-#endif
12378}
1247912580static void handle_rt_signal(int signum)
···12883 struct linux_sigaction sa;
1298413085 sa.sa_sigaction = sigrt_handler;
131131- sa.sa_mask = 0;
132132- sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART;
8686+ sa.sa_mask = (1ull << (SIGNAL_SIGEXC_SUSPEND-1));
8787+ sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART | LINUX_SA_ONSTACK;
13388 sa.sa_restorer = sig_restorer;
1348913590 rv = LINUX_SYSCALL(__NR_rt_sigaction, signum,
···14196 //external/lkm_call(0x1028, buf);
14297}
14398144144-bool darling_am_i_ptraced(void)
9999+void sigexc_setup(void)
145100{
146146- return am_i_ptraced;
101101+ darling_sigexc_self();
102102+ sigexc_setup1();
103103+ sigexc_setup2();
104104+#ifdef VARIANT_DYLD
105105+ if (lkm_call(NR_started_suspended, 0))
106106+ {
107107+ kern_printf("sigexc: start_suspended -> suspending (ret to %p)\n", __builtin_return_address(0));
108108+ task_suspend(mach_task_self());
109109+ kern_printf("sigexc: start_suspended -> wokenup (ret to %p)\n", __builtin_return_address(0));
110110+ }
111111+ else if (lkm_call(NR_get_tracer, NULL) != 0)
112112+ {
113113+ kern_printf("sigexc: already traced -> SIGTRAP\n");
114114+ sys_kill(0, SIGTRAP, 0);
115115+ }
116116+#else
117117+118118+#endif
147119}
148120149121void sigrt_handler(int signum, struct linux_siginfo* info, void* ctxt)
150122{
151151- kern_printf("sigexc: sigrt_handler signum=%d, si_value=%x\n", signum, info->si_value);
123123+#if defined(__x86_64__)
124124+ x86_thread_state64_t tstate;
125125+ x86_float_state64_t fstate;
126126+#elif defined(__i386__)
127127+ x86_thread_state32_t tstate;
128128+ x86_float_state32_t fstate;
129129+#endif
152130153153- if (signum == SIGNAL_SIGEXC_TOGGLE)
154154- {
155155- if (((uint32_t) info->si_value) == SIGRT_MAGIC_ENABLE_SIGEXC)
156156- {
157157- darling_sigexc_self();
131131+ struct thread_suspended_args args;
132132+ args.state.tstate = &tstate;
133133+ args.state.fstate = &fstate;
158134159159- // Stop on attach
160160- sigexc_handler(LINUX_SIGSTOP, NULL, (struct linux_ucontext*) ctxt);
161161- }
162162- else if (((uint32_t) info->si_value) == SIGRT_MAGIC_DISABLE_SIGEXC)
163163- {
164164- darling_sigexc_uninstall();
165165- }
166166- }
167167- else if (signum == SIGNAL_SIGEXC_THUPDATE)
168168- {
169169- if (!am_i_ptraced)
170170- return;
135135+ kern_printf("sigexc: sigrt_handler SUSPEND\n");
136136+137137+ thread_t thread = mach_thread_self();
138138+ state_to_kernel(ctxt, &args.state);
171139172172- // Examine info->si_value
173173- // If 0, drop the signal
174174- // If >0, process the signal
175175- // If <0, introduce a new signal
176176- int sig = info->si_value;
177177- if (sig == SIGNAL_THREAD_SUSPEND)
178178- {
179179- kern_printf("sigexc: SIGNAL_THREAD_SUSPEND\n");
180180- if (_pthread_getspecific_direct(SIGEXC_TSD_KEY) == 0)
181181- sigexc_fake_suspend(ctxt);
182182- else
183183- {
184184- kern_printf("sigexc: already suspended\n");
185185- void* ctxt = _pthread_getspecific_direct(SIGEXC_CONTEXT_TSD_KEY);
140140+ lkm_call(NR_thread_suspended, &args);
186141187187- if (ctxt)
188188- {
189189- thread_t thread = mach_thread_self();
190190- state_to_kernel(ctxt, thread);
191191- kern_printf("sigexc: state_to_kernel complete\n");
192192- }
193193- }
194194- }
195195- else if (sig == SIGNAL_THREAD_RESUME)
196196- {
197197- kern_printf("sigexc: SIGNAL_THREAD_RESUME\n");
198198- }
199199- else if (sig < 0)
200200- {
201201- // This is only used to pass a SIGSTOP to the traced process (from the debugger)
202202- // and have it passed back through the sigexc mechanism.
203203- // See sys_kill().
204204- sigexc_handler(-sig, NULL, (struct linux_ucontext*) ctxt);
205205- }
206206- else
207207- {
208208- // This is the debugger telling us how to deal with the signal.
209209- _pthread_setspecific_direct(SIGEXC_TSD_KEY, sig);
210210- }
211211- }
142142+ state_from_kernel(ctxt, &args.state);
212143}
144144+213145214146void darling_sigexc_self(void)
215147{
···219151 // Make sigexc_handler the handler for all signals in the process
220152 for (int i = 1; i <= 31; i++)
221153 {
222222- if (i == LINUX_SIGSTOP || i == LINUX_SIGKILL)
154154+ if (i == LINUX_SIGSTOP || i == LINUX_SIGKILL || i == LINUX_SIGCHLD)
223155 continue;
224156225157 struct linux_sigaction sa;
226158 sa.sa_sigaction = (linux_sig_handler*) sigexc_handler;
227159 sa.sa_mask = 0x7fffffff; // all other standard Unix signals should be blocked while the handler is run
160160+ sa.sa_mask |= (1ull << (SIGNAL_SIGEXC_SUSPEND-1));
228161 sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART | LINUX_SA_ONSTACK;
229162 sa.sa_restorer = sig_restorer;
230163···238171 .ss_size = sizeof(sigexc_altstack),
239172 .ss_flags = 0
240173 };
241241- sys_sigaltstack(&newstack, &orig_stack);
174174+ sys_sigaltstack(&newstack, NULL);
242175}
243243-void darling_sigexc_uninstall(void)
244244-{
245245- am_i_ptraced = false;
246176247247- // __simple_printf("darling_sigexc_uninstall()\n");
248248- for (int i = 1; i <= 31; i++)
249249- {
250250- if (i == LINUX_SIGSTOP || i == LINUX_SIGKILL)
251251- continue;
252252-253253- struct linux_sigaction sa;
254177255255- if (sig_handlers[i] == SIG_DFL || sig_handlers[i] != SIG_IGN
256256- || sig_handlers[i] != SIG_ERR)
257257- {
258258- sa.sa_sigaction = (linux_sig_handler*) sig_handlers[i];
259259- }
260260- else
261261- sa.sa_sigaction = &handler_linux_to_bsd;
262262-263263- sa.sa_mask = sig_masks[i];
264264- sa.sa_flags = sig_flags[i];
265265- sa.sa_restorer = sig_restorer;
266266-267267- LINUX_SYSCALL(__NR_rt_sigaction, i,
268268- &sa, NULL,
269269- sizeof(sa.sa_mask));
270270- }
271271-272272- sys_sigaltstack(&orig_stack, NULL);
273273-}
274274-275275-static mach_port_t get_exc_port(int type, int* behavior)
276276-{
277277- mach_msg_type_number_t count = 0;
278278- exception_mask_t masks[EXC_TYPES_COUNT];
279279- mach_port_t ports[EXC_TYPES_COUNT];
280280- exception_behavior_t behaviors[EXC_TYPES_COUNT];
281281- thread_state_flavor_t flavors[EXC_TYPES_COUNT];
282282-283283- kern_return_t result = task_get_exception_ports(mach_task_self(), 1 << type,
284284- masks, &count, ports, behaviors, flavors);
285285-286286- if (result != KERN_SUCCESS)
287287- return 0;
288288-289289- for (int i = 0; i < count; i++)
290290- {
291291- if (masks[i] & (1 << type))
292292- {
293293- if (behavior != NULL)
294294- *behavior = behaviors[i];
295295- return ports[i];
296296- }
297297- }
298298-299299- return 0;
300300-}
301301-302302-static void state_to_kernel(struct linux_ucontext* ctxt, thread_t thread)
178178+static void state_to_kernel(struct linux_ucontext* ctxt, struct thread_state* kernel_state)
303179{
304180#if defined(__x86_64__)
305305- x86_thread_state64_t tstate;
306306- x86_float_state64_t fstate;
307181308308- if (ctxt != NULL)
309309- {
310310- mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, &tstate);
311311- mcontext_to_float_state(ctxt->uc_mcontext.fpregs, &fstate);
312312- /*
313313-#ifdef __x86_64__
314314- if (bsd_signum == SIGTRAP)
315315- {
316316- uint8_t* rip = (uint8_t*) ctxt->uc_mcontext.gregs.rip;
317317- kern_printf("rip is %p\n", rip);
318318- kern_printf("Value at rip-1 on suspend: 0x%x\n", *(rip-1));
319319- }
320320-#endif
321321- */
322322- }
323323- else
324324- {
325325- memset(&tstate, 0, sizeof(tstate));
326326- memset(&fstate, 0, sizeof(fstate));
327327- }
182182+ dump_gregs(&ctxt->uc_mcontext.gregs);
183183+ mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, (x86_thread_state64_t*) kernel_state->tstate);
184184+ mcontext_to_float_state(ctxt->uc_mcontext.fpregs, (x86_float_state64_t*) kernel_state->fstate);
328185329329- __simple_kprintf("sigexc: Telling kernel our RIP is %p\n", tstate.__rip);
330330-331331- thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t) &tstate, x86_THREAD_STATE64_COUNT);
332332- thread_set_state(thread, x86_FLOAT_STATE64, (thread_state_t) &fstate, x86_FLOAT_STATE64_COUNT);
333186#elif defined(__i386__)
334334- x86_thread_state32_t tstate;
335335- x86_float_state32_t fstate;
336336-337337- if (ctxt != NULL)
338338- {
339339- mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, &tstate);
340340- mcontext_to_float_state(ctxt->uc_mcontext.fpregs, &fstate);
341341- }
342342- else
343343- {
344344- memset(&tstate, 0, sizeof(tstate));
345345- memset(&fstate, 0, sizeof(fstate));
346346- }
347347-348348- thread_set_state(thread, x86_THREAD_STATE32, (thread_state_t) &tstate, x86_THREAD_STATE32_COUNT);
349349- thread_set_state(thread, x86_FLOAT_STATE32, (thread_state_t) &fstate, x86_FLOAT_STATE32_COUNT);
187187+ mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, (x86_thread_state32_t*) kernel_state->tstate);
188188+ mcontext_to_float_state(ctxt->uc_mcontext.fpregs, (x86_float_state32_t*) kernel_state->fstate);
350189#endif
351190352191}
353192354354-static void state_from_kernel(struct linux_ucontext* ctxt, thread_t thread)
193193+static void state_from_kernel(struct linux_ucontext* ctxt, const struct thread_state* kernel_state)
355194{
356195#if defined(__x86_64__)
357357- x86_thread_state64_t tstate;
358358- x86_float_state64_t fstate;
359359- mach_msg_type_number_t count;
360196361361- count = x86_THREAD_STATE64_COUNT;
362362- thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t) &tstate, &count);
363363- count = x86_FLOAT_STATE64_COUNT;
364364- thread_get_state(thread, x86_FLOAT_STATE64, (thread_state_t) &fstate, &count);
197197+ thread_state_to_mcontext((x86_thread_state64_t*) kernel_state->tstate, &ctxt->uc_mcontext.gregs);
198198+ float_state_to_mcontext((x86_float_state64_t*) kernel_state->fstate, ctxt->uc_mcontext.fpregs);
365199366366- thread_state_to_mcontext(&tstate, &ctxt->uc_mcontext.gregs);
367367- float_state_to_mcontext(&fstate, ctxt->uc_mcontext.fpregs);
200200+ dump_gregs(&ctxt->uc_mcontext.gregs);
368201369202#elif defined(__i386__)
370370- x86_thread_state32_t tstate;
371371- x86_float_state32_t fstate;
372372- mach_msg_type_number_t count;
373373-374374- count = x86_THREAD_STATE32_COUNT;
375375- thread_get_state(thread, x86_THREAD_STATE32, (thread_state_t) &tstate, &count);
376376- count = x86_FLOAT_STATE32_COUNT;
377377- thread_get_state(thread, x86_FLOAT_STATE32, (thread_state_t) &fstate, &count);
378378-379379- thread_state_to_mcontext(&tstate, &ctxt->uc_mcontext.gregs);
380380- float_state_to_mcontext(&fstate, ctxt->uc_mcontext.fpregs);
203203+ thread_state_to_mcontext((x86_thread_state32_t*) kernel_state->tstate, &ctxt->uc_mcontext.gregs);
204204+ float_state_to_mcontext((x86_float_state32_t*) kernel_state->fstate, ctxt->uc_mcontext.fpregs);
381205#endif
382206}
383207384384-void sigexc_fake_suspend(struct linux_ucontext* ctxt)
385385-{
386386- if (_pthread_getspecific_direct(SIGEXC_TSD_KEY) != 0)
387387- return;
388388- thread_t thread = mach_thread_self();
389389-390390- kern_printf("sigexc_fake_suspend -> state_to_kernel\n");
391391- state_to_kernel(ctxt, thread);
392392-393393- linux_sigset_t set = -1ll;
394394- set &= ~(1ull << (SIGNAL_SIGEXC_THUPDATE-1));
395395-396396- LINUX_SYSCALL(__NR_rt_sigsuspend, &set, 8);
397397-398398- kern_printf("sigexc_fake_suspend -> state_from_kernel\n");
399399- state_from_kernel(ctxt, thread);
400400-}
401401-402402-// syscall tracking
403403-#define LINUX_TRAP_BRKPT 1
404404-// single-stepping
405405-#define LINUX_TRAP_TRACE 2
406406-// ???
407407-#define LINUX_TRAP_BRANCH 3
408408-// memory watchpoint
409409-#define LINUX_TRAP_HWBKPT 4
410410-// int3 (on x86, other platforms probably use TRAP_BRKPT)
411411-#define LINUX_SI_KERNEL 0x80
412412-413208void sigexc_handler(int linux_signum, struct linux_siginfo* info, struct linux_ucontext* ctxt)
414209{
415210 kern_printf("sigexc_handler(%d, %p, %p)\n", linux_signum, info, ctxt);
416211417417- if (!darling_am_i_ptraced())
418418- {
419419- kern_printf("sigexc: NOT TRACED!\n");
420420- return;
421421- }
422422-212212+423213 if (linux_signum == LINUX_SIGCONT)
424214 return;
425215426426- // Send a Mach message to the debugger.
427427- // The debugger may use ptrace(PT_THUPDATE) to change how the signal is processed.
428428-429429- int mach_exception, behavior;
430430- long long codes[EXCEPTION_CODE_MAX] = { 0 };
431431- mach_port_t port;
432432- thread_t thread = mach_thread_self();
433433-434216 int bsd_signum = signum_linux_to_bsd(linux_signum);
435217 if (bsd_signum <= 0)
436218 {
···438220 return;
439221 }
440222441441- if (linux_signum == 11)
442442- {
443443- kern_printf("sigexc: faulting address: %p, code: %d\n", info->si_addr, info->si_code);
444444- }
223223+ struct sigprocess_args sigprocess;
224224+ sigprocess.signum = bsd_signum;
445225446446- // SIGSEGV + SIGBUS -> EXC_BAD_ACCESS
447447- // SIGTRAP -> EXC_BREAKPOINT
448448- // SIGILL -> EXC_BAD_INSTRUCTION
449449- // SIGFPE -> EXC_ARITHMETIC
450450- // * -> EXC_SOFTWARE with EXC_SOFT_SIGNAL (e.g. SIGSTOP)
226226+ memcpy(&sigprocess.linux_siginfo, info, sizeof(*info));
227227+228228+#ifdef __x86_64__
229229+ kern_printf("sigexc: have RIP 0x%x\n", ctxt->uc_mcontext.gregs.rip);
230230+#endif
451231452452- // Only real exceptions produced by the CPU get translated to these
453453- // Mach exceptions. The rest comes as EXC_SOFTWARE.
454454- if (info != NULL && info->si_code != 0)
455455- {
456456- switch (bsd_signum)
457457- {
458458- case SIGSEGV:
459459- mach_exception = EXC_BAD_ACCESS;
460460- codes[0] = EXC_I386_GPFLT;
461461- break;
462462- case SIGBUS:
463463- mach_exception = EXC_BAD_ACCESS;
464464- codes[0] = EXC_I386_ALIGNFLT;
465465- break;
466466- case SIGILL:
467467- mach_exception = EXC_BAD_INSTRUCTION;
468468- codes[0] = EXC_I386_INVOP;
469469- break;
470470- case SIGFPE:
471471- mach_exception = EXC_ARITHMETIC;
472472- codes[0] = info->si_code;
473473- break;
474474- case SIGTRAP:
475475- mach_exception = EXC_BREAKPOINT;
476476- codes[0] = (info->si_code == LINUX_SI_KERNEL) ? EXC_I386_BPT : EXC_I386_SGL;
232232+ thread_t thread = mach_thread_self();
477233478478- if (info->si_code == LINUX_TRAP_HWBKPT)
479479- {
480480- // Memory watchpoint triggered
481481- struct last_triggered_watchpoint_args args;
482482- if (lkm_call(NR_last_triggered_watchpoint, &args) == 0)
483483- {
484484- codes[1] = args.address;
485485- // codes[2] = args.flags;
486486- }
487487- }
488488- break;
489489- default:
490490- mach_exception = EXC_SOFTWARE;
491491- codes[0] = EXC_SOFT_SIGNAL;
492492- codes[1] = bsd_signum;
493493- }
494494- }
495495- else
496496- {
497497- mach_exception = EXC_SOFTWARE;
498498- codes[0] = EXC_SOFT_SIGNAL;
499499- codes[1] = bsd_signum;
500500- }
234234+#if defined(__x86_64__)
235235+ x86_thread_state64_t tstate;
236236+ x86_float_state64_t fstate;
237237+#elif defined(__i386__)
238238+ x86_thread_state32_t tstate;
239239+ x86_float_state32_t fstate;
240240+#endif
501241502502- port = get_exc_port(mach_exception, &behavior);
242242+ sigprocess.state.tstate = &tstate;
243243+ sigprocess.state.fstate = &fstate;
503244504504- // Pass register states to LKM
505505- state_to_kernel(ctxt, thread);
245245+ state_to_kernel(ctxt, &sigprocess.state);
246246+ lkm_call(NR_sigprocess, &sigprocess);
247247+ state_from_kernel(ctxt, &sigprocess.state);
506248507507- // __simple_printf("Passing Mach exception to port %d\n", port);
508508- if (port != 0)
249249+ if (!sigprocess.signum)
509250 {
510510- _pthread_setspecific_direct(SIGEXC_TSD_KEY, bsd_signum);
511511- _pthread_setspecific_direct(SIGEXC_CONTEXT_TSD_KEY, ctxt);
512512-513513- kern_return_t ret;
251251+ kern_printf("sigexc: drop signal\n");
252252+ return;
253253+ }
514254515515- if (behavior & MACH_EXCEPTION_CODES)
516516- {
517517- ret = mach_exception_raise(port, thread, mach_task_self(), mach_exception, codes, sizeof(codes) / sizeof(codes[0]));
518518- }
519519- else
520520- {
521521- exception_data_type_t small_codes[2] = { (exception_data_type_t) codes[0], (exception_data_type_t) codes[1] };
522522- ret = exception_raise(port, thread, mach_task_self(), mach_exception, small_codes, sizeof(small_codes) / sizeof(small_codes[0]));
523523- }
255255+ linux_signum = signum_bsd_to_linux(sigprocess.signum);
524256525525- if (ret == MACH_RCV_PORT_DIED || ret == MACH_SEND_INVALID_DEST)
257257+ if (sig_handlers[linux_signum] != SIG_IGN)
258258+ {
259259+ if (sig_handlers[linux_signum])
526260 {
527527- kern_printf("Exception handler death? ret is 0x%x\n", ret);
528528- darling_sigexc_uninstall();
529529- }
261261+ kern_printf("sigexc: will forward signal to app handler (%p)\n", sig_handlers[linux_signum]);
530262531531- bsd_signum = _pthread_getspecific_direct(SIGEXC_TSD_KEY);
532532- _pthread_setspecific_direct(SIGEXC_TSD_KEY, 0);
533533- }
263263+ // Update the signal mask to what the application actually wanted
264264+ linux_sigset_t set = sig_masks[linux_signum];
534265535535- // Get (possibly updated by GDB) register states from LKM
536536- if (ctxt != NULL)
537537- state_from_kernel(ctxt, thread);
266266+ // Keep the current signal blocked, which is the default behavior
267267+ if (!(sig_flags[linux_signum] & LINUX_SA_NODEFER))
268268+ set |= (1ull << (linux_signum-1));
538269539539- // Pass the signal to the application handler or emulate the effects of the signal if SIG_DFL is set.
540540- if (bsd_signum)
541541- {
542542- const int linux_signum = signum_bsd_to_linux(bsd_signum);
270270+ LINUX_SYSCALL(__NR_rt_sigprocmask, 2 /* LINUX_SIG_SETMASK */,
271271+ &set, NULL, sizeof(linux_sigset_t));
543272544544- bsd_sig_handler* handler = sig_handlers[linux_signum];
545545- if (handler == SIG_DFL || handler == SIG_ERR)
273273+ handler_linux_to_bsd(linux_signum, info, ctxt);
274274+ }
275275+ else
546276 {
547547- /*
548548- switch (bsd_signum)
277277+ if (sigprocess.signum == SIGTSTP || sigprocess.signum == SIGSTOP)
278278+ {
279279+ kern_printf("sigexc: emulating SIGTSTP/SIGSTOP\n");
280280+ LINUX_SYSCALL(__NR_kill, 0, LINUX_SIGSTOP);
281281+ }
282282+ else
549283 {
550550- // We have to stop the process manually
551551- case SIGSTOP:
552552- case SIGTSTP:
553553- task_suspend(mach_task_self());
554554- break;
284284+ kern_printf("sigexc: emulating default signal effects\n");
285285+ // Set handler to SIG_DFL
286286+ struct linux_sigaction sa;
287287+ sa.sa_sigaction = (linux_sig_handler*) NULL; // SIG_DFL
288288+ sa.sa_mask = 0x7fffffff; // all other standard Unix signals should be blocked while the handler is run
289289+ sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART | LINUX_SA_ONSTACK;
290290+ sa.sa_restorer = sig_restorer;
291291+292292+ LINUX_SYSCALL(__NR_rt_sigaction, linux_signum,
293293+ &sa, NULL,
294294+ sizeof(sa.sa_mask));
555295556556- // These signals do nothing by default
557557- case SIGCHLD:
558558- case SIGWINCH:
559559- case SIGURG:
560560- break;
561561- case SIGTRAP:
562562- if (ctxt == NULL)
563563- break; // This trap wasn't caused by int3, carry on
564564-565565- // Other signals cause termination or core dump.
566566- default:
567567- {
568568- int linux_signum = signum_bsd_to_linux(bsd_signum);
569569- sys_exit(linux_signum);
570570- }
296296+ // Resend signal to self
297297+ LINUX_SYSCALL(__NR_kill, 0, linux_signum);
571298 }
572572- */
573573- }
574574- else if (handler != SIG_IGN)
575575- {
576576- handler_linux_to_bsd(linux_signum, info, ctxt);
577299 }
578300 }
579579-301301+580302 kern_printf("sigexc: handler (%d) returning\n", linux_signum);
581303}
304304+305305+#define DUMPREG(regname) kern_printf("sigexc: " #regname ": 0x%x\n", regs->regname);
582306583307#if defined(__x86_64__)
584308void mcontext_to_thread_state(const struct linux_gregset* regs, x86_thread_state64_t* s)
···605329 s->__fs = regs->fs;
606330 s->__gs = regs->gs;
607331608608- kern_printf("sigexc: saving to kernel: RIP %p, eflags 0x%x\n", regs->rip, regs->efl);
332332+ kern_printf("sigexc: saving to kernel:\n");
333333+ DUMPREG(rip);
334334+ DUMPREG(efl);
335335+ DUMPREG(rax);
336336+ DUMPREG(rbx);
337337+ DUMPREG(rcx);
338338+ DUMPREG(rdx);
339339+ DUMPREG(rdi);
340340+ DUMPREG(rsi);
341341+ DUMPREG(rbp);
342342+ DUMPREG(rsp);
609343}
610344611345void mcontext_to_float_state(const linux_fpregset_t fx, x86_float_state64_t* s)
···651385 regs->fs = s->__fs;
652386 regs->gs = s->__gs;
653387654654- kern_printf("sigexc: Next RIP will be %p, eflags: 0x%x\n", regs->rip, regs->efl); // single step trace bit is 0x100
388388+ kern_printf("sigexc: restored from kernel:\n");
389389+ DUMPREG(rip);
390390+ DUMPREG(efl);
391391+ DUMPREG(rax);
392392+ DUMPREG(rbx);
393393+ DUMPREG(rcx);
394394+ DUMPREG(rdx);
395395+ DUMPREG(rdi);
396396+ DUMPREG(rsi);
397397+ DUMPREG(rbp);
398398+ DUMPREG(rsp);
655399}
656400657401void float_state_to_mcontext(const x86_float_state64_t* s, linux_fpregset_t fx)
···746490}
747491#endif
748492749749-#define LINUX_SI_QUEUE (-1)
750750-int linux_sigqueue(int pid, int rtsig, int value)
493493+void sigexc_thread_setup(void)
751494{
752752- struct linux_siginfo si;
495495+ struct bsd_stack newstack = {
496496+ .ss_size = sizeof(sigexc_altstack),
497497+ .ss_flags = 0
498498+ };
753499754754- memset(&si, 0, sizeof(si));
755755- si.si_signo = rtsig;
756756- si.si_code = LINUX_SI_QUEUE;
757757- si.si_pid = getpid();
758758- si.si_uid = LINUX_SYSCALL(__NR_getuid);
759759- si.si_value = value;
760760-761761- return LINUX_SYSCALL(__NR_rt_sigqueueinfo, pid, rtsig, &si);
500500+ newstack.ss_sp = (void*) sys_mmap(NULL, sizeof(sigexc_altstack), PROT_READ | PROT_WRITE,
501501+ MAP_ANON | MAP_PRIVATE, -1, 0);
502502+ sys_sigaltstack(&newstack, NULL);
762503}
763504764764-int linux_sigqueue_thread(int pid, int tid, int rtsig, int value)
505505+void sigexc_thread_exit(void)
765506{
766766- struct linux_siginfo si;
767767-768768- memset(&si, 0, sizeof(si));
769769- si.si_signo = rtsig;
770770- si.si_code = LINUX_SI_QUEUE;
771771- si.si_pid = getpid();
772772- si.si_uid = LINUX_SYSCALL(__NR_getuid);
773773- si.si_value = value;
507507+ struct bsd_stack oldstack;
508508+ sys_sigaltstack(NULL, &oldstack);
774509775775- return LINUX_SYSCALL(__NR_rt_tgsigqueueinfo, pid, tid, rtsig, &si);
510510+ sys_munmap(oldstack.ss_sp, oldstack.ss_flags);
776511}
777512
+3-15
src/kernel/emulation/linux/signal/sigexc.h
···6677// NOTE: Keep these definitions up to date with lkm/darling/binfmt.c!
88// Uses one of the below magic values to toggle the debugging state
99-#define SIGNAL_SIGEXC_TOGGLE LINUX_SIGRTMIN
1010-1111-// A BSD signal number is passed as value
1212-#define SIGNAL_SIGEXC_THUPDATE (LINUX_SIGRTMIN + 1)
1313-1414-#define SIGNAL_THREAD_SUSPEND -100
1515-#define SIGNAL_THREAD_RESUME -101
1616-1717-#define SIGRT_MAGIC_ENABLE_SIGEXC 0xdebdeb01
1818-#define SIGRT_MAGIC_DISABLE_SIGEXC 0xdebdeb00
99+#define SIGNAL_SIGEXC_SUSPEND LINUX_SIGRTMIN
19102011void sigexc_setup(void);
2121-2222-// Is this process currently traced by a debugger?
2323-bool darling_am_i_ptraced(void);
24122513// for PT_SIGEXC to handle this operation synchronously
2614void darling_sigexc_self(void);
2715void sigexc_handler(int linux_signum, struct linux_siginfo* info, struct linux_ucontext* ctxt);
28162929-int linux_sigqueue(int pid, int rtsig, int value);
3030-int linux_sigqueue_thread(int pid, int tid, int rtsig, int value);
1717+void sigexc_thread_setup(void);
1818+void sigexc_thread_exit(void);
31193220#endif
3321