summaryrefslogtreecommitdiff
path: root/docs/debug/debug_slab.md
blob: b64dca8687cbc21143fcb4c542a1a37b3a9751b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# Debug

发现user_init加载之后无法正常跳转到shell

检查fork

添加调试信息
```cxx
printf("fork start\n");
int pid = fork();
printf("fork suceess, pid=%i\n", pid);
```
正常打印,fork()没有问题

尝试在 'exec(sh_path, argv);' 前后添加调试信息

该代码之前有输出,之后无输出

尝试解决exec.cc的问题

在exec()函数开头处添加调试信息

```CXX
        Drivers::uart_puts("Enter Exec\n");
        // Get Inode
        Inode *raw_ip = VFS::namei(path);
        if (!raw_ip)
            return -1;
        InodeGuard iguard(raw_ip);
```

没有输出

怀疑是系统注册的问题,但不可能,因为在实现shell之前的简易测试程序证明系统调用没有问题

尝试 GDB 调试

![alt text](debug_slab_1.png)

发现卡在 sret 返回的部分,跳转的地址没有问题,但是卡死,说明CPU没有跑飞,可能遇到了死循环

检查sys_exec()

通过在每行代码前后添加打印调试信息,发现问题出在这行代码:
```cxx
        kargv.args[i] = (char *)Slab::kmalloc(KernelArgv::MAX_ARG_LEN);
```
这行代码之后的打印信息没有输出,说明这里一直在执行!

检查Slab

像之前一样通过在每行代码前后添加打印调试信息,发现问题出在这里:
```cxx
for (uint i = 0; i < c->obj_count_per_slab - 1; i++)
        {
            // The content of the i-th object is i+1
            uint16 *ptr = (uint16 *)(base + i * c->obj_size);
            *ptr = i + 1;
        }
```
这段代码之前的信息可以输出,之后的不能输出,说明这里出问题了

在循环内部打印信息,发现调试信息刷屏

证明了在GDB里面看到的消息,并不是CPU跑到了某些神秘地址,而是一直卡在这个死循环!

这里出现了死循环,说明这里循环终止条件出了问题,根本原因需要排查

可能是错误的计算,导致这里成了ull的最大值,即使在 3 GHz CPU 上跑空循环,跑满 unsigned long long 最大值次数也需要 近千年。

怀疑之前这个值是0

添加代码:
```cxx
    if (c->obj_count_per_slab == 0)
        Drivers::uart_puts("it is 0");
```
证明猜测正确

这里检查发现这个值确实是0,但它为什么能是0呢?

可能是初始化的问题????

检查系统初始化main.cc

发现Slab确实没有初始化,导致c->obj_count_per_slab这个值一直是0!

初始化!

正常加载shell

说明 ELF 加载,只读 FAT32 文件系统 正常实现

该bug解决