我正在做一些x86练习;我的任务让我在调试器中逐步调试write()
库调用的汇编代码,直到我们达到SYSENTER
指令,但我得到的结果与我的一些同学不同。我在SYSENTER
前看到的是:
│0xf7fdf421 <__kernel_vsyscall+1> push %edx
│0xf7fdf422 <__kernel_vsyscall+2> push %ebp
│0xf7fdf423 <__kernel_vsyscall+3> mov %esp,%ebp
│0xf7fdf425 <__kernel_vsyscall+5> sysenter
这是我应该看到的吗?如果是这样,为什么它与我的一些同学看到的不一样?
在执行sysenter
指令之前,%edx和%ebp寄存器也保存在堆栈中吗? (根据我得到的答案,或者我错了,它似乎不是这样吗?)
这是我作业的原始说明:
汇编代码:
.file "A3Program2.c"
.section .rodata
.LC0:
.string "hello\n"
.LC1:
.string "xxxx\n"
.text
.globl secondCall
.type secondCall, @function
secondCall:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $6, 8(%esp)
movl $.LC0, 4(%esp)
movl $1, (%esp)
call write
movl %eax, -12(%ebp)
movl $8, 8(%esp)
movl $.LC1, 4(%esp)
movl $1, (%esp)
call write
addl %eax, -12(%ebp)
movl 12(%ebp), %eax
movl 8(%ebp), %edx
leal (%edx,%eax), %eax
addl %eax, -12(%ebp)
movl -12(%ebp), %eax
leave
ret
.size secondCall, .-secondCall
.globl firstCall
.type firstCall, @function
firstCall:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $2, 4(%esp)
movl $4, (%esp)
call secondCall
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
leave
ret
.size firstCall, .-firstCall
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
call firstCall
movl %eax, 12(%esp)
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
.section .note.GNU-stack,"",@progbits
以下说明适用于Linux:
在secondCall中找到第二次写入调用的行号“call write” 功能。在此行设置断点。根据我的说法,这是22。
在此行设置断点。
break 22
在调试器中运行程序。
run
程序将在您设置的断点处停止。 进入没有调试信息的代码。
si
您将在源布局中看到“[No Source Available]”。所以你需要查看 拆解的指示。
layout asm
重复步入(si然后返回/输入将执行si命令 反复)直到你看到“sysenter”出现在屏幕的asm布局部分。 我试图从asm布局部分的顶部复制指令(包括它们的地址),直到并包括sysenter指令。
提示:您可以通过键入Ctrl-x o将键盘的焦点更改为命令区域。这个 方式箭头键可以用来带回早期的命令(它只是节省一些 打字)。
答案 0 :(得分:10)
您正在追踪所谓的'virtual dynamic shared object' (VDSO) - 其内容是Linux内核的实现细节。有许多条件可能导致VDSO的内容发生变化;因此这里没有单一的正确答案。
特别是,在32位x86系统上,至少有三种不同的机制可用于进行系统调用:
INT $0x80
SYSCALL
(最近的AMD CPU)SYSENTER
(最近的英特尔CPU)你会注意到只有INT $0x80
适用于所有CPU(事实上,即使有更现代的替代方案,内核也可以用于遗留应用程序);然而,它也很慢。内核将探测引导时支持哪些内容,并选择使用最有效机制的VDSO版本。
因此,根据您的CPU型号,您可能会在VDSO中看到不同的代码 - 特别是,如果您有AMD CPU,您可能会看到SYSCALL
路径,如果您有真的很老的CPU甚至可能会看到INT $0x80
路径。如果你对其他人感到好奇,这里是源代码:
INT $0x80
method SYSCALL
method SYSENTER
method - 阅读有关推送%ecx
,%edx
和%ebp
的原因的评论最有可能的是,你实验室中得到不同结果的其他人有一个AMD CPU并正在查看SYSCALL
路径(或者他们有一台古董PC,正在查看INT $0x80
路径)。
另请注意,在64位进程中,SYSCALL
将直接使用,而无需通过VDSO。