[PATCHv1] strace: add :signal option to efault
Seraphime Kirkovski
kirkseraph at gmail.com
Mon Dec 26 17:24:46 UTC 2016
This extends the -e fault capability with a :signal option which
delivers a signal on entry of the specified syscall.
:signal and :error are complementary, if they are both specified the
syscall will be injected as per normal and a signal will be sent to the
process.
Signed-off-by: Seraphime Kirkovski <kirkseraph at gmail.com>
---
This takes account of the changes requested by Dmitry, i.e.
this makes :signal and :error complementary rather than mutually exclusive.
defs.h | 4 +++-
qualify.c | 11 ++++++++++-
strace.c | 4 +++-
syscall.c | 16 +++++++++-------
4 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/defs.h b/defs.h
index 0a4c616..597bdd3 100644
--- a/defs.h
+++ b/defs.h
@@ -218,6 +218,7 @@ struct fault_opts {
uint16_t first;
uint16_t step;
uint16_t err;
+ int16_t signo;
};
#if defined LINUX_MIPSN32 || defined X32
@@ -457,13 +458,14 @@ extern int read_int_from_file(const char *, int *);
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 *);
extern void clear_regs(void);
extern void get_regs(pid_t pid);
extern int get_scno(struct tcb *tcp);
+
/**
* Convert syscall number to syscall name.
*
diff --git a/qualify.c b/qualify.c
index a7d276c..d707bfe 100644
--- a/qualify.c
+++ b/qualify.c
@@ -414,6 +414,11 @@ parse_fault_token(const char *const token, struct fault_opts *const fopts)
if (intval < 1)
return false;
fopts->err = intval;
+ } else if ((val = strip_prefix("signal=", token))) {
+ intval = sigstr_to_uint(val);
+ if (intval < 0)
+ return false;
+ fopts->signo = intval;
} else {
return false;
}
@@ -494,13 +499,17 @@ qualify_fault(const char *const str)
struct fault_opts opts = {
.first = 1,
.step = 1,
- .err = 0
+ .signo = -1,
+ .err = -1
};
char *buf = NULL;
char *name = parse_fault_expression(str, &buf, &opts);
if (!name) {
error_msg_and_die("invalid %s '%s'", "fault argument", str);
}
+ /* If no error, nor signal is specified, fallback to ENOSYS */
+ if (opts.signo == -1 && (int16_t)opts.err == -1)
+ opts.err = ENOSYS;
struct number_set tmp_set[SUPPORTED_PERSONALITIES];
diff --git a/strace.c b/strace.c
index 4659ddb..23ca108 100644
--- a/strace.c
+++ b/strace.c
@@ -2447,7 +2447,8 @@ show_stopsig:
* 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.
@@ -2461,6 +2462,7 @@ show_stopsig:
*/
return true;
}
+ goto restart_tracee;
restart_tracee_with_sig_0:
sig = 0;
diff --git a/syscall.c b/syscall.c
index 63d3b00..e4fd36b 100644
--- a/syscall.c
+++ b/syscall.c
@@ -573,7 +573,7 @@ tcb_fault_opts(struct tcb *tcp)
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] =
@@ -595,7 +595,9 @@ inject_syscall_fault_entering(struct tcb *tcp)
opts->first = opts->step;
- if (!arch_set_scno(tcp, -1))
+ if (opts->signo != -1)
+ *signo = opts->signo;
+ if ((int16_t)opts->err != -1 && !arch_set_scno(tcp, -1))
tcp->flags |= TCB_FAULT_INJ;
return 0;
@@ -617,7 +619,7 @@ update_syscall_fault_exiting(struct tcb *tcp)
}
static int
-trace_syscall_entering(struct tcb *tcp)
+trace_syscall_entering(struct tcb *tcp, unsigned int *sig)
{
int res, scno_good;
@@ -688,7 +690,7 @@ trace_syscall_entering(struct tcb *tcp)
}
if (tcp->qual_flg & QUAL_FAULT)
- inject_syscall_fault_entering(tcp);
+ inject_syscall_fault_entering(tcp, sig);
if (cflag == CFLAG_ONLY_STATS) {
res = 0;
@@ -716,7 +718,7 @@ trace_syscall_entering(struct tcb *tcp)
/* Measure the entrance time as late as possible to avoid errors. */
if (Tflag || cflag)
gettimeofday(&tcp->etime, NULL);
- return res;
+ return 0;
}
static bool
@@ -981,10 +983,10 @@ trace_syscall_exiting(struct tcb *tcp)
}
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
--
2.10.2
More information about the Strace-devel
mailing list