linux系统调用追踪

本文介绍调试系统调用的两种方法

 

一 自定义创建syscall debug系统调用

自定义的debug系统调用需要自己申请一个系统调用接口,用一个flag的标志来控制打印。

平台aarch64

1 添加系统调用号

diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index d901272..ea4d459 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -740,9 +740,13 @@ __SC_COMP(__NR_io_pgetevents, sys_io_pgetevents, compat_sys_io_pgetevents)
 __SYSCALL(__NR_rseq, sys_rseq)
 #define __NR_kexec_file_load 294
 __SYSCALL(__NR_kexec_file_load,     sys_kexec_file_load)
+#define __NR_debug_syscall 295
+__SYSCALL(__NR_debug_syscall, sys_debug_syscall)
+
 
 #undef __NR_syscalls
-#define __NR_syscalls 295
+/* #define __NR_syscalls 296 */
+#define __NR_syscalls 300

2 申明一个系统调用

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 257cccb..d0954ed 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1315,4 +1315,6 @@ static inline unsigned int ksys_personality(unsigned int personality)
 	return old;
 }
 
+asmlinkage long sys_debug_syscall(int enable);
+
 #endif

 

3 实现系统调用

diff --git a/kernel/sys.c b/kernel/sys.c
index f7eb62e..f5c39bb 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2583,6 +2583,20 @@ SYSCALL_DEFINE1(sysinfo, struct sysinfo __user *, info)
 	return 0;
 }
 
+int syscall_debug_enable;
+EXPORT_SYMBOL(syscall_debug_enable);
+
+SYSCALL_DEFINE1(debug_syscall, int, enable)
+{
+	if (enable)
+		syscall_debug_enable = 1;
+	else
+		syscall_debug_enable = 0;
+
+	return 0;
+}
+
+
 #ifdef CONFIG_COMPAT
 struct compat_sysinfo {
 	s32 uptime;

4 内核使用系统调用

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 8f0e68e..c4f1a58 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -1033,4 +1033,25 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
 	 /* OTHER_WRITABLE?  Generally considered a bad idea. */		\
 	 BUILD_BUG_ON_ZERO((perms) & 2) +					\
 	 (perms))
+
+#define syscall_debug(...)				\
+({										\
+	 extern int syscall_debug_enable;	\
+	 if (syscall_debug_enable)			\
+		pr_func(__VA_ARGS__);			\
+})
+
+#define syscall_debug_enable()			\
+({										\
+	 extern int syscall_debug_enable;	\
+	 syscall_debug_enable = 1			\
+})
+
+#define syscall_debug_disable()			\
+({										\
+	 extern int syscall_debug_enable;	\
+	 syscall_debug_enable = 0			\
+})
+
+
 #endif

直接在系统调用接口 里 像prink一样使用这个接口

如:brk系统调用

syscall_debug(" brk  0x%llx\n", brk);

 

5 开关实现

内核里要打印的地方使用enable函数,然后任性打印,完事后使用disable函数

应用层实现

明确系统调用号

#define __NR_debug_syscall 295

使用接口

     #include
       #include    /* For SYS_xxx definitions */

       long syscall(long number, ...);

 

比如开启打印

syscall(__NR_debug_syscall, 1);

关闭打印

syscall(__NR_debug_syscall, 0);

 

二 使用strace工具

平台aarch64

下载源码https://github.com/strace/strace

解压进入目录

执行

./bootstrap

sudo ./configure --prefix=/xxx/strace/output-aarch64/ --host=aarch64-linux CC=/xxx/bin/aarch64-linux-gnu-gcc LD=/xxx/bin/aarch64-linux-gnu-ld --enable-mpers=no

sudo make LDFLAGS+='-static -pthread'    静态编译,如果不需要静态编译直接make

make install

生成如下tree output-aarch64/
output-aarch64/
├── bin
│   ├── strace
│   ├── strace-graph
│   └── strace-log-merge
└── share
    └── man
        └── man1
            ├── strace.1
            └── strace-log-merge.1

4 directories, 5 files

将strace工具放根文件系统就可以使用了

来追一下

 ./strace /mnt/my_fork
execve("/mnt/my_fork", ["/mnt/my_fork"], 0x7fff6c5680 /* 8 vars */) = 0
brk(NULL)                               = 0x28151000
faccessat(AT_FDCWD, "/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/tls/aarch64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/lib/tls/aarch64", 0x7febd1b840, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/lib/tls", 0x7febd1b840, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/aarch64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/lib/aarch64", 0x7febd1b840, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0h\370\1\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=15355504, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f923e7000
mmap(NULL, 1360488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f92273000
mprotect(0x7f923a6000, 65536, PROT_NONE) = 0
mmap(0x7f923b6000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x133000) = 0x7f923b6000
mmap(0x7f923bc000, 12904, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f923bc000
close(3)                                = 0
mprotect(0x7f923b6000, 16384, PROT_READ) = 0
mprotect(0x410000, 4096, PROT_READ)     = 0
mprotect(0x7f923eb000, 4096, PROT_READ) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f923e7c20) = 1254
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x5, 0x1), ...}) = 0
=====child=====
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1254, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
brk(NULL)                               = 0x28151000
brk(0x28173000)                         = 0x28173000
write(1, "=====parent=====\n", 17=====parent=====
)      = 17
nanosleep({tv_sec=1, tv_nsec=0}, 0x7febd1c680) = 0
exit_group(0)                           = ?
+++ exited with 0 +++

=========================================================================

编译方法也可以使用参考的方法

vi build_static_example.sh

修改BUILDFLAG="--prefix=/xxx/strace/output-aarch64/ --host=aarch64-linux CC=/xxx/bin/aarch64-linux-gnu-gcc LD=/xxx/bin/aarch64-linux-gnu-ld --enable-mpers=no"

修改CC=“/xxx/bin/aarch64-linux-gnu-gcc”

在CFLAGS中添加 -pthread

sudo执行脚本

 

 

 

 

 

你可能感兴趣的:(C/C++,linux)