内核调试--VFS路径名查找

发布于 2022-10-15 04:04:52 字数 4357 浏览 40 评论 0

经过一个月对Linux vfs层的代码进行阅读总算有点眉目,今天这些天的心得写到这里,希望有大侠能够指正我的理解误区,现在这里拜谢了。
这篇笔记主要是记录在Linux2.6.37 的UML模式中调试vfs中的路径名查找的过程
1.搭建UML环境,
a.至少需要一个内核,文件系统(你可以手工制作文件系统)
我的内核采用Linux 2.6.37 文件系统从网上下载的现成的叫DSLxxx具体叫什么我忘了,因为下载下来我把它改了一个名字
b.这一部分至关重要,是后面的调试关键,我在这里也费了几乎一个星期的时间,废话少说,先介绍难点。最困难的不是选择编译选项而是内核在编译的时候使用优化默认O2,导致一些代码的次序改变,单步的时候乱跳,让你不知其所以然。我们先看看一个文件 内核文件夹下的scripts/Makefile.build 前几行
  1. # ==========================================================================
  2. # Building
  3. # ==========================================================================

  4. src := $(obj)

  5. PHONY := __build
  6. __build:

  7. # Init all relevant variables used in kbuild files so
  8. # 1) they have correct type
  9. # 2) they do not inherit any value from the environment
  10. obj-y :=
  11. obj-m :=
  12. lib-y :=
  13. lib-m :=
  14. always :=
  15. targets :=
  16. subdir-y :=
  17. subdir-m :=
  18. EXTRA_AFLAGS   :=
  19. EXTRA_CFLAGS   :=
  20. EXTRA_CPPFLAGS :=
  21. EXTRA_LDFLAGS  :=
  22. asflags-y  :=
  23. ………………
复制代码看到EXTRA_CFLAGS这个,具体是干啥,可以自己去查查
我们不能关闭内核优化选项,不然需要修改很多代码,我们在我们需要的调试的的模块部分
让内核去掉优化,我们可以这样做。我要对文件系统进行调试,打开fs/Makefile 在文件开头加入 EXTRA_CFLAGS += -O0.文件如下

1.png (19.17 KB, 下载次数: 72)

下载附件

2011-06-17 14:01 上传


接下来 执行
make menuconfig ARCH=um
配置内核选项,注意打开内核的调试选项,(在kernel hacking --->kernel debug--->compile ...debug info 记得不是很清楚)
make ARCH=um
在内核目录中会生成一个叫 linux可执行文件,接下来可以新建一个文件夹,把内核源码目录下生成的linux 文件和根文件系统放到一起如下

2.png (20.62 KB, 下载次数: 21)

下载附件

2011-06-17 14:05 上传


2.调试内核。
a.在调试内核的时候你可以选择多种方法调试,一般使用下面命令
gdb ./linux ubda=root_fs(ubda=你的文件系统的路径)
上述调试方法会有一个问题,当你的内核完全启动完毕,即启动到命令行的时候,你无法产生断点,除非你在执行gdb >run命令前,在某一个函数前打了断点,但是在启动过程中,可能会引起无数的断点影响调试效果。
最开始我准备调试link_path_walk函数,在这里打了一个断点,启动的时候内核会查找文件,导致断点成千上万,我禁止断点后,启动到命令行了,无法使gdb产生断点。导致调试转了很大的弯路。
现在使用另外一种方法调试,gdb 调试进程
首先启动要调试的内核,对于上面,执行下面的命令
./linux ubda=root_fs  效果如下图

3.png (44.12 KB, 下载次数: 20)

下载附件

2011-06-17 14:08 上传

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

那一片橙海, 2022-10-22 04:04:52

本帖最后由 jjinl 于 2011-06-17 14:19 编辑

其次查找上述UML的进程PID如下图,注意需要pid最小的那一个

4.png (17.23 KB, 下载次数: 29)

下载附件

2011-06-17 14:13 上传



接着使用gdb调试,命令:”gdb program xxx”其中xxx为名为linux的进程中pid最小的pid号,操作如下图

5.png (52.29 KB, 下载次数: 19)

下载附件

2011-06-17 14:13 上传



现在运行UML的那个终端已被停止,我们在link_path_walk打一个断点,如下图

6.png (33.26 KB, 下载次数: 21)

下载附件

2011-06-17 14:14 上传



接下来在gdb中执行 continue,如下图

7.png (33 KB, 下载次数: 22)

下载附件

2011-06-17 14:14 上传



在上图中,他自动在link_path_walk停住,如果没有停住,先检查断点是否正确,你可以在uml中输入,例如ls命令,就会使之跑到这里
调试效果如下

8.png (42.46 KB, 下载次数: 19)

下载附件

2011-06-17 14:15 上传


9.png (55.33 KB, 下载次数: 18)

下载附件

2011-06-17 14:15 上传


10.png (46.23 KB, 下载次数: 27)

下载附件

2011-06-17 14:15 上传



下个星期补充....link_path_walk函数流程

风月客 2022-10-22 04:04:52

回复 1# jjinl

感谢 LZ 分享。

被翻牌 2022-10-22 04:04:52

我们主要调试的函数是在fs/namei.c 的817行的link_path_walk,,在调试之前,为了便于说明一些情况,我们对这个源码进行小幅度的修改,输出当前进程的task_struct,代码如下

1.png (18.82 KB, 下载次数: 25)

下载附件

2011-06-20 11:39 上传



接下来我们重点讲述这个函数,

2.png (32.67 KB, 下载次数: 17)

下载附件

2011-06-20 11:39 上传



上述一个断点产生在link_path_walk上,在执行路径名到inode转换前,需要对相关结构进行初始化,包括查找的起始路径,查找的标志,这些信息都暂时存放在struct nameidate *nd中,这个结果内容如下

  1. struct nameidata {
  2.         struct path        path;
  3.         struct qstr        last;
  4.         struct path        root;
  5.         unsigned int        flags;
  6.         int                last_type;
  7.         unsigned        depth;
  8.         char *saved_names[MAX_NESTED_LINKS + 1];
  9.         /* Intent data */
  10.         union {
  11.                 struct open_intent open;
  12.         } intent;
  13. };

复制代码接下来我们打印一下,看看nd中到底有什么

3.png (38.53 KB, 下载次数: 25)

下载附件

2011-06-20 11:39 上传



我们知道要查找的文件是“/dev/initctl”,是绝对路径的查找,上图中第一部分是nd中的内容。其中
nd->path->mnt                =0xa0524e0
nd->path->dentry                =0x9c49214
pcur->fs->pwd->mnt        =0xa0524e0
pcur->fs->pwd->dentry        =0x9c49214
pcur->fs->root->mnt        =0xa0524e0
pcur->fs->root->dentry        =0x9c49214
$esp                        =0xa05cb4c
Pcur                        =0xa05bb20
有没有发现nd中的path的内容和当前的进程的fs->pwd和root是一样的,这是这样的在查找之前对判断路径名的第一个字母如果是”/”,则把当前进程的fs->root赋值给nd->path;如果是”.”则把当前进程的fs->pwd赋值给nd->path,因为我的系统当前在根目录下所以会有,fs->root=fs->pwd.最后我打印出寄存器esp的内容和当前函数中的局部变量pcur的地址如下图。大家有没有发现esp和当前函数的局部变量的关系,当前处于内核态,esp指向内核栈,这些局部变量使用当前进程的内核栈,内核栈的很小,使用的时候应当注意

4.png (14.98 KB, 下载次数: 19)

下载附件

2011-06-20 11:39 上传



言归正传,在826行处理路径名最前面的任何“/”接下来准备取出第一个路径分量,在inode中查找对应的文件(文件夹)如下图,831行,

5.png (27.21 KB, 下载次数: 22)

下载附件

2011-06-20 11:39 上传



对取出来的路径分量进行散列计算,接下来判断路径分量中的路径名是否为特殊的文件名如”.”,”..”

6.png (22.56 KB, 下载次数: 18)

下载附件

2011-06-20 11:39 上传



838行的do_lookup查找对应this这个字符串在nd->path中对应的路径分量,结果放在next中,接着888行取出对应路径分量的inode
.........

維他命╮ 2022-10-22 04:04:52

good

酒几许 2022-10-22 04:04:52

强烈支持一下

々眼睛长脚气 2022-10-22 04:04:52

好文,顶。
最近弄了个UML,流程和Lz一样。但是每次只能成功启动一次。启动进入shell 后我init 0关机后。再次启动
./linux ubda=root_fs
就挂了,出错如下,帮忙看看,谢谢

[img]EXT3-fs (ubda): error: couldn't mount because of unsupported optional features (240)
EXT2-fs (ubda): error: couldn't mount because of unsupported optional features (240)
EXT4-fs (ubda): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext4 filesystem) readonly on device 98:0.
                Welcome to Fedora
Starting udev: udevd[232]: failed to create queue file: No such file or directory

udevd[232]: error creating queue file

error sending message: Connection refused
udevadm[235]: error sending message: Connection refused

[FAILED]
Setting hostname localhost:  [  OK  ]
Checking filesystems
Checking all file systems.
[  OK  ]
Remounting root filesystem in read-write mode:  mount: can't find / in /etc/fstab or /etc/mtab
[FAILED]
mount: can't find / in /etc/fstab or /etc/mtab
Mounting local filesystems:  [  OK  ]
chmod: changing permissions of `/var/lib/random-seed': Read-only file system
rm: cannot remove `/var/run/utmp': Read-only file system
rm: cannot remove `/var/run/cron.reboot': Read-only file system
/etc/rc.d/rc.sysinit: line 593: /var/run/utmp: Read-only file system
touch: cannot touch `/var/log/wtmp': Read-only file system
touch: cannot touch `/var/log/btmp': Read-only file system
chgrp: changing group of `/var/run/utmp': Read-only file system
chgrp: changing group of `/var/log/wtmp': Read-only file system
chgrp: changing group of `/var/log/btmp': Read-only file system
chmod: changing permissions of `/var/run/utmp': Read-only file system
chmod: changing permissions of `/var/log/wtmp': Read-only file system
chmod: changing permissions of `/var/log/btmp': Read-only file system
rm: cannot remove `/tmp/.ICE-unix': Read-only file system
chown: changing ownership of `/tmp/.ICE-unix': Read-only file system
Enabling /etc/fstab swaps:  [  OK  ]
modprobe: FATAL: Could not load /lib/modules/2.6.38-124329-gebcb904/modules.dep: No such file or directory

mv: cannot move `/var/log/dmesg' to `/var/log/dmesg.old': Read-only file system
/etc/rc.d/rc.sysinit: line 651: /var/log/dmesg: Read-only file system
modprobe: FATAL: Could not load /lib/modules/2.6.38-124329-gebcb904/modules.dep: No such file or directory

Entering non-interactive startup
Starting auditd: modprobe: FATAL: Could not load /lib/modules/2.6.38-124329-gebcb904/modules.dep: No such file or directory

[FAILED]
Starting system logger: Can't open or create /var/run/syslogd.pid.
Can't write pid.
[img][/img][/img]

谜兔 2022-10-22 04:04:52

有时间我也搞个UML试试,才听说这个东西

全部不再 2022-10-22 04:04:52

回复 7# 懂医术的厨师

你好,请问下以上帖子中你提及的问题解决了吗?如何解决的啊,我也遇到了相似的问题,还望交流下,谢谢~!
   

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文