Chinaunix首页 | 论坛 | 博客
  • 博客访问: 363004
  • 博文数量: 38
  • 博客积分: 1935
  • 博客等级: 上尉
  • 技术积分: 724
  • 用 户 组: 普通用户
  • 注册时间: 2005-11-23 16:34
文章存档

2010年(4)

2009年(33)

2008年(1)

分类:

2009-05-03 22:14:40

  x86 下 segment 保护核心就是 gate 机制,x64 的 long 模式下 segment 保护有所弱化,AMD 号称 long 模式取消了 segment 机制,实际上,现阶段的的 x64 体系中,segment 机制是不可取消的。只不过是将平坦内存模式从软件层移到硬件层,等取于取消了 segment 机制。
  现在的操作系统都将 protected 重心放在了 paging 阶段,x64 体系从硬件层体现了这个思想。



5.7.3.1、 gate 是什么

  gate 机制体现在 gate descriptor 的设置,显然,gate descriptor 像是一道通关令符。顾名思义,门是通过另一片天地的必经之路。这片天地通常会得到更多的资源,这片天地通常就是系统的核心代码部分。
  gate descripotr 门符就是指引通往这片天地的钥匙。有权限获得门符就可以访问更底层的代码。


  gate descriptor 的作用相当于 C 语言里的指针,并且这个指针就是函数指针。

如下:

void foo()
{
        ... ...
}

int main()
{
        void (*pf)() = foo;
        ... ...
        
        pf();             /* call gate 类似 */
        ... ...
}


  gate 机制是一种间接的转移控制方式。gate 的主要作用是用来检查权限、切换权限。上面的 c 代码中,函数指针 pf 相当一个 call gate descritpor。gate descriptor 结构里指出了真正要跳转代码的地方。


有以下几种 gate 类型:
● call gate
● interrupt gate
● trap gate
● task gate



上面的图是这几种 gate descriptor 的格式。


1、在 task gate descriptor 里,关键的元素就是 TSS selector,这个 TSS selector 给出目标进程的 TSS selector,通过使用 task gate descriptor 达到使用 TSS 来进行进程的切换。

2、可见 interrupt gate descriptor 与 trap gate descriptor 的格式是完全一致的,它们的匹别只是 type 的不同。

3、而 call gate descriptor 与 interrupt/trap gate descriptor 的区别只是,使用 call gate 可以传递总共 31 个参数。




5.7.3.2、  如何使用 call gate 传递参数

  在 call gate descriptor 的 parameter count 部分里指出了参数的个数。这个参数是告诉目标代码将要有多少个参数传递过来。

看下面的例子:

/* caller */

push param1                     /* parameter */
push param2
push param3

call 0x20:00000000              /* call gate */

... ...


在调用方里使用 call gate 进行切换。caller 先压入了 3 个参数,然后通过 call gate 来调用子例程


/* callee */

... ...

ret 0x0c


子例程 callee 完成工作后,很正常地 ret 返回。

那么,当发生 stack 切换时,即:caller 在 CPL =3 下, callee 在 CPL = 0 下,这时会发生 stack 的切换。

此时,processor 会做相当多的必要工作,在假设通过权限的检查下:

1、首先从 TSS segment 里得到 0 级下的 stack 指针(即:SS 和 ESP)加载到 SS 以及 ESP。这时属于 0 级下的 stack 空间了。

2、将原来的 SS 及 ESP 保存到新的 stack 里,也就是压入旧的 SS 及 ESP。

3、然后,这里根据 call gate descriptor 里的 parameter count 参数个数,从旧的 stack 里复制参数到新的 stack 里。在这个例子里是 3 个参数,也就是依次压入 param1、param2 及 param3 在 stack 上。
  在这一步里就实现了传递参数。


4、然后,再保存返回指针(即:CS 及 EIP)。

5、在 callee 返回时执行 ret 0x0c 时,pop 出 CS 及 EIP,ret 0x0c 会消去压入的 12 个字节的。

6、pop 出 原来的 stack 指针(SS 及 ESP)。从而 0 级的 stack 恢复正常。


  使用 call gate 传递参数,是一种 caller 与 callee 的约定方式,caller 压入参数,并明确告诉 callee 有多少个参数。而 callee 必须负责做消除 stack 工作。
  这个例程的使用参数一旦定下来,caller 与 callee 就不能改变。若一方改变了这种约定,就会造成 stack 混乱。

阅读(1143) | 评论(0) | 转发(0) |
0

上一篇:LDT descriptor

下一篇:gate 的用法

给主人留下些什么吧!~~