1 /*
2 * Copyright (c) 2002 Andi Kleen <ak@suse.de>
3 * Copyright (c) 2002 Michal Ludvig <mludvig@suse.cz>
4 * Copyright (c) 2002 Roland McGrath <roland@redhat.com>
5 * Copyright (c) 2008-2013 Denys Vlasenko <vda.linux@googlemail.com>
6 * Copyright (c) 2012 H.J. Lu <hongjiu.lu@intel.com>
7 * Copyright (c) 2010-2015 Dmitry V. Levin <ldv@strace.io>
8 * Copyright (c) 2015-2021 The strace developers.
9 * All rights reserved.
10 *
11 * SPDX-License-Identifier: LGPL-2.1-or-later
12 */
13
14 /* Return codes: 1 - ok, 0 - ignore, other - error. */
15 static int
16 arch_get_scno(struct tcb *tcp)
17 {
18 kernel_ulong_t scno = 0;
19 unsigned int currpers;
20
21 /*
22 * GETREGSET of NT_PRSTATUS tells us regset size,
23 * which unambiguously detects i386.
24 *
25 * Linux kernel distinguishes x86-64 and x32 processes
26 * solely by looking at __X32_SYSCALL_BIT:
27 * arch/x86/include/asm/compat.h::is_x32_task():
28 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
29 * return true;
30 */
31 if (x86_io.iov_len == sizeof(i386_regs)) {
32 scno = i386_regs.orig_eax;
33 currpers = 1;
34 } else {
35 scno = x86_64_regs.orig_rax;
36 currpers = 0;
37 if (scno & __X32_SYSCALL_BIT) {
38 /*
39 * Syscall number -1 requires special treatment:
40 * it might be a side effect of SECCOMP_RET_ERRNO
41 * filtering that sets orig_rax to -1
42 * in some versions of linux kernel.
43 * If that is the case, then
44 * __X32_SYSCALL_BIT logic does not apply.
45 */
46 if ((long long) x86_64_regs.orig_rax != -1) {
47 currpers = 2;
48 } else {
49 #ifdef X32
50 currpers = 2;
51 #endif
52 }
53 }
54 }
55
56 #ifdef X32
57 /*
58 * If we are built for a x32 system, then personality 0 is x32
59 * (not x86_64), and stracing of x86_64 apps is not supported.
60 * Stracing of i386 apps is still supported.
61 */
62 if (currpers == 0) {
63 error_msg("syscall_%" PRI_klu "(...) in unsupported "
64 "64-bit mode of process PID=%d", scno, tcp->pid);
65 return 0;
66 }
67 currpers &= ~2; /* map 2,1 to 0,1 */
68 #endif /* X32 */
69
70 update_personality(tcp, currpers);
71 tcp->scno = scno;
72 return 1;
73 }