/* * Clear registers on exec */ void setregs(struct proc *p, struct exec_package *pack, u_long stack, register_t rval[2]) { struct trapframe *tf; struct pcb *pcb = p->p_md.md_pcb; p->p_md.md_flags &= ~MDP_USEDFPU; tf = p->p_md.md_regs; tf->tf_r0 = 0; tf->tf_r1 = 0; tf->tf_r2 = 0; tf->tf_r3 = 0; copyin((caddr_t)stack, &tf->tf_r4, sizeof(register_t)); /* argc */ tf->tf_r5 = stack + 4; /* argv */ tf->tf_r6 = stack + 4 * tf->tf_r4 + 8; /* envp */ tf->tf_r7 = 0; tf->tf_r8 = 0; tf->tf_r9 = (int)PS_STRINGS; tf->tf_r10 = 0; tf->tf_r11 = 0; tf->tf_r12 = 0; tf->tf_r13 = 0; tf->tf_r14 = 0; tf->tf_spc = pack->ep_entry; tf->tf_ssr = PSL_USERSET; tf->tf_r15 = stack; #ifdef SH4 if (CPU_IS_SH4) { /* * Clear floating point registers. */ bzero(&pcb->pcb_fp, sizeof(pcb->pcb_fp)); pcb->pcb_fp.fpr_fpscr = FPSCR_PR; fpu_restore(&pcb->pcb_fp); } #endif rval[1] = 0; }
void sigtrap_handler(HANDLER_ARGS) { unsigned int trap; #ifdef __linux__ GET_CONTEXT #endif #if 0 fprintf(stderr, "x86sigtrap: %8x %x\n", context->sc_pc, *(unsigned char *) (context->sc_pc - 1)); fprintf(stderr, "sigtrap(%d %d %x)\n", signal, code, context); #endif if (single_stepping && (signal == SIGTRAP)) { #if 0 fprintf(stderr, "* Single step trap %x\n", single_stepping); #endif #ifndef __linux__ /* Un-install single step helper instructions. */ *(single_stepping - 3) = single_step_save1; *(single_stepping - 2) = single_step_save2; *(single_stepping - 1) = single_step_save3; #else context->eflags ^= 0x100; #endif /* * Re-install the breakpoint if possible. */ if ((int) context->sc_pc == (int) single_stepping + 1) fprintf(stderr, "* Breakpoint not re-install\n"); else { char *ptr = (char *) single_stepping; ptr[0] = BREAKPOINT_INST; /* x86 INT3 */ ptr[1] = trap_Breakpoint; } single_stepping = NULL; return; } /* This is just for info in case monitor wants to print an approx */ current_control_stack_pointer = (unsigned long *) context->sc_sp; #if defined(__linux__) && (defined(i386) || defined(__x86_64)) /* * Restore the FPU control word, setting the rounding mode to nearest. */ if (contextstruct.fpstate) #if defined(__x86_64) setfpucw(contextstruct.fpstate->cwd & ~0xc00); #else setfpucw(contextstruct.fpstate->cw & ~0xc00); #endif #endif /* * On entry %eip points just after the INT3 byte and aims at the * 'kind' value (eg trap_Cerror). For error-trap and Cerror-trap a * number of bytes will follow, the first is the length of the byte * arguments to follow. */ trap = *(unsigned char *) (context->sc_pc); switch (trap) { case trap_PendingInterrupt: DPRINTF(0, (stderr, "<trap Pending Interrupt.>\n")); arch_skip_instruction(context); interrupt_handle_pending(context); break; case trap_Halt: { #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) int fpu_state[27]; fpu_save(fpu_state); #endif fake_foreign_function_call(context); lose("%%primitive halt called; the party is over.\n"); undo_fake_foreign_function_call(context); #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) fpu_restore(fpu_state); #endif arch_skip_instruction(context); break; } case trap_Error: case trap_Cerror: DPRINTF(0, (stderr, "<trap Error %d>\n", code)); #ifdef __linux__ interrupt_internal_error(signal, contextstruct, code == trap_Cerror); #else interrupt_internal_error(signal, code, context, code == trap_Cerror); #endif break; case trap_Breakpoint: #if 0 fprintf(stderr, "*C break\n"); #endif (char *) context->sc_pc -= 1; handle_breakpoint(signal, code, context); #if 0 fprintf(stderr, "*C break return\n"); #endif break; case trap_FunctionEndBreakpoint: (char *) context->sc_pc -= 1; context->sc_pc = (int) handle_function_end_breakpoint(signal, code, context); break; #ifdef DYNAMIC_SPACE_OVERFLOW_WARNING_HIT case trap_DynamicSpaceOverflowWarning: interrupt_handle_space_overflow(SymbolFunction (DYNAMIC_SPACE_OVERFLOW_WARNING_HIT), context); break; #endif #ifdef DYNAMIC_SPACE_OVERFLOW_ERROR_HIT case trap_DynamicSpaceOverflowError: interrupt_handle_space_overflow(SymbolFunction (DYNAMIC_SPACE_OVERFLOW_ERROR_HIT), context); break; #endif default: DPRINTF(0, (stderr, "[C--trap default %d %d %x]\n", signal, code, context)); #ifdef __linux__ interrupt_handle_now(signal, contextstruct); #else interrupt_handle_now(signal, code, context); #endif break; } }
/* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper privileges or to cause * a machine fault. */ int sys_sigreturn(struct proc *p, void *v, register_t *retval) { struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; struct sigcontext *scp, context; struct trapframe *tf; int error; /* * The trampoline code hands us the context. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ scp = SCARG(uap, sigcntxp); if ((error = copyin((caddr_t)scp, &context, sizeof(*scp))) != 0) return (error); /* Restore signal context. */ tf = p->p_md.md_regs; /* Check for security violations. */ if (((context.sc_reg.r_ssr ^ tf->tf_ssr) & PSL_USERSTATIC) != 0) return (EINVAL); tf->tf_spc = context.sc_reg.r_spc; tf->tf_ssr = context.sc_reg.r_ssr; tf->tf_macl = context.sc_reg.r_macl; tf->tf_mach = context.sc_reg.r_mach; tf->tf_pr = context.sc_reg.r_pr; tf->tf_r13 = context.sc_reg.r_r13; tf->tf_r12 = context.sc_reg.r_r12; tf->tf_r11 = context.sc_reg.r_r11; tf->tf_r10 = context.sc_reg.r_r10; tf->tf_r9 = context.sc_reg.r_r9; tf->tf_r8 = context.sc_reg.r_r8; tf->tf_r7 = context.sc_reg.r_r7; tf->tf_r6 = context.sc_reg.r_r6; tf->tf_r5 = context.sc_reg.r_r5; tf->tf_r4 = context.sc_reg.r_r4; tf->tf_r3 = context.sc_reg.r_r3; tf->tf_r2 = context.sc_reg.r_r2; tf->tf_r1 = context.sc_reg.r_r1; tf->tf_r0 = context.sc_reg.r_r0; tf->tf_r15 = context.sc_reg.r_r15; tf->tf_r14 = context.sc_reg.r_r14; #ifdef SH4 if (CPU_IS_SH4) fpu_restore(&context.sc_fpreg); #endif /* Restore signal stack. */ if (context.sc_onstack) p->p_sigstk.ss_flags |= SS_ONSTACK; else p->p_sigstk.ss_flags &= ~SS_ONSTACK; /* Restore signal mask. */ p->p_sigmask = context.sc_mask & ~sigcantmask; return (EJUSTRETURN); }