Skip to content

@zym0017d /defs.h.diff
Last active

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
some representative changes to strace
diff --git a/defs.h b/defs.h
index 1a3b483..3f4c36c 100644
--- a/defs.h
+++ b/defs.h
@@ -559,6 +559,7 @@ extern cflag_t cflag;
extern bool debug_flag;
extern bool Tflag;
extern bool iflag;
+extern bool jflag;
extern bool count_wallclock;
extern unsigned int qflag;
extern bool not_failing_only;
@@ -766,7 +767,9 @@ extern struct tcb *printing_tcp;
extern void printleader(struct tcb *);
extern void line_ended(void);
extern void tabto(void);
+extern void _tprintf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
extern void tprintf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+extern void tvprintf(const char *fmt, va_list args);
extern void tprints(const char *str);
#if SUPPORTED_PERSONALITIES > 1
@@ -829,3 +832,29 @@ extern unsigned num_quals;
/* Only ensures that sysent[scno] isn't out of range */
#define SCNO_IN_RANGE(scno) \
((unsigned long)(scno) < nsyscalls)
+
+
+/*
+ * JSON format support
+ */
+#define JSON_SYSCALL_BEGIN "{\"type\": \"syscall\", \"name\": "
+#define JSON_PAIR_FORMAT(key, value) "\"" key "\": " value
+#define JSON_SIGPLUS_FORMAT(name, args) "{\"type\": \"+++\", \"name\": \"" name "\", \"info\": " args " }\n"
+
+#define JSONSTR(json_str, normal_str) (jflag?(json_str):(normal_str))
+const char* jsonstr(const char* with_jflag, const char* without_jflag);
+
+extern int json_printflags_array_enable;
+void json_set_printflags_array(int is_enable, const char* output);
+
+
+const char* json_escape_string(const char *str);
+const char* json_translate_format(const char *fmt);
+
+void jprints(const char *str);
+void jprintf_struct(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+void jprintf(const char *json_fmt, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
+/*
+ * End OF JSON format support
+ */
\ No newline at end of file
void
tvprintf(const char *fmt, va_list args)
{
if (current_tcp) {
int n = strace_vfprintf(current_tcp->outf, fmt, args);
if (n < 0) {
if (current_tcp->outf != stderr)
perror_msg("%s", outfname);
} else
current_tcp->curcol += n;
}
}
/*
* replace specifier %o,%x and %p,%s with %u and "%p","%s"
*/
void
tprintf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (jflag) {
fmt = json_translate_format(fmt);
}
tvprintf(fmt, args);
va_end(args);
}
/*
* here, we have no need to modify the tprintf in sys_read(), we only need to modify printfd() and printstr()
*/
int
sys_read(struct tcb *tcp)
{
if (entering(tcp)) {
printfd(tcp, tcp->u_arg[0]);
tprints(", ");
} else {
if (syserror(tcp))
tprintf("%#lx", tcp->u_arg[1]);
else
printstr(tcp, tcp->u_arg[1], tcp->u_rval);
tprintf(", %lu", tcp->u_arg[2]);
}
return 0;
}
/*
* we use the new jprintf to make our output in a array, the $ sign will replace by the corresponding specifier
* here, they will become "[%d, \"$s\"]".
*/
void
printfd(struct tcb *tcp, int fd)
{
char path[PATH_MAX + 1];
if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
jprintf("[$, $]", "%d<%s>", fd, path);
else
tprintf("%d", fd);
}
/*
* this is another example to modify the existing strace code
*/
int
printflags(const struct xlat *xlat, int flags, const char *dflt)
{
int n;
const char *sep;
if (flags == 0 && xlat->val == 0) {
tprintf("%s", xlat->str);
return 1;
}
sep = json_printflags_array_enable ? jsonstr("[", "") : "";
for (n = 0; xlat->str; xlat++) {
if (xlat->val && (flags & xlat->val) == xlat->val) {
jprintf("%s'%s'", "%s%s", sep, xlat->str);
flags &= ~xlat->val;
sep = jsonstr(",", "|");
n++;
}
}
if (n) {
if (flags) {
jprintf("%s $", "%s%#x", sep, flags);
n++;
}
sep = json_printflags_array_enable ? jsonstr("]", "") : "";
tprints(sep);
} else {
if (flags) {
if (dflt)
jprintf("$", " /* %s */", dflt);
} else {
if (dflt)
tprints("0");
}
}
return n;
}
diff --git a/io.c b/io.c
index fea1218..40fe78e 100644
--- a/io.c
+++ b/io.c
@@ -112,15 +112,15 @@ tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr, int deco
if (cur > addr)
tprints(", ");
if (cur >= abbrev_end) {
- tprints("...");
+ jprints("...");
break;
}
if (umoven(tcp, cur, sizeof_iov, (char *) &iov) < 0) {
- tprints("?");
+ jprints("?");
failed = 1;
break;
}
- tprints("{");
+ tprints(jsonstr("[", "{"));
if (decode_iov) {
unsigned long len = iov_iov_len;
if (len > data_size)
@@ -129,11 +129,13 @@ tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr, int deco
printstr(tcp, (long) iov_iov_base, len);
} else
tprintf("%#lx", (long) iov_iov_base);
- tprintf(", %lu}", (unsigned long)iov_iov_len);
+ jprintf(", $]", ", %lu}", (unsigned long)iov_iov_len);
}
tprints("]");
- if (failed)
- tprintf(" %#lx", addr);
+ if (failed) {
+ jprints(jsonstr(", ", ""));
+ tprintf("%#lx", addr);
+ }
#undef sizeof_iov
#undef iov_iov_base
#undef iov_iov_len
@@ -256,7 +258,7 @@ print_off_t(struct tcb *tcp, long addr)
unsigned long offset;
if (!addr) {
- tprints("NULL");
+ jprints("NULL");
return;
}
@@ -296,7 +298,7 @@ print_loff_t(struct tcb *tcp, long addr)
loff_t offset;
if (!addr)
- tprints("NULL");
+ jprints("NULL");
else if (umove(tcp, addr, &offset) < 0)
tprintf("%#lx", addr);
else
@@ -387,9 +389,11 @@ sys_ioctl(struct tcb *tcp)
tprints(", ");
iop = ioctl_lookup(tcp->u_arg[1]);
if (iop) {
- tprints(iop->symbol);
- while ((iop = ioctl_next_match(iop)))
- tprintf(" or %s", iop->symbol);
+ jprintf("[$", "%s", iop->symbol);
+ while ((iop = ioctl_next_match(iop))) {
+ jprintf(", $", " or %s", iop->symbol);
+ }
+ jprintf("]", NULL);
} else
tprintf("%#lx", tcp->u_arg[1]);
ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]);
#include "defs.h"
#include <stdarg.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
/*
* return the length of the specifer starting from fmt
* -1 when couldn't find any specifier
* e.g.
* "abcd" -> -1
* "%" -> -1
* "%d" -> 2
* "%+lld" -> 5
*/
static int check_specifier(const char *fmt)
{
if (*fmt++ != '%') return -1;
size_t len = strcspn(fmt, "diuoxXfFeEgGaAcspn%");
if (*(fmt + len) == '\0') return -1;
return len + 2;
}
/*
* Extract the % specifier in a format string
* buf should be long enough to contain the whole specifier string
*
* Return the next start position or
* NULL(couldn't find any format specifier in the string, will not write to buf)
*/
static const char* get_next_specifier(const char *fmt, char *buf)
{
if (fmt == NULL) return NULL;
while (*fmt != '%' && *fmt != '\0') ++fmt;
if (*fmt == '\0') return NULL;
const char *end = fmt + 1;
end += strcspn(end, "diuoxXfFeEgGaAcspn%");
if (*end++ == '\0')
return NULL;
while (fmt != end) *buf++ = *fmt++;
*buf = '\0';
return fmt;
}
/*
* copy a printf format specifer to dst
*
* spec: point to the first '%' character of a format specifier
* spec_len: length of the specifier
* ignore: ignored chars when copying
* new_spec: replace the end of dst with new_spec
*
* return the next to-write position of dst
*/
static char* copy_specifier(char *dst, const char *spec, int spec_len,
const char* ignore, char new_spec)
{
int i;
for (i = 0; i < spec_len - 1; i++) {
if (strchr(ignore, spec[i]) == NULL) {
*dst++ = spec[i];
}
}
*dst++ = new_spec;
return dst;
}
static char* replace_specifier(char *dst, const char *specifier, int spec_len, int no_quotes)
{
char spec = *(specifier + spec_len - 1);
if (spec == 'x' || spec == 'X' || spec == 'o') {
dst = copy_specifier(dst, specifier, spec_len, "#0123456789", 'u');
} else if (spec == 'p' || spec == 's') {
if (!no_quotes) *dst++ = '\"';
dst = copy_specifier(dst, specifier, spec_len, "", spec == 'p' ? 'p' : 's');
if (!no_quotes) *dst++ = '\"';
} else {
while (spec_len--)
*dst++ = *specifier++;
*dst = '\0';
}
return dst;
}
static void jvprintf(const char *json_fmt, const char *fmt, va_list args)
{
static char json_fmt_buf[100];
char* new_fmt = json_fmt_buf;
#define JSON_SPECIFIER_MAX_COUNT (50)
static char specifier[JSON_SPECIFIER_MAX_COUNT][50];
static int specifier_length[JSON_SPECIFIER_MAX_COUNT];
int sp_counts = 0;
while((fmt = get_next_specifier(fmt, specifier[sp_counts])) != NULL) {
specifier_length[sp_counts] = strlen(specifier[sp_counts]);
++sp_counts;
assert(sp_counts != JSON_SPECIFIER_MAX_COUNT);
}
int sp_i = 0;
while (*json_fmt != '\0') {
if (*json_fmt == '$') {
assert(sp_i < sp_counts);
new_fmt = replace_specifier(new_fmt, specifier[sp_i], specifier_length[sp_i], 0);
++json_fmt;
++sp_i;
} else {
if (*json_fmt == '%' && *(json_fmt + 1) != '%') {
sp_i++;
} else if (*json_fmt == '\'') {
*new_fmt++ = '\"';
++json_fmt;
continue;
}
*new_fmt++ = *json_fmt++;
}
}
*new_fmt++ = '\0';
tvprintf(json_fmt_buf, args);
}
/*
* JSON format interface implementation
*/
inline const char* jsonstr(const char* with_jflag, const char* without_jflag)
{
return jflag ? with_jflag : without_jflag;
}
/*
* control the behavir of printflags()
* is_enable == 1 will print the '[' and ']' before,after the flags
* is_enable == 0 will NOT print '[' and ']'
*
* will also print the string output, you can set it to NULL to ignore
*
* work only when jflag != 0
*/
int json_printflags_array_enable = 1;
void json_set_printflags_array(int is_enable, const char* output)
{
if (!jflag) return;
if (is_enable)
json_printflags_array_enable = 1;
else
json_printflags_array_enable = 0;
tprints(output);
return;
}
const char* json_escape_string(const char *str)
{
static char buffer[1024];
if (!jflag || str == NULL)
return str;
int i = 0;
while(i < 1000) {
switch(*str) {
case '\0':
buffer[i] = '\0';
return buffer;
case '\"':
buffer[i++] = '\\';
buffer[i++] = '\"';
++str;
break;
case '\\':
buffer[i++] = '\\';
buffer[i++] = '\\';
++str;
break;
default:
buffer[i++] = *str++;
break;
}
}
// FIXME: str is too long
assert(0);
return NULL;
}
/*
* return json parsed format string, replace some specifier in fmt when -j is enabled
* replace rules:
* %x -> %u (with length but ignore char in "#0123456789")
* %X -> %u (with length but ignore char in "#0123456789")
* %o -> %u (with length but ignore char in "#0123456789")
* %p -> \"%p\"
* %s -> \"%s\"
*/
const char* json_translate_format(const char *fmt)
{
static char newfmt[200];
char *pnf = newfmt;
size_t len;
while (*fmt != '\0') {
if ((len = check_specifier(fmt)) == -1) {
*pnf++ = *fmt++;
} else {
int no_quotes = 0;
if (fmt[len-1] == 's' && fmt[-1] == '\"' && fmt[len] == '\"')
no_quotes = 1;
pnf = replace_specifier(pnf, fmt, len, no_quotes);
fmt += len;
}
}
*pnf++ = '\0';
return newfmt;
}
void jprints(const char *str)
{
if (jflag) {
static char buf[100];
char* pb = buf;
while (*str != '\0') {
switch (*str) {
case '?':
pb = stpcpy(pb, "false");
++str;
break;
case 'N':
if (strncmp(str, "NULL", 4) == 0) {
pb = stpcpy(pb, "null");
str += 4;
break;
}
case '.':
if (strncmp(str, "...", 3) == 0) {
pb = stpcpy(pb, "\"...\"");
str += 3;
break;
}
default:
*pb++ = *str++;
}
}
*pb++ = '\0';
str = buf;
}
tprints(str);
}
void jprintf_struct(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (jflag) {
static char newfmt[100];
char* pnf = newfmt;
while(*fmt != '\0') {
if (isalnum(*fmt)) {
char* equal = strchr(fmt, '=');
if (equal) {
pnf += sprintf(pnf, "\"%.*s\": ", (int)(equal-fmt), fmt);
fmt = equal + 1;
continue;
}
} else if (*fmt == '%') {
size_t len = check_specifier(fmt);
if (len != -1) {
int no_quotes = 0;
if (fmt[len-1] == 's' && fmt[-1] == '\"' && fmt[len] == '\"')
no_quotes = 1;
pnf = replace_specifier(pnf, fmt, len, no_quotes);
fmt += len;
continue;
}
}
*pnf++ = *fmt++;
}
*pnf++ = '\0';
fmt = newfmt;
}
tvprintf(fmt, args);
va_end(args);
}
/*
* print like tprintf but provide some special format extend when -j is enabled
*
* 1, when -j is NOT enabled, just the same to tprintf(), ignore the first argument
*
* 2, when -j is enabled, use the first argument as the format string
* you can use $ in json_fmt, and all $ in json_fmt will be replaced by the
* corresponding specifer in fmt
*
* Note: the replace rules for specifier is the same to jprinta()
* e.g.
* jprintf("[$, $]", "{%d = %u}", 123, 345) equal to
* tprintf("[%d, %u]", 123, 345)
*
* jprintf("{'abcd': [$, $]}", "abcd: {%s= %#llx}", "xyz", 123) equal to
* tprintf("{\"abcd\": [\"%s\", %llu]}", "xyz", 123)
*
* you can also use any original % specifer in json_fmt.
* e.g.
* jprintf("%#llx and $", "%#llx and %#llx", 123, 456) equal to
* tprintf("%#llx and %llu", 123, 456)
*
*/
void jprintf(const char *json_fmt, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if(jflag && json_fmt != NULL) {
jvprintf(json_fmt, fmt, args);
} else if (!jflag && fmt != NULL){
tvprintf(fmt, args);
}
va_end(args);
}
diff --git a/syscall.c b/syscall.c
index b0ad47e..65dde6d 100644
--- a/syscall.c
+++ b/syscall.c
@@ -632,7 +632,7 @@ printargs(struct tcb *tcp)
int i;
int n = tcp->s_ent->nargs;
for (i = 0; i < n; i++)
- tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
+ jprintf("%s$", "%s%#lx", i ? ", " : "", tcp->u_arg[i]);
}
return 0;
}
@@ -644,7 +644,7 @@ printargs_lu(struct tcb *tcp)
int i;
int n = tcp->s_ent->nargs;
for (i = 0; i < n; i++)
- tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
+ _tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
}
return 0;
}
@@ -656,7 +656,7 @@ printargs_ld(struct tcb *tcp)
int i;
int n = tcp->s_ent->nargs;
for (i = 0; i < n; i++)
- tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
+ _tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
}
return 0;
}
@@ -1983,13 +1983,14 @@ trace_syscall_entering(struct tcb *tcp)
}
if (res != 1) {
+ tprints(jsonstr(JSON_SYSCALL_BEGIN, ""));
printleader(tcp);
if (scno_good != 1)
- tprints("????" /* anti-trigraph gap */ "(");
+ tprints(jsonstr("\"?\", " JSON_PAIR_FORMAT("args", "["), "????" /* anti-trigraph gap */ "("));
else if (tcp->qual_flg & UNDEFINED_SCNO)
- tprintf("%s(", undefined_scno_name(tcp));
+ jprintf("$, " JSON_PAIR_FORMAT("args", "["), "%s(", undefined_scno_name(tcp));
else
- tprintf("%s(", tcp->s_ent->sys_name);
+ jprintf("$, " JSON_PAIR_FORMAT("args", "["), "%s(", tcp->s_ent->sys_name);
/*
* " <unavailable>" will be added later by the code which
* detects ptrace errors.
@@ -2047,15 +2048,17 @@ trace_syscall_entering(struct tcb *tcp)
}
#endif
+ tprints(jsonstr(JSON_SYSCALL_BEGIN, ""));
printleader(tcp);
if (tcp->qual_flg & UNDEFINED_SCNO)
- tprintf("%s(", undefined_scno_name(tcp));
+ jprintf("$, " JSON_PAIR_FORMAT("args", "["), "%s(", undefined_scno_name(tcp));
else
- tprintf("%s(", tcp->s_ent->sys_name);
+ jprintf("$, " JSON_PAIR_FORMAT("args", "["), "%s(", tcp->s_ent->sys_name);
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:
@@ -2560,17 +2563,20 @@ trace_syscall_exiting(struct tcb *tcp)
tcp->flags &= ~TCB_REPRINT;
printleader(tcp);
if (tcp->qual_flg & UNDEFINED_SCNO)
- tprintf("<... %s resumed> ", undefined_scno_name(tcp));
+ jprintf("<... $ resumed, please use -ff to output valid JSON result> ",
+ "<... %s resumed> ", undefined_scno_name(tcp));
else
- tprintf("<... %s resumed> ", tcp->s_ent->sys_name);
+ jprintf("<... $ resumed, please use -ff to output valid JSON result> ",
+ "<... %s resumed> ", tcp->s_ent->sys_name);
}
printing_tcp = tcp;
if (res != 1) {
/* There was error in one of prior ptrace ops */
- tprints(") ");
+ tprints(jsonstr("], ", ") "));
tabto();
- tprints("= ? <unavailable>\n");
+ jprintf(JSON_PAIR_FORMAT("ret", "\"?\", ") JSON_PAIR_FORMAT("desc", "$"),
+ "= ? <%s>\n", "unavailable");
line_ended();
tcp->flags &= ~TCB_INSYSCALL;
return res;
@@ -2593,14 +2599,15 @@ trace_syscall_exiting(struct tcb *tcp)
sys_res = tcp->s_ent->sys_func(tcp);
}
- tprints(") ");
+ tprints(jsonstr("], ", ") "));
tabto();
u_error = tcp->u_error;
if (tcp->qual_flg & QUAL_RAW) {
if (u_error)
- tprintf("= -1 (errno %ld)", u_error);
+ jprintf(JSON_PAIR_FORMAT("ret", "$, ") JSON_PAIR_FORMAT("errno", "$, "),
+ "= %d (errno %ld)", -1, u_error);
else
- tprintf("= %#lx", tcp->u_rval);
+ jprintf(JSON_PAIR_FORMAT("ret", "$"), "= %#lx", tcp->u_rval);
}
else if (!(sys_res & RVAL_NONE) && u_error) {
switch (u_error) {
@@ -2625,13 +2632,15 @@ 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)");
+ jprintf(JSON_PAIR_FORMAT("ret", "'?', ") JSON_PAIR_FORMAT("desc", "$"),
+ "= ? %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)");
+ jprintf(JSON_PAIR_FORMAT("ret", "'?', ") JSON_PAIR_FORMAT("desc", "$"),
+ "= ? %s", "ERESTARTNOINTR (To be restarted)");
break;
case ERESTARTNOHAND:
/* pause(), rt_sigsuspend() etc use this code.
@@ -2641,7 +2650,8 @@ 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)");
+ jprintf(JSON_PAIR_FORMAT("ret", "'?', ") JSON_PAIR_FORMAT("desc", "$"),
+ "= ? %s", "ERESTARTNOHAND (To be restarted if no handler)");
break;
case ERESTART_RESTARTBLOCK:
/* Syscalls like nanosleep(), poll() which can't be
@@ -2655,62 +2665,70 @@ 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)");
+ jprintf(JSON_PAIR_FORMAT("ret", "'?', ") JSON_PAIR_FORMAT("desc", "$"),
+ "= ? %s", "ERESTART_RESTARTBLOCK (Interrupted by signal)");
break;
default:
if (u_error < 0)
- tprintf("= -1 E??? (errno %ld)", u_error);
+ jprintf(JSON_PAIR_FORMAT("ret", "-1, ")
+ JSON_PAIR_FORMAT("error", "$, ")
+ JSON_PAIR_FORMAT("errno", "$"),
+ "= -1 %s (errno %ld)", "E???", u_error);
else if (u_error < nerrnos)
- tprintf("= -1 %s (%s)", errnoent[u_error],
- strerror(u_error));
+ jprintf(JSON_PAIR_FORMAT("ret", "-1, ")
+ JSON_PAIR_FORMAT("error" ,"$, ")
+ JSON_PAIR_FORMAT("strerror", "$"),
+ "= -1 %s (%s)", errnoent[u_error], strerror(u_error));
else
- tprintf("= -1 ERRNO_%ld (%s)", u_error,
- strerror(u_error));
+ jprintf(JSON_PAIR_FORMAT("ret", "-1, ")
+ JSON_PAIR_FORMAT("errno", "$, ")
+ JSON_PAIR_FORMAT("strerror", "$"),
+ "= -1 ERRNO_%ld (%s)", u_error, strerror(u_error));
break;
}
if ((sys_res & RVAL_STR) && tcp->auxstr)
- tprintf(" (%s)", tcp->auxstr);
+ jprintf(", " JSON_PAIR_FORMAT("auxstr", "$"), " (%s)", tcp->auxstr);
}
else {
if (sys_res & RVAL_NONE)
- tprints("= ?");
+ jprintf(JSON_PAIR_FORMAT("ret", "'?'"), "= ?");
else {
switch (sys_res & RVAL_MASK) {
case RVAL_HEX:
- tprintf("= %#lx", tcp->u_rval);
+ jprintf(JSON_PAIR_FORMAT("ret", "$"), "= %#lx", tcp->u_rval);
break;
case RVAL_OCTAL:
- tprintf("= %#lo", tcp->u_rval);
+ jprintf(JSON_PAIR_FORMAT("ret", "$"), "= %#lo", tcp->u_rval);
break;
case RVAL_UDECIMAL:
- tprintf("= %lu", tcp->u_rval);
+ jprintf(JSON_PAIR_FORMAT("ret", "$"), "= %lu", tcp->u_rval);
break;
case RVAL_DECIMAL:
- tprintf("= %ld", tcp->u_rval);
+ jprintf(JSON_PAIR_FORMAT("ret", "$"), "= %ld", tcp->u_rval);
break;
case RVAL_FD:
if (show_fd_path) {
- tprints("= ");
+ tprints(jsonstr(JSON_PAIR_FORMAT("ret", "") , "= "));
printfd(tcp, tcp->u_rval);
}
else
- tprintf("= %ld", tcp->u_rval);
+ jprintf(JSON_PAIR_FORMAT("ret", "$"), "= %ld", tcp->u_rval);
break;
#if defined(LINUX_MIPSN32) || defined(X32)
/*
case RVAL_LHEX:
- tprintf("= %#llx", tcp->u_lrval);
+ jprintf(JSON_PAIR_FORMAT("ret", "$"), "= %#llx", tcp->u_lrval);
break;
case RVAL_LOCTAL:
- tprintf("= %#llo", tcp->u_lrval);
+ jprintf(JSON_PAIR_FORMAT("ret", "$"), "= %#llo", tcp->u_lrval);
break;
*/
case RVAL_LUDECIMAL:
- tprintf("= %llu", tcp->u_lrval);
+ jprintf(JSON_PAIR_FORMAT("ret", "$"), "= %llu", tcp->u_lrval);
break;
/*
case RVAL_LDECIMAL:
- tprintf("= %lld", tcp->u_lrval);
+ jprintf(JSON_PAIR_FORMAT("ret", "$"), "= %lld", tcp->u_lrval);
break;
*/
#endif
@@ -2721,14 +2739,14 @@ trace_syscall_exiting(struct tcb *tcp)
}
}
if ((sys_res & RVAL_STR) && tcp->auxstr)
- tprintf(" (%s)", tcp->auxstr);
+ jprintf(", " JSON_PAIR_FORMAT("auxstr", "$"), " (%s)", tcp->auxstr);
}
if (Tflag) {
tv_sub(&tv, &tv, &tcp->etime);
tprintf(" <%ld.%06ld>",
(long) tv.tv_sec, (long) tv.tv_usec);
}
- tprints("\n");
+ tprints(jsonstr("}\n", "\n"));
dumpio(tcp);
line_ended();
diff --git a/util.c b/util.c
index 33482d5..06e0302 100644
--- a/util.c
+++ b/util.c
@@ -215,9 +215,9 @@ printxval(const struct xlat *xlat, int val, const char *dflt)
const char *str = xlookup(xlat, val);
if (str)
- tprints(str);
+ tprintf("%s", str);
else
- tprintf("%#x /* %s */", val, dflt);
+ jprintf("[$, $]", "%#x /* %s */", val, dflt);
}
/*
@@ -285,12 +285,12 @@ addflags(const struct xlat *xlat, int flags)
{
for (; xlat->str; xlat++) {
if (xlat->val && (flags & xlat->val) == xlat->val) {
- tprintf("|%s", xlat->str);
+ jprintf(", $", "|%s", xlat->str);
flags &= ~xlat->val;
}
}
if (flags) {
- tprintf("|%#x", flags);
+ jprintf(", $", "|%#x", flags);
}
}
@@ -335,36 +335,36 @@ printflags(const struct xlat *xlat, int flags, const char *dflt)
const char *sep;
if (flags == 0 && xlat->val == 0) {
- tprints(xlat->str);
+ tprintf("%s", xlat->str);
return 1;
}
- sep = "";
+ sep = json_printflags_array_enable ? jsonstr("[", "") : "";
for (n = 0; xlat->str; xlat++) {
if (xlat->val && (flags & xlat->val) == xlat->val) {
- tprintf("%s%s", sep, xlat->str);
+ jprintf("%s'%s'", "%s%s", sep, xlat->str);
flags &= ~xlat->val;
- sep = "|";
+ sep = jsonstr(",", "|");
n++;
}
}
if (n) {
if (flags) {
- tprintf("%s%#x", sep, flags);
+ jprintf("%s $", "%s%#x", sep, flags);
n++;
}
+ sep = json_printflags_array_enable ? jsonstr("]", "") : "";
+ tprints(sep);
} else {
if (flags) {
- tprintf("%#x", flags);
if (dflt)
- tprintf(" /* %s */", dflt);
+ jprintf("$", " /* %s */", dflt);
} else {
if (dflt)
tprints("0");
}
}
-
return n;
}
@@ -374,7 +374,7 @@ printnum(struct tcb *tcp, long addr, const char *fmt)
long num;
if (!addr) {
- tprints("NULL");
+ jprints("NULL");
return;
}
if (umove(tcp, addr, &num) < 0) {
@@ -392,7 +392,7 @@ printnum_int(struct tcb *tcp, long addr, const char *fmt)
int num;
if (!addr) {
- tprints("NULL");
+ jprints("NULL");
return;
}
if (umove(tcp, addr, &num) < 0) {
@@ -410,7 +410,7 @@ printfd(struct tcb *tcp, int fd)
char path[PATH_MAX + 1];
if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
- tprintf("%d<%s>", fd, path);
+ jprintf("[$, $]", "%d<%s>", fd, path);
else
tprintf("%d", fd);
}
@@ -418,7 +418,7 @@ printfd(struct tcb *tcp, int fd)
void
printuid(const char *text, unsigned long uid)
{
- tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
+ _tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
}
/*
@@ -470,7 +470,8 @@ string_quote(const char *instr, char *outstr, long len, int size)
}
}
- *s++ = '\"';
+ if(!jflag)
+ *s++ = '\"';
if (usehex) {
/* Hex-quote the whole string. */
@@ -543,7 +544,8 @@ string_quote(const char *instr, char *outstr, long len, int size)
}
}
- *s++ = '\"';
+ if(!jflag)
+ *s++ = '\"';
*s = '\0';
/* Return zero if we printed entire ASCIZ string (didn't truncate it) */
@@ -557,7 +559,8 @@ string_quote(const char *instr, char *outstr, long len, int size)
return 1;
asciz_ended:
- *s++ = '\"';
+ if(!jflag)
+ *s++ = '\"';
*s = '\0';
/* Return zero: we printed entire ASCIZ string (didn't truncate it) */
return 0;
@@ -574,7 +577,7 @@ printpathn(struct tcb *tcp, long addr, int n)
int nul_seen;
if (!addr) {
- tprints("NULL");
+ jprints("NULL");
return;
}
@@ -593,9 +596,9 @@ printpathn(struct tcb *tcp, long addr, int n)
n++;
outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
string_quote(path, outstr, -1, n);
- tprints(outstr);
+ tprintf("%s", json_escape_string(outstr));
if (!nul_seen)
- tprints("...");
+ tprints(jsonstr("", "..."));
}
}
@@ -620,7 +623,7 @@ printstr(struct tcb *tcp, long addr, long len)
int ellipsis;
if (!addr) {
- tprints("NULL");
+ jprintf("null", "NULL");
return;
}
/* Allocate static buffers if they are not allocated yet. */
@@ -664,9 +667,9 @@ printstr(struct tcb *tcp, long addr, long len)
ellipsis = (string_quote(str, outstr, len, size) &&
(len < 0 || len > max_strlen));
- tprints(outstr);
+ tprintf("%s", json_escape_string(outstr));
if (ellipsis)
- tprints("...");
+ tprints(jsonstr("", "..."));
}
#if HAVE_SYS_UIO_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.