[PATCH v3 1/3] Stop condition based on number of syscalls

Sahil Siddiq icegambit91 at gmail.com
Wed Mar 1 21:38:42 UTC 2023


Add option to detach strace after capturing a specified
number of syscalls.

* src/defs.h: Add syscall_limit variable.
* src/strace.c: Implementation of -l/--syscall-limit option.
* src/syscall.c: Move updation of syscall_limit here.

Signed-off-by: Sahil Siddiq <icegambit91 at gmail.com>
---
 src/defs.h    |  1 +
 src/strace.c  | 21 ++++++++++++++++++---
 src/syscall.c |  3 +++
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/src/defs.h b/src/defs.h
index 6c93d8460..cb01c96f6 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -513,6 +513,7 @@ extern int Tflag_scale;
 extern int Tflag_width;
 extern bool iflag;
 extern bool count_wallclock;
+extern int syscall_limit;
 
 struct path_set_item {
 	const char *path;
diff --git a/src/strace.c b/src/strace.c
index 21b693d02..977e7e497 100644
--- a/src/strace.c
+++ b/src/strace.c
@@ -84,6 +84,7 @@ int Tflag_scale = 1000;
 int Tflag_width = 6;
 bool iflag;
 bool count_wallclock;
+int syscall_limit = -1;
 static bool nflag;
 static int tflag_scale = 1000000000;
 static unsigned tflag_width = 0;
@@ -461,6 +462,10 @@ Statistics:\n\
   -w, --summary-wall-clock\n\
                  summarise syscall latency (default is system time)\n\
 \n\
+Stop condition:\n\
+  -l LIMIT, --syscall-limit=LIMIT\n\
+                 Detach tracer after tracing LIMIT syscalls\n\
+\n\
 Tampering:\n\
   -e inject=SET[:error=ERRNO|:retval=VALUE][:signal=SIG][:syscall=SYSCALL]\n\
             [:delay_enter=DELAY][:delay_exit=DELAY]\n\
@@ -1108,7 +1113,7 @@ droptcb(struct tcb *tcp)
 				fprintf(tcp->outf, " <detached ...>\n");
 			fclose(tcp->outf);
 		} else {
-			if (printing_tcp == tcp && tcp->curcol != 0 && publish)
+			if (syscall_limit == 0 || (printing_tcp == tcp && tcp->curcol != 0 && publish))
 				fprintf(tcp->outf, " <detached ...>\n");
 			flush_tcp_output(tcp);
 		}
@@ -2245,7 +2250,7 @@ init(int argc, char *argv[])
 #endif
 
 	static const char optstring[] =
-		"+a:Ab:cCdDe:E:fFhiI:kno:O:p:P:qrs:S:tTu:U:vVwxX:yYzZ";
+		"+a:Ab:cCdDe:E:fFhiI:kl:no:O:p:P:qrs:S:tTu:U:vVwxX:yYzZ";
 
 	enum {
 		GETOPT_SECCOMP = 0x100,
@@ -2291,6 +2296,7 @@ init(int argc, char *argv[])
 		{ "instruction-pointer", no_argument,      0, 'i' },
 		{ "interruptible",	required_argument, 0, 'I' },
 		{ "stack-traces",	no_argument,	   0, 'k' },
+		{ "syscall-limit",	required_argument, 0, 'l' },
 		{ "syscall-number",	no_argument,	   0, 'n' },
 		{ "output",		required_argument, 0, 'o' },
 		{ "summary-syscall-overhead", required_argument, 0, 'O' },
@@ -2432,6 +2438,11 @@ init(int argc, char *argv[])
 					  "build of strace");
 #endif
 			break;
+		case 'l':
+			syscall_limit = string_to_uint(optarg);
+			if (syscall_limit <= 0)
+				error_opt_arg(c, lopt, optarg);
+			break;
 		case 'n':
 			nflag = 1;
 			break;
@@ -3047,7 +3058,7 @@ static struct tcb *
 maybe_allocate_tcb(const int pid, int status)
 {
 	if (!WIFSTOPPED(status)) {
-		if (detach_on_execve && pid == strace_child) {
+		if ((detach_on_execve || syscall_limit == 0) && pid == strace_child) {
 			/* example: strace -bexecve sh -c 'exec true' */
 			strace_child = 0;
 			return NULL;
@@ -3716,6 +3727,10 @@ dispatch_event(const struct tcb_wait_data *wd)
 			 */
 			return true;
 		}
+		if (syscall_limit == 0) {
+			detach(current_tcp);
+			return true;
+		}
 		if (has_seccomp_filter(current_tcp)) {
 			/*
 			 * Syscall and seccomp stops can happen in different
diff --git a/src/syscall.c b/src/syscall.c
index cc37aa30c..696b81dfd 100644
--- a/src/syscall.c
+++ b/src/syscall.c
@@ -849,6 +849,9 @@ syscall_exiting_trace(struct tcb *tcp, struct timespec *ts, int res)
 		}
 	}
 
+	if (syscall_limit != -1)
+		syscall_limit--;
+
 	tprint_arg_end();
 	tprint_space();
 	tabto();
-- 
2.39.2



More information about the Strace-devel mailing list