Advanced Debugging
About AdvDbg Consult Train Services Products Tools Community Contact  
欢迎光临 高端调试 登录 | 注册 | FAQ
 
  ACPI调试
Linux内核调试
Windows内核调试
 
  调试战役
调试原理
新工具观察
 
  Linux
Windows Vista
Windows
 
  Linux驱动
WDF
WDM
 
  PCI Express
PCI/PCI-X
USB
无线通信协议
 
  64位CPU
ARM
IA-32
  CPU Info Center
 
  ACPI标准
系统认证
Desktop
服务器
 
  Embedded Linux
嵌入式开发工具
VxWorks
WinCE
嵌入式Windows
 
  格蠹调试套件(GDK)
  格蠹学院
  小朱书店
  老雷的微博
  《软件调试》
  《格蠹汇编》
  《软件调试(第二版)》
沪ICP备11027180号-1

Windows内核调试

帖子发起人: sgyhm   发起时间: 2007-04-13 20:49 下午   回复: 3

Print Search
帖子排序:    
   2007-04-13, 20:49 下午
sgyhm 离线,最后访问时间: 2007/6/24 9:14:32 sgyhm

发帖数前75位
注册: 2007-02-09
发 贴: 16
请教advdbg和Ramond 老师这实在是太令人费解了。
Reply Quote

 

是这样的,我想问下Windows 在Intel Protection Mode下工作的问题。
在指令手册第三卷system programming 可以看到,通常GDT只有一个,而LDT可以有很多的。
本来我很天真地想:
那么我有多少个进程在running 就应该有多少个LDT才对。
于是我打开softice, 输入GDT
结果只有一个被标为LDT,参考了using softice,只看到如下一段:
Under Winnt , LDT are per process data structures and are only used for virtual dos machines.
The 16 bit WOW box is executed within a NTVDM process and has an LDT.
Like Windows 3.1 the LDT for a WOW contains the selectors for every 16 bit proteced mode code and data segment for each 16 bit application or DLL that is loaded.  It also contains the selectors for each task database, module database, local heaps, global allocation, and all USER and GDI objects that require the creation of a selector.  Under a WOW, because the number of selectors needed can be quite large, a full LDT is created with a majority of the entries initially reserved.  These reserved selectors are allocated as needed.  Under a non-WOW VDM, the size of the LDT is significant smaller.

老实说我不知道它在说什么,最后的结果就是我只能看到一个LDT.
这实在太奇怪了,请问难道windows不用LDT?

第二个奇怪的是
GDTbase=80036000     Limit=03FF
0008     Code32     Base=00000000     Lim=FFFFFFFF     DPL=0     P     R
0010     Data32     Base=00000000     Lim=FFFFFFFF     DPL=0     P     R
001B     Code32     Base=00000000     Lim=FFFFFFFF     DPL=3     P     R
0023     Data32     Base=00000000     Lim=FFFFFFFF     DPL=3     P     R
0028     TSS32     Base=8000B000     Lim=000020AB     DPL=0     P     B
0030     Data32     Base=FFDFF000     Lim=00001FFF     DPL=0     P     R
003B     Data32     Base=7FFDE000     Lim=00000FFF     DPL=3     P     R
0043     Data16     Base=00000400     Lim=0000FFFF     DPL=3     P     R
0048     LDT     Base=E156C000     Lim=0000FFEF     DPL=0     P    

显然code32 data32也就是从0008-001b
这段是固定的,所谓的flat mode,可是真的不明白,
明明规定4g地址只有低2g空间是用户可以访问的。
高2G操作系统用,也就是ring0才能访问。
那么这里有两个Code32,一个是ring3(0008),一个是ring0(001B)
那么同一句汇编指令,访问32位偏移0xYYYYYYYY地址,
操作系统怎么知道是访问上面那个还是下面那个,
有两个段,这两个段根本都覆盖了4g空间,却具有不同的权限,dpl 不同,
同一个地址到底要怎么解释呢?

晕眩。


IP 地址: 已记录   报告
   2007-04-13, 22:38 下午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: 请教advdbg和Ramond 老师这实在是太令人费解了。
Reply Quote
所谓flat mode,就是整个进程的代码和数据都使用一个段,这个段的基地址为0。这样同一进程内的不同模块的代码相互调用时就不必担心段的差异。在16位时,同一进程内的不同的函数可能使用不同的代码段,因此函数调用时要考虑是否跨段,跨段的一定要使用所谓长调用(far call),段内的调用叫near call。平坦模式不再有这样的问题,进程内不再有段的差异(缝隙),因此叫平坦模式。

对于最后一个问题:
首先会根据段寄存器中的段选择子在GDT或LDT中找到一个描述符,取其中的基地值,加上这个偏移,等到所谓的线性地址,线性地址大于0x80000000便是一个内核的地址。其实现代操作系统主要使用页属性来标识权限。根据线性地址,找到对应的PTE,判断其权限。

IP 地址: 已记录   报告
   2007-04-14, 09:20 上午
sgyhm 离线,最后访问时间: 2007/6/24 9:14:32 sgyhm

发帖数前75位
注册: 2007-02-09
发 贴: 16
Re: 请教advdbg和Ramond 老师这实在是太令人费解了。
Reply Quote


  是的是的,我已经非常非常清楚,您所说的:
首先会根据段寄存器中的段选择子在GDT或LDT中找到一个描述符,取其中的基地值,加上这个偏移,等到所谓的线性地址

其实Intel 指令手册第三卷中关于保护模式已经详细地说明了这个问题,我觉得我自己是比较清楚了。
关于PTE,页属性我也都看了,我觉得我非常清楚了,


让我很混乱的是:
所谓Windows Flat内存模式,Undocument Winnt上指示说那代表其实windows是不分段的,只使用段偏移,
段选择子只加载一次,如下
0008     Code32     Base=00000000     Lim=FFFFFFFF     DPL=0     P     R
0010     Data32     Base=00000000     Lim=FFFFFFFF     DPL=0     P     R
001B     Code32     Base=00000000     Lim=FFFFFFFF     DPL=3     P     R
0023     Data32     Base=00000000     Lim=FFFFFFFF     DPL=3     P     R
这前面四个段,就是不分段的证明。

原文是这么写的:
首先我们来看 Windows NT 是如何为进程提供平面地址空间的。 通过前面一节我们知道,Intel 的 80386 既提供了分段又提供了分页。那么 Windows NT 又是如何只提供平面内存而不提供分段的呢?关闭了分段吗?80386 上的分段可是关不掉的。 但是操作系统可以只加载一次段寄存器然后再后面的指令里只指定偏移,这在 80386 处理器上是可以做到的。Windows NT 就是这么干的。Windows NT 初始化所有的寄存器使之指向 0 到 4GB 的内存单元。页就是说基址设为 0,界限值设为 4GB。 CS、SS、DS 和 ES 都用指向 0 至 4GB 内存单元的独立的描述符初始化。现在,应用程序就可以只用32位偏移了。 最后,我们看到的就是32位平面地址空间。Windows NT 下的32位应用程序不用改变任何的段寄存器。

让我疑惑的是同一个4g地址为什么要有两个同样的段Code32和Data32,是不是当CPL = 0 指代的就是DPL=0的那个Code32?
更奇怪的是,windows是不是基本上都不用LDT?
否则,不应该只有一个LDT显示才对的。

其实我就是想对照386 protection mode和windows的工作方式应该能够看到一一对应才对。
真是可惜首先LDT就对不上号,TSS32也对不上,
386当中说每个任务都有tss,104个字节,这确实不错,可惜Softice里面的第一个tss,不是104个字节的。
而且似乎只有5个TSS段在GDT内,这也不符合386保护模式,也只有一个描述LDT的段描述符在GDT内,

如下摘录win32汇编:

GDTR指向的描述符表为全局描述符表GDTGlobal Descriptor Table)。它包含系统中所有任务都可用的段描述符,通常包含描述操作系统所使用的代码段、数据段和堆栈段的描述符及各任务的LDT段等;全局描述符表只有一个。

LDTR则指向局部描述符表LDTLocal Descriptor Table)。80386处理器设计成每个任务都有一个独立的LDT。它包含有每个任务私有的代码段、数据段和堆栈段的描述符,也包含该任务所使用的一些门描述符,如任务门和调用门描述符等。

不同任务的局部描述符表分别组成不同的内存段,描述这些内存段的描述符当做系统描述符放在全局描述符表中。和GDTR直接指向内存地址不同,LDTRCSDS等段选择器一样只存放索引值,指向局部描述符表内存段对应的描述符在全局描述符表中的位置。随着任务的切换,只要改变LDTR的值,系统当前的局部描述符表LDT也随之切换,这样便于各任务之间数据的隔离。但GDT并不随着任务的切换而切换。

看到这里,读者可能会提出一个问题,既然有全局描述符表和局部描述符表两个表,那么段选择器中的索引值对应哪个表中的描述符呢。实际上,16位的段选择器中只有高13位表示索引值。剩下的3个数据位中,第01位表示程序的当前优先级RPL;第2TI位用来表示在段描述符的位置;TI0表示在GDT中,TI1表示在LDT中。

 

 

 

我猜测如果windows基本不用LDT,那么TI永远等于0也就不存在到LDT去找线性地址的可能了。

WINDOWS下平坦模式难道就是直接直接从偏移取线性地址的,因为段选择子limit= 0 ~ 4G.

0023     Data32     Base=00000000     Lim=FFFFFFFF     DPL=3     P     R
0028     TSS32     Base=8000B000     Lim=000020AB     DPL=0     P     B

而这个更是违反规则的,段描述符是64位的,

0023-0028只有5个字节,怎么可能?
 


IP 地址: 已记录   报告
   2007-04-17, 21:34 下午
advdbg 离线,最后访问时间: 2007/3/28 13:25:15 advdbg

发帖数前75位
注册: 2005-12-19
发 贴: 14
Re: 请教advdbg和Ramond 老师这实在是太令人费解了。
Reply Quote
段描述秒只是选择LDT或者GDT的一个表项。段选择子的高13位用作索引,意味着最多可索引2^13=8K=8192个描述符,所以GDT和LDT表的最大表项数都是8192。也就是最多有这么多个段。
IP 地址: 已记录   报告
高端调试 » 软件调试 » Windows内核调试 » 请教advdbg和Ramond 老师这实在是太令人费解了。

 
Legal Notice Privacy Statement Corporate Governance Corporate Governance
(C)2004-2020 ADVDBG.ORG All Rights Reserved.