예제 #1
0
파일: syscall.c 프로젝트: masatake/strace
int
syscall_entering_trace(struct tcb *tcp, unsigned int *sig)
{
	/* Restrain from fault injection while the trace executes strace code. */
	if (hide_log(tcp)) {
		tcp->qual_flg &= ~QUAL_INJECT;
	}

	switch (tcp->s_ent->sen) {
		case SEN_execve:
		case SEN_execveat:
#if defined SPARC || defined SPARC64
		case SEN_execv:
#endif
			tcp->flags &= ~TCB_HIDE_LOG;
			break;
	}

	if (!traced(tcp) || (tracing_paths && !pathtrace_match(tcp))) {
		tcp->flags |= TCB_FILTERED;
		return 0;
	}

	tcp->flags &= ~TCB_FILTERED;

	if (hide_log(tcp)) {
		return 0;
	}

	if (inject(tcp))
		tamper_with_syscall_entering(tcp, sig);

	if (cflag == CFLAG_ONLY_STATS) {
		return 0;
	}

#ifdef USE_LIBUNWIND
	if (stack_trace_enabled) {
		if (tcp->s_ent->sys_flags & STACKTRACE_CAPTURE_ON_ENTER)
			unwind_capture_stacktrace(tcp);
	}
#endif

	printleader(tcp);
	tprintf("%s(", tcp->s_ent->sys_name);
	int res = raw(tcp) ? printargs(tcp) : tcp->s_ent->sys_func(tcp);
	fflush(tcp->outf);
	return res;
}
예제 #2
0
void menu_main(){
  switch(current_function)//get current function and make decision based on it
  {
    case 0: //function 0 log
      if(!isShowingLog) show_log(); //if the log isnt showing show it
        if(nNxtButtonPressed == 2){ //if we are pressing left
          while(nNxtButtonPressed == 2); //must click and release to scroll another line
          scroll_down();
        }
        if(nNxtButtonPressed == 1){ //if we are pressing right
          while(nNxtButtonPressed==1); //must click and release to scroll another line
          scroll_up();
        }
    break;
    case 1: //function 1 menu
      display_menu();
    break;
  }
  if(nNxtButtonPressed==3 && current_function!=1){ //if we press enter and are not on menu
    while(nNxtButtonPressed==3); //dont allow double reads. you have to release before anything happens
    hide_log(); //hide the menu. cant hurt
    previous_function=current_function; //save the old function number
    current_function=1; //set the current function to menu
  }
}
예제 #3
0
파일: syscall.c 프로젝트: masatake/strace
/* Returns:
 * 0: "bail out".
 * 1: ok.
 * -1: error in one of ptrace ops.
 *
 * If not 0, call syscall_exiting_trace(tcp, res), where res is the return
 *    value. Anyway, call syscall_exiting_finish(tcp) then.
 */
int
syscall_exiting_decode(struct tcb *tcp, struct timeval *ptv)
{
	/* Measure the exit time as early as possible to avoid errors. */
	if ((Tflag || cflag) && !(filtered(tcp) || hide_log(tcp)))
		gettimeofday(ptv, NULL);

#ifdef USE_LIBUNWIND
	if (stack_trace_enabled) {
		if (tcp->s_ent->sys_flags & STACKTRACE_INVALIDATE_CACHE)
			unwind_cache_invalidate(tcp);
	}
#endif

	if (filtered(tcp) || hide_log(tcp))
		return 0;

	get_regs(tcp->pid);
#if SUPPORTED_PERSONALITIES > 1
	update_personality(tcp, tcp->currpers);
#endif
	return get_regs_error ? -1 : get_syscall_result(tcp);
}
예제 #4
0
static int
trace_syscall_exiting(struct tcb *tcp)
{
	int sys_res;
	struct timeval tv;
	int res;
	unsigned long u_error;
	const char *u_error_str;

	/* Measure the exit time as early as possible to avoid errors. */
	if (Tflag || cflag)
		gettimeofday(&tv, NULL);

#ifdef USE_LIBUNWIND
	if (stack_trace_enabled) {
		if (tcp->s_ent->sys_flags & STACKTRACE_INVALIDATE_CACHE)
			unwind_cache_invalidate(tcp);
	}
#endif

#if SUPPORTED_PERSONALITIES > 1
	update_personality(tcp, tcp->currpers);
#endif
	res = (get_regs_error ? -1 : get_syscall_result(tcp));
	if (filtered(tcp) || hide_log(tcp))
		goto ret;

	if (syserror(tcp) && syscall_fault_injected(tcp))
		update_syscall_fault_exiting(tcp);

	if (cflag) {
		count_syscall(tcp, &tv);
		if (cflag == CFLAG_ONLY_STATS) {
			goto ret;
		}
	}

	/* If not in -ff mode, and printing_tcp != tcp,
	 * then the log currently does not end with output
	 * of _our syscall entry_, but with something else.
	 * We need to say which syscall's return is this.
	 *
	 * Forced reprinting via TCB_REPRINT is used only by
	 * "strace -ff -oLOG test/threaded_execve" corner case.
	 * It's the only case when -ff mode needs reprinting.
	 */
	if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
		tcp->flags &= ~TCB_REPRINT;
		printleader(tcp);
		tprintf("<... %s resumed> ", tcp->s_ent->sys_name);
	}
	printing_tcp = tcp;

	tcp->s_prev_ent = NULL;
	if (res != 1) {
		/* There was error in one of prior ptrace ops */
		tprints(") ");
		tabto();
		tprints("= ? <unavailable>\n");
		line_ended();
		tcp->flags &= ~(TCB_INSYSCALL | TCB_FAULT_INJ);
		tcp->sys_func_rval = 0;
		free_tcb_priv_data(tcp);
		return res;
	}
	tcp->s_prev_ent = tcp->s_ent;

	sys_res = 0;
	if (tcp->qual_flg & QUAL_RAW) {
		/* sys_res = printargs(tcp); - but it's nop on sysexit */
	} else {
	/* FIXME: not_failing_only (IOW, option -z) is broken:
	 * failure of syscall is known only after syscall return.
	 * Thus we end up with something like this on, say, ENOENT:
	 *     open("doesnt_exist", O_RDONLY <unfinished ...>
	 *     {next syscall decode}
	 * whereas the intended result is that open(...) line
	 * is not shown at all.
	 */
		if (not_failing_only && tcp->u_error)
			goto ret;	/* ignore failed syscalls */
		if (tcp->sys_func_rval & RVAL_DECODED)
			sys_res = tcp->sys_func_rval;
		else
			sys_res = tcp->s_ent->sys_func(tcp);
	}

	tprints(") ");
	tabto();
	u_error = tcp->u_error;

	if (tcp->qual_flg & QUAL_RAW) {
		if (u_error) {
			tprintf("= -1 (errno %lu)", u_error);
			if (syscall_fault_injected(tcp))
				tprints(" (INJECTED)");
		} else {
			tprintf("= %#" PRI_klx, tcp->u_rval);
		}
	}
	else if (!(sys_res & RVAL_NONE) && u_error) {
		switch (u_error) {
		/* Blocked signals do not interrupt any syscalls.
		 * In this case syscalls don't return ERESTARTfoo codes.
		 *
		 * Deadly signals set to SIG_DFL interrupt syscalls
		 * and kill the process regardless of which of the codes below
		 * is returned by the interrupted syscall.
		 * In some cases, kernel forces a kernel-generated deadly
		 * signal to be unblocked and set to SIG_DFL (and thus cause
		 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
		 * or SIGILL. (The alternative is to leave process spinning
		 * forever on the faulty instruction - not useful).
		 *
		 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
		 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
		 * but kernel will always restart them.
		 */
		case ERESTARTSYS:
			/* Most common type of signal-interrupted syscall exit code.
			 * The system call will be restarted with the same arguments
			 * if SA_RESTART is set; otherwise, it will fail with EINTR.
			 */
			tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
			break;
		case ERESTARTNOINTR:
			/* Rare. For example, fork() returns this if interrupted.
			 * SA_RESTART is ignored (assumed set): the restart is unconditional.
			 */
			tprints("= ? ERESTARTNOINTR (To be restarted)");
			break;
		case ERESTARTNOHAND:
			/* pause(), rt_sigsuspend() etc use this code.
			 * SA_RESTART is ignored (assumed not set):
			 * syscall won't restart (will return EINTR instead)
			 * even after signal with SA_RESTART set. However,
			 * after SIG_IGN or SIG_DFL signal it will restart
			 * (thus the name "restart only if has no handler").
			 */
			tprints("= ? ERESTARTNOHAND (To be restarted if no handler)");
			break;
		case ERESTART_RESTARTBLOCK:
			/* Syscalls like nanosleep(), poll() which can't be
			 * restarted with their original arguments use this
			 * code. Kernel will execute restart_syscall() instead,
			 * which changes arguments before restarting syscall.
			 * SA_RESTART is ignored (assumed not set) similarly
			 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
			 * since restart data is saved in "restart block"
			 * in task struct, and if signal handler uses a syscall
			 * which in turn saves another such restart block,
			 * old data is lost and restart becomes impossible)
			 */
			tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
			break;
		default:
			u_error_str = err_name(u_error);
			if (u_error_str)
				tprintf("= -1 %s (%s)",
					u_error_str, strerror(u_error));
			else
				tprintf("= -1 %lu (%s)",
					u_error, strerror(u_error));
			break;
		}
		if (syscall_fault_injected(tcp))
			tprintf(" (INJECTED)");
		if ((sys_res & RVAL_STR) && tcp->auxstr)
			tprintf(" (%s)", tcp->auxstr);
	}
	else {
		if (sys_res & RVAL_NONE)
			tprints("= ?");
		else {
			switch (sys_res & RVAL_MASK) {
			case RVAL_HEX:
#if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
				if (current_wordsize < sizeof(tcp->u_rval)) {
					tprintf("= %#x",
						(unsigned int) tcp->u_rval);
				} else
#endif
				{
					tprintf("= %#" PRI_klx, tcp->u_rval);
				}
				break;
			case RVAL_OCTAL:
				tprints("= ");
				print_numeric_long_umask(tcp->u_rval);
				break;
			case RVAL_UDECIMAL:
#if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
				if (current_wordsize < sizeof(tcp->u_rval)) {
					tprintf("= %u",
						(unsigned int) tcp->u_rval);
				} else
#endif
				{
					tprintf("= %" PRI_klu, tcp->u_rval);
				}
				break;
			case RVAL_DECIMAL:
				tprintf("= %" PRI_kld, tcp->u_rval);
				break;
			case RVAL_FD:
				if (show_fd_path) {
					tprints("= ");
					printfd(tcp, tcp->u_rval);
				}
				else
					tprintf("= %" PRI_kld, tcp->u_rval);
				break;
			default:
				error_msg("invalid rval format");
				break;
			}
		}
		if ((sys_res & RVAL_STR) && tcp->auxstr)
			tprintf(" (%s)", tcp->auxstr);
	}
	if (Tflag) {
		tv_sub(&tv, &tv, &tcp->etime);
		tprintf(" <%ld.%06ld>",
			(long) tv.tv_sec, (long) tv.tv_usec);
	}
	tprints("\n");
	dumpio(tcp);
	line_ended();

#ifdef USE_LIBUNWIND
	if (stack_trace_enabled)
		unwind_print_stacktrace(tcp);
#endif

 ret:
	tcp->flags &= ~(TCB_INSYSCALL | TCB_FAULT_INJ);
	tcp->sys_func_rval = 0;
	free_tcb_priv_data(tcp);
	return 0;
}
예제 #5
0
static int
trace_syscall_entering(struct tcb *tcp, unsigned int *sig)
{
	int res, scno_good;

	scno_good = res = get_scno(tcp);
	if (res == 0)
		return res;
	if (res == 1)
		res = get_syscall_args(tcp);

	if (res != 1) {
		printleader(tcp);
		tprintf("%s(", scno_good == 1 ? tcp->s_ent->sys_name : "????");
		/*
		 * " <unavailable>" will be added later by the code which
		 * detects ptrace errors.
		 */
		goto ret;
	}

#ifdef LINUX_MIPSO32
	if (SEN_syscall == tcp->s_ent->sen)
		decode_mips_subcall(tcp);
#endif

#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
	switch (tcp->s_ent->sen) {
# ifdef SYS_socket_subcall
		case SEN_socketcall:
			decode_socket_subcall(tcp);
			break;
# endif
# ifdef SYS_ipc_subcall
		case SEN_ipc:
			decode_ipc_subcall(tcp);
			break;
# endif
	}
#endif

	/* Restrain from fault injection while the trace executes strace code. */
	if (hide_log(tcp)) {
		tcp->qual_flg &= ~QUAL_FAULT;
	}

	switch (tcp->s_ent->sen) {
		case SEN_execve:
		case SEN_execveat:
#if defined SPARC || defined SPARC64
		case SEN_execv:
#endif
			tcp->flags &= ~TCB_HIDE_LOG;
			break;
	}

	if (!(tcp->qual_flg & QUAL_TRACE)
	 || (tracing_paths && !pathtrace_match(tcp))
	) {
		tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
		tcp->sys_func_rval = 0;
		return 0;
	}

	tcp->flags &= ~TCB_FILTERED;

	if (hide_log(tcp)) {
		res = 0;
		goto ret;
	}

	if (tcp->qual_flg & QUAL_FAULT)
		inject_syscall_fault_entering(tcp, sig);

	if (cflag == CFLAG_ONLY_STATS) {
		res = 0;
		goto ret;
	}

#ifdef USE_LIBUNWIND
	if (stack_trace_enabled) {
		if (tcp->s_ent->sys_flags & STACKTRACE_CAPTURE_ON_ENTER)
			unwind_capture_stacktrace(tcp);
	}
#endif

	printleader(tcp);
	tprintf("%s(", tcp->s_ent->sys_name);
	if (tcp->qual_flg & QUAL_RAW)
		res = printargs(tcp);
	else
		res = tcp->s_ent->sys_func(tcp);

	fflush(tcp->outf);
 ret:
	tcp->flags |= TCB_INSYSCALL;
	tcp->sys_func_rval = res;
	/* Measure the entrance time as late as possible to avoid errors. */
	if (Tflag || cflag)
		gettimeofday(&tcp->etime, NULL);
	return res;
}