大家都知道lseek就是移动文件的读写位置, 也就是对应内核中file结构体中的某一个变量, 今天就是特别想看一下具体之间的关系.
软件就在于实践
首先需要有一个很方便调用lseek的环境, 这样才不会影响我们调试的兴趣, 希望能达到像python, matlab这样每个函数可以手动跑, 而不像c语言一样要编写, 然后编译, 然后执行, 然后再修改, 编译. gdb可以
- 先准备文件1.c, 前面的头文件很重要, 不能漏
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main()
{
return 0;
}
gcc 1.c -ggdb3
-ggdb3是为了能方便的使用宏
gdb ./a.out
b main
r
接下来会使用call open来打开文件, 但是如何找到我们将要打开的文件在内核中的file结构体的地址呢? kgtp
找到a.out进程号是1138
找到内核do_sys_open源代码
1012 long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
1013 {
1014 struct open_flags op;
1015 int lookup = build_open_flags(flags, mode, &op);
1016 struct filename *tmp = getname(filename);
1017 int fd = PTR_ERR(tmp);
(gdb)
1018
1019 if (!IS_ERR(tmp)) {
1020 fd = get_unused_fd_flags(flags);
1021 if (fd >= 0) {
1022 struct file *f = do_filp_open(dfd, tmp, &op, lookup);
1023 if (IS_ERR(f)) {
所以要在1023设置tracepoint找到f的值, 并且使用pid 1138来过滤, 总结就是要得到进程1138调用do_sys_open的时候的f的值
kgtp命令
tmp=`mktemp`; echo 'set pagination off
set confirm off
set circular-trace-buffer on
target remote /sys/kernel/debug/gtp
d
trace open.c:1023
actions
collect f
end
tstart' > $tmp; echo $tmp; cat $tmp; sudo gdb /usr/lib/debug/lib/modules/3.10.0-327.el7.x86_64/vmlinux -x $tmp
`f' has been optimized out, cannot use
但是发现f被优化, 只能找汇编地址来定位f的值
0xffffffff811dd7de <+238>: callq 0xffffffff811efdf0 <do_filp_open>
0xffffffff811dd7e3 <+243>: cmp $0xfffffffffffff000,%rax
所以tracepoint到0xffffffff811dd7e3
kgtp的命令
tmp=`mktemp`; echo 'set pagination off
set confirm off
set circular-trace-buffer on
target remote /sys/kernel/debug/gtp
d
trace *0xffffffff811dd7e3 if ((struct task_struct *)$current_task)->pid == 1138
actions
collect $rax
end
tstart' > $tmp; echo $tmp; cat $tmp; sudo gdb /usr/lib/debug/lib/modules/3.10.0-327.el7.x86_64/vmlinux -x $tmp
Tracepoint 1 at 0xffffffff811dd7e3: file fs/open.c, line 1023
回到gdb中手动调用call open
(gdb) call open("/root/1.c", O_WRONLY )
$5 = 7
回到kgtp中查看f的值
(gdb) p/x $rax
$3 = 0xffff88003ad2ee00
(gdb) tfind -1
(gdb) p ((struct file*)$3)->f_pos
$7 = 0
到gdb中call lseek
(gdb) call lseek(7, 1, 0)
$6 = 1
查看file结构体
p ((struct file*)$3)->f_pos
$9 = 1
到gdb中call lseek
(gdb) call lseek(7, 234, 0)
$7 = 234
查看file结构体
(gdb) p ((struct file*)$3)->f_pos
$10 = 234