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 ------------------------------------------------------------------------------ HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions Find What Matters Most in Your Big Data with HPCC Systems Open Source. Fast. Scalable. Simple. Ideal for Dirty Data. Leverages Graph Analysis for Fast Processing & Easy Data Exploration http://p.sf.net/sfu/hpccsystems _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel