]> granicus.if.org Git - strace/commitdiff
syscall.c: add support for printing return value and error code
authorEugene Syromyatnikov <evgsyr@gmail.com>
Sun, 7 Jan 2018 02:53:53 +0000 (03:53 +0100)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 8 Jan 2018 00:40:22 +0000 (00:40 +0000)
Some weird syscalls (like modify_ldt) return value that doesn't indicate
an error (less than -4096), but it is, in fact, erroneous (because they
decide to clip the return value to 32-bit, for example).

Add a flag to print decoded error code along with syscall return value.

* defs.h (RVAL_PRINT_ERR_VAL): New rval flag.
* syscall.c (syscall_exiting_trace): Handle it.

defs.h
syscall.c

diff --git a/defs.h b/defs.h
index b470c6d66adc819d9d0507b096a5f40bbcde6e5f..e7d7b2dfcdde4bc38058bdc13887f6e5d1a8bcf5 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -312,6 +312,10 @@ extern const struct xlat whence_codes[];
 #define RVAL_DECODED   0100    /* syscall decoding finished */
 #define RVAL_IOCTL_DECODED 0200        /* ioctl sub-parser successfully decoded
                                   the argument */
+#define RVAL_PRINT_ERR_VAL 0400 /* Print decoded error code along with
+                                  syscall return value.  Needed for modify_ldt
+                                  that for some reason decides to return
+                                  an error with higher bits set to 0.  */
 
 #define IOCTL_NUMBER_UNKNOWN 0
 #define IOCTL_NUMBER_HANDLED 1
index 4deb1e8bb89a46f3ac50678de876c56abedaf444..d36abf2e1e3d2b0ea8b2bdc4430d1357ef363ccd 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -808,6 +808,7 @@ syscall_exiting_trace(struct tcb *tcp, struct timeval tv, int res)
        tprints(") ");
        tabto();
        unsigned long u_error = tcp->u_error;
+       kernel_long_t u_rval;
 
        if (raw(tcp)) {
                if (u_error) {
@@ -875,13 +876,15 @@ syscall_exiting_trace(struct tcb *tcp, struct timeval tv, int res)
                        tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
                        break;
                default:
+                       u_rval = sys_res & RVAL_PRINT_ERR_VAL ?
+                                tcp->u_rval : -1;
                        u_error_str = err_name(u_error);
                        if (u_error_str)
-                               tprintf("= -1 %s (%s)",
-                                       u_error_str, strerror(u_error));
+                               tprintf("= %" PRI_kld " %s (%s)",
+                                       u_rval, u_error_str, strerror(u_error));
                        else
-                               tprintf("= -1 %lu (%s)",
-                                       u_error, strerror(u_error));
+                               tprintf("= %" PRI_kld " %lu (%s)",
+                                       u_rval, u_error, strerror(u_error));
                        break;
                }
                if (syscall_tampered(tcp))