]> granicus.if.org Git - strace/commitdiff
ARM: make it one-personality arch
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 21 Feb 2013 14:46:34 +0000 (15:46 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 21 Feb 2013 14:46:34 +0000 (15:46 +0100)
ARM in fact _is_ one personality.

We had two personalities for it because it has a handful of
syscalls with huge scnos (0x000f00xx).

Extending syscall table to have [0x000f0005] index is of course
not a good idea.

Someone decided to handle that by having a separate personality
just for these syscalls.

But multi-personality arch does a bit more work in other parts.

This patch is another alternative: "move" 0x000f00nn syscalls
down to the entries just above last ordinary syscall,
by manipulating scno if it falls into the 0x000f00xx range.

In order to not worsen genuine undefined scnos' printing,
the code remaps scno back to actual value before printing
"syscall_NNN" string.

* defs.h: Remove multi-reprsonality defines from ARM.
* syscall.c (shuffle_scno): New function.
(undefined_scno_name): New function.
(get_scno): [ARM] Replace personality setting with scno shuffling.
(trace_syscall_entering): Print unknown syscall name using
undefined_scno_name().
(trace_syscall_exiting): Likewise.
* linux/arm/syscallent.h: Add ARM specific syscalls at the end.
* linux/arm/errnoent1.h: Deleted.
* linux/arm/ioctlent1.h: Deleted.
* linux/arm/signalent1.h: Deleted.
* linux/arm/syscallent1.h: Deleted.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
defs.h
linux/arm/errnoent1.h [deleted file]
linux/arm/ioctlent1.h [deleted file]
linux/arm/signalent1.h [deleted file]
linux/arm/syscallent.h
linux/arm/syscallent1.h [deleted file]
syscall.c

diff --git a/defs.h b/defs.h
index 8f397126889ed670878f6912f3a40fbd27709655..fc8f8e7856d9ac05d1d907fe9173abceb6aecb5e 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -318,9 +318,7 @@ struct arm_pt_regs {
 #endif
 
 #ifdef ARM
-# define SUPPORTED_PERSONALITIES 2
-# define PERSONALITY0_WORDSIZE 4
-# define PERSONALITY1_WORDSIZE 4
+/* one personality */
 #endif
 
 #ifdef AARCH64
diff --git a/linux/arm/errnoent1.h b/linux/arm/errnoent1.h
deleted file mode 100644 (file)
index 2ec4061..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/* "ARM specific syscall" personality */
-#include "../errnoent.h"
diff --git a/linux/arm/ioctlent1.h b/linux/arm/ioctlent1.h
deleted file mode 100644 (file)
index b0f8d87..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/* "ARM specific syscall" personality */
-#include "../ioctlent.h"
diff --git a/linux/arm/signalent1.h b/linux/arm/signalent1.h
deleted file mode 100644 (file)
index 130972b..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/* "ARM specific syscall" personality */
-#include "../signalent.h"
index 53c01a86b93c64e3443d52e325babf8bba69b0bf..043a2858662e841ad4653417cf7f2b2965b156b7 100644 (file)
        { 2,    TD,     sys_setns,              "setns"         }, /* 375 */
        { 6,    0,      sys_process_vm_readv,   "process_vm_readv"      }, /* 376 */
        { 6,    0,      sys_process_vm_writev,  "process_vm_writev"     }, /* 377 */
-
-#ifndef __ARM_EABI__
+#ifdef __ARM_EABI__
+# define ARM_LAST_ORDINARY_SYSCALL 377
+#else
        { 5,    0,      NULL,                   NULL            }, /* 378 */
        { 5,    0,      NULL,                   NULL            }, /* 379 */
        { 5,    0,      NULL,                   NULL            }, /* 380 */
        { 5,    0,      NULL,                   NULL            }, /* 397 */
        { 5,    0,      NULL,                   NULL            }, /* 398 */
        { 5,    0,      NULL,                   NULL            }, /* 399 */
-#if SYS_socket_subcall != 400
- #error fix me
-#endif
+# if SYS_socket_subcall != 400
+#  error fix me
+# endif
        { 6,    0,      printargs,              "socket_subcall"}, /* 400 */
        { 3,    TN,     sys_socket,             "socket"        }, /* 401 */
        { 3,    TN,     sys_bind,               "bind"          }, /* 402 */
        { 4,    TN,     sys_accept4,            "accept4"       }, /* 418 */
        { 5,    TN,     sys_recvmmsg,           "recvmmsg"      }, /* 419 */
 
-#if SYS_ipc_subcall != 420
- #error fix me
-#endif
+# if SYS_ipc_subcall != 420
+#  error fix me
+# endif
        { 4,    0,      printargs,              "ipc_subcall"   }, /* 420 */
        { 4,    TI,     sys_semop,              "semop"         }, /* 421 */
        { 4,    TI,     sys_semget,             "semget"        }, /* 422 */
        { 4,    TI,     sys_shmdt,              "shmdt"         }, /* 442 */
        { 4,    TI,     sys_shmget,             "shmget"        }, /* 443 */
        { 4,    TI,     sys_shmctl,             "shmctl"        }, /* 444 */
-#endif
+# define ARM_LAST_ORDINARY_SYSCALL 444
+#endif /* !EABI */
+
+       /* __ARM_NR_cmpxchg (0x000ffff0).
+        * Remapped by shuffle_scno() to be directly after ordinary syscalls
+        * in this table.
+        */
+       { 5,    0,      printargs,              "cmpxchg"               },
+
+       /* ARM specific syscalls. Encoded with scno 0x000f00xx.
+        * Remapped by shuffle_scno() to be directly after __ARM_NR_cmpxchg.
+        */
+       { 5,    0,      NULL,                   NULL                    }, /* 0 */
+       { 5,    0,      printargs,              "breakpoint"            }, /* 1 */
+       { 5,    0,      printargs,              "cacheflush"            }, /* 2 */
+       { 5,    0,      printargs,              "usr26"                 }, /* 3 */
+       { 5,    0,      printargs,              "usr32"                 }, /* 4 */
+       { 5,    0,      printargs,              "set_tls"               }, /* 5 */
+#define ARM_LAST_SPECIAL_SYSCALL 5
diff --git a/linux/arm/syscallent1.h b/linux/arm/syscallent1.h
deleted file mode 100644 (file)
index a2ac61d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/* "ARM specific syscall" personality */
-       { 5,    0,      NULL,                   NULL                    }, /* 0 */
-       { 5,    0,      printargs,              "breakpoint"            }, /* 1 */
-       { 5,    0,      printargs,              "cacheflush"            }, /* 2 */
-       { 5,    0,      printargs,              "usr26"                 }, /* 3 */
-       { 5,    0,      printargs,              "usr32"                 }, /* 4 */
-       { 5,    0,      printargs,              "set_tls"               }, /* 5 */
index 7e2d0e848c6613a21df19780c92e3418bc10a899..b1a407b0eff4807fcacf1144d51134fb51486f9c 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -899,6 +899,51 @@ printcall(struct tcb *tcp)
 #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 */
+static long
+shuffle_scno(unsigned long scno)
+{
+       if (scno <= ARM_LAST_ORDINARY_SYSCALL)
+               return scno;
+
+       /* __ARM_NR_cmpxchg? Swap with LAST_ORDINARY+1 */
+       if (scno == 0x000ffff0)
+               return ARM_LAST_ORDINARY_SYSCALL+1;
+       if (scno == ARM_LAST_ORDINARY_SYSCALL+1)
+               return 0x000ffff0;
+
+       /* Is it ARM specific syscall?
+        * Swap with [LAST_ORDINARY+2, LAST_ORDINARY+2 + LAST_SPECIAL] range.
+        */
+       if (scno >= 0x000f0000
+        && scno <= 0x000f0000 + ARM_LAST_SPECIAL_SYSCALL
+       ) {
+               return scno - 0x000f0000 + (ARM_LAST_ORDINARY_SYSCALL+2);
+       }
+       if (/* scno >= ARM_LAST_ORDINARY_SYSCALL+2 - always true */ 1
+        && scno <= (ARM_LAST_ORDINARY_SYSCALL+2) + ARM_LAST_SPECIAL_SYSCALL
+       ) {
+               return scno + 0x000f0000 - (ARM_LAST_ORDINARY_SYSCALL+2);
+       }
+
+       return scno;
+}
+#else
+# define shuffle_scno(scno) ((long)(scno))
+#endif
+
+static char*
+undefined_scno_name(struct tcb *tcp)
+{
+       static char buf[sizeof("syscall_%lu") + sizeof(long)*3];
+
+       sprintf(buf, "syscall_%lu", shuffle_scno(tcp->scno));
+       return buf;
+}
+
 #ifndef get_regs
 long get_regs_error;
 void
@@ -1246,13 +1291,8 @@ get_scno(struct tcb *tcp)
                        scno &= 0x000fffff;
                }
        }
-       if (scno & 0x000f0000) {
-               /* ARM specific syscall. We handle it as a separate "personality" */
-               update_personality(tcp, 1);
-               scno &= 0x0000ffff;
-       } else {
-               update_personality(tcp, 0);
-       }
+
+       scno = shuffle_scno(scno);
 #elif defined(M68K)
        if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
                return -1;
@@ -1835,7 +1875,7 @@ trace_syscall_entering(struct tcb *tcp)
                if (scno_good != 1)
                        tprints("????" /* anti-trigraph gap */ "(");
                else if (!SCNO_IS_VALID(tcp->scno))
-                       tprintf("syscall_%lu(", tcp->scno);
+                       tprintf("%s(", undefined_scno_name(tcp));
                else
                        tprintf("%s(", sysent[tcp->scno].sys_name);
                /*
@@ -1882,7 +1922,7 @@ trace_syscall_entering(struct tcb *tcp)
 
        printleader(tcp);
        if (!SCNO_IS_VALID(tcp->scno))
-               tprintf("syscall_%lu(", tcp->scno);
+               tprintf("%s(", undefined_scno_name(tcp));
        else
                tprintf("%s(", sysent[tcp->scno].sys_name);
        if (!SCNO_IS_VALID(tcp->scno) ||
@@ -2369,7 +2409,7 @@ trace_syscall_exiting(struct tcb *tcp)
                tcp->flags &= ~TCB_REPRINT;
                printleader(tcp);
                if (!SCNO_IS_VALID(tcp->scno))
-                       tprintf("<... syscall_%lu resumed> ", tcp->scno);
+                       tprintf("<... %s resumed> ", undefined_scno_name(tcp));
                else
                        tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
        }