struct fault_opts {
uint16_t first;
uint16_t step;
- uint16_t err;
+ int16_t err;
+ uint16_t signo;
};
/* Trace Control Block */
extern void set_sortby(const char *);
extern void set_overhead(int);
extern void print_pc(struct tcb *);
-extern int trace_syscall(struct tcb *);
+extern int trace_syscall(struct tcb *, unsigned int *);
extern void count_syscall(struct tcb *, const struct timeval *);
extern void call_summary(FILE *);
*/
#include "defs.h"
+#include "nsig.h"
typedef unsigned int number_slot_t;
#define BITS_PER_SLOT (sizeof(number_slot_t) * 8)
if (intval < 1)
return false;
fopts->err = intval;
+ } else if ((val = strip_prefix("signal=", token))) {
+ intval = sigstr_to_uint(val);
+ if (intval < 1 || intval > NSIG_BYTES * 8)
+ return false;
+ fopts->signo = intval;
} else {
return false;
}
struct fault_opts opts = {
.first = 1,
.step = 1,
- .err = 0
+ .err = -1,
+ .signo = 0
};
char *buf = NULL;
char *name = parse_fault_expression(str, &buf, &opts);
error_msg_and_die("invalid %s '%s'", "fault argument", str);
}
+ /*
+ * If neither error nor signal is specified,
+ * fallback to the default platform error code.
+ */
+ if (opts.signo == 0 && opts.err == -1)
+ opts.err = 0;
struct number_set tmp_set[SUPPORTED_PERSONALITIES];
memset(tmp_set, 0, sizeof(tmp_set));
* This should be syscall entry or exit.
* Handle it.
*/
- if (trace_syscall(tcp) < 0) {
+ sig = 0;
+ if (trace_syscall(tcp, &sig) < 0) {
/*
* ptrace() failed in trace_syscall().
* Likely a result of process disappearing mid-flight.
*/
return true;
}
+ goto restart_tracee;
restart_tracee_with_sig_0:
sig = 0;
static long
-inject_syscall_fault_entering(struct tcb *tcp)
+inject_syscall_fault_entering(struct tcb *tcp, unsigned int *signo)
{
if (!tcp->fault_vec[current_personality]) {
tcp->fault_vec[current_personality] =
opts->first = opts->step;
- if (!arch_set_scno(tcp, -1))
+ if (opts->signo > 0)
+ *signo = opts->signo;
+ if (opts->err != -1 && !arch_set_scno(tcp, -1))
tcp->flags |= TCB_FAULT_INJ;
return 0;
{
struct fault_opts *opts = tcb_fault_opts(tcp);
- if (opts && opts->err && tcp->u_error != opts->err) {
+ if (opts && opts->err > 0 && tcp->u_error != (uint16_t) opts->err) {
unsigned long u_error = tcp->u_error;
tcp->u_error = opts->err;
if (arch_set_error(tcp))
}
static int
-trace_syscall_entering(struct tcb *tcp)
+trace_syscall_entering(struct tcb *tcp, unsigned int *sig)
{
int res, scno_good;
}
if (tcp->qual_flg & QUAL_FAULT)
- inject_syscall_fault_entering(tcp);
+ inject_syscall_fault_entering(tcp, sig);
if (cflag == CFLAG_ONLY_STATS) {
res = 0;
}
int
-trace_syscall(struct tcb *tcp)
+trace_syscall(struct tcb *tcp, unsigned int *signo)
{
return exiting(tcp) ?
- trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
+ trace_syscall_exiting(tcp) : trace_syscall_entering(tcp, signo);
}
bool