this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Work in progress on debugging support - fixes for process synchronization with debugserver

+122 -38
+1
src/kernel/emulation/linux/mach/CMakeLists.txt
··· 7 7 ${CMAKE_SOURCE_DIR}/src/kernel/emulation/linux/ext 8 8 ${CMAKE_SOURCE_DIR}/src/kernel/libsyscall/wrappers 9 9 ${CMAKE_SOURCE_DIR}/src/startup 10 + ${CMAKE_BINARY_DIR}/src/startup 10 11 ) 11 12 12 13 set(mach_server_client_sources
+9 -3
src/kernel/emulation/linux/mach/lkm.c
··· 1 1 #include "lkm.h" 2 2 #include "../../lkm/api.h" 3 + #include "../signal/sigexc.h" 4 + #include "../base.h" 5 + #include "../linux-syscalls/linux.h" 3 6 #include <fcntl.h> 4 7 #include <unistd.h> 5 8 #include <sys/resource.h> ··· 19 22 extern int sys_dup2(int, int); 20 23 extern int sys_fcntl(int, int, int); 21 24 extern _libkernel_functions_t _libkernel_functions; 25 + 26 + extern void sigexc_setup1(void); 27 + extern void sigexc_setup2(void); 22 28 23 29 static void setup_dyld_info(void); 24 30 ··· 37 43 38 44 driver_fd = (*p)(); 39 45 46 + // Setup TASK_DYLD_INFO (needed for debuggers) 47 + setup_dyld_info(); 48 + 40 49 if (driver_fd != -1) 41 50 return; 42 51 } ··· 70 79 71 80 driver_fd = d; 72 81 } 73 - 74 - // Setup TASK_DYLD_INFO (needed for debuggers) 75 - setup_dyld_info(); 76 82 } 77 83 78 84 static void setup_dyld_info(void)
+14 -3
src/kernel/emulation/linux/misc/ptrace.c
··· 66 66 else 67 67 { 68 68 // This triggers darling_sigexc_self() in the remote process. 69 - linux_sigqueue(pid, SIGNAL_SIGEXC_TOGGLE, SIGRT_MAGIC_ENABLE_SIGEXC); 69 + ret = linux_sigqueue(pid, SIGNAL_SIGEXC_TOGGLE, SIGRT_MAGIC_ENABLE_SIGEXC); 70 + 71 + if (ret < 0) 72 + ret = errno_linux_to_bsd(ret); 73 + // This doesn't work if the process is stopped, e.g. when spawning a stopped 74 + // process via posix_spawn(). So now we have to resume the process so that 75 + // it gets the RT signal above and triggers a fake SIGSTOP on its own. 76 + // int pstate = lkm_call(NR_pid_get_state, (void*)(long) pid); 77 + // if (pstate & 4 /* __TASK_STOPPED */) 78 + // sys_kill(pid, SIGCONT, 1); 70 79 } 71 80 72 81 cmd = "PT_ATTACHEXC"; ··· 151 160 } 152 161 } 153 162 163 + char buf[128]; 154 164 if (cmd != NULL) 155 - __simple_printf("ptrace() req=%s, ret=%d\n", cmd, ret); 165 + __simple_sprintf(buf, "ptrace() req=%s, ret=%d\n", cmd, ret); 156 166 else 157 - __simple_printf("ptrace() req=%d\n", request); 167 + __simple_sprintf(buf, "ptrace() req=%d\n", request); 168 + lkm_call(0x1028, buf); 158 169 159 170 return ret; 160 171 }
+11
src/kernel/emulation/linux/process/execve.c
··· 6 6 #include "../unistd/read.h" 7 7 #include "../unistd/close.h" 8 8 #include "../unistd/readlink.h" 9 + #include "../signal/sigexc.h" 9 10 #include <stdint.h> 10 11 #include <stddef.h> 11 12 #include <stdbool.h> ··· 149 150 150 151 // otherwise, it's a native Linux executable (ELF) 151 152 153 + linux_sigset_t set; 154 + set = (1ull << (SIGNAL_SIGEXC_TOGGLE-1)); 155 + set |= (1ull << (SIGNAL_SIGEXC_THUPDATE-1)); 156 + 157 + LINUX_SYSCALL(__NR_rt_sigprocmask, 0 /* LINUX_SIG_BLOCK */, 158 + &set, NULL, sizeof(linux_sigset_t)); 159 + 152 160 ret = LINUX_SYSCALL(__NR_execve, fname, argvp, envp); 153 161 if (ret < 0) 154 162 ret = errno_linux_to_bsd(ret); 163 + 164 + LINUX_SYSCALL(__NR_rt_sigprocmask, 1 /* LINUX_SIG_UNBLOCK */, 165 + &set, NULL, sizeof(linux_sigset_t)); 155 166 156 167 return ret; 157 168 }
+83 -30
src/kernel/emulation/linux/signal/sigexc.c
··· 40 40 static void float_state_to_mcontext(const x86_float_state32_t* s, linux_fpregset_t fx); 41 41 #endif 42 42 43 - void sigexc_setup(void) 43 + char xyzbuf[128]; 44 + void sigexc_setup1(void) 44 45 { 46 + lkm_call(0x1028, "sigexc_setup1()"); 45 47 // Setup handler for SIGNAL_SIGEXC_TOGGLE and SIGNAL_SIGEXC_THUPDATE 46 48 handle_rt_signal(SIGNAL_SIGEXC_TOGGLE); 47 49 handle_rt_signal(SIGNAL_SIGEXC_THUPDATE); 50 + } 51 + 52 + void sigexc_setup2(void) 53 + { 54 + lkm_call(0x1028, xyzbuf); 55 + lkm_call(0x1028, "sigexc_setup2()\n"); 56 + 57 + linux_sigset_t set; 58 + set = (1ull << (SIGNAL_SIGEXC_TOGGLE-1)); 59 + set |= (1ull << (SIGNAL_SIGEXC_THUPDATE-1)); 60 + 61 + LINUX_SYSCALL(__NR_rt_sigprocmask, 1 /* LINUX_SIG_UNBLOCK */, 62 + &set, NULL, sizeof(linux_sigset_t)); 48 63 49 64 // If we have a tracer (i.e. we are a new process after execve), 50 65 // enable sigexc handling and send SIGTRAP to self to allow 51 66 // the debugger to handle this situation. 52 - if (lkm_call(NR_get_tracer, NULL) != 0) 67 + if (!am_i_ptraced && lkm_call(NR_get_tracer, NULL) != 0) 53 68 { 54 69 __simple_printf("the predecessor is traced\n"); 55 70 darling_sigexc_self(); ··· 57 72 } 58 73 } 59 74 75 + void sigexc_setup(void) 76 + { 77 + sigexc_setup1(); 78 + if (lkm_call(NR_started_suspended, 0)) 79 + { 80 + // sigsuspend until resumed or debugger attached 81 + linux_sigset_t set = -1ll; 82 + set &= ~(1ull << (LINUX_SIGCONT-1)); 83 + set &= ~(1ull << (SIGNAL_SIGEXC_TOGGLE-1)); 84 + set &= ~(1ull << (SIGNAL_SIGEXC_THUPDATE-1)); 85 + 86 + LINUX_SYSCALL(__NR_rt_sigsuspend, &set, 8); 87 + } 88 + sigexc_setup2(); 89 + } 90 + 60 91 static void handle_rt_signal(int signum) 61 92 { 62 - struct linux_sigaction sa; 93 + int rv; 94 + struct linux_sigaction sa; 95 + 63 96 sa.sa_sigaction = sigrt_handler; 64 97 sa.sa_mask = 0; 65 98 sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART; 66 99 sa.sa_restorer = sig_restorer; 67 100 68 - LINUX_SYSCALL(__NR_rt_sigaction, signum, 101 + rv = LINUX_SYSCALL(__NR_rt_sigaction, signum, 69 102 &sa, NULL, 70 103 sizeof(sa.sa_mask)); 104 + 105 + //char buf[128]; 106 + __simple_sprintf(xyzbuf, "Setting handler for RT signal %d: %d", signum, rv); 107 + //lkm_call(0x1028, buf); 71 108 } 72 109 73 110 bool darling_am_i_ptraced(void) ··· 77 114 78 115 void sigrt_handler(int signum, struct linux_siginfo* info, void* ctxt) 79 116 { 80 - __simple_printf("sigrt_handler signum=%d\n", signum); 117 + char buf[128]; 118 + __simple_sprintf(buf, "sigrt_handler signum=%d, si_value=%x\n", signum, info->si_value); 119 + lkm_call(0x1028, buf); 81 120 if (signum == SIGNAL_SIGEXC_TOGGLE) 82 121 { 83 - if (info->si_value == SIGRT_MAGIC_ENABLE_SIGEXC) 122 + if (((uint32_t) info->si_value) == SIGRT_MAGIC_ENABLE_SIGEXC) 84 123 { 85 124 darling_sigexc_self(); 86 125 87 126 // Stop on attach 88 127 sigexc_handler(LINUX_SIGSTOP, NULL, NULL); 89 128 } 90 - else if (info->si_value == SIGRT_MAGIC_DISABLE_SIGEXC) 129 + else if (((uint32_t) info->si_value) == SIGRT_MAGIC_DISABLE_SIGEXC) 91 130 { 92 131 darling_sigexc_uninstall(); 93 132 } ··· 121 160 { 122 161 am_i_ptraced = true; 123 162 124 - __simple_printf("darling_sigexc_self()\n"); 163 + lkm_call(0x1028, "darling_sigexc_self()\n"); 125 164 // Make sigexc_handler the handler for all signals in the process 126 165 for (int i = 1; i <= 31; i++) 127 166 { 167 + if (i == LINUX_SIGSTOP || i == LINUX_SIGKILL) 168 + continue; 169 + 128 170 struct linux_sigaction sa; 129 171 sa.sa_sigaction = (linux_sig_handler*) sigexc_handler; 130 - sa.sa_mask = 0xffffffff; // all other standard Unix signals should be blocked while the handler is run 172 + sa.sa_mask = 0x7fffffff; // all other standard Unix signals should be blocked while the handler is run 131 173 sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART | LINUX_SA_ONSTACK; 132 174 sa.sa_restorer = sig_restorer; 133 175 ··· 150 192 __simple_printf("darling_sigexc_uninstall()\n"); 151 193 for (int i = 1; i <= 31; i++) 152 194 { 195 + if (i == LINUX_SIGSTOP || i == LINUX_SIGKILL) 196 + continue; 197 + 153 198 struct linux_sigaction sa; 154 199 155 200 if (sig_handlers[i] == SIG_DFL || sig_handlers[i] != SIG_IGN ··· 201 246 202 247 void sigexc_handler(int linux_signum, struct linux_siginfo* info, struct linux_ucontext* ctxt) 203 248 { 204 - __simple_printf("sigexc_handler(%d)\n", linux_signum); 249 + char buf[128]; 250 + __simple_sprintf(buf, "sigexc_handler(%d, %p)\n", linux_signum, info); 251 + lkm_call(0x1028, buf); 252 + 205 253 if (!darling_am_i_ptraced()) 206 254 { 207 255 __simple_printf("NOT TRACED!\n"); ··· 234 282 235 283 switch (bsd_signum) 236 284 { 237 - case SIGSEGV: 238 - mach_exception = EXC_BAD_ACCESS; 239 - codes[0] = EXC_I386_GPFLT; 240 - break; 241 - case SIGBUS: 242 - mach_exception = EXC_BAD_ACCESS; 243 - codes[0] = EXC_I386_ALIGNFLT; 244 - break; 245 - case SIGTRAP: 246 - mach_exception = EXC_BREAKPOINT; 247 - codes[0] = EXC_I386_BPT; 248 - break; 249 - case SIGILL: 250 - mach_exception = EXC_BAD_INSTRUCTION; 251 - codes[0] = EXC_I386_INVOP; 252 - break; 253 - case SIGFPE: 254 - mach_exception = EXC_ARITHMETIC; 255 - codes[0] = info->si_code; 256 - break; 285 + // Only real exceptions produced by the CPU get translated to these 286 + // Mach exceptions. The rest comes as EXC_SOFTWARE. 287 + if (info != NULL && info->si_code == 0x80 /* SI_KERNEL */) 288 + { 289 + case SIGSEGV: 290 + mach_exception = EXC_BAD_ACCESS; 291 + codes[0] = EXC_I386_GPFLT; 292 + break; 293 + case SIGBUS: 294 + mach_exception = EXC_BAD_ACCESS; 295 + codes[0] = EXC_I386_ALIGNFLT; 296 + break; 297 + case SIGILL: 298 + mach_exception = EXC_BAD_INSTRUCTION; 299 + codes[0] = EXC_I386_INVOP; 300 + break; 301 + case SIGFPE: 302 + mach_exception = EXC_ARITHMETIC; 303 + codes[0] = info->si_code; 304 + break; 305 + case SIGTRAP: 306 + mach_exception = EXC_BREAKPOINT; 307 + codes[0] = EXC_I386_BPT; 308 + break; 309 + } 257 310 default: 258 311 mach_exception = EXC_SOFTWARE; 259 312 codes[0] = EXC_SOFT_SIGNAL;
+4 -2
src/kernel/emulation/linux/signal/sigexc.h
··· 13 13 #define SIGRT_MAGIC_ENABLE_SIGEXC 0xdebdeb01 14 14 #define SIGRT_MAGIC_DISABLE_SIGEXC 0xdebdeb00 15 15 16 - // Initializes this module 17 - void sigexc_setup(void); 16 + // Initializes this module (before opening LKM) 17 + void sigexc_setup1(void); 18 + // Finish initialization (after opening LKM) 19 + void sigexc_setup2(void); 18 20 19 21 // Is this process currently traced by a debugger? 20 22 bool darling_am_i_ptraced(void);