本文介绍调试系统调用的两种方法
一 自定义创建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
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执行脚本