【问题标题】:Why do I get different result when tracing into write() than other people?为什么我在追踪 write() 时得到的结果与其他人不同?
【发布时间】:2011-10-16 00:58:34
【问题描述】:

我正在做一些 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 中找到第二个调用 write 的行号,“call write” 功能。在这一行设置一个断点。据我说是22。

在此行设置断点。

 break 22

在调试器中运行程序。

 run

程序将在您设置的断点处停止。 进入没有调试信息的代码。

  si 

您将在源布局中看到“[No Source Available]”。所以你需要查看 反汇编指令。

 layout asm

反复 step into (si 然后回车/回车就会执行 si 命令 重复)直到您看到“sysenter”出现在屏幕的 asm 布局部分。 我正在尝试从 asm 布局部分的顶部复制指令(包括它们的地址),一直到并包括 sysenter 指令。

提示:您可以通过键入 Ctrl-x o 将键盘的焦点更改为命令区域。这 箭头键可用于恢复较早的命令的方式(它只是节省了一些 打字)。

【问题讨论】:

  • 请不要在得到答案时编辑掉问题的内容。如果可以在下面找到答案,请接受;否则写下你找到的答案并接受你自己的答案。这将有助于将来有相同问题的搜索者。
  • 所以发布您的答案,以便其他人受益。或者不要理会这个问题,希望有人会出现并发布对其他人有帮助的答案。不要只是删除所有上下文。我花了相当长的时间来回答我的问题,我希望看到它对其他人有所帮助,即使您不关心答案。
  • 如果您真的想删除您的问题,请将其标记为版主注意,并在说明中给出充分的理由。
  • 我自己不会再回复这个了。但我已经向版主报告了这一点。你来这里寻求建议,即使你认为你不再想要它,你至少可以把这个问题留在一个可以帮助其他人的形式中。无论如何,在底部添加一些内容说“我不再关心”,但是要求一个答案,甚至不说为什么就拒绝它,然后让问题(和答案!)对其他人无用只是简单的 粗鲁

标签: c linux assembly x86 system-calls


【解决方案1】:

您正在追踪所谓的'virtual dynamic shared object' (VDSO) - 其内容是Linux 内核的实现细节。有许多情况会导致 VDSO 的内容发生变化;因此这里没有一个正确的答案

特别是在 32 位 x86 系统上,至少有三种不同的机制可用于进行系统调用:

  • INT $0x80
  • SYSCALL(最近的 AMD CPU)
  • SYSENTER(最新的 Intel CPU)

您会注意到,只有INT $0x80 可以在所有 CPU 上运行(事实上,即使还有更现代的替代方案可用,内核也使其可用于遗留应用程序);但是,它也很慢。内核将在启动时探测支持的版本,并选择使用最有效机制的 VDSO 版本。

因此,根据您的 CPU 型号,您可能会在 VDSO 中看到不同的代码 - 特别是,如果您有 AMD CPU,您可能会看到 SYSCALL 路径,如果您有一个非常旧的CPU 你甚至可能会看到INT $0x80 路径。如果您对其他人感到好奇,以下是源代码:

很可能,您实验室中获得不同结果的其他人拥有 AMD CPU 并且正在查看 SYSCALL 路径(或者他们有一台古董 PC,并且正在查看 INT $0x80 路径)。

还要注意,在 64 位进程中,SYSCALL 将被直接使用,根本不经过 VDSO。

【讨论】:

  • 我并不是真的在寻找这种答案。我只想知道我得到的答案是否正确,如果不是那么如何解决它。
  • @Jay,这里没有一个“正确答案”。 VDSO 的内容是一个实现细节。内核人员可以随时更改它 - 正如我所说,它确实有所不同。如果你感兴趣的只是这是否“正确”,我认为你误解了练习的目的——不是为了理解你看到的行为吗?
  • 还要注意,即使内核在 VDSO 中选择了另一种方法,INT $0x80 也始终可用。这不是意外。
  • @Jay,哇,bdonlan 给出了我见过的关于此功能的 最好的 文章之一 - 顺便说一下,为您提供了为什么您和您的其他辅导员得到了不同的答案——而你不开心??
  • 写的很好。我的笔记里有。谢谢你的文章。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多