]> granicus.if.org Git - strace/blobdiff - syscall.c
tests: add a test for -yy option
[strace] / syscall.c
index 1b49bb3c159447058762592d14249a8a73ee5ecd..e74881d5e1ce4a38d144739ce529cf3d515b83c0 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -37,9 +37,6 @@
 
 #ifdef HAVE_SYS_REG_H
 # include <sys/reg.h>
-# ifndef PTRACE_PEEKUSR
-#  define PTRACE_PEEKUSR PTRACE_PEEKUSER
-# endif
 #elif defined(HAVE_LINUX_PTRACE_H)
 # undef PTRACE_SYSCALL
 # ifdef HAVE_STRUCT_IA64_FPREG
 # ifdef HAVE_STRUCT_PT_ALL_USER_REGS
 #  define pt_all_user_regs XXX_pt_all_user_regs
 # endif
+# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
+#  define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
+# endif
 # include <linux/ptrace.h>
+# undef ptrace_peeksiginfo_args
 # undef ia64_fpreg
 # undef pt_all_user_regs
 #endif
@@ -97,6 +98,8 @@
 #define TM TRACE_MEMORY
 #define NF SYSCALL_NEVER_FAILS
 #define MA MAX_ARGS
+#define SI STACKTRACE_INVALIDATE_CACHE
+#define SE STACKTRACE_CAPTURE_ON_ENTER
 
 const struct_sysent sysent0[] = {
 #include "syscallent.h"
@@ -124,6 +127,8 @@ static const struct_sysent sysent2[] = {
 #undef TM
 #undef NF
 #undef MA
+#undef SI
+#undef SE
 
 /*
  * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
@@ -318,7 +323,7 @@ set_personality(int personality)
 }
 
 static void
-update_personality(struct tcb *tcp, int personality)
+update_personality(struct tcb *tcp, unsigned int personality)
 {
        if (personality == current_personality)
                return;
@@ -365,7 +370,7 @@ update_personality(struct tcb *tcp, int personality)
 static int qual_syscall(), qual_signal(), qual_desc();
 
 static const struct qual_options {
-       int bitflag;
+       unsigned int bitflag;
        const char *option_name;
        int (*qualify)(const char *, int, int);
        const char *argument_name;
@@ -391,7 +396,7 @@ static const struct qual_options {
 };
 
 static void
-reallocate_qual(int n)
+reallocate_qual(const unsigned int n)
 {
        unsigned p;
        qualbits_t *qp;
@@ -405,9 +410,9 @@ reallocate_qual(int n)
 }
 
 static void
-qualify_one(int n, int bitflag, int not, int pers)
+qualify_one(const unsigned int n, unsigned int bitflag, const int not, const int pers)
 {
-       unsigned p;
+       int p;
 
        if (num_quals <= n)
                reallocate_qual(n + 1);
@@ -423,10 +428,10 @@ qualify_one(int n, int bitflag, int not, int pers)
 }
 
 static int
-qual_syscall(const char *s, int bitflag, int not)
+qual_syscall(const char *s, const unsigned int bitflag, const int not)
 {
-       unsigned p;
-       unsigned i;
+       int p;
+       unsigned int i;
        int rc = -1;
 
        if (*s >= '0' && *s <= '9') {
@@ -452,9 +457,9 @@ qual_syscall(const char *s, int bitflag, int not)
 }
 
 static int
-qual_signal(const char *s, int bitflag, int not)
+qual_signal(const char *s, const unsigned int bitflag, const int not)
 {
-       int i;
+       unsigned int i;
 
        if (*s >= '0' && *s <= '9') {
                int signo = string_to_uint(s);
@@ -475,7 +480,7 @@ qual_signal(const char *s, int bitflag, int not)
 }
 
 static int
-qual_desc(const char *s, int bitflag, int not)
+qual_desc(const char *s, const unsigned int bitflag, const int not)
 {
        if (*s >= '0' && *s <= '9') {
                int desc = string_to_uint(s);
@@ -511,20 +516,20 @@ void
 qualify(const char *s)
 {
        const struct qual_options *opt;
-       int not;
        char *copy;
        const char *p;
-       int i, n;
+       int not;
+       unsigned int i;
 
        if (num_quals == 0)
                reallocate_qual(MIN_QUALS);
 
        opt = &qual_options[0];
        for (i = 0; (p = qual_options[i].option_name); i++) {
-               n = strlen(p);
-               if (strncmp(s, p, n) == 0 && s[n] == '=') {
+               unsigned int len = strlen(p);
+               if (strncmp(s, p, len) == 0 && s[len] == '=') {
                        opt = &qual_options[i];
-                       s += n + 1;
+                       s += len + 1;
                        break;
                }
        }
@@ -550,6 +555,7 @@ qualify(const char *s)
        if (!copy)
                die_out_of_memory();
        for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
+               int n;
                if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
                        unsigned pers;
                        for (pers = 0; pers < SUPPORTED_PERSONALITIES; pers++) {
@@ -774,6 +780,9 @@ static struct user_gp_regs metag_regs;
 # define ARCH_REGS_FOR_GETREGSET metag_regs
 #elif defined(XTENSA)
 static long xtensa_a2;
+# elif defined(ARC)
+static struct user_regs_struct arc_regs;
+# define ARCH_REGS_FOR_GETREGSET arc_regs
 #endif
 
 void
@@ -914,13 +923,15 @@ print_pc(struct tcb *tcp)
                return;
        }
        tprintf("[%08lx] ", pc);
+#elif defined(ARC)
+       tprintf("[%08lx] ", arc_regs.efa);
 #endif /* architecture */
 }
 
 /* Shuffle syscall numbers so that we don't have huge gaps in syscall table.
  * The shuffling should be reversible: shuffle_scno(shuffle_scno(n)) == n.
  */
-#if defined(ARM) /* So far only ARM needs this */
+#if defined(ARM) || defined(AARCH64) /* So far only 32-bit ARM needs this */
 static long
 shuffle_scno(unsigned long scno)
 {
@@ -1009,7 +1020,8 @@ static void get_regset(pid_t pid)
 # if defined(ARM) \
   || defined(I386) \
   || defined(METAG) \
-  || defined(OR1K)
+  || defined(OR1K) \
+  || defined(ARC)
        static struct iovec io = {
                .iov_base = &ARCH_REGS_FOR_GETREGSET,
                .iov_len = sizeof(ARCH_REGS_FOR_GETREGSET)
@@ -1035,7 +1047,7 @@ void
 get_regs(pid_t pid)
 {
 /* PTRACE_GETREGSET only */
-# if defined(METAG) || defined(OR1K) || defined(X32) || defined(AARCH64)
+# if defined(METAG) || defined(OR1K) || defined(X32) || defined(AARCH64) || defined(ARC)
        get_regset(pid);
 
 /* PTRACE_GETREGS only */
@@ -1209,14 +1221,15 @@ get_scno(struct tcb *tcp)
 #elif defined(POWERPC)
        scno = ppc_regs.gpr[0];
 # ifdef POWERPC64
-       int currpers;
+       unsigned int currpers;
 
-       /* Check for 64/32 bit mode. */
-       /* SF is bit 0 of MSR */
-       if ((ppc_regs.msr >> 63) & 1)
-               currpers = 0;
-       else
-               currpers = 1;
+       /*
+        * Check for 64/32 bit mode.
+        * Embedded implementations covered by Book E extension of PPC use
+        * bit 0 (CM) of 32-bit Machine state register (MSR).
+        * Other implementations use bit 0 (SF) of 64-bit MSR.
+        */
+       currpers = (ppc_regs.msr & 0x8000000080000000) ? 0 : 1;
        update_personality(tcp, currpers);
 # endif
 #elif defined(AVR32)
@@ -1230,7 +1243,7 @@ get_scno(struct tcb *tcp)
 # ifndef __X32_SYSCALL_BIT
 #  define __X32_SYSCALL_BIT    0x40000000
 # endif
-       int currpers;
+       unsigned int currpers;
 # if 1
        /* GETREGSET of NT_PRSTATUS tells us regset size,
         * which unambiguously detects i386.
@@ -1339,6 +1352,7 @@ get_scno(struct tcb *tcp)
                        /* We are in 32-bit mode */
                        /* Note: we don't support OABI, unlike 32-bit ARM build */
                        scno = arm_regs.ARM_r7;
+                       scno = shuffle_scno(scno);
                        update_personality(tcp, 0);
                        break;
        }
@@ -1351,8 +1365,7 @@ get_scno(struct tcb *tcp)
        }
        /* Note: we support only 32-bit CPUs, not 26-bit */
 
-# ifndef STRACE_KNOWS_ONLY_EABI
-# warning STRACE_KNOWS_ONLY_EABI not set, will PTRACE_PEEKTEXT on every syscall (slower tracing)
+# if !defined(__ARM_EABI__) || ENABLE_ARM_OABI
        if (arm_regs.ARM_cpsr & 0x20)
                /* Thumb mode */
                goto scno_in_r7;
@@ -1376,7 +1389,7 @@ get_scno(struct tcb *tcp)
  scno_in_r7:
                scno = arm_regs.ARM_r7;
        }
-# else
+# else /* __ARM_EABI__ || !ENABLE_ARM_OABI */
        scno = arm_regs.ARM_r7;
 # endif
        scno = shuffle_scno(scno);
@@ -1518,7 +1531,7 @@ get_scno(struct tcb *tcp)
        if (upeek(tcp->pid, 4*PT_R9, &scno) < 0)
                return -1;
 #elif defined(TILE)
-       int currpers;
+       unsigned int currpers;
        scno = tile_regs.regs[10];
 # ifdef __tilepro__
        currpers = 1;
@@ -1542,6 +1555,8 @@ get_scno(struct tcb *tcp)
 #elif defined(XTENSA)
        if (upeek(tcp->pid, SYSCALL_NR, &scno) < 0)
                return -1;
+# elif defined(ARC)
+       scno = arc_regs.scratch.r8;
 #endif
 
        tcp->scno = scno;
@@ -1698,7 +1713,6 @@ syscall_fixup_for_fork_exec(struct tcb *tcp)
        func = tcp->s_ent->sys_func;
 
        if (   sys_fork == func
-           || sys_vfork == func
            || sys_clone == func
           ) {
                internal_fork(tcp);
@@ -1932,6 +1946,11 @@ get_syscall_args(struct tcb *tcp)
        for (i = 0; i < nargs; ++i)
                if (upeek(tcp->pid, REG_A_BASE + xtensaregs[i], &tcp->u_arg[i]) < 0)
                        return -1;
+# elif defined(ARC)
+       long *arc_args = &arc_regs.scratch.r0;
+       for (i = 0; i < nargs; ++i)
+               tcp->u_arg[i] = *arc_args--;
+
 #else /* Other architecture (32bits specific) */
        for (i = 0; i < nargs; ++i)
                if (upeek(tcp->pid, i*4, &tcp->u_arg[i]) < 0)
@@ -2022,6 +2041,13 @@ trace_syscall_entering(struct tcb *tcp)
                goto ret;
        }
 
+#ifdef USE_LIBUNWIND
+       if (stack_trace_enabled) {
+               if (tcp->s_ent->sys_flags & STACKTRACE_CAPTURE_ON_ENTER)
+                       unwind_capture_stacktrace(tcp);
+       }
+#endif
+
        printleader(tcp);
        if (tcp->qual_flg & UNDEFINED_SCNO)
                tprintf("%s(", undefined_scno_name(tcp));
@@ -2130,6 +2156,8 @@ get_syscall_result(struct tcb *tcp)
 #elif defined(XTENSA)
        if (upeek(tcp->pid, REG_A_BASE + 2, &xtensa_a2) < 0)
                return -1;
+#elif defined(ARC)
+       /* already done by get_regs */
 #endif
        return 1;
 }
@@ -2435,6 +2463,14 @@ get_error(struct tcb *tcp)
        else {
                tcp->u_rval = xtensa_a2;
        }
+#elif defined(ARC)
+       if (check_errno && is_negated_errno(arc_regs.scratch.r0)) {
+               tcp->u_rval = -1;
+               u_error = -arc_regs.scratch.r0;
+       }
+       else {
+               tcp->u_rval = arc_regs.scratch.r0;
+       }
 #endif
        tcp->u_error = u_error;
 }
@@ -2485,6 +2521,13 @@ trace_syscall_exiting(struct tcb *tcp)
        if (Tflag || cflag)
                gettimeofday(&tv, NULL);
 
+#ifdef USE_LIBUNWIND
+       if (stack_trace_enabled) {
+               if (tcp->s_ent->sys_flags & STACKTRACE_INVALIDATE_CACHE)
+                       unwind_cache_invalidate(tcp);
+       }
+#endif
+
 #if SUPPORTED_PERSONALITIES > 1
        update_personality(tcp, tcp->currpers);
 #endif
@@ -2499,8 +2542,7 @@ trace_syscall_exiting(struct tcb *tcp)
        }
 
        if (cflag) {
-               struct timeval t = tv;
-               count_syscall(tcp, &t);
+               count_syscall(tcp, &tv);
                if (cflag == CFLAG_ONLY_STATS) {
                        goto ret;
                }
@@ -2619,7 +2661,7 @@ trace_syscall_exiting(struct tcb *tcp)
                default:
                        if (u_error < 0)
                                tprintf("= -1 E??? (errno %ld)", u_error);
-                       else if (u_error < nerrnos)
+                       else if ((unsigned long) u_error < nerrnos)
                                tprintf("= -1 %s (%s)", errnoent[u_error],
                                        strerror(u_error));
                        else
@@ -2647,6 +2689,14 @@ trace_syscall_exiting(struct tcb *tcp)
                        case RVAL_DECIMAL:
                                tprintf("= %ld", tcp->u_rval);
                                break;
+                       case RVAL_FD:
+                               if (show_fd_path) {
+                                       tprints("= ");
+                                       printfd(tcp, tcp->u_rval);
+                               }
+                               else
+                                       tprintf("= %ld", tcp->u_rval);
+                               break;
 #if defined(LINUX_MIPSN32) || defined(X32)
                        /*
                        case RVAL_LHEX:
@@ -2683,6 +2733,11 @@ trace_syscall_exiting(struct tcb *tcp)
        dumpio(tcp);
        line_ended();
 
+#ifdef USE_LIBUNWIND
+       if (stack_trace_enabled)
+               unwind_print_stacktrace(tcp);
+#endif
+
  ret:
        tcp->flags &= ~TCB_INSYSCALL;
        return 0;