]> granicus.if.org Git - strace/blobdiff - fcntl.c
Implement -e trace=%fstat option
[strace] / fcntl.c
diff --git a/fcntl.c b/fcntl.c
index a3f73e077a16d70c76b5426bc786a32e4c03fc11..74168c6a26cedc78c0ac89dd3501951a576d7c3a 100644 (file)
--- a/fcntl.c
+++ b/fcntl.c
 #include "defs.h"
 #include "flock.h"
 
+#include "xlat/f_owner_types.h"
+#include "xlat/f_seals.h"
 #include "xlat/fcntlcmds.h"
+#include "xlat/fcntl64cmds.h"
 #include "xlat/fdflags.h"
 #include "xlat/lockfcmds.h"
 #include "xlat/notifyflags.h"
 
 static void
-printflock64(struct tcb *tcp, long addr, int getlk)
+print_struct_flock64(const struct_kernel_flock64 *fl, const int getlk)
+{
+       tprints("{l_type=");
+       printxval(lockfcmds, (unsigned short) fl->l_type, "F_???");
+       tprints(", l_whence=");
+       printxval(whence_codes, (unsigned short) fl->l_whence, "SEEK_???");
+       tprintf(", l_start=%" PRId64 ", l_len=%" PRId64,
+               (int64_t) fl->l_start, (int64_t) fl->l_len);
+       if (getlk)
+               tprintf(", l_pid=%lu", (unsigned long) fl->l_pid);
+       tprints("}");
+}
+
+static void
+printflock64(struct tcb *const tcp, const kernel_ulong_t addr, const int getlk)
 {
        struct_kernel_flock64 fl;
 
-       if (umove_or_printaddr(tcp, addr, &fl))
-               return;
-       tprints("{type=");
-       printxval(lockfcmds, fl.l_type, "F_???");
-       tprints(", whence=");
-       printxval(whence_codes, fl.l_whence, "SEEK_???");
-       tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len);
-       if (getlk)
-               tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
-       else
-               tprints("}");
+       if (fetch_struct_flock64(tcp, addr, &fl))
+               print_struct_flock64(&fl, getlk);
 }
 
 static void
-printflock(struct tcb *tcp, long addr, int getlk)
+printflock(struct tcb *const tcp, const kernel_ulong_t addr, const int getlk)
 {
-       struct_kernel_flock fl;
+       struct_kernel_flock64 fl;
 
-#if SUPPORTED_PERSONALITIES > 1
-       if (
-# if SIZEOF_OFF_T > SIZEOF_LONG
-           current_personality != DEFAULT_PERSONALITY &&
-# endif
-           current_wordsize != sizeof(fl.l_start)) {
-               if (current_wordsize == 4) {
-                       /* 32-bit x86 app on x86_64 and similar cases */
-                       struct {
-                               short int l_type;
-                               short int l_whence;
-                               int32_t l_start; /* off_t */
-                               int32_t l_len; /* off_t */
-                               int32_t l_pid; /* pid_t */
-                       } fl32;
-                       if (umove_or_printaddr(tcp, addr, &fl32))
-                               return;
-                       fl.l_type = fl32.l_type;
-                       fl.l_whence = fl32.l_whence;
-                       fl.l_start = fl32.l_start;
-                       fl.l_len = fl32.l_len;
-                       fl.l_pid = fl32.l_pid;
-               } else {
-                       /* let people know we have a problem here */
-                       tprintf("<decode error: unsupported wordsize %d>",
-                               current_wordsize);
-                       return;
-               }
-       } else
-#endif
-       if (umove_or_printaddr(tcp, addr, &fl))
+       if (fetch_struct_flock(tcp, addr, &fl))
+               print_struct_flock64(&fl, getlk);
+}
+
+static void
+print_f_owner_ex(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct { int type, pid; } owner;
+
+       if (umove_or_printaddr(tcp, addr, &owner))
                return;
+
        tprints("{type=");
-       printxval(lockfcmds, fl.l_type, "F_???");
-       tprints(", whence=");
-       printxval(whence_codes, fl.l_whence, "SEEK_???");
-#if SIZEOF_OFF_T > SIZEOF_LONG
-       tprintf(", start=%lld, len=%lld", fl.l_start, fl.l_len);
-#else
-       tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
-#endif
-       if (getlk)
-               tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
-       else
-               tprints("}");
+       printxval(f_owner_types, owner.type, "F_OWNER_???");
+       tprintf(", pid=%d}", owner.pid);
+}
+
+static int
+print_fcntl(struct tcb *tcp)
+{
+       const unsigned int cmd = tcp->u_arg[1];
+
+       switch (cmd) {
+       case F_SETFD:
+               tprints(", ");
+               printflags(fdflags, tcp->u_arg[2], "FD_???");
+               break;
+       case F_SETOWN:
+       case F_SETPIPE_SZ:
+               tprintf(", %" PRI_kld, tcp->u_arg[2]);
+               break;
+       case F_DUPFD:
+       case F_DUPFD_CLOEXEC:
+               tprintf(", %" PRI_kld, tcp->u_arg[2]);
+               return RVAL_DECODED | RVAL_FD;
+       case F_SETFL:
+               tprints(", ");
+               tprint_open_modes(tcp->u_arg[2]);
+               break;
+       case F_SETLK:
+       case F_SETLKW:
+               tprints(", ");
+               printflock(tcp, tcp->u_arg[2], 0);
+               break;
+       case F_OFD_SETLK:
+       case F_OFD_SETLKW:
+               tprints(", ");
+               printflock64(tcp, tcp->u_arg[2], 0);
+               break;
+       case F_SETOWN_EX:
+               tprints(", ");
+               print_f_owner_ex(tcp, tcp->u_arg[2]);
+               break;
+       case F_NOTIFY:
+               tprints(", ");
+               printflags64(notifyflags, tcp->u_arg[2], "DN_???");
+               break;
+       case F_SETLEASE:
+               tprints(", ");
+               printxval64(lockfcmds, tcp->u_arg[2], "F_???");
+               break;
+       case F_ADD_SEALS:
+               tprints(", ");
+               printflags64(f_seals, tcp->u_arg[2], "F_SEAL_???");
+               break;
+       case F_SETSIG:
+               tprints(", ");
+               tprints(signame(tcp->u_arg[2]));
+               break;
+       case F_GETOWN:
+       case F_GETPIPE_SZ:
+               break;
+       case F_GETFD:
+               if (entering(tcp) || syserror(tcp) || tcp->u_rval == 0)
+                       return 0;
+               tcp->auxstr = sprintflags("flags ", fdflags,
+                                         (kernel_ulong_t) tcp->u_rval);
+               return RVAL_HEX | RVAL_STR;
+       case F_GETFL:
+               if (entering(tcp) || syserror(tcp))
+                       return 0;
+               tcp->auxstr = sprint_open_modes(tcp->u_rval);
+               return RVAL_HEX | RVAL_STR;
+       case F_GETLK:
+               if (entering(tcp))
+                       return 0;
+               tprints(", ");
+               printflock(tcp, tcp->u_arg[2], 1);
+               break;
+       case F_OFD_GETLK:
+               if (entering(tcp))
+                       return 0;
+               tprints(", ");
+               printflock64(tcp, tcp->u_arg[2], 1);
+               break;
+       case F_GETOWN_EX:
+               if (entering(tcp))
+                       return 0;
+               tprints(", ");
+               print_f_owner_ex(tcp, tcp->u_arg[2]);
+               break;
+       case F_GETLEASE:
+               if (entering(tcp) || syserror(tcp))
+                       return 0;
+               tcp->auxstr = xlookup(lockfcmds, (kernel_ulong_t) tcp->u_rval);
+               return RVAL_HEX | RVAL_STR;
+       case F_GET_SEALS:
+               if (entering(tcp) || syserror(tcp) || tcp->u_rval == 0)
+                       return 0;
+               tcp->auxstr = sprintflags("seals ", f_seals,
+                                         (kernel_ulong_t) tcp->u_rval);
+               return RVAL_HEX | RVAL_STR;
+       case F_GETSIG:
+               if (entering(tcp) || syserror(tcp) || tcp->u_rval == 0)
+                       return 0;
+               tcp->auxstr = signame(tcp->u_rval);
+               return RVAL_STR;
+       default:
+               tprintf(", %#" PRI_klx, tcp->u_arg[2]);
+               break;
+       }
+       return RVAL_DECODED;
 }
 
 SYS_FUNC(fcntl)
@@ -111,71 +196,47 @@ SYS_FUNC(fcntl)
        if (entering(tcp)) {
                printfd(tcp, tcp->u_arg[0]);
                tprints(", ");
-               printxval(fcntlcmds, tcp->u_arg[1], "F_???");
-               switch (tcp->u_arg[1]) {
-               case F_SETFD:
-                       tprints(", ");
-                       printflags(fdflags, tcp->u_arg[2], "FD_???");
-                       break;
-               case F_SETOWN: case F_DUPFD:
-               case F_DUPFD_CLOEXEC:
-                       tprintf(", %ld", tcp->u_arg[2]);
-                       break;
-               case F_SETFL:
-                       tprints(", ");
-                       tprint_open_modes(tcp->u_arg[2]);
-                       break;
-               case F_SETLK: case F_SETLKW:
-                       tprints(", ");
-                       printflock(tcp, tcp->u_arg[2], 0);
-                       break;
-               case F_SETLK64: case F_SETLKW64:
-                       tprints(", ");
-                       printflock64(tcp, tcp->u_arg[2], 0);
-                       break;
-               case F_NOTIFY:
-                       tprints(", ");
-                       printflags(notifyflags, tcp->u_arg[2], "DN_???");
-                       break;
-               case F_SETLEASE:
-                       tprints(", ");
-                       printxval(lockfcmds, tcp->u_arg[2], "F_???");
-                       break;
-               case F_GETOWN:
-                       break;
-               default:
-                       return 0;
+               const unsigned int cmd = tcp->u_arg[1];
+               const char *str = xlookup(fcntlcmds, cmd);
+               if (str) {
+                       tprints(str);
+               } else {
+                       /*
+                        * fcntl syscall does not recognize these
+                        * constants, but we would like to show them
+                        * for better debugging experience.
+                        */
+                       printxval(fcntl64cmds, cmd, "F_???");
+               }
+       }
+       return print_fcntl(tcp);
+}
+
+SYS_FUNC(fcntl64)
+{
+       const unsigned int cmd = tcp->u_arg[1];
+       if (entering(tcp)) {
+               printfd(tcp, tcp->u_arg[0]);
+               tprints(", ");
+               const char *str = xlookup(fcntl64cmds, cmd);
+               if (str) {
+                       tprints(str);
+               } else {
+                       printxval(fcntlcmds, cmd, "F_???");
                }
-               return RVAL_DECODED;
-       } else {
-               switch (tcp->u_arg[1]) {
-               case F_GETFD:
-                       if (syserror(tcp) || tcp->u_rval == 0)
-                               return 0;
-                       tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval);
-                       return RVAL_HEX|RVAL_STR;
-               case F_GETFL:
-                       if (syserror(tcp))
-                               return 0;
-                       tcp->auxstr = sprint_open_modes(tcp->u_rval);
-                       return RVAL_HEX|RVAL_STR;
-               case F_GETLK:
+       }
+       switch (cmd) {
+               case F_SETLK64:
+               case F_SETLKW64:
                        tprints(", ");
-                       printflock(tcp, tcp->u_arg[2], 1);
-                       break;
+                       printflock64(tcp, tcp->u_arg[2], 0);
+                       return RVAL_DECODED;
                case F_GETLK64:
-                       tprints(", ");
-                       printflock64(tcp, tcp->u_arg[2], 1);
-                       break;
-               case F_GETLEASE:
-                       if (syserror(tcp))
-                               return 0;
-                       tcp->auxstr = xlookup(lockfcmds, tcp->u_rval);
-                       return RVAL_HEX|RVAL_STR;
-               default:
-                       tprintf(", %#lx", tcp->u_arg[2]);
-                       break;
-               }
+                       if (exiting(tcp)) {
+                               tprints(", ");
+                               printflock64(tcp, tcp->u_arg[2], 1);
+                       }
+                       return 0;
        }
-       return 0;
+       return print_fcntl(tcp);
 }