Exemplo n.º 1
0
void
handle_event(Event *event) {
	if (exiting == 1) {
		exiting = 2;
		debug(1, "ltrace about to exit");
		ltrace_exiting();
	}
	debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)",
	      event->proc ? event->proc->pid : -1, event->type);

	/* If the thread group or an individual task define an
	   overriding event handler, give them a chance to kick in.
	   We will end up calling both handlers, if the first one
	   doesn't sink the event.  */
	if (event->proc != NULL) {
		event = call_handler(event->proc, event);
		if (event == NULL)
			/* It was handled.  */
			return;

		/* Note: the previous handler has a chance to alter
		 * the event.  */
		if (event->proc != NULL
		    && event->proc->leader != NULL
		    && event->proc != event->proc->leader) {
			event = call_handler(event->proc->leader, event);
			if (event == NULL)
				return;
		}
	}

	switch (event->type) {
	case EVENT_NONE:
		debug(1, "event: none");
		return;
	case EVENT_SIGNAL:
		debug(1, "event: signal (%s [%d])",
		      shortsignal(event->proc, event->e_un.signum),
		      event->e_un.signum);
		handle_signal(event);
		return;
	case EVENT_EXIT:
		debug(1, "event: exit (%d)", event->e_un.ret_val);
		handle_exit(event);
		return;
	case EVENT_EXIT_SIGNAL:
		debug(1, "event: exit signal (%s [%d])",
		      shortsignal(event->proc, event->e_un.signum),
		      event->e_un.signum);
		handle_exit_signal(event);
		return;
	case EVENT_SYSCALL:
		debug(1, "event: syscall (%s [%d])",
		      sysname(event->proc, event->e_un.sysnum),
		      event->e_un.sysnum);
		handle_syscall(event);
		return;
	case EVENT_SYSRET:
		debug(1, "event: sysret (%s [%d])",
		      sysname(event->proc, event->e_un.sysnum),
		      event->e_un.sysnum);
		handle_sysret(event);
		return;
	case EVENT_ARCH_SYSCALL:
		debug(1, "event: arch_syscall (%s [%d])",
				arch_sysname(event->proc, event->e_un.sysnum),
				event->e_un.sysnum);
		handle_arch_syscall(event);
		return;
	case EVENT_ARCH_SYSRET:
		debug(1, "event: arch_sysret (%s [%d])",
				arch_sysname(event->proc, event->e_un.sysnum),
				event->e_un.sysnum);
		handle_arch_sysret(event);
		return;
	case EVENT_CLONE:
	case EVENT_VFORK:
		debug(1, "event: clone (%u)", event->e_un.newpid);
		handle_clone(event);
		return;
	case EVENT_EXEC:
		debug(1, "event: exec()");
		handle_exec(event);
		return;
	case EVENT_BREAKPOINT:
		debug(1, "event: breakpoint");
		handle_breakpoint(event);
		return;
	case EVENT_NEW:
		debug(1, "event: new process");
		handle_new(event);
		return;
	default:
		fprintf(stderr, "Error! unknown event?\n");
		exit(1);
	}
}
Exemplo n.º 2
0
int handle_event(struct task *task)
{
	int ret;

	if (!task)
		return 0;

	debug(DEBUG_EVENT, "+++ process pid=%d event: %d", task->pid, task->event.type);

	assert(task->stopped);

	if (task->defer_func) {
		ret = task->defer_func(task, task->defer_data);

		if (ret == RET_DELETED)
			return 1;

		task->defer_func = NULL;
		task->defer_data = NULL;
		goto out2;
	}

	struct event *event = &task->event;
	enum event_type type = event->type;

	switch (type) {
	case EVENT_NONE:
		ret = continue_task(task, task->event.e_un.signum);
		break;
	case EVENT_SIGNAL:
		ret = handle_signal(task);
		break;
	case EVENT_ABOUT_EXIT:
		ret = handle_about_exit(task);
		goto out1;
	case EVENT_EXIT:
		ret = handle_exit(task);
		break;
	case EVENT_EXIT_SIGNAL:
		ret = handle_exit_signal(task);
		break;
	case EVENT_FORK:
	case EVENT_VFORK:
	case EVENT_CLONE:
		ret = handle_child(task);
		break;
	case EVENT_EXEC:
		ret = handle_exec(task);
		break;
	case EVENT_BREAKPOINT:
		ret = handle_breakpoint(task);
		goto out2;
	case EVENT_NEW:
		ret = handle_new(task);
		break;
	default:
		fprintf(stderr, "fatal error, unknown event %d\n", type);
		abort();
	}

	if (ret == RET_DELETED)
		return 1;

	if (ret != RET_DEFERED) {
		assert(task->event.type == EVENT_NONE);
		assert(task->stopped == 0);
	}
out2:
	assert(task->is_new == 0);
out1:
	return (ret < 0) ? ret : 0;
}
Exemplo n.º 3
0
void
sigtrap_handler(HANDLER_ARGS)
{
    unsigned int trap;
    os_context_t* os_context = (os_context_t *) context;
#if 0
    fprintf(stderr, "x86sigtrap: %8x %x\n",
            SC_PC(os_os_context), *(unsigned char *) (SC_PC(os_context) - 1));
    fprintf(stderr, "sigtrap(%d %d %x)\n", signal, CODE(code), os_context);
#endif

    if (single_stepping && (signal == SIGTRAP)) {
#if 0
	fprintf(stderr, "* Single step trap %p\n", single_stepping);
#endif

#ifdef SC_EFLAGS
	/* Disable single-stepping */
	SC_EFLAGS(os_context) ^= 0x100;
#else
	/* Un-install single step helper instructions. */
	*(single_stepping - 3) = single_step_save1;
	*(single_stepping - 2) = single_step_save2;
	*(single_stepping - 1) = single_step_save3;
        DPRINTF(0, (stderr, "Uninstalling helper instructions\n"));
#endif

	/*
	 * Re-install the breakpoint if possible.
	 */
	if ((int) SC_PC(os_context) == (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 *) SC_SP(os_context);

    RESTORE_FPU(os_context);

    /*
     * 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 *) SC_PC(os_context);

    switch (trap) {
      case trap_PendingInterrupt:
	  DPRINTF(0, (stderr, "<trap Pending Interrupt.>\n"));
	  arch_skip_instruction(os_context);
	  interrupt_handle_pending(os_context);
	  break;

      case trap_Halt:
	  {
              FPU_STATE(fpu_state);
              save_fpu_state(fpu_state);

	      fake_foreign_function_call(os_context);
	      lose("%%primitive halt called; the party is over.\n");
	      undo_fake_foreign_function_call(os_context);

              restore_fpu_state(fpu_state);
	      arch_skip_instruction(os_context);
	      break;
	  }

      case trap_Error:
      case trap_Cerror:
	  DPRINTF(0, (stderr, "<trap Error %x>\n", CODE(code)));
	  interrupt_internal_error(signal, code, os_context, CODE(code) == trap_Cerror);
	  break;

      case trap_Breakpoint:
#if 0
	  fprintf(stderr, "*C break\n");
#endif
	  SC_PC(os_context) -= 1;

	  handle_breakpoint(signal, CODE(code), os_context);
#if 0
	  fprintf(stderr, "*C break return\n");
#endif
	  break;

      case trap_FunctionEndBreakpoint:
	  SC_PC(os_context) -= 1;
	  SC_PC(os_context) =
	      (int) handle_function_end_breakpoint(signal, CODE(code), os_context);
	  break;

#ifdef trap_DynamicSpaceOverflowWarning
      case trap_DynamicSpaceOverflowWarning:
	  interrupt_handle_space_overflow(SymbolFunction
					  (DYNAMIC_SPACE_OVERFLOW_WARNING_HIT),
					  os_context);
	  break;
#endif
#ifdef trap_DynamicSpaceOverflowError
      case trap_DynamicSpaceOverflowError:
	  interrupt_handle_space_overflow(SymbolFunction
					  (DYNAMIC_SPACE_OVERFLOW_ERROR_HIT),
					  os_context);
	  break;
#endif
      default:
	  DPRINTF(0,
		  (stderr, "[C--trap default %d %d %p]\n", signal, CODE(code),
		   os_context));
	  interrupt_handle_now(signal, code, os_context);
	  break;
    }
}
Exemplo n.º 4
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;
    }
}
Exemplo n.º 5
0
void
arch_handle_breakpoint(os_context_t *context)
{
    *os_context_pc_addr(context) -= BREAKPOINT_WIDTH;
    handle_breakpoint(context);
}
Exemplo n.º 6
0
void
arch_handle_breakpoint(os_context_t *context)
{
    handle_breakpoint(context);
}