Liping Zou bio photo

Liping Zou

An Android Developer

Email Twitter Instagram Github

本次已经是OS的第五次实验了,这次要做的内容有:

用Bochs调试工具跟踪Linux 0.11的地址翻译(地址映射)过程,了解IA-32和Linux 0.11的内容管理机制;

在Ubuntu上编写多进程的生产者—消费者程序,用共享内存做缓冲区;

在信号量实验的基础上,为Linux 0.11增加共享内存功能,并将生产者—消费者程序移植到Linux 0.11。

第一个内容,跟踪地址的翻译过程。指导书上的顺序是有一点乱的。这个过程是比较机械的,下面主要是截图说明每步的操作。

首先,是编译运行test.c。可以看到下图中的结果。

pic

接着是,按下“Ctrl+C”,进入调试状态,可以看见下图中的结果。

pic

接着使用“u/7”命令,可以看到上图中的反汇编结果,会发现ds:ox3004,说明了变量i保存在这个地址中。我们要找的便是他所对应的物理地址。根据Linux0.11的内存分段管理机制,可以知道的是ds寄存器中存的就是ds段的段选择子。

用“sreg”命令可以看到ds段的具体信息。段选择子是16位的寄存器,他的每一位都有特殊的含义。在下图中看到的ds的信息时0x0017,根据段选择子的各位的含义,可以知道TI值为1,所以我们要去LDT中去查询,索引值为2,表示是LDT的第三项(从0开始)。还是从下图中,我们可以看到ldtr的值和gdtr的值,ldtr的值显示了LDT表存放在GDT表的位置,即LDT在GDT的13号位置,而gdtr的值表示了GDT的位置,在物理地址的0x00005cb8。

pic

接下来,通过命令“0x00005cc8 + 13 * 8”。“xp /2w 0x00005cb8 + 13 * 8”,可以找到我们要找的那个表项,可以在下图中看到。根据我们刚才看到的内容的某种组合形式,我们可以知道LDT表的物理地址。

pic

再用命令“xp /8w 0x00f9c2d0”就可以看到LDT表的前4项内容了。根据我们之前得到的结果,我们知道我们要找的是LDT的第三项,即“0x00003fff 0x10c0f300“。根据这一项的某种组合,可以知道的是,ds段的基地址“0x10000000”。

好了,我们的ds段的线性地址已经可以得出了,是段基址+段内偏移,为0x10003004。可以用命令“calc ds:0x3004”可以验证这个结果,如下:

pic

接下来的工作是,根据这个线性地址得到物理地址了。

根据这个线性地址可以算出页目录号,页表号,页内偏移。0x10003004对应的页目录号是64,页表号时3,页内偏移是4。

通过命令“creg”可以看到,CR3寄存器的内容,这里存着页目录表的位置。根据上图可以看到CR3= 0x00000000,说明页目录表的基址是0. 通过命令“xp /68w 0”可以查看页目录表内容:

pic

而我们需要的内容可以通过这个命令“xp /w 0+64*4”来查看:

pic

可以对看到的这个内容进行分析,发现页表所在物理页框号为0x00fa7,通过0x00fa7000这个位置来查找3号页表项,通过命令“xp /w 0x00fa000+3*4”可以看到如下结果:

pic

线性地址0x10003004对应的物理页框号为0x00fa6,和页内偏移0x004接到一起,得到0x00fa6004,这就是变量i的物理地址。 可以通过两种方法验证。

第一种方法是用命令“page 0x10003004”,可以得到信息:“linear page 0x10003000 maps to physical page 0x00fa6000”。

第二种方法是用命令“xp /w 0x00fa7004”,可以看到:

pic

现在,通过直接修改内存来改变i的值为0,命令是: setpmem 0x00fa6004 4 0,表示从0x00fa6004地址开始的4个字节都设为0。然后再用“c”命令继续Bochs的运行,可以看到test退出了,说明i的修改成功了。

pic

至于后面的两个内容,等到这周有空闲的时间再写吧。

报告:

1.根据我们得到的结果,我认为最重要的有一下几步:

(1)根据反汇编的结果,我们可以知道变量i处于ds段,那么我们通过命令查看ds寄存器的内容时(也即查看ds段的选择子时),要根据段选择子各个二进制位的定义得到一些信息,比如我们要查找LDT表而非GDT表,这步比较重要,结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<bochs:4> u /7
10000063: (                    ): cmp dword ptr ds:0x3004, 0x00000000 ; 833d0430000000
1000006a: (                    ): jz .+0x00000004           ; 7404
1000006c: (                    ): jmp .+0xfffffff5          ; ebf5
1000006e: (                    ): add byte ptr ds:[eax], al ; 0000
10000070: (                    ): xor eax, eax              ; 31c0
10000072: (                    ): jmp .+0x00000000          ; eb00
10000074: (                    ): leave                     ; c9
<bochs:5> sreg
cs:s=0x000f, dl=0x00000002, dh=0x10c0fa00, valid=1
ds:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=3
ss:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
es:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
fs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
gs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
ldtr:s=0x0068, dl=0xc2d00068, dh=0x000082dd, valid=1
tr:s=0x0060, dl=0xc2e80068, dh=0x00008bdd, valid=1
gdtr:base=0x00005cb8, limit=0x7ff
idtr:base=0x000054b8, limit=0x7ff

(2) 通过sreg命令看到ldtr的值,即LDT在GDT中的描述符的索引。GDT的位置已经由gdtr明确给出,知道了GDT的位置和我们要找的LDT描述符在GDT中的索引值,就可以找到我们要找的描述符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<bochs:5> sreg
cs:s=0x000f, dl=0x00000002, dh=0x10c0fa00, valid=1
ds:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=3
ss:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
es:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
fs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
gs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
ldtr:s=0x0068, dl=0xc2d00068, dh=0x000082dd, valid=1
tr:s=0x0060, dl=0xc2e80068, dh=0x00008bdd, valid=1
gdtr:base=0x00005cb8, limit=0x7ff
idtr:base=0x000054b8, limit=0x7ff
<bochs:6> xp /32w 0x00005cb8
[bochs]:
0x00005cb8 <bogus+       0>: 0x000000000x000000000x00000fff0x00c09a00
0x00005cc8 <bogus+      16>: 0x00000fff0x00c093000x000000000x00000000
0x00005cd8 <bogus+      32>: 0xa44800680x000089010xa43000680x00008201
0x00005ce8 <bogus+      48>: 0xf2e800680x000089ff0xf2d000680x000082ff
0x00005cf8 <bogus+      64>: 0xb2e800680x000089fa0xb2d000680x000082fa
0x00005d08 <bogus+      80>: 0xf2e800680x000089fb0xf2d000680x000082fb
0x00005d18 <bogus+      96>: 0xc2e800680x00008bdd0xc2d000680x000082dd
0x00005d28 <bogus+     112>: 0xe2e800680x000089e10xe2d000680x000082e1

(3)根据上面的描述符找到了LDT表的起始地址,和我们要找的描述符在这个LDT中的偏移量,就能知道ds段的描述符了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<bochs:10> xp /8w 0x00ddc2d0
[bochs]:
0x00ddc2d0 <bogus+       0>: 0x000000000x000000000x000000020x10c0fa00
0x00ddc2e0 <bogus+      16>: 0x00003fff0x10c0f3000x000000000x00ddd000
<bochs:11> sreg
cs:s=0x000f, dl=0x00000002, dh=0x10c0fa00, valid=1
ds:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=3
ss:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
es:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
fs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
gs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
ldtr:s=0x0068, dl=0xc2d00068, dh=0x000082dd, valid=1
tr:s=0x0060, dl=0xc2e80068, dh=0x00008bdd, valid=1
gdtr:base=0x00005cb8, limit=0x7ff
idtr:base=0x000054b8, limit=0x7ff

(4)知道了变量i的线性地址,进行线性地址到物理地址的映射时,要根据线性地址的各个位的含义找到页目录表和页表,再进行地址翻译。

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
<bochs:31> creg
CR0=0x8000001b: PG cd nw ac wp ne ET TS em MP PE
CR2=page fault laddr=0x10002fac
CR3=0x00000000
    PCD=page-level cache disable=0
    PWT=page-level writes transparent=0
CR4=0x00000000: osxmmexcpt osfxsr pce pge mce pae pse de tsd pvi vme
<bochs:32> xp/68w 0
[bochs]:
0x00000000 <bogus+       0>: 0x000010270x000020070x000030070x00004027
0x00000010 <bogus+      16>: 0x000000000x0002a6bc0x000000000x00000000
0x00000020 <bogus+      32>: 0x000000000x000000000x000000000x00000000
0x00000030 <bogus+      48>: 0x000000000x000000000x000000000x00000000
0x00000040 <bogus+      64>: 0x00ffe0270x000000000x000000000x00000000
0x00000050 <bogus+      80>: 0x000000000x000000000x000000000x00000000
0x00000060 <bogus+      96>: 0x000000000x000000000x000000000x00000000
0x00000070 <bogus+     112>: 0x000000000x000000000x000000000x00000000
0x00000080 <bogus+     128>: 0x00fa00270x000000000x000000000x00000000
0x00000090 <bogus+     144>: 0x000000000x000000000x000000000x00000000
0x000000a0 <bogus+     160>: 0x000000000x000000000x000000000x00000000
0x000000b0 <bogus+     176>: 0x000000000x000000000x000000000x00fa2027
0x000000c0 <bogus+     192>: 0x00fa50270x000000000x000000000x00000000
0x000000d0 <bogus+     208>: 0x000000000x000000000x000000000x00000000
0x000000e0 <bogus+     224>: 0x000000000x000000000x000000000x00000000
0x000000f0 <bogus+     240>: 0x000000000x000000000x000000000x00fa7027
0x00000100 <bogus+     256>: 0x00da30270x000000000x000000000x00000000
<bochs:33> xp/w 0+64*4
[bochs]:
0x00000100 <bogus+       0>: 0x00da3027
<bochs:34> xp/w 0x00da3000+3*4
[bochs]:
0x00da300c <bogus+       0>: 0x00da2067
<bochs:35> xp/w 0x00da2004
[bochs]:
0x00da2004 <bogus+       0>: 0x12345678

我的跟踪地址映射的过程如下:

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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
open@open-Lenovo ~/oslab $./dbg-asm
========================================================================
                       Bochs x86 Emulator 2.3.7
               Build from CVS snapshot, on June 3, 2008
========================================================================
00000000000i[     ] reading configuration from ./bochs/bochsrc.bxrc
00000000000i[     ] installing x module as the Bochs GUI
00000000000i[     ] using log file ./bochsout.txt
Next at t=0
(0) [0xfffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b         ; ea5be000f0
<bochs:1> c
^CNext at t=899505258
(0) [0x00dcf06a] 000f:0000006a (unk. ctxt): jz .+0x00000004 (0x10000070) ; 7404
<bochs:2> n
Next at t=899505259
(0) [0x00dcf06c] 000f:0000006c (unk. ctxt): jmp .+0xfffffff5 (0x10000063) ; ebf5
<bochs:3> n
Next at t=899505260
(0) [0x00dcf063] 000f:00000063 (unk. ctxt): cmp dword ptr ds:0x3004, 0x00000000 ; 833d0430000000
<bochs:4> u /7
10000063: (                    ): cmp dword ptr ds:0x3004, 0x00000000 ; 833d0430000000
1000006a: (                    ): jz .+0x00000004           ; 7404
1000006c: (                    ): jmp .+0xfffffff5          ; ebf5
1000006e: (                    ): add byte ptr ds:[eax], al ; 0000
10000070: (                    ): xor eax, eax              ; 31c0
10000072: (                    ): jmp .+0x00000000          ; eb00
10000074: (                    ): leave                     ; c9
<bochs:5> sreg
cs:s=0x000f, dl=0x00000002, dh=0x10c0fa00, valid=1
ds:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=3
ss:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
es:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
fs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
gs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
ldtr:s=0x0068, dl=0xc2d00068, dh=0x000082dd, valid=1
tr:s=0x0060, dl=0xc2e80068, dh=0x00008bdd, valid=1
gdtr:base=0x00005cb8, limit=0x7ff
idtr:base=0x000054b8, limit=0x7ff
<bochs:6> xp /32w 0x00005cb8
[bochs]:
0x00005cb8 <bogus+       0>: 0x000000000x000000000x00000fff0x00c09a00
0x00005cc8 <bogus+      16>: 0x00000fff0x00c093000x000000000x00000000
0x00005cd8 <bogus+      32>: 0xa44800680x000089010xa43000680x00008201
0x00005ce8 <bogus+      48>: 0xf2e800680x000089ff0xf2d000680x000082ff
0x00005cf8 <bogus+      64>: 0xb2e800680x000089fa0xb2d000680x000082fa
0x00005d08 <bogus+      80>: 0xf2e800680x000089fb0xf2d000680x000082fb
0x00005d18 <bogus+      96>: 0xc2e800680x00008bdd0xc2d000680x000082dd
0x00005d28 <bogus+     112>: 0xe2e800680x000089e10xe2d000680x000082e1
<bochs:7> xp /32w 0x00005cb8
[bochs]:
0x00005cb8 <bogus+       0>: 0x000000000x000000000x00000fff0x00c09a00
0x00005cc8 <bogus+      16>: 0x00000fff0x00c093000x000000000x00000000
0x00005cd8 <bogus+      32>: 0xa44800680x000089010xa43000680x00008201
0x00005ce8 <bogus+      48>: 0xf2e800680x000089ff0xf2d000680x000082ff
0x00005cf8 <bogus+      64>: 0xb2e800680x000089fa0xb2d000680x000082fa
0x00005d08 <bogus+      80>: 0xf2e800680x000089fb0xf2d000680x000082fb
0x00005d18 <bogus+      96>: 0xc2e800680x00008bdd0xc2d000680x000082dd
0x00005d28 <bogus+     112>: 0xe2e800680x000089e10xe2d000680x000082e1
<bochs:8> xp /2w 0x00005cb8+13*8
[bochs]:
0x00005d20 <bogus+       0>: 0xc2d000680x000082dd
<bochs:9> sreg
cs:s=0x000f, dl=0x00000002, dh=0x10c0fa00, valid=1
ds:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=3
ss:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
es:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
fs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
gs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
ldtr:s=0x0068, dl=0xc2d00068, dh=0x000082dd, valid=1
tr:s=0x0060, dl=0xc2e80068, dh=0x00008bdd, valid=1
gdtr:base=0x00005cb8, limit=0x7ff
idtr:base=0x000054b8, limit=0x7ff
<bochs:10> xp /8w 0x00ddc2d0
[bochs]:
0x00ddc2d0 <bogus+       0>: 0x000000000x000000000x000000020x10c0fa00
0x00ddc2e0 <bogus+      16>: 0x00003fff0x10c0f3000x000000000x00ddd000
<bochs:11> sreg
cs:s=0x000f, dl=0x00000002, dh=0x10c0fa00, valid=1
ds:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=3
ss:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
es:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
fs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
gs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
ldtr:s=0x0068, dl=0xc2d00068, dh=0x000082dd, valid=1
tr:s=0x0060, dl=0xc2e80068, dh=0x00008bdd, valid=1
gdtr:base=0x00005cb8, limit=0x7ff
idtr:base=0x000054b8, limit=0x7ff
<bochs:12> calc ds:0x3004
0x10003004 268447748
<bochs:13> creg
CR0=0x8000001b: PG cd nw ac wp ne ET TS em MP PE
CR2=page fault laddr=0x10002fac
CR3=0x00000000
    PCD=page-level cache disable=0
    PWT=page-level writes transparent=0
CR4=0x00000000: osxmmexcpt osfxsr pce pge mce pae pse de tsd pvi vme
<bochs:14> xp /68w 0
[bochs]:
0x00000000 <bogus+       0>: 0x000010270x000020070x000030070x00004027
0x00000010 <bogus+      16>: 0x000000000x0002a6bc0x000000000x00000000
0x00000020 <bogus+      32>: 0x000000000x000000000x000000000x00000000
0x00000030 <bogus+      48>: 0x000000000x000000000x000000000x00000000
0x00000040 <bogus+      64>: 0x00ffe0270x000000000x000000000x00000000
0x00000050 <bogus+      80>: 0x000000000x000000000x000000000x00000000
0x00000060 <bogus+      96>: 0x000000000x000000000x000000000x00000000
0x00000070 <bogus+     112>: 0x000000000x000000000x000000000x00000000
0x00000080 <bogus+     128>: 0x00fa00270x000000000x000000000x00000000
0x00000090 <bogus+     144>: 0x000000000x000000000x000000000x00000000
0x000000a0 <bogus+     160>: 0x000000000x000000000x000000000x00000000
0x000000b0 <bogus+     176>: 0x000000000x000000000x000000000x00fa2027
0x000000c0 <bogus+     192>: 0x00fa50270x000000000x000000000x00000000
0x000000d0 <bogus+     208>: 0x000000000x000000000x000000000x00000000
0x000000e0 <bogus+     224>: 0x000000000x000000000x000000000x00000000
0x000000f0 <bogus+     240>: 0x000000000x000000000x000000000x00fa7027
0x00000100 <bogus+     256>: 0x00dce0270x000000000x000000000x00000000
<bochs:15> xp /w 0+64*4
[bochs]:
0x00000100 <bogus+       0>: 0x00dce027
<bochs:16> xp /w 0x00dce000+3*4            
[bochs]:
0x00dce00c <bogus+       0>: 0x00dcd067
<bochs:17> page 0x10003004
linear page 0x10003000 maps to physical page 0x00dcd000
<bochs:18> xp /w 0x00dcd004
[bochs]:
0x00dcd004 <bogus+       0>: 0x12345678
<bochs:19> setpmem 0x00dcd004 4 0
<bochs:20> c
  1. test.c退出后,如果马上再运行一次,并再进行地址跟踪,你发现有哪些异同?为什么?
1
2
3
4
5
6
7
8
9
10
11
<bochs:15> xp /w 0+64*4
[bochs]:
0x00000100 <bogus+       0>: 0x00dce027
<bochs:16> xp /w 0x00dce000+3*4            
[bochs]:
0x00dce00c <bogus+       0>: 0x00dcd067
<bochs:17> page 0x10003004
linear page 0x10003000 maps to physical page 0x00dcd000
<bochs:18> xp /w 0x00dcd004
[bochs]:
0x00dcd004 <bogus+       0>: 0x12345678

在查看页表的物理内存地址时出现了不同。因为系统是以页为单位分配的,而这种分配是随机的,具有不确定性。