Exemple #1
0
/* * * * * * * * 
 *
 * this routine writes the maptable in a file
 */
void write_map_table(char  *filename  /* map file name */
)

{
FILE
   *fp;
MAPTABLEPTR
   map;
time_t
   the_time;
/*   time(); */
int
   column;

if((fp = fopen(filename,"w")) == NULL)
   {
   if(!access(filename, 0))
      fprintf(stderr,"WARNING: mapfile '%s' appears to be present, but it's not writable,\n", filename);
   else
      fprintf(stderr,"WARNING: cannot write mapfile '%s' in this directory,\n", filename);
      fprintf(stderr,"         No mapfile written!\n", filename);
   return;
   }

if(maptable == NULL)
   {  /* add the nelsis primitives */
   add_nelsis_primitives();
   }

/*
 * print header
 */
the_time = time(0);
fprintf(fp,"# This is a maptable for nelsis <--> seadif conversion, generated/maintained by 'nelsea'\n");
fprintf(fp,"# Written on: %s", asctime(localtime(&the_time)));
fprintf(fp,"# You can edit this file to control the mapping process\n"); 
fprintf(fp,"# Each line contains the name of a nelsis cell and its corresponding seadif cell\n");
fprintf(fp,"# The status field may contain the following values:\n");
fprintf(fp,"#    'written'       the cell was succesfully written into seadif resp. nelsis\n");
fprintf(fp,"#    'primitive'     the cell is a primitive which should not be read or converted\n");
fprintf(fp,"#    [anything else] the cell will be written if necessary\n");
fprintf(fp,"# To check the consistency of this table: use 'nelsea -C'\n");
fprintf(fp,"#    N E L S I S     |                   S E A D I F                     | nelsis->sdf sdf->nelsis\n");
fprintf(fp,"# view    cellname   | library      function     circuit      layout     |   status      status\n");
fprintf(fp,"#--------------------+---------------------------------------------------+------------------------\n");

for(map = maptable; map != NULL; map = map->next)
   {
   column = 1;
   /*
    * view
    */
   fprintf(fp," %s ", map->view);

   column = tabto(9, column, map->view, fp);

   /*
    * cellname
    */
   fprintf(fp,"%s ", map->cell);
   column = tabto(13, column, map->cell, fp);

   /*
    * library name
    */
   fprintf(fp,"%s ", map->library);
   column = tabto(13, column, map->library, fp);

   /*
    * function name
    */
   fprintf(fp,"%s ", map->function);
   column = tabto(13, column, map->function, fp);

   /*
    * circuit name
    */
   fprintf(fp,"%s ", map->circuit);
   column = tabto(13, column, map->circuit, fp);

   /*
    * layout name
    */
   fprintf(fp,"%s ", map->layout);
   column = tabto(13, column, map->layout, fp);

   /*
    * nelseastatus
    */
   fprintf(fp,"%s", map->nelseastatus);
   column = tabto(13, column, map->nelseastatus, fp);

   /*
    * seanelstatus
    */
   fprintf(fp,"%s\n", map->seanelstatus);
   }

fclose(fp);
}
Exemple #2
0
int
syscall_exiting_trace(struct tcb *tcp, struct timeval tv, int res)
{
	if (syserror(tcp) && syscall_tampered(tcp))
		tamper_with_syscall_exiting(tcp);

	if (cflag) {
		count_syscall(tcp, &tv);
		if (cflag == CFLAG_ONLY_STATS) {
			return 0;
		}
	}

	/* 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();
		return res;
	}
	tcp->s_prev_ent = tcp->s_ent;

	int sys_res = 0;
	if (raw(tcp)) {
		/* 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("does_not_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)
			return 0;	/* 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();
	unsigned long u_error = tcp->u_error;

	if (raw(tcp)) {
		if (u_error) {
			tprintf("= -1 (errno %lu)", u_error);
		} else {
			tprintf("= %#" PRI_klx, tcp->u_rval);
		}
		if (syscall_tampered(tcp))
			tprints(" (INJECTED)");
	} else if (!(sys_res & RVAL_NONE) && u_error) {
		const char *u_error_str;

		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_tampered(tcp))
			tprints(" (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 (syscall_tampered(tcp))
			tprints(" (INJECTED)");
	}
	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
	return 0;
}
Exemple #3
0
static int
trace_syscall_exiting(struct tcb *tcp)
{
	int sys_res;
	struct timeval tv;
	int res;
	long u_error;

	/* 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 (res == 1) {
		if (filtered(tcp) || hide_log_until_execve)
			goto ret;
	}

	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);
		if (tcp->qual_flg & UNDEFINED_SCNO)
			tprintf("<... %s resumed> ", undefined_scno_name(tcp));
		else
			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;
		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 */
		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 %ld)", u_error);
		else
			tprintf("= %#lx", 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:
			if ((unsigned long) u_error < nerrnos
			    && errnoent[u_error])
				tprintf("= -1 %s (%s)", errnoent[u_error],
					strerror(u_error));
			else
				tprintf("= -1 ERRNO_%lu (%s)", u_error,
					strerror(u_error));
			break;
		}
		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 SUPPORTED_PERSONALITIES > 1
				if (current_wordsize < sizeof(long))
					tprintf("= %#x",
						(unsigned int) tcp->u_rval);
				else
#endif
					tprintf("= %#lx", tcp->u_rval);
				break;
			case RVAL_OCTAL:
				tprintf("= %#lo", tcp->u_rval);
				break;
			case RVAL_UDECIMAL:
				tprintf("= %lu", tcp->u_rval);
				break;
			case RVAL_DECIMAL:
				tprintf("= %ld", tcp->u_rval);
				break;
			case RVAL_FD:
				if (show_fd_path) {
					tprints("= ");
					printfd(tcp, tcp->u_rval);
				}
				else
					tprintf("= %ld", tcp->u_rval);
				break;
#if defined(LINUX_MIPSN32) || defined(X32)
			/*
			case RVAL_LHEX:
				tprintf("= %#llx", tcp->u_lrval);
				break;
			case RVAL_LOCTAL:
				tprintf("= %#llo", tcp->u_lrval);
				break;
			*/
			case RVAL_LUDECIMAL:
				tprintf("= %llu", tcp->u_lrval);
				break;
			/*
			case RVAL_LDECIMAL:
				tprintf("= %lld", tcp->u_lrval);
				break;
			*/
#endif
			default:
				fprintf(stderr,
					"invalid rval format\n");
				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;
	return 0;
}
void
output_right(enum tof type, struct process *proc, struct library_symbol *libsym,
             struct timedelta *spent)
{
    assert(! options.summary);

    struct prototype *func = lookup_symbol_prototype(proc, libsym);
    if (func == NULL)
        return;

    if (current_proc != NULL
            && (current_proc != proc
                || current_depth != proc->callstack_depth)) {
        fprintf(options.output, " <unfinished ...>\n");
        current_proc = NULL;
    }
    if (current_proc != proc) {
        begin_of_line(proc, type == LT_TOF_FUNCTIONR, 1);
#ifdef USE_DEMANGLE
        current_column +=
            fprintf(options.output, "<... %s resumed> ",
                    options.demangle ? my_demangle(libsym->name)
                    : libsym->name);
#else
        current_column +=
            fprintf(options.output, "<... %s resumed> ", libsym->name);
#endif
    }

    struct callstack_element *stel
            = &proc->callstack[proc->callstack_depth - 1];

    struct fetch_context *context = stel->fetch_context;

    /* Fetch & enter into dictionary the retval first, so that
     * other values can use it in expressions.  */
    struct value retval;
    bool own_retval = false;
    if (context != NULL) {
        value_init(&retval, proc, NULL, func->return_info, 0);
        own_retval = true;
        if (fetch_retval(context, type, proc, func->return_info,
                         &retval) < 0)
            value_set_type(&retval, NULL, 0);
        else if (stel->arguments != NULL
                 && val_dict_push_named(stel->arguments, &retval,
                                        "retval", 0) == 0)
            own_retval = false;
    }

    if (stel->arguments != NULL)
        output_params(stel->arguments, stel->out.params_left,
                      val_dict_count(stel->arguments),
                      &stel->out.need_delim);

    current_column += fprintf(options.output, ") ");
    tabto(options.align - 1);
    fprintf(options.output, "= ");

    if (context != NULL && retval.type != NULL) {
        struct format_argument_data data = { &retval, stel->arguments };
        format_argument_cb(options.output, &data);
    }

    if (own_retval)
        value_destroy(&retval);

    if (opt_T) {
        assert(spent != NULL);
        fprintf(options.output, " <%lu.%06d>",
                (unsigned long) spent->tm.tv_sec,
                (int) spent->tm.tv_usec);
    }

    fprintf(options.output, "\n");

#if defined(HAVE_LIBUNWIND)
    if (options.bt_depth > 0
            && proc->unwind_priv != NULL
            && proc->unwind_as != NULL) {
        unw_cursor_t cursor;
        arch_addr_t ip, function_offset;
        struct library *lib = NULL;
        int unwind_depth = options.bt_depth;
        char fn_name[100];
        const char *lib_name;
        size_t distance;

        /* Verify that we can safely cast arch_addr_t* to
         * unw_word_t*.  */
        (void)sizeof(char[1 - 2*(sizeof(unw_word_t)
                                 != sizeof(arch_addr_t))]);
        unw_init_remote(&cursor, proc->unwind_as, proc->unwind_priv);
        while (unwind_depth) {

            int rc = unw_get_reg(&cursor, UNW_REG_IP,
                                 (unw_word_t *) &ip);
            if (rc < 0) {
                fprintf(options.output, " > Error: %s\n",
                        unw_strerror(rc));
                goto cont;
            }

            /* We are looking for the library with the base address
             * closest to the current ip.  */
            lib_name = "unmapped_area";
            distance = (size_t) -1;
            lib = proc->libraries;
            while (lib != NULL) {
                /* N.B.: Assumes sizeof(size_t) ==
                 * sizeof(arch_addr_t).
                 * Keyword: double cast.  */
                if ((ip >= lib->base) &&
                        ((size_t)(ip - lib->base)
                         < distance)) {
                    distance = ip - lib->base;
                    lib_name = lib->pathname;
                }
                lib = lib->next;
            }

            rc = unw_get_proc_name(&cursor, fn_name,
                                   sizeof(fn_name),
                                   (unw_word_t *) &function_offset);
            if (rc == 0 || rc == -UNW_ENOMEM)
                fprintf(options.output, " > %s(%s+%p) [%p]\n",
                        lib_name, fn_name, function_offset, ip);
            else
                fprintf(options.output, " > %s(??\?) [%p]\n",
                        lib_name, ip);

cont:
            if (unw_step(&cursor) <= 0)
                break;
            unwind_depth--;
        }
        fprintf(options.output, "\n");
    }
#endif /* defined(HAVE_LIBUNWIND) */

#if defined(HAVE_LIBDW)
    if (options.bt_depth > 0 && proc->leader->dwfl != NULL) {
        int frames = options.bt_depth;
        if (dwfl_getthread_frames(proc->leader->dwfl, proc->pid,
                                  frame_callback, &frames) < 0) {
            // Only print an error if we couldn't show anything.
            // Otherwise just show there might be more...
            if (frames == options.bt_depth)
                fprintf(stderr,
                        "dwfl_getthread_frames tid %d: %s\n",
                        proc->pid, dwfl_errmsg(-1));
            else
                fprintf(options.output, " > [...]\n");
        }
        fprintf(options.output, "\n");
    }
#endif /* defined(HAVE_LIBDW) */

    current_proc = NULL;
    current_column = 0;
}