tools/testing/selftests/x86/syscall_numbering.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/x86/syscall_numbering.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/x86/syscall_numbering.c
Extension
.c
Size
11549 bytes
Lines
484
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: syscall or user/kernel boundary
Status
core implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct shared {
	unsigned int nerr;	/* Total error count */
	unsigned int indent;	/* Message indentation level */
	enum ptrace_pass ptrace_pass;
	bool probing_syscall;	/* In probe_syscall() */
};
static volatile struct shared *sh;

static inline unsigned int offset(void)
{
	unsigned int level = sh ? sh->indent : 0;

	return 8 + level * 4;
}

#define msg(lvl, fmt, ...) printf("%-*s" fmt, offset(), "[" #lvl "]", \
				  ## __VA_ARGS__)

#define run(fmt, ...)  msg(RUN,  fmt, ## __VA_ARGS__)
#define info(fmt, ...) msg(INFO, fmt, ## __VA_ARGS__)
#define ok(fmt, ...)   msg(OK,   fmt, ## __VA_ARGS__)

#define fail(fmt, ...)					\
	do {						\
		msg(FAIL, fmt, ## __VA_ARGS__);		\
		sh->nerr++;				\
       } while (0)

#define crit(fmt, ...)					\
	do {						\
		sh->indent = 0;				\
		msg(FAIL, fmt, ## __VA_ARGS__);		\
		msg(SKIP, "Unable to run test\n");	\
		exit(EX_OSERR);				\
       } while (0)

/* Sentinel for ptrace-modified return value */
#define MODIFIED_BY_PTRACE	-9999

/*
 * Directly invokes the given syscall with nullfd as the first argument
 * and the rest zero. Avoids involving glibc wrappers in case they ever
 * end up intercepting some system calls for some reason, or modify
 * the system call number itself.
 */
static long long probe_syscall(int msb, int lsb)
{
	register long long arg1 asm("rdi") = nullfd;
	register long long arg2 asm("rsi") = 0;
	register long long arg3 asm("rdx") = 0;
	register long long arg4 asm("r10") = 0;
	register long long arg5 asm("r8")  = 0;
	register long long arg6 asm("r9")  = 0;
	long long nr = ((long long)msb << 32) | (unsigned int)lsb;
	long long ret;

	/*
	 * We pass in an extra copy of the extended system call number
	 * in %rbx, so we can examine it from the ptrace handler without
	 * worrying about it being possibly modified. This is to test
	 * the validity of struct user regs.orig_rax a.k.a.
	 * struct pt_regs.orig_ax.
	 */
	sh->probing_syscall = true;
	asm volatile("syscall"
		     : "=a" (ret)
		     : "a" (nr), "b" (nr),
		       "r" (arg1), "r" (arg2), "r" (arg3),
		       "r" (arg4), "r" (arg5), "r" (arg6)
		     : "rcx", "r11", "memory", "cc");
	sh->probing_syscall = false;

	return ret;
}

static const char *syscall_str(int msb, int start, int end)
{
	static char buf[64];
	const char * const type = (start & X32_BIT) ? "x32" : "x64";
	int lsb = start;

	/*
	 * Improve readability by stripping the x32 bit, but round
	 * toward zero so we don't display -1 as -1073741825.
	 */
	if (lsb < 0)
		lsb |= X32_BIT;
	else
		lsb &= ~X32_BIT;

Annotation

Implementation Notes