本次已经是OS的第五次实验了,这次要做的内容有:
首先,是编译运行test.c。可以看到下图中的结果。
接着是,按下“Ctrl+C”,进入调试状态,可以看见下图中的结果。
接着使用“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。
接下来,通过命令“0x00005cc8 +13* 8”。“xp /2w 0x00005cb8 + 13 * 8”,可以找到我们要找的那个表项,可以在下图中看到。根据我们刚才看到的内容的某种组合形式,我们可以知道LDT表的物理地址。
再用命令“xp /8w 0x00f9c2d0”就可以看到LDT表的前4项内容了。根据我们之前得到的结果,我们知道我们要找的是LDT的第三项,即“0x00003fff 0x10c0f300“。根据这一项的某种组合,可以知道的是,ds段的基地址“0x10000000”。
好了,我们的ds段的线性地址已经可以得出了,是段基址+段内偏移,为0x10003004。可以用命令“calc ds:0x3004”可以验证这个结果,如下:
接下来的工作是,根据这个线性地址得到物理地址了。
根据这个线性地址可以算出页目录号,页表号,页内偏移。0x10003004对应的页目录号是64,页表号时3,页内偏移是4。
通过命令“creg”可以看到,CR3寄存器的内容,这里存着页目录表的位置。根据上图可以看到CR3= 0x00000000,说明页目录表的基址是0.
通过命令“xp /68w 0”可以查看页目录表内容:
而我们需要的内容可以通过这个命令“xp /w 0+64*4”来查看:
可以对看到的这个内容进行分析,发现页表所在物理页框号为0x00fa7,通过0x00fa7000这个位置来查找3号页表项,通过命令“xp /w 0x00fa000+3*4”可以看到如下结果:
线性地址0x10003004对应的物理页框号为0x00fa6,和页内偏移0x004接到一起,得到0x00fa6004,这就是变量i的物理地址。
可以通过两种方法验证。
第一种方法是用命令“page 0x10003004”,可以得到信息:“linear page 0x10003000 maps to physical page 0x00fa6000”。
第二种方法是用命令“xp /w 0x00fa7004”,可以看到:
现在,通过直接修改内存来改变i的值为0,命令是: setpmem 0x00fa6004 4 0,表示从0x00fa6004地址开始的4个字节都设为0。然后再用“c”命令继续Bochs的运行,可以看到test退出了,说明i的修改成功了。
至于后面的两个内容,等到这周有空闲的时间再写吧。
报告:
1.根据我们得到的结果,我认为最重要的有一下几步:
(1)根据反汇编的结果,我们可以知道变量i处于ds段,那么我们通过命令查看ds寄存器的内容时(也即查看ds段的选择子时),要根据段选择子各个二进制位的定义得到一些信息,比如我们要查找LDT表而非GDT表,这步比较重要,结果如下:
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
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中的索引值,就可以找到我们要找的描述符
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]:
0x00005cb8
0x00005cc8
0x00005cd8
0x00005ce8
0x00005cf8
0x00005d08
0x00005d18
0x00005d28
(3)根据上面的描述符找到了LDT表的起始地址,和我们要找的描述符在这个LDT中的偏移量,就能知道ds段的描述符了。
[bochs]:
0x00ddc2d0
0x00ddc2e0
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的线性地址,进行线性地址到物理地址的映射时,要根据线性地址的各个位的含义找到页目录表和页表,再进行地址翻译。
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]:
0x00000000
0x00000010
0x00000020
0x00000030
0x00000040
0x00000050
0x00000060
0x00000070
0x00000080
0x00000090
0x000000a0
0x000000b0
0x000000c0
0x000000d0
0x000000e0
0x000000f0
0x00000100
[bochs]:
0x00000100
[bochs]:
0x00da300c
[bochs]:
0x00da2004
我的跟踪地址映射的过程如下:
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
^CNext at t=899505258
(0) [0x00dcf06a] 000f:0000006a (unk. ctxt): jz .+0x00000004 (0x10000070) ; 7404
Next at t=899505259
(0) [0x00dcf06c] 000f:0000006c (unk. ctxt): jmp .+0xfffffff5 (0x10000063) ; ebf5
Next at t=899505260
(0) [0x00dcf063] 000f:00000063 (unk. ctxt): cmp dword ptr ds:0x3004, 0x00000000 ; 833d0430000000
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
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]:
0x00005cb8
0x00005cc8
0x00005cd8
0x00005ce8
0x00005cf8
0x00005d08
0x00005d18
0x00005d28
[bochs]:
0x00005cb8
0x00005cc8
0x00005cd8
0x00005ce8
0x00005cf8
0x00005d08
0x00005d18
0x00005d28
[bochs]:
0x00005d20
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]:
0x00ddc2d0
0x00ddc2e0
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
0x10003004 268447748
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]:
0x00000000
0x00000010
0x00000020
0x00000030
0x00000040
0x00000050
0x00000060
0x00000070
0x00000080
0x00000090
0x000000a0
0x000000b0
0x000000c0
0x000000d0
0x000000e0
0x000000f0
0x00000100
[bochs]:
0x00000100
[bochs]:
0x00dce00c
linear page 0x10003000 maps to physical page 0x00dcd000
[bochs]:
0x00dcd004
2. test.c退出后,如果马上再运行一次,并再进行地址跟踪,你发现有哪些异同?为什么?
[bochs]:
0x00000100
[bochs]:
0x00dce00c
linear page 0x10003000 maps to physical page 0x00dcd000
[bochs]:
0x00dcd004
在查看页表的物理内存地址时出现了不同。因为系统是以页为单位分配的,而这种分配是随机的,具有不确定性。