Syscall查找方式

Android9.0采用如下Tips3,4进行定位

Tips 1: 用户空间的方法xxx,对应系统调用层方法则是sys_xxx;
Tips 2: unistd.h文件记录着系统调用中断号的信息。(搜索__SYSCALL找到unistd.d文件位置)

/* kernel/signal.c */
__SYSCALL(__NR_kill, sys_kill)

Tips 3: 宏定义SYSCALL_DEFINEx(xxx,…),展开后对应的方法则是sys_xxx;
Tips 4: 方法参数的个数x,对应于SYSCALL_DEFINEx。

kill(int pid, int sig)方法共两个参数,则对应方法于SYSCALL_DEFINE2(kill,...),进入signal.c文件,再次搜索关键字,便能看到方法:

include/linux/syscalls.h

syscalls.h

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)

#define SYSCALL_DEFINEx(x, sname, ...)				\
	SYSCALL_METADATA(sname, x, __VA_ARGS__)			\
	__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)


#define __SYSCALL_DEFINEx(x, name, ...)					\
	asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))	\
		__attribute__((alias(__stringify(SyS##name))));		\
	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));	\
	asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));	\
	asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))	\
	{								\
		long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));	\
		__MAP(x,__SC_TEST,__VA_ARGS__);				\
		__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));	\
		return ret;						\
	}								\
	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))

fs/ioctl.c

ioctl

kgdb调试堆栈

#0  binder_ioctl (filp=0xffff8800618f6a00, cmd=3224396289, arg=3463711848)
    at drivers/android/binder.c:4738
#1  0xffffffff803873fe in C_SYSC_ioctl (arg32=<optimized out>, cmd=<optimized out>,
    fd=<optimized out>) at fs/compat_ioctl.c:1592
#2  compat_SyS_ioctl (fd=46, cmd=3224396289, arg32=3463711848) at fs/compat_ioctl.c:1544
#3  0xffffffff80201a69 in do_syscall_32_irqs_on (regs=<optimized out>) at arch/x86/entry/common.c:392
#4  do_fast_syscall_32 (regs=0xffff880052e33f58) at arch/x86/entry/common.c:459
#5  0xffffffff80941c75 in entry_SYSENTER_compat () at arch/x86/entry/entry_64_compat.S:126
#6  0x0000000000000000 in ?? ()

frame 2 compat_SyS_ioctl对应COMPAT_SYSCALL_DEFINE3(ioctl, …),实现和下述SYSCALL_DEFINE3类似

SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
{
	int error;
	struct fd f = fdget(fd);

	if (!f.file)
		return -EBADF;
	error = security_file_ioctl(f.file, cmd, arg);
	if (!error)
		error = do_vfs_ioctl(f.file, fd, cmd, arg);
	fdput(f);
	return error;
}

vfs_ioctl

/**
 * vfs_ioctl - call filesystem specific ioctl methods
 * @filp:	open file to invoke ioctl method on
 * @cmd:	ioctl command to execute
 * @arg:	command-specific argument for ioctl
 *
 * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise
 * returns -ENOTTY.
 *
 * Returns 0 on success, -errno on error.
 */
static long vfs_ioctl(struct file *filp, unsigned int cmd,
		      unsigned long arg)
{
	int error = -ENOTTY;

	if (!filp->f_op->unlocked_ioctl)
		goto out;

	error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
	if (error == -ENOIOCTLCMD)
		error = -ENOTTY;
 out:
	return error;
}

drivers/android/binder.c

.unlocked_ioctl = binder_ioctl

static const struct file_operations binder_fops = {
	.owner = THIS_MODULE,
	.poll = binder_poll,
	.unlocked_ioctl = binder_ioctl,
	.compat_ioctl = binder_ioctl,
	.mmap = binder_mmap,
	.open = binder_open,
	.flush = binder_flush,
	.release = binder_release,
};

drivers/staging/android/ashmem.c

ashmem

ashmem_fops

static const struct file_operations ashmem_fops = {
	.owner = THIS_MODULE,
	.open = ashmem_open,
	.release = ashmem_release,
	.read = ashmem_read,
	.llseek = ashmem_llseek,
	.mmap = ashmem_mmap,
	.unlocked_ioctl = ashmem_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = compat_ashmem_ioctl,
#endif
};

static struct miscdevice ashmem_misc = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = "ashmem",
	.fops = &ashmem_fops,
};
static int __init ashmem_init(void)
{
	int ret;
	ashmem_area_cachep = kmem_cache_create("ashmem_area_cache",
					       sizeof(struct ashmem_area),
					       0, 0, NULL);

	ashmem_range_cachep = kmem_cache_create("ashmem_range_cache",
						sizeof(struct ashmem_range),
						0, 0, NULL);

	ret = misc_register(&ashmem_misc);
	register_shrinker(&ashmem_shrinker);
	return 0;
}
device_initcall(ashmem_init);

fs/eventpoll.c

epoll_wait

kgdb调试堆栈

#0  ep_poll (ep=0xffff88006ac71180, events=0xcab7adb8, maxevents=16, timeout=0)
    at fs/eventpoll.c:1599
#1  0xffffffff8037b095 in SYSC_epoll_wait (timeout=<optimized out>, maxevents=<optimized out>,
    events=<optimized out>, epfd=<optimized out>) at fs/eventpoll.c:2009
#2  SyS_epoll_wait (epfd=<optimized out>, events=<optimized out>, maxevents=16,
    timeout=<optimized out>) at fs/eventpoll.c:1974
#3  0xffffffff8037b148 in SYSC_epoll_pwait (sigsetsize=<optimized out>, sigmask=<optimized out>,
    timeout=<optimized out>, maxevents=<optimized out>, events=<optimized out>, epfd=<optimized out>)
    at fs/eventpoll.c:2040
#4  SyS_epoll_pwait (epfd=38, events=3401035192, maxevents=16, timeout=0, sigmask=0,
    sigsetsize=<optimized out>) at fs/eventpoll.c:2020
#5  0xffffffff80201a69 in do_syscall_32_irqs_on (regs=<optimized out>) at arch/x86/entry/common.c:392
#6  do_fast_syscall_32 (regs=0xffff88006175bf58) at arch/x86/entry/common.c:459
#7  0xffffffff80941c75 in entry_SYSENTER_compat () at arch/x86/entry/entry_64_compat.S:126
#8  0x0000000000000000 in ?? ()

frame 2 SyS_epoll_wait对应下述方法:

/*
 * Implement the event wait interface for the eventpoll file. It is the kernel
 * part of the user space epoll_wait(2).
 */
SYSCALL_DEFINE4(epoll_wait, int, epfd, struct epoll_event __user *, events,
		int, maxevents, int, timeout)
{

include/linux/fs.h

struct file

struct file {
	union {
		struct llist_node	fu_llist;
		struct rcu_head 	fu_rcuhead;
	} f_u;
	struct path		f_path;
	struct inode		*f_inode;	/* cached value */
	const struct file_operations	*f_op;

	/*
	 * Protects f_ep_links, f_flags.
	 * Must not be taken from IRQ context.
	 */
	spinlock_t		f_lock;
	atomic_long_t		f_count;
	unsigned int 		f_flags;
	fmode_t			f_mode;
	struct mutex		f_pos_lock;
	loff_t			f_pos;
	struct fown_struct	f_owner;
	const struct cred	*f_cred;
	struct file_ra_state	f_ra;

	u64			f_version;
#ifdef CONFIG_SECURITY
	void			*f_security;
#endif
	/* needed for tty driver, and maybe others */
	void			*private_data;

#ifdef CONFIG_EPOLL
	/* Used by fs/eventpoll.c to link all the hooks to this file */
	struct list_head	f_ep_links;
	struct list_head	f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */
	struct address_space	*f_mapping;
} __attribute__((aligned(4)));	/* lest something weird decides that 2 is OK */

参考

http://gityuan.com/2016/05/21/syscall/