From 16510517f10757355944ee5c07285ba2a8b61aff Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 30 Nov 2015 01:46:52 +0000 Subject: [PATCH] cleanup: make get_scno.c files more readable Make get_scno.c files more self-contained. While they are still being included by syscall.c, the latter no longer provides a function framework for them. * linux/aarch64/get_scno.c (arch_get_scno): Define. * linux/alpha/get_scno.c: Likewise. * linux/arc/get_scno.c: Likewise. * linux/arm/get_scno.c: Likewise. * linux/avr32/get_scno.c: Likewise. * linux/bfin/get_scno.c: Likewise. * linux/crisv10/get_scno.c: Likewise. * linux/hppa/get_scno.c: Likewise. * linux/i386/get_scno.c: Likewise. * linux/ia64/get_scno.c: Likewise. * linux/m68k/get_scno.c: Likewise. * linux/metag/get_scno.c: Likewise. * linux/microblaze/get_scno.c: Likewise. * linux/mips/get_scno.c: Likewise. * linux/nios2/get_scno.c: Likewise. * linux/or1k/get_scno.c: Likewise. * linux/powerpc/get_scno.c: Likewise. * linux/powerpc64/get_scno.c: Likewise. * linux/s390/get_scno.c: Likewise. * linux/sh/get_scno.c: Likewise. * linux/sh64/get_scno.c: Likewise. * linux/sparc/get_scno.c: Likewise. * linux/sparc64/get_scno.c: Likewise. * linux/tile/get_scno.c: Likewise. * linux/x86_64/get_scno.c: Likewise. * linux/xtensa/get_scno.c: Likewise. * syscall.c (arch_get_scno): New declaration. Include "get_scno.c" in file scope. (get_scno): Use arch_get_scno. Requested-by: Denys Vlasenko --- linux/aarch64/get_scno.c | 36 ++++--- linux/alpha/get_scno.c | 36 ++++--- linux/arc/get_scno.c | 8 +- linux/arm/get_scno.c | 80 +++++++++------- linux/avr32/get_scno.c | 8 +- linux/bfin/get_scno.c | 8 +- linux/crisv10/get_scno.c | 8 +- linux/hppa/get_scno.c | 8 +- linux/i386/get_scno.c | 8 +- linux/ia64/get_scno.c | 10 +- linux/m68k/get_scno.c | 8 +- linux/metag/get_scno.c | 8 +- linux/microblaze/get_scno.c | 8 +- linux/mips/get_scno.c | 20 ++-- linux/nios2/get_scno.c | 8 +- linux/or1k/get_scno.c | 8 +- linux/powerpc/get_scno.c | 8 +- linux/powerpc64/get_scno.c | 26 ++--- linux/s390/get_scno.c | 8 +- linux/sh/get_scno.c | 40 +++++--- linux/sh64/get_scno.c | 12 ++- linux/sparc/get_scno.c | 8 +- linux/sparc64/get_scno.c | 42 ++++---- linux/tile/get_scno.c | 23 +++-- linux/x86_64/get_scno.c | 186 +++++++++++++++++++----------------- linux/xtensa/get_scno.c | 8 +- syscall.c | 19 ++-- 27 files changed, 408 insertions(+), 242 deletions(-) diff --git a/linux/aarch64/get_scno.c b/linux/aarch64/get_scno.c index 610b38d7..a712a948 100644 --- a/linux/aarch64/get_scno.c +++ b/linux/aarch64/get_scno.c @@ -1,14 +1,24 @@ -switch (aarch64_io.iov_len) { - case sizeof(aarch64_regs): - /* We are in 64-bit mode */ - scno = aarch64_regs.regs[8]; - update_personality(tcp, 1); - break; - case sizeof(arm_regs): - /* 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; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + long scno = 0; + + switch (aarch64_io.iov_len) { + case sizeof(aarch64_regs): + /* We are in 64-bit mode */ + scno = aarch64_regs.regs[8]; + update_personality(tcp, 1); + break; + case sizeof(arm_regs): + /* 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; + } + + tcp->scno = scno; + return 1; } diff --git a/linux/alpha/get_scno.c b/linux/alpha/get_scno.c index bf8c3ada..fc099216 100644 --- a/linux/alpha/get_scno.c +++ b/linux/alpha/get_scno.c @@ -1,16 +1,26 @@ -if (upeek(tcp->pid, REG_A3, &alpha_a3) < 0) - return -1; -if (upeek(tcp->pid, REG_R0, &scno) < 0) - return -1; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + long scno = 0; -/* - * Do some sanity checks to figure out if it's - * really a syscall entry - */ -if (!SCNO_IN_RANGE(scno)) { - if (alpha_a3 == 0 || alpha_a3 == -1) { - if (debug_flag) - error_msg("stray syscall exit: r0 = %ld", scno); - return 0; + if (upeek(tcp->pid, REG_A3, &alpha_a3) < 0) + return -1; + if (upeek(tcp->pid, REG_R0, &scno) < 0) + return -1; + + /* + * Do some sanity checks to figure out if it's + * really a syscall entry + */ + if (!SCNO_IN_RANGE(scno)) { + if (alpha_a3 == 0 || alpha_a3 == -1) { + if (debug_flag) + error_msg("stray syscall exit: r0 = %ld", scno); + return 0; + } } + + tcp->scno = scno; + return 1; } diff --git a/linux/arc/get_scno.c b/linux/arc/get_scno.c index cc45d468..d2046b2d 100644 --- a/linux/arc/get_scno.c +++ b/linux/arc/get_scno.c @@ -1 +1,7 @@ -scno = arc_regs.scratch.r8; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = arc_regs.scratch.r8; + return 1; +} diff --git a/linux/arm/get_scno.c b/linux/arm/get_scno.c index 6591aa84..d9b6ffc5 100644 --- a/linux/arm/get_scno.c +++ b/linux/arm/get_scno.c @@ -1,45 +1,57 @@ -/* Note: we support only 32-bit CPUs, not 26-bit */ +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + long scno = 0; + + /* Note: we support only 32-bit CPUs, not 26-bit */ #if !defined(__ARM_EABI__) || ENABLE_ARM_OABI -if (arm_regs.ARM_cpsr & 0x20) { - /* Thumb mode */ - goto scno_in_r7; -} -/* ARM mode */ -/* Check EABI/OABI by examining SVC insn's low 24 bits */ -errno = 0; -scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL); -if (errno) - return -1; -/* EABI syscall convention? */ -if ((unsigned long) scno != 0xef000000) { - /* No, it's OABI */ - if ((scno & 0x0ff00000) != 0x0f900000) { - error_msg("pid %d unknown syscall trap 0x%08lx", - tcp->pid, scno); + if (arm_regs.ARM_cpsr & 0x20) { + /* Thumb mode */ + goto scno_in_r7; + } + /* ARM mode */ + /* Check EABI/OABI by examining SVC insn's low 24 bits */ + errno = 0; + scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL); + if (errno) return -1; + /* EABI syscall convention? */ + if ((unsigned long) scno != 0xef000000) { + /* No, it's OABI */ + if ((scno & 0x0ff00000) != 0x0f900000) { + error_msg("pid %d unknown syscall trap 0x%08lx", + tcp->pid, scno); + return -1; + } + /* Fixup the syscall number */ + scno &= 0x000fffff; + } else { + scno_in_r7: + scno = arm_regs.ARM_r7; } - /* Fixup the syscall number */ - scno &= 0x000fffff; -} else { -scno_in_r7: - scno = arm_regs.ARM_r7; -} #else /* __ARM_EABI__ || !ENABLE_ARM_OABI */ -scno = arm_regs.ARM_r7; + scno = arm_regs.ARM_r7; #endif -scno = shuffle_scno(scno); + scno = shuffle_scno(scno); + + /* + * Do some sanity checks to figure out + * whether it's really a syscall entry. + */ + if (arm_regs.ARM_ip && !SCNO_IN_RANGE(scno)) { + if (debug_flag) + error_msg("pid %d stray syscall exit:" + " ARM_ip = %ld, scno = %ld", + tcp->pid, arm_regs.ARM_ip, + shuffle_scno(scno)); + return 0; + } -/* - * Do some sanity checks to figure out - * whether it's really a syscall entry. - */ -if (arm_regs.ARM_ip && !SCNO_IN_RANGE(scno)) { - if (debug_flag) - error_msg("pid %d stray syscall exit: ARM_ip = %ld, scno = %ld", - tcp->pid, arm_regs.ARM_ip, shuffle_scno(scno)); - return 0; + tcp->scno = scno; + return 1; } diff --git a/linux/avr32/get_scno.c b/linux/avr32/get_scno.c index 01423299..092dad30 100644 --- a/linux/avr32/get_scno.c +++ b/linux/avr32/get_scno.c @@ -1 +1,7 @@ -scno = avr32_regs.r8; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = avr32_regs.r8; + return 1; +} diff --git a/linux/bfin/get_scno.c b/linux/bfin/get_scno.c index dfdb0a7c..8c3a7d21 100644 --- a/linux/bfin/get_scno.c +++ b/linux/bfin/get_scno.c @@ -1,2 +1,6 @@ -if (upeek(tcp->pid, PT_ORIG_P0, &scno)) - return -1; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + return upeek(tcp->pid, PT_ORIG_P0, &tcp->scno) < 0 ? -1 : 1; +} diff --git a/linux/crisv10/get_scno.c b/linux/crisv10/get_scno.c index 5bbbe8be..14ff3386 100644 --- a/linux/crisv10/get_scno.c +++ b/linux/crisv10/get_scno.c @@ -1,2 +1,6 @@ -if (upeek(tcp->pid, 4*PT_R9, &scno) < 0) - return -1; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + return upeek(tcp->pid, 4 * PT_R9, &tcp->scno) < 0 ? -1 : 1; +} diff --git a/linux/hppa/get_scno.c b/linux/hppa/get_scno.c index 0dc1a465..7da2fc40 100644 --- a/linux/hppa/get_scno.c +++ b/linux/hppa/get_scno.c @@ -1,2 +1,6 @@ -if (upeek(tcp->pid, PT_GR20, &scno) < 0) - return -1; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + return upeek(tcp->pid, PT_GR20, &tcp->scno) < 0 ? -1 : 1; +} diff --git a/linux/i386/get_scno.c b/linux/i386/get_scno.c index fa22fa6c..c2e55510 100644 --- a/linux/i386/get_scno.c +++ b/linux/i386/get_scno.c @@ -1 +1,7 @@ -scno = i386_regs.orig_eax; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = i386_regs.orig_eax; + return 1; +} diff --git a/linux/ia64/get_scno.c b/linux/ia64/get_scno.c index 86333fd8..0ddc17a9 100644 --- a/linux/ia64/get_scno.c +++ b/linux/ia64/get_scno.c @@ -1,5 +1,7 @@ -if (ia64_ia32mode) { - scno = ia64_regs.gr[0]; -} else { - scno = ia64_regs.gr[15]; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = ia64_ia32mode ? ia64_regs.gr[0] : ia64_regs.gr[15]; + return 1; } diff --git a/linux/m68k/get_scno.c b/linux/m68k/get_scno.c index 1a6d28e5..716a7616 100644 --- a/linux/m68k/get_scno.c +++ b/linux/m68k/get_scno.c @@ -1,2 +1,6 @@ -if (upeek(tcp->pid, 4*PT_ORIG_D0, &scno) < 0) - return -1; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + return upeek(tcp->pid, 4 * PT_ORIG_D0, &tcp->scno) < 0 ? -1 : 1; +} diff --git a/linux/metag/get_scno.c b/linux/metag/get_scno.c index 45cfa48e..6dc2ab4a 100644 --- a/linux/metag/get_scno.c +++ b/linux/metag/get_scno.c @@ -1 +1,7 @@ -scno = metag_regs.dx[0][1]; /* syscall number in D1Re0 (D1.0) */ +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = metag_regs.dx[0][1]; /* syscall number in D1Re0 (D1.0) */ + return 1; +} diff --git a/linux/microblaze/get_scno.c b/linux/microblaze/get_scno.c index cf1d919b..6f98f834 100644 --- a/linux/microblaze/get_scno.c +++ b/linux/microblaze/get_scno.c @@ -1,2 +1,6 @@ -if (upeek(tcp->pid, 0, &scno) < 0) - return -1; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + return upeek(tcp->pid, 0, &tcp->scno) < 0 ? -1 : 1; +} diff --git a/linux/mips/get_scno.c b/linux/mips/get_scno.c index 126cedec..f9b5e7d7 100644 --- a/linux/mips/get_scno.c +++ b/linux/mips/get_scno.c @@ -1,9 +1,17 @@ -scno = mips_REG_V0; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = mips_REG_V0; -if (!SCNO_IN_RANGE(scno)) { - if (mips_REG_A3 == 0 || mips_REG_A3 == (uint64_t) -1) { - if (debug_flag) - error_msg("stray syscall exit: v0 = %ld", scno); - return 0; + if (!SCNO_IN_RANGE(tcp->scno)) { + if (mips_REG_A3 == 0 || mips_REG_A3 == (uint64_t) -1) { + if (debug_flag) + error_msg("stray syscall exit: v0 = %ld", + tcp->scno); + return 0; + } } + + return 1; } diff --git a/linux/nios2/get_scno.c b/linux/nios2/get_scno.c index c820bcea..f4db85ee 100644 --- a/linux/nios2/get_scno.c +++ b/linux/nios2/get_scno.c @@ -1 +1,7 @@ -scno = nios2_regs.regs[2]; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = nios2_regs.regs[2]; + return 1; +} diff --git a/linux/or1k/get_scno.c b/linux/or1k/get_scno.c index 99fada29..f446c907 100644 --- a/linux/or1k/get_scno.c +++ b/linux/or1k/get_scno.c @@ -1 +1,7 @@ -scno = or1k_regs.gpr[11]; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = or1k_regs.gpr[11]; + return 1; +} diff --git a/linux/powerpc/get_scno.c b/linux/powerpc/get_scno.c index a311734b..ef06656f 100644 --- a/linux/powerpc/get_scno.c +++ b/linux/powerpc/get_scno.c @@ -1 +1,7 @@ -scno = ppc_regs.gpr[0]; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = ppc_regs.gpr[0]; + return 1; +} diff --git a/linux/powerpc64/get_scno.c b/linux/powerpc64/get_scno.c index 1e670102..8a943e8d 100644 --- a/linux/powerpc64/get_scno.c +++ b/linux/powerpc64/get_scno.c @@ -1,11 +1,15 @@ -scno = ppc_regs.gpr[0]; -unsigned int currpers; - -/* - * 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); +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = ppc_regs.gpr[0]; + /* + * 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. + */ + unsigned int currpers = (ppc_regs.msr & 0x8000000080000000) ? 0 : 1; + update_personality(tcp, currpers); + return 1; +} diff --git a/linux/s390/get_scno.c b/linux/s390/get_scno.c index b9e1c19d..8650e1f1 100644 --- a/linux/s390/get_scno.c +++ b/linux/s390/get_scno.c @@ -1 +1,7 @@ -scno = s390_regset.gprs[2]; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = s390_regset.gprs[2]; + return 1; +} diff --git a/linux/sh/get_scno.c b/linux/sh/get_scno.c index b8ce272c..a9bc5d8f 100644 --- a/linux/sh/get_scno.c +++ b/linux/sh/get_scno.c @@ -1,17 +1,27 @@ -/* - * In the new syscall ABI, the system call number is in R3. - */ -if (upeek(tcp->pid, 4*(REG_REG0+3), &scno) < 0) - return -1; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + long scno = 0; -if (scno < 0) { - /* Odd as it may seem, a glibc bug has been known to cause - glibc to issue bogus negative syscall numbers. So for - our purposes, make strace print what it *should* have been */ - long correct_scno = (scno & 0xff); - if (debug_flag) - error_msg("Detected glibc bug: bogus system call" - " number = %ld, correcting to %ld", - scno, correct_scno); - scno = correct_scno; + /* + * In the new syscall ABI, the system call number is in R3. + */ + if (upeek(tcp->pid, 4*(REG_REG0+3), &scno) < 0) + return -1; + + if (scno < 0) { + /* Odd as it may seem, a glibc bug has been known to cause + glibc to issue bogus negative syscall numbers. So for + our purposes, make strace print what it *should* have been */ + long correct_scno = (scno & 0xff); + if (debug_flag) + error_msg("Detected glibc bug: bogus system call" + " number = %ld, correcting to %ld", + scno, correct_scno); + scno = correct_scno; + } + + tcp->scno = scno; + return 1; } diff --git a/linux/sh64/get_scno.c b/linux/sh64/get_scno.c index 9e7ecd43..50a52232 100644 --- a/linux/sh64/get_scno.c +++ b/linux/sh64/get_scno.c @@ -1,3 +1,9 @@ -if (upeek(tcp->pid, REG_SYSCALL, &scno) < 0) - return -1; -scno &= 0xFFFF; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + if (upeek(tcp->pid, REG_SYSCALL, &tcp->scno) < 0) + return -1; + tcp->scno &= 0xffff; + return 1; +} diff --git a/linux/sparc/get_scno.c b/linux/sparc/get_scno.c index b190b6c5..f041259d 100644 --- a/linux/sparc/get_scno.c +++ b/linux/sparc/get_scno.c @@ -1 +1,7 @@ -scno = sparc_regs.u_regs[U_REG_G1]; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + tcp->scno = sparc_regs.u_regs[U_REG_G1]; + return 1; +} diff --git a/linux/sparc64/get_scno.c b/linux/sparc64/get_scno.c index b92366e9..32384e69 100644 --- a/linux/sparc64/get_scno.c +++ b/linux/sparc64/get_scno.c @@ -1,19 +1,25 @@ -/* Retrieve the syscall trap instruction. */ -unsigned long trap; -errno = 0; -trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.tpc, 0); -if (errno) - return -1; -trap >>= 32; -switch (trap) { -case 0x91d02010: - /* Linux/SPARC syscall trap. */ - update_personality(tcp, 0); - break; -case 0x91d0206d: - /* Linux/SPARC64 syscall trap. */ - update_personality(tcp, 1); - break; -} +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + /* Retrieve the syscall trap instruction. */ + unsigned long trap; + errno = 0; + trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.tpc, 0); + if (errno) + return -1; + trap >>= 32; + switch (trap) { + case 0x91d02010: + /* Linux/SPARC syscall trap. */ + update_personality(tcp, 0); + break; + case 0x91d0206d: + /* Linux/SPARC64 syscall trap. */ + update_personality(tcp, 1); + break; + } -scno = sparc_regs.u_regs[U_REG_G1]; + tcp->scno = sparc_regs.u_regs[U_REG_G1]; + return 1; +} diff --git a/linux/tile/get_scno.c b/linux/tile/get_scno.c index 1ae65c96..e8403d9b 100644 --- a/linux/tile/get_scno.c +++ b/linux/tile/get_scno.c @@ -1,17 +1,22 @@ -unsigned int currpers; - -scno = tile_regs.regs[10]; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + unsigned int currpers; #ifdef __tilepro__ -currpers = 1; + currpers = 1; #else # ifndef PT_FLAGS_COMPAT # define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */ # endif -if (tile_regs.flags & PT_FLAGS_COMPAT) - currpers = 1; -else - currpers = 0; + if (tile_regs.flags & PT_FLAGS_COMPAT) + currpers = 1; + else + currpers = 0; #endif + update_personality(tcp, currpers); + tcp->scno = tile_regs.regs[10]; -update_personality(tcp, currpers); + return 1; +} diff --git a/linux/x86_64/get_scno.c b/linux/x86_64/get_scno.c index 02ff0a73..8b163de5 100644 --- a/linux/x86_64/get_scno.c +++ b/linux/x86_64/get_scno.c @@ -1,104 +1,116 @@ +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + long scno = 0; + unsigned int currpers; + #ifndef __X32_SYSCALL_BIT # define __X32_SYSCALL_BIT 0x40000000 #endif -unsigned int currpers; - #if 1 -/* GETREGSET of NT_PRSTATUS tells us regset size, - * which unambiguously detects i386. - * - * Linux kernel distinguishes x86-64 and x32 processes - * solely by looking at __X32_SYSCALL_BIT: - * arch/x86/include/asm/compat.h::is_x32_task(): - * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT) - * return true; - */ -if (x86_io.iov_len == sizeof(i386_regs)) { - scno = i386_regs.orig_eax; - currpers = 1; -} else { - scno = x86_64_regs.orig_rax; - currpers = 0; - if (scno & __X32_SYSCALL_BIT) { - /* - * Syscall number -1 requires special treatment: - * it might be a side effect of SECCOMP_RET_ERRNO - * filtering that sets orig_rax to -1 - * in some versions of linux kernel. - * If that is the case, then - * __X32_SYSCALL_BIT logic does not apply. - */ - if ((long long) x86_64_regs.orig_rax != -1) { - scno -= __X32_SYSCALL_BIT; - currpers = 2; - } else { + /* + * GETREGSET of NT_PRSTATUS tells us regset size, + * which unambiguously detects i386. + * + * Linux kernel distinguishes x86-64 and x32 processes + * solely by looking at __X32_SYSCALL_BIT: + * arch/x86/include/asm/compat.h::is_x32_task(): + * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT) + * return true; + */ + if (x86_io.iov_len == sizeof(i386_regs)) { + scno = i386_regs.orig_eax; + currpers = 1; + } else { + scno = x86_64_regs.orig_rax; + currpers = 0; + if (scno & __X32_SYSCALL_BIT) { + /* + * Syscall number -1 requires special treatment: + * it might be a side effect of SECCOMP_RET_ERRNO + * filtering that sets orig_rax to -1 + * in some versions of linux kernel. + * If that is the case, then + * __X32_SYSCALL_BIT logic does not apply. + */ + if ((long long) x86_64_regs.orig_rax != -1) { + scno -= __X32_SYSCALL_BIT; + currpers = 2; + } else { # ifdef X32 - currpers = 2; + currpers = 2; # endif + } } } -} #elif 0 -/* cs = 0x33 for long mode (native 64 bit and x32) - * cs = 0x23 for compatibility mode (32 bit) - * ds = 0x2b for x32 mode (x86-64 in 32 bit) - */ -scno = x86_64_regs.orig_rax; -switch (x86_64_regs.cs) { - case 0x23: currpers = 1; break; - case 0x33: - if (x86_64_regs.ds == 0x2b) { - currpers = 2; - scno &= ~__X32_SYSCALL_BIT; - } else - currpers = 0; - break; - default: - error_msg("Unknown value CS=0x%08X while " - "detecting personality of process PID=%d", - (int)x86_64_regs.cs, tcp->pid); - currpers = current_personality; - break; -} + /* + * cs = 0x33 for long mode (native 64 bit and x32) + * cs = 0x23 for compatibility mode (32 bit) + * ds = 0x2b for x32 mode (x86-64 in 32 bit) + */ + scno = x86_64_regs.orig_rax; + switch (x86_64_regs.cs) { + case 0x23: currpers = 1; break; + case 0x33: + if (x86_64_regs.ds == 0x2b) { + currpers = 2; + scno &= ~__X32_SYSCALL_BIT; + } else + currpers = 0; + break; + default: + error_msg("Unknown value CS=0x%08X while " + "detecting personality of process PID=%d", + (int)x86_64_regs.cs, tcp->pid); + currpers = current_personality; + break; + } #elif 0 -/* This version analyzes the opcode of a syscall instruction. - * (int 0x80 on i386 vs. syscall on x86-64) - * It works, but is too complicated, and strictly speaking, unreliable. - */ -unsigned long call, rip = x86_64_regs.rip; -/* sizeof(syscall) == sizeof(int 0x80) == 2 */ -rip -= 2; -errno = 0; -call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0); -if (errno) - perror_msg("ptrace_peektext failed"); -switch (call & 0xffff) { - /* x86-64: syscall = 0x0f 0x05 */ - case 0x050f: currpers = 0; break; - /* i386: int 0x80 = 0xcd 0x80 */ - case 0x80cd: currpers = 1; break; - default: - currpers = current_personality; - error_msg("Unknown syscall opcode (0x%04X) while " - "detecting personality of process PID=%d", - (int)call, tcp->pid); - break; -} + /* + * This version analyzes the opcode of a syscall instruction. + * (int 0x80 on i386 vs. syscall on x86-64) + * It works, but is too complicated, and strictly speaking, unreliable. + */ + unsigned long call, rip = x86_64_regs.rip; + /* sizeof(syscall) == sizeof(int 0x80) == 2 */ + rip -= 2; + errno = 0; + call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0); + if (errno) + perror_msg("ptrace_peektext failed"); + switch (call & 0xffff) { + /* x86-64: syscall = 0x0f 0x05 */ + case 0x050f: currpers = 0; break; + /* i386: int 0x80 = 0xcd 0x80 */ + case 0x80cd: currpers = 1; break; + default: + currpers = current_personality; + error_msg("Unknown syscall opcode (0x%04X) while " + "detecting personality of process PID=%d", + (int)call, tcp->pid); + break; + } #endif #ifdef X32 -/* If we are built for a x32 system, then personality 0 is x32 - * (not x86_64), and stracing of x86_64 apps is not supported. - * Stracing of i386 apps is still supported. - */ -if (currpers == 0) { - error_msg("syscall_%lu(...) in unsupported " - "64-bit mode of process PID=%d", scno, tcp->pid); - return 0; -} -currpers &= ~2; /* map 2,1 to 0,1 */ + /* + * If we are built for a x32 system, then personality 0 is x32 + * (not x86_64), and stracing of x86_64 apps is not supported. + * Stracing of i386 apps is still supported. + */ + if (currpers == 0) { + error_msg("syscall_%lu(...) in unsupported " + "64-bit mode of process PID=%d", scno, tcp->pid); + return 0; + } + currpers &= ~2; /* map 2,1 to 0,1 */ #endif /* X32 */ -update_personality(tcp, currpers); + update_personality(tcp, currpers); + tcp->scno = scno; + return 1; +} diff --git a/linux/xtensa/get_scno.c b/linux/xtensa/get_scno.c index 42991630..d230f73b 100644 --- a/linux/xtensa/get_scno.c +++ b/linux/xtensa/get_scno.c @@ -1,2 +1,6 @@ -if (upeek(tcp->pid, SYSCALL_NR, &scno) < 0) - return -1; +/* Return codes: 1 - ok, 0 - ignore, other - error. */ +static int +arch_get_scno(struct tcb *tcp) +{ + return upeek(tcp->pid, SYSCALL_NR, &tcp->scno) < 0 ? -1 : 1; +} diff --git a/syscall.c b/syscall.c index 91bd4fa9..3f43a57d 100644 --- a/syscall.c +++ b/syscall.c @@ -1302,7 +1302,11 @@ get_regs(pid_t pid) #endif } -/* Returns: +static int arch_get_scno(struct tcb *tcp); +#include "get_scno.c" + +/* + * Returns: * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently. * 1: ok, continue in trace_syscall_entering(). * other: error, trace_syscall_entering() should print error indicator @@ -1314,14 +1318,13 @@ get_scno(struct tcb *tcp) if (get_regs_error) return -1; - long scno = 0; - -#include "get_scno.c" + int rc = arch_get_scno(tcp); + if (rc != 1) + return rc; - tcp->scno = scno; if (SCNO_IS_VALID(tcp->scno)) { - tcp->s_ent = &sysent[scno]; - tcp->qual_flg = qual_flags[scno]; + tcp->s_ent = &sysent[tcp->scno]; + tcp->qual_flg = qual_flags[tcp->scno]; } else { static const struct_sysent unknown = { .nargs = MAX_ARGS, @@ -1332,7 +1335,7 @@ get_scno(struct tcb *tcp) tcp->s_ent = &unknown; tcp->qual_flg = UNDEFINED_SCNO | QUAL_RAW | DEFAULT_QUAL_FLAGS; if (debug_flag) - error_msg("pid %d invalid syscall %ld", tcp->pid, scno); + error_msg("pid %d invalid syscall %ld", tcp->pid, tcp->scno); } return 1; } -- 2.40.0