/*
 * Copyright (c) 2002 Andi Kleen <ak@suse.de>
 * Copyright (c) 2002 Michal Ludvig <mludvig@suse.cz>
 * Copyright (c) 2002 Roland McGrath <roland@redhat.com>
 * Copyright (c) 2008-2013 Denys Vlasenko <vda.linux@googlemail.com>
 * Copyright (c) 2012 H.J. Lu <hongjiu.lu@intel.com>
 * Copyright (c) 2010-2015 Dmitry V. Levin <ldv@altlinux.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* 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

#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 {
# ifdef X32
				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;
	}
#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;
	}
#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 */
#endif /* X32 */

	update_personality(tcp, currpers);
	tcp->scno = scno;
	return 1;
}
