[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