static void dump_fault_addr(log_t* log, pid_t tid, int sig)
{
    siginfo_t si;

    memset(&si, 0, sizeof(si));
    if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
        _LOG(log, false, "cannot get siginfo: %s\n", strerror(errno));
    } else if (signal_has_address(sig)) {
        _LOG(log, false, "signal %d (%s), code %d (%s), fault addr %08x\n",
             sig, get_signame(sig),
             si.si_code, get_sigcode(sig, si.si_code),
             (uintptr_t) si.si_addr);
    } else {
        _LOG(log, false, "signal %d (%s), code %d (%s), fault addr --------\n",
             sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
    }
}
void dump_fault_addr(int tfd, int pid, int sig)
{
    siginfo_t si;
    
    memset(&si, 0, sizeof(si));
    if(ptrace(PTRACE_GETSIGINFO, pid, 0, &si)){
        _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno));
    } else {
        _LOG(tfd, false, "signal %d (%s), fault addr %08x\n",
            sig, get_signame(sig), si.si_addr);
    }
}
Exemple #3
0
/**
   Generates target result listing, designed for text output and console 
   viewing.
*/
static void print_status_plain (const struct target_status* status)
{
    unsigned valid_timing;
    assert (0 != status);
    assert (ST_OK <= status->status && ST_LAST > status->status);

    valid_timing =    status->usr_time != (clock_t)-1
                   && status->sys_time != (clock_t)-1
                   && ST_NOT_KILLED != status->status;

    if (status->status) /* if status is set, print it */
        printf ("%6s", short_st_name [status->status]);
    else if (status->signaled) /* if exit signal is non-zero, print it */
        printf ("%6s", get_signame (status->exit));
    else if (status->exit) /* if exit code is non-zero, print it */
        printf ("%6d", status->exit);
    else 
        printf ("     0");

    printf (" %4u", status->c_warn + status->l_warn + status->t_warn);

    /* Print assetions, if any registered */
    if (   (unsigned)-1 != status->assert
        && 0 == status->status 
        && 0 == status->exit) {
        if (status->assert) {
            const int percnt = int (  100.0
                                    * (status->assert - status->failed)
                                    / status->assert);
            printf (" %7u %6u %5d%%", status->assert, status->failed, percnt);
        }
        else {
            printf ("       0 %6u   100%%", status->failed);
        }
    }
    else if (valid_timing || status->wall_time != (clock_t)-1)
        printf ("                      ");

    /* Print timings, if available */
    if (valid_timing)
        printf (" %7.3f %7.3f", (float)status->usr_time / TICKS_PER_SEC,
                (float)status->sys_time / TICKS_PER_SEC);
    else if (status->wall_time != (clock_t)-1)
        printf ("                ");

    if (status->wall_time != (clock_t)-1)
        printf (" %7.3f\n", (float)status->wall_time / TICKS_PER_SEC);
    else
        puts ("");
}
Exemple #4
0
/**
   Generates verbose target result listing.
*/
static void
print_status_verbose (const struct target_status* status)
{
    unsigned valid_timing;

    assert (0 != status);
    assert (ST_OK <= status->status && ST_LAST > status->status);

    valid_timing =    status->usr_time != (clock_t)-1
                   && status->sys_time != (clock_t)-1
                   && ST_NOT_KILLED != status->status;

    if (status->status) /* if status is set, print it */
        printf ("  Status: %s\n", verbose_st_name [status->status]);
    else if (status->signaled) /* if exit signal is non-zero, print it */
        printf ("  Process signalled:    %s\n", get_signame (status->exit));
    else {
        printf ("  Exit status:          %6d%s\n"
                "  Compiler warnings:    %6u\n"
                "  Linker warnings:      %6u\n"
                "  Runtime warnings:     %6u\n",
                status->exit, 0 == status->exit ? " (success)" : "",
                status->c_warn,
                status->l_warn,
                status->t_warn);

        /* Print assetions, if any registered */
        if ((unsigned)-1 != status->assert && status->assert) {
            printf ("  Failed assertions:    %6u\n"
                    "  Total assertions:     %6u\n",
                    status->failed, status->assert);
        }
    }

    /* Print timings, if available */
    if (valid_timing) {
        const float wall = (float)status->wall_time / TICKS_PER_SEC;
        const float user = (float)status->usr_time  / TICKS_PER_SEC;
        const float sys  = (float)status->sys_time  / TICKS_PER_SEC;

        printf ("  Times:\n"
                "    Real               %7.3fs\n"
                "    User               %7.3fs\n"
                "    Sys                %7.3fs\n",
                wall, user, sys);
    }

    puts ("");
}
Exemple #5
0
int 
eval_options (int argc, char **argv, struct target_opts* defaults, 
              const char** exe_opts)
{
    const char opt_timeout[]  = "-t";
    const char opt_data_dir[] = "-d";
    const char opt_t_flags[]  = "-x";
    const char opt_compat[]   = "--compat";
    const char opt_exit[]     = "--exit";
    const char opt_help[]     = "--help";
    const char opt_ignore[]   = "--ignore";
    const char opt_nocompat[] = "--nocompat";
    const char opt_signal[]   = "--signal";
    const char opt_sleep[]    = "--sleep";
    const char opt_ulimit[]   = "--ulimit";
    const char opt_verbose[]  = "--verbose";
    const char opt_warn[]     = "--warn";

    int i;

    assert (0 != argv);
    assert (0 != defaults);

    memset (defaults, 0, sizeof (target_opts));

    /* The chain of preprocesor logic below initializes the defaults->c_warn 
       and defaults->l_warn values.
    */
#ifdef __GNUG__
    parse_warn_opts ("Gcc", defaults);
#elif defined (__HP_aCC)
    parse_warn_opts ("Acc", defaults);
#elif defined (__IBMCPP__)
    parse_warn_opts ("Xlc", defaults);
#elif defined (__SUNPRO_CC)
    parse_warn_opts ("Sunpro", defaults);
#elif defined (SNI)
    parse_warn_opts ("Cds", defaults);
#elif defined (__APOGEE__) /* EDG variant that doesn't define __EDG__. */
    parse_warn_opts ("Como", defaults);

/* The following are EDG variants, that define __EDG__ */
#elif defined (__DECCXX)
    parse_warn_opts ("Cxx", defaults);
#elif defined (_SGI_COMPILER_VERSION)
    parse_warn_opts ("Mipspro", defaults);
#elif defined (__INTEL_COMPILER)
    parse_warn_opts ("Icc", defaults);

/* So we need to check for __EDG__ after we check for them. */
#elif defined (__EDG__)
    parse_warn_opts ("Eccp", defaults);
#endif

    if (1 == argc || '-' != argv [1][0])
        return 1;

    for (i = 1; i < argc && '-' == argv [i][0]; ++i) {

        /* the name of the option being processed */
        const char* optname = argv [i];

        /* the option's argument, if any */
        const char* optarg  = 0;

        char* end = 0;

        switch (argv [i][1]) {
        case '?':   /* display help and exit with status of 0 */
        case 'h':
            show_usage (0);

        case 'r':
            ++i; /* Ignore -r option (makefile compat) */
            break;

        case 't':   /* executable timeout in seconds */
            optname = opt_timeout;
            optarg  = get_short_val (argv, &i);
            if (optarg) {
                if (!isdigit (*optarg))
                    bad_value (optname, optarg);

                errno = 0;
                defaults->timeout = strtol (optarg, &end, 10);
                if (*end || errno)
                    bad_value (optname, optarg);
            }
            else
                missing_value (optname);

            break;

        case 'd':   /* directory containing example reference files */
            optname = opt_data_dir;
            defaults->data_dir = get_short_val (argv, &i);
            if (!defaults->data_dir)
                missing_value (optname);
            break;

        case 'v':   /* enable verbose mode */
            optname = opt_verbose;
            ++defaults->verbose;
            break;

        case 'x':   /* command line options to pass to targets */
            optname  = opt_t_flags;
            *exe_opts = get_short_val (argv, &i);
            if (!*exe_opts)
                missing_value (optname);
            break;

        case '-':   /* long options */
        {
            const size_t arglen = strlen (argv [i]);

            /* abort processing on --, eat token */
            if ('\0' == argv [i][2])
                return i+1;

            if (   sizeof opt_compat - 1 == arglen
                && !memcmp (opt_compat, argv [i], sizeof opt_compat)) {
                /* enter compatibility mode */
                defaults->compat = 1;
                break;
            }
            else if (   sizeof opt_nocompat - 1 == arglen
                     && !memcmp (opt_nocompat, argv [i], sizeof opt_nocompat)) {
                /* exit compatibility mode */
                defaults->compat = 0;
                break;
            }
            else if (   sizeof opt_exit - 1 <= arglen
                     && !memcmp (opt_exit, argv [i], sizeof opt_exit - 1)) {
                /* exit immediately with the specified status */
                optname = opt_exit;
                optarg  = get_long_val (argv, &i, sizeof opt_exit - 1);
                if (optarg && *optarg) {
                    if (!isdigit (*optarg))
                        bad_value (optname, optarg);

                    errno = 0;
                    const long code = strtol (optarg, &end, 10);
                    if ('\0' == *end && !errno)
                        exit (code);
                }
            }
            else if (   sizeof opt_help - 1 == arglen
                     && !memcmp (opt_help, argv [i], sizeof opt_help - 1)) {
                /* display help and exit with status of 0 */
                optname = opt_help;
                show_usage (0);
                break;
            }
            else if (   sizeof opt_sleep - 1 <= arglen
                     && !memcmp (opt_sleep, argv [i], sizeof opt_sleep - 1)) {
                /* sleep for the specified number of seconds */ 
                optname = opt_sleep;
                optarg  = get_long_val (argv, &i, sizeof opt_sleep - 1);
                if (optarg && *optarg) {
                    if (!isdigit (*optarg))
                        bad_value (optname, optarg);

                    errno = 0;
                    const long nsec = strtol (optarg, &end, 10);
                    if ('\0' == *end && 0 <= nsec && !errno) {
                        rw_sleep (nsec);
                        break;
                    }
                }
            }
            else if (   sizeof opt_signal - 1 <= arglen
                     && !memcmp (opt_signal, argv [i], sizeof opt_signal - 1)) {
                /* send ourselves the specified signal */
                optname = opt_signal;
                optarg  = get_long_val (argv, &i, sizeof opt_signal - 1);
                if (optarg && *optarg) {
                    const int signo = get_signo (optarg);
                    if (0 <= signo) {
                        if (0 > raise (signo))
                            terminate (1, "raise(%s) failed: %s\n",
                                       get_signame (signo), strerror (errno));
                        break;
                    }
                }
            }
            else if (   sizeof opt_ignore - 1 <= arglen
                     && !memcmp (opt_ignore, argv [i], sizeof opt_ignore - 1)) {
                /* ignore the specified signal */
                optname = opt_ignore;
                optarg  = get_long_val (argv, &i, sizeof opt_ignore - 1);
                if (optarg && *optarg) {
                    const int signo = get_signo (optarg);
                    if (0 <= signo) {
                        if (rw_signal (signo, 0 /* SIG_IGN */))
                            terminate (1, "rw_signal(%s, ...) failed: %s\n",
                                       get_signame (signo), strerror (errno));
                        break;
                    }
                }
            }
            else if (   sizeof opt_ulimit - 1 <= arglen
                     && !memcmp (opt_ulimit, argv [i], sizeof opt_ulimit - 1)) {
                /* set child process resource utilization limits */
                optname = opt_ulimit;
                optarg  = get_long_val (argv, &i, sizeof opt_ulimit - 1);
                if (optarg && *optarg) {
                    if (!parse_limit_opts (optarg, defaults)) {
                        break;
                    }
                }
            }
            else if (   sizeof opt_warn - 1 <= arglen
                     && !memcmp (opt_warn, argv [i], sizeof opt_warn - 1)) {
                /* set compiler warning mode */
                optname = opt_warn;
                optarg  = get_long_val (argv, &i, sizeof opt_warn - 1);
                if (optarg && *optarg) {
                    if (!parse_warn_opts (optarg, defaults)) {
                        break;
                    }
                }
            }
            /* fall through */
        }
        default:
            if (optarg) {
                if (*optarg)
                    bad_value (optname, optarg);
                else
                    missing_value (optname);
            }

            if (argv [i])
                bad_option (argv [i]);
            else
                missing_value (optname);
        }
    }

    return i;
}
Exemple #6
0
int kill_main(int argc, char **argv)
{
	char *arg;
	pid_t pid;
	int signo = SIGTERM, errors = 0, quiet = 0;
#if !ENABLE_KILLALL && !ENABLE_KILLALL5
#define killall 0
#define killall5 0
#else
/* How to determine who we are? find 3rd char from the end:
 * kill, killall, killall5
 *  ^i       ^a        ^l  - it's unique
 * (checking from the start is complicated by /bin/kill... case) */
	const char char3 = argv[0][strlen(argv[0]) - 3];
#define killall (ENABLE_KILLALL && char3 == 'a')
#define killall5 (ENABLE_KILLALL5 && char3 == 'l')
#endif

	/* Parse any options */
	argc--;
	arg = *++argv;

	if (argc < 1 || arg[0] != '-') {
		goto do_it_now;
	}

	/* The -l option, which prints out signal names.
	 * Intended usage in shell:
	 * echo "Died of SIG`kill -l $?`"
	 * We try to mimic what kill from coreutils-6.8 does */
	if (arg[1] == 'l' && arg[2] == '\0') {
		if (argc == 1) {
			/* Print the whole signal list */
			print_signames();
			return 0;
		}
		/* -l <sig list> */
		while ((arg = *++argv)) {
			if (isdigit(arg[0])) {
				signo = bb_strtou(arg, NULL, 10);
				if (errno) {
					bb_error_msg("unknown signal '%s'", arg);
					return EXIT_FAILURE;
				}
				/* Exitcodes >= 0x80 are to be treated
				 * as "killed by signal (exitcode & 0x7f)" */
				puts(get_signame(signo & 0x7f));
				/* TODO: 'bad' signal# - coreutils says:
				 * kill: 127: invalid signal
				 * we just print "127" instead */
			} else {
				signo = get_signum(arg);
				if (signo < 0) {
					bb_error_msg("unknown signal '%s'", arg);
					return EXIT_FAILURE;
				}
				printf("%d\n", signo);
			}
		}
		/* If they specified -l, we are all done */
		return EXIT_SUCCESS;
	}

	/* The -q quiet option */
	if (killall && arg[1] == 'q' && arg[2] == '\0') {
		quiet = 1;
		arg = *++argv;
		argc--;
		if (argc < 1)
			bb_show_usage();
		if (arg[0] != '-')
			goto do_it_now;
	}

	arg++; /* skip '-' */

	/* -o PID? (if present, it always is at the end of command line) */
	if (killall5 && arg[0] == 'o')
		goto do_it_now;

	if (argc > 1 && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */
		argc--;
		arg = *++argv;
	} /* else it must be -SIG */
	signo = get_signum(arg);
	if (signo < 0) { /* || signo > MAX_SIGNUM ? */
		bb_error_msg("bad signal name '%s'", arg);
		return EXIT_FAILURE;
	}
	arg = *++argv;
	argc--;

 do_it_now:
	pid = getpid();

	if (killall5) {
		pid_t sid;
		procps_status_t* p = NULL;
		int ret = 0;

		/* Find out our session id */
		sid = getsid(pid);
		/* Stop all processes */
		if (signo != SIGSTOP && signo != SIGCONT)
			kill(-1, SIGSTOP);
		/* Signal all processes except those in our session */
		while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID)) != NULL) {
			int i;

			if (p->sid == (unsigned)sid
			 || p->pid == (unsigned)pid
			 || p->pid == 1
			) {
				continue;
			}

			/* All remaining args must be -o PID options.
			 * Check p->pid against them. */
			for (i = 0; i < argc; i++) {
				pid_t omit;

				arg = argv[i];
				if (arg[0] != '-' || arg[1] != 'o') {
					bb_error_msg("bad option '%s'", arg);
					ret = 1;
					goto resume;
				}
				arg += 2;
				if (!arg[0] && argv[++i])
					arg = argv[i];
				omit = bb_strtoi(arg, NULL, 10);
				if (errno) {
					bb_error_msg("invalid number '%s'", arg);
					ret = 1;
					goto resume;
				}
				if (p->pid == omit)
					goto dont_kill;
			}
			kill(p->pid, signo);
 dont_kill: ;
		}
 resume:
		/* And let them continue */
		if (signo != SIGSTOP && signo != SIGCONT)
			kill(-1, SIGCONT);
		return ret;
	}

	/* Pid or name is required for kill/killall */
	if (argc < 1) {
		bb_error_msg("you need to specify whom to kill");
		return EXIT_FAILURE;
	}

	if (killall) {
		/* Looks like they want to do a killall.  Do that */
		while (arg) {
			pid_t* pidList;

			pidList = find_pid_by_name(arg);
			if (*pidList == 0) {
				errors++;
				if (!quiet)
					bb_error_msg("%s: no process killed", arg);
			} else {
				pid_t *pl;

				for (pl = pidList; *pl; pl++) {
					if (*pl == pid)
						continue;
					if (kill(*pl, signo) == 0)
						continue;
					errors++;
					if (!quiet)
						bb_perror_msg("can't kill pid %d", (int)*pl);
				}
			}
			free(pidList);
			arg = *++argv;
		}
		return errors;
	}

	/* Looks like they want to do a kill. Do that */
	while (arg) {
#if ENABLE_ASH || ENABLE_HUSH
		/*
		 * We need to support shell's "hack formats" of
		 * " -PRGP_ID" (yes, with a leading space)
		 * and " PID1 PID2 PID3" (with degenerate case "")
		 */
		while (*arg != '\0') {
			char *end;
			if (*arg == ' ')
				arg++;
			pid = bb_strtoi(arg, &end, 10);
			if (errno && (errno != EINVAL || *end != ' ')) {
				bb_error_msg("invalid number '%s'", arg);
				errors++;
				break;
			}
			if (kill(pid, signo) != 0) {
				bb_perror_msg("can't kill pid %d", (int)pid);
				errors++;
			}
			arg = end; /* can only point to ' ' or '\0' now */
		}
#else
		pid = bb_strtoi(arg, NULL, 10);
		if (errno) {
			bb_error_msg("invalid number '%s'", arg);
			errors++;
		} else if (kill(pid, signo) != 0) {
			bb_perror_msg("can't kill pid %d", (int)pid);
			errors++;
		}
#endif
		arg = *++argv;
	}
	return errors;
}
Exemple #7
0
int kill_main(int argc, char **argv)
{
	char *arg;
	pid_t pid;
	int signo = SIGTERM, errors = 0, quiet = 0;
#if !ENABLE_KILLALL && !ENABLE_KILLALL5
#define killall 0
#define killall5 0
#else
/* How to determine who we are? find 3rd char from the end:
 * kill, killall, killall5
 *  ^i       ^a        ^l  - it's unique
 * (checking from the start is complicated by /bin/kill... case) */
	const char char3 = argv[0][strlen(argv[0]) - 3];
#define killall (ENABLE_KILLALL && char3 == 'a')
#define killall5 (ENABLE_KILLALL5 && char3 == 'l')
#endif

	/* Parse any options */
	argc--;
	arg = *++argv;

	if (argc < 1 || arg[0] != '-') {
		goto do_it_now;
	}

	/* The -l option, which prints out signal names.
	 * Intended usage in shell:
	 * echo "Died of SIG`kill -l $?`"
	 * We try to mimic what kill from coreutils-6.8 does */
	if (arg[1] == 'l' && arg[2] == '\0') {
		if (argc == 1) {
			/* Print the whole signal list */
			print_signames();
			return 0;
		}
		/* -l <sig list> */
		while ((arg = *++argv)) {
			if (isdigit(arg[0])) {
				signo = bb_strtou(arg, NULL, 10);
				if (errno) {
					bb_error_msg("unknown signal '%s'", arg);
					return EXIT_FAILURE;
				}
				/* Exitcodes >= 0x80 are to be treated
				 * as "killed by signal (exitcode & 0x7f)" */
				puts(get_signame(signo & 0x7f));
				/* TODO: 'bad' signal# - coreutils says:
				 * kill: 127: invalid signal
				 * we just print "127" instead */
			} else {
				signo = get_signum(arg);
				if (signo < 0) {
					bb_error_msg("unknown signal '%s'", arg);
					return EXIT_FAILURE;
				}
				printf("%d\n", signo);
			}
		}
		/* If they specified -l, we are all done */
		return EXIT_SUCCESS;
	}

	/* The -q quiet option */
	if (killall && arg[1] == 'q' && arg[2] == '\0') {
		quiet = 1;
		arg = *++argv;
		argc--;
		if (argc < 1) bb_show_usage();
		if (arg[0] != '-') goto do_it_now;
	}

	/* -SIG */
	signo = get_signum(&arg[1]);
	if (signo < 0) { /* || signo > MAX_SIGNUM ? */
		bb_error_msg("bad signal name '%s'", &arg[1]);
		return EXIT_FAILURE;
	}
	arg = *++argv;
	argc--;

do_it_now:
	pid = getpid();

	if (killall5) {
		pid_t sid;
		procps_status_t* p = NULL;

		/* Find out our own session id */
		sid = getsid(pid);
		/* Now stop all processes */
		kill(-1, SIGSTOP);
		/* Now kill all processes except our session */
		while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID))) {
			if (p->sid != (unsigned)sid && p->pid != (unsigned)pid && p->pid != 1)
				kill(p->pid, signo);
		}
		/* And let them continue */
		kill(-1, SIGCONT);
		return 0;
	}

	/* Pid or name is required for kill/killall */
	if (argc < 1) {
		bb_error_msg("you need to specify whom to kill");
		return EXIT_FAILURE;
	}

	if (killall) {
		/* Looks like they want to do a killall.  Do that */
		while (arg) {
			pid_t* pidList;

			pidList = find_pid_by_name(arg);
			if (*pidList == 0) {
				errors++;
				if (!quiet)
					bb_error_msg("%s: no process killed", arg);
			} else {
				pid_t *pl;

				for (pl = pidList; *pl; pl++) {
					if (*pl == pid)
						continue;
					if (kill(*pl, signo) == 0)
						continue;
					errors++;
					if (!quiet)
						bb_perror_msg("cannot kill pid %u", (unsigned)*pl);
				}
			}
			free(pidList);
			arg = *++argv;
		}
		return errors;
	}

	/* Looks like they want to do a kill. Do that */
	while (arg) {
		/* Support shell 'space' trick */
		if (arg[0] == ' ')
			arg++;
		pid = bb_strtoi(arg, NULL, 10);
		if (errno) {
			bb_error_msg("bad pid '%s'", arg);
			errors++;
		} else if (kill(pid, signo) != 0) {
			bb_perror_msg("cannot kill pid %d", (int)pid);
			errors++;
		}
		arg = *++argv;
	}
	return errors;
}