当前位置:主页   - 电脑 - 操作系统 - 其它系统
Linux2.6对新型CPU的支持(2)
来源:网络   作者:来源:Linux爱好者/责编:编程入门 刘子锐    更新时间:2010-09-26
收藏此页】    【字号    】    【打印】    【关闭

由用户态经库函数进入内核态

为了配合内核使用新的系统调用方式,glibc中要做一定的修改。新的glibc-2.3.2(及其以后版本中)中已经包含了这个改动,在glibc源代码的sysdeps/unix/sysv/linux/i386/sysdep.h文件中,处理系统调用的宏INTERNAL_SYSCALL在不同的编译选项下有不同的结果。在打开支持sysenter/sysexit指令的选项I386_USE_SYSENTER下,系统调用会有两种方式,在静态链接(编译时加上-static选项)情况下,采用"call *_dl_sysinfo"指令;在动态链接情况下,采用"call *%gs:0x10"指令。这两种情况由glibc库采用哪种方法链接,实际上最终都相当于调用某个固定地址的代码。下面我们通过一个小小的程序,配合gdb来验证。

首先是一个静态编译的程序,代码很简单:

  main()
{
  getuid();
}

将代码加上static选项用gcc静态编译,然后用gdb装载并反编译main函数。

[root@test opt]# gcc test.c -o ./static -static
[root@test opt]# gdb ./static
(gdb) disassemble main
0x08048204 <main+0>:  push  %ebp
0x08048205 <main+1>:  mov  %esp,%ebp
0x08048207 <main+3>:  sub  $0x8,%esp
0x0804820a <main+6>:  and  $0xfffffff0,%esp
0x0804820d <main+9>:  mov  $0x0,%eax
0x08048212 <main+14>:  sub  %eax,%esp
0x08048214 <main+16>:  call  0x804cb20 <__getuid>
0x08048219 <main+21>:  leave
0x0804821a <main+22>:  ret

可以看出,main函数中调用了__getuid函数,接着反编译__getuid函数。

(gdb) disassemble 0x804cb20
0x0804cb20 <__getuid+0>:    push  %ebp
0x0804cb21 <__getuid+1>:    mov  0x80aa028,%eax
0x0804cb26 <__getuid+6>:    mov  %esp,%ebp
0x0804cb28 <__getuid+8>:    test  %eax,%eax
0x0804cb2a <__getuid+10>:    jle  0x804cb40 <__getuid+32>
0x0804cb2c <__getuid+12>:    mov  $0x18,%eax
0x0804cb31 <__getuid+17>:    call  *0x80aa054
0x0804cb37 <__getuid+23>:    pop  %ebp
0x0804cb38 <__getuid+24>:    ret

上面只是__getuid函数的一部分。可以看到__getuid将eax寄存器赋值为getuid系统调用的功能号0x18然后调用了另一个函数,这个函数的入口在哪里呢?接着查看位于地址0x80aa054的值。

(gdb) X 0x80aa054

0x80aa054 <_dl_sysinfo>:    0x0804d7f6

看起来不像是指向内核映射页面内的代码,但是,可以确认,__dl_sysinfo指针的指向的地址就是0x80aa054。下面,我们试着启动这个程序,然后停在程序第一条语句,再查看这个地方的值。

(gdb) b main
Breakpoint 1 at 0x804820a
(gdb) r
Starting program: /opt/static
Breakpoint 1, 0x0804820a in main ()
(gdb) X 0x80aa054
0x80aa054 <_dl_sysinfo>:    0xffffe400

可以看到,_dl_sysinfo指针指向的数值已经发生了变化,指向了0xffffe400,如果我们继续运行程序,__getuid函数将会调用地址0xffffe400处的代码。

接下来,我们将上面的代码编译成动态链接的方式,即默认方式,用gdb装载并反编译main函数

[root@test opt]# gcc test.c -o ./dynamic
[root@test opt]# gdb ./dynamic
(gdb) disassemble main
0x08048204 <main+0>:  push  %ebp
0x08048205 <main+1>:  mov  %esp,%ebp
0x08048207 <main+3>:  sub  $0x8,%esp
0x0804820a <main+6>:  and  $0xfffffff0,%esp
0x0804820d <main+9>:  mov  $0x0,%eax
0x08048212 <main+14>:  sub  %eax,%esp
0x08048214 <main+16>:  call  0x8048288
0x08048219 <main+21>:  leave
0x0804821a <main+22>:  ret

其它资源
来源声明

版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明