[PATCH] arm: make it one-personality arch
Denys Vlasenko
dvlasenk at redhat.com
Thu Feb 21 12:31:18 UTC 2013
On 02/21/2013 10:24 AM, Denys Vlasenko wrote:
> By combining my patch and print_undefined_scno()
> we can have both: remapping will give us decoding,
> and print_undefined_scno() can do *reverse* remapping
> before it prints "syscall_NN()" thing.
Like this:
diff -d -urpN strace.2/linux/arm/syscallent.h strace.3/linux/arm/syscallent.h
--- strace.2/linux/arm/syscallent.h 2013-02-20 18:28:39.062552420 +0100
+++ strace.3/linux/arm/syscallent.h 2013-02-21 13:08:17.858657269 +0100
@@ -486,11 +486,15 @@
# define ARM_LAST_ORDINARY_SYSCALL 444
#endif /* !EABI */
- /* ARM specific syscalls. Encoded with scno 0x000fxxxx,
- * remapped by get_scno() to be directly after ordinary syscalls
- * in the table.
+ /* __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 */
diff -d -urpN strace.2/syscall.c strace.3/syscall.c
--- strace.2/syscall.c 2013-02-20 18:57:14.495845195 +0100
+++ strace.3/syscall.c 2013-02-21 13:09:58.242653484 +0100
@@ -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 ARM_LAST_ORDINARY_SYSCALL+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
@@ -1247,25 +1292,7 @@ get_scno(struct tcb *tcp)
}
}
-//TODO: why bother? All special syscalls in syscallent.h are printargs anyway
-//TODO: support "doubly special" __ARM_NR_cmpxchg with scno == 0x000ffff0
-
-# define ARM_NUM_ORDINARY_SYSCALLS (ARM_LAST_ORDINARY_SYSCALL + 1)
-
- if (scno > ARM_LAST_ORDINARY_SYSCALL) {
- /* Is it ARM specific syscall? */
- if ((scno & 0xffff0000) == 0x000f0000
- && scno <= 0x000f0000 + ARM_LAST_SPECIAL_SYSCALL
- ) {
- /* Yes. Remap 0x000f00nn -> ARM_NUM_ORDINARY_SYSCALLS + nn */
- scno -= 0x000f0000 - ARM_NUM_ORDINARY_SYSCALLS;
- } else
- /* Is it a (bad) syscall no from the hole we remap into? */
- if (scno <= ARM_NUM_ORDINARY_SYSCALLS + ARM_LAST_SPECIAL_SYSCALL) {
- /* Yes. Make sure it doesn't collide with special syscalls */
- scno += 0x000f0000 - ARM_NUM_ORDINARY_SYSCALLS;
- }
- }
+ scno = shuffle_scno(scno);
#elif defined(M68K)
if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
return -1;
@@ -1848,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);
/*
@@ -1895,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) ||
@@ -2382,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);
}
More information about the Strace-devel
mailing list