[GSOC 2014][PATCH 2/4] JSON: Add support to entering/exiting of syscall

Zhu YangMin zym0017d at gmail.com
Wed Jun 18 16:29:48 UTC 2014


Now the JSON output is one dict object each line, representing a
the enter/exit of a syscall. The dict object contain key filed
such as 'type', 'name', 'ret' of a syscall. All the value are string.

* syscall.c(trace_syscall_entering, trace_syscall_exiting): Modify to support
in JSON format.
* process.c(sys_exit): Modify to support in JSON format.
* strace.c(trace): Modify to support the last exited signal in JSON format.
---
 process.c |  6 +++++
 strace.c  |  7 +++++-
 syscall.c | 84 +++++++++++++++++++++++++++++++++++++++++++--------------------
 3 files changed, 70 insertions(+), 27 deletions(-)

diff --git a/process.c b/process.c
index a880f9e..9b40922 100644
--- a/process.c
+++ b/process.c
@@ -258,7 +258,13 @@ sys_exit(struct tcb *tcp)
 		return -1;
 	}
 	/* special case: we stop tracing this process, finish line now */
+	JSON_BEGIN_META_MODE;
 	tprintf("%ld) ", tcp->u_arg[0]);
+	json_event(4, EVENT_ARG,
+				  EVENT_ARGS_END | SEPARATOR,
+				  EVENT_RET,
+				  EVENT_CALL_END | NEWLINE);
+
 	tabto();
 	tprints("= ?\n");
 	line_ended();
diff --git a/strace.c b/strace.c
index 800f229..792189f 100644
--- a/strace.c
+++ b/strace.c
@@ -2303,7 +2303,12 @@ trace(void)
 			if (cflag != CFLAG_ONLY_STATS &&
 			    qflag < 2) {
 				printleader(tcp);
-				tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
+				JSON_BEGIN_META_MODE;
+				tprintf("+++ %s with %d +++\n", "exited", WEXITSTATUS(status));
+				json_event(4, EVENT_SIGNAL_BEGIN | SEPARATOR,
+							  EVENT_DESC | SEPARATOR,
+							  EVENT_SIGCODE,
+							  EVENT_SIGNAL_END | NEWLINE);
 				line_ended();
 			}
 			droptcb(tcp);
diff --git a/syscall.c b/syscall.c
index b0ad47e..9ccc504 100644
--- a/syscall.c
+++ b/syscall.c
@@ -1984,8 +1984,12 @@ trace_syscall_entering(struct tcb *tcp)
 
 	if (res != 1) {
 		printleader(tcp);
-		if (scno_good != 1)
-			tprints("????" /* anti-trigraph gap */ "(");
+		json_event(1, EVENT_CALL_BEGIN | SEPARATOR);
+		JSON_BEGIN_META_MODE;
+		if (scno_good != 1) {
+			JSON_META( tprints("????"); );
+			tprints("(");
+		}
 		else if (tcp->qual_flg & UNDEFINED_SCNO)
 			tprintf("%s(", undefined_scno_name(tcp));
 		else
@@ -1994,6 +1998,7 @@ trace_syscall_entering(struct tcb *tcp)
 		 * " <unavailable>" will be added later by the code which
 		 * detects ptrace errors.
 		 */
+		json_event(2, EVENT_NAME | SEPARATOR, EVENT_ARGS_BEGIN);
 		goto ret;
 	}
 
@@ -2048,14 +2053,20 @@ trace_syscall_entering(struct tcb *tcp)
 #endif
 
 	printleader(tcp);
+	json_event(1, EVENT_CALL_BEGIN | SEPARATOR);
+	JSON_BEGIN_META_MODE;
 	if (tcp->qual_flg & UNDEFINED_SCNO)
 		tprintf("%s(", undefined_scno_name(tcp));
 	else
 		tprintf("%s(", tcp->s_ent->sys_name);
-	if ((tcp->qual_flg & QUAL_RAW) && tcp->s_ent->sys_func != sys_exit)
+	json_event(2, EVENT_NAME | SEPARATOR, EVENT_ARGS_BEGIN);
+
+	if ((tcp->qual_flg & QUAL_RAW) && tcp->s_ent->sys_func != sys_exit) {
 		res = printargs(tcp);
-	else
+	}
+	else {
 		res = tcp->s_ent->sys_func(tcp);
+	}
 
 	fflush(tcp->outf);
  ret:
@@ -2567,10 +2578,14 @@ trace_syscall_exiting(struct tcb *tcp)
 	printing_tcp = tcp;
 
 	if (res != 1) {
+		JSON_BEGIN_META_MODE;
 		/* There was error in one of prior ptrace ops */
-		tprints(") ");
+		tprintf(") = %s <%s>\n", "?", "unavailable");
+		json_event(4, EVENT_ARGS_END | SEPARATOR,
+					  EVENT_RET | SEPARATOR,
+					  EVENT_DESC,
+					  EVENT_CALL_END | NEWLINE);
 		tabto();
-		tprints("= ? <unavailable>\n");
 		line_ended();
 		tcp->flags &= ~TCB_INSYSCALL;
 		return res;
@@ -2594,15 +2609,22 @@ trace_syscall_exiting(struct tcb *tcp)
 	}
 
 	tprints(") ");
+	json_event(1, EVENT_ARGS_END | SEPARATOR);
 	tabto();
+	JSON_BEGIN_META_MODE;
 	u_error = tcp->u_error;
 	if (tcp->qual_flg & QUAL_RAW) {
-		if (u_error)
-			tprintf("= -1 (errno %ld)", u_error);
-		else
+		if (u_error) {
+			tprintf("= %s (errno %ld)", "-1", u_error);
+			json_event(2, EVENT_RET | SEPARATOR, EVENT_ERRNO);
+		}
+		else {
 			tprintf("= %#lx", tcp->u_rval);
+			json_event(1, EVENT_RET);
+		}
 	}
 	else if (!(sys_res & RVAL_NONE) && u_error) {
+		json_type_event second = EVENT_DESC;
 		switch (u_error) {
 		/* Blocked signals do not interrupt any syscalls.
 		 * In this case syscalls don't return ERESTARTfoo codes.
@@ -2625,13 +2647,13 @@ trace_syscall_exiting(struct tcb *tcp)
 			 * 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)");
+			tprintf("= %s %s (%s)", "?", "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)");
+			tprintf("= %s %s (%s)", "?", "ERESTARTNOINTR", "To be restarted");
 			break;
 		case ERESTARTNOHAND:
 			/* pause(), rt_sigsuspend() etc use this code.
@@ -2641,7 +2663,7 @@ trace_syscall_exiting(struct tcb *tcp)
 			 * 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)");
+			tprintf("= %s %s (%s)", "?", "ERESTARTNOHAND", "To be restarted if no handler");
 			break;
 		case ERESTART_RESTARTBLOCK:
 			/* Syscalls like nanosleep(), poll() which can't be
@@ -2655,25 +2677,31 @@ trace_syscall_exiting(struct tcb *tcp)
 			 * which in turn saves another such restart block,
 			 * old data is lost and restart becomes impossible)
 			 */
-			tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
+			tprintf("= %s %s (%s)", "?", "ERESTART_RESTARTBLOCK", "Interrupted by signal");
 			break;
 		default:
 			if (u_error < 0)
-				tprintf("= -1 E??? (errno %ld)", u_error);
+				tprintf("= %d %s (errno %ld)", -1, "E???", u_error);
 			else if (u_error < nerrnos)
-				tprintf("= -1 %s (%s)", errnoent[u_error],
-					strerror(u_error));
-			else
-				tprintf("= -1 ERRNO_%ld (%s)", u_error,
-					strerror(u_error));
+				tprintf("= %d %s (%s)", -1, errnoent[u_error], strerror(u_error));
+			else {
+				tprintf("= %d ERRNO_%ld (%s)", -1, u_error, strerror(u_error));
+				second = EVENT_ERRNO;
+			}
 			break;
 		}
-		if ((sys_res & RVAL_STR) && tcp->auxstr)
+		json_event(3, EVENT_RET | SEPARATOR, second | SEPARATOR, EVENT_DESC_LONG);
+
+		if ((sys_res & RVAL_STR) && tcp->auxstr) {
+			JSON_BEGIN_META_MODE;
 			tprintf(" (%s)", tcp->auxstr);
+			json_event(1, BEF_SEPRATOR | EVENT_AUXSTR);
+		}
 	}
 	else {
-		if (sys_res & RVAL_NONE)
-			tprints("= ?");
+		if (sys_res & RVAL_NONE) {
+			tprintf("= %s", "?");
+		}
 		else {
 			switch (sys_res & RVAL_MASK) {
 			case RVAL_HEX:
@@ -2691,7 +2719,7 @@ trace_syscall_exiting(struct tcb *tcp)
 			case RVAL_FD:
 				if (show_fd_path) {
 					tprints("= ");
-					printfd(tcp, tcp->u_rval);
+					JSON_META( printfd(tcp, tcp->u_rval); );
 				}
 				else
 					tprintf("= %ld", tcp->u_rval);
@@ -2715,13 +2743,16 @@ trace_syscall_exiting(struct tcb *tcp)
 			*/
 #endif
 			default:
-				fprintf(stderr,
-					"invalid rval format\n");
+				fprintf(stderr, "invalid rval format\n");
 				break;
 			}
+			json_event(1, EVENT_RET);
 		}
-		if ((sys_res & RVAL_STR) && tcp->auxstr)
+		if ((sys_res & RVAL_STR) && tcp->auxstr) {
+			JSON_BEGIN_META_MODE;
 			tprintf(" (%s)", tcp->auxstr);
+			json_event(1, BEF_SEPRATOR | EVENT_AUXSTR);
+		}
 	}
 	if (Tflag) {
 		tv_sub(&tv, &tv, &tcp->etime);
@@ -2729,6 +2760,7 @@ trace_syscall_exiting(struct tcb *tcp)
 			(long) tv.tv_sec, (long) tv.tv_usec);
 	}
 	tprints("\n");
+	json_event(1, EVENT_CALL_END | NEWLINE);
 	dumpio(tcp);
 	line_ended();
 
-- 
1.9.1





More information about the Strace-devel mailing list