【问题标题】:Why am I getting a segfault when I `ret'? (FASM) [duplicate]为什么当我“ret”时会出现段错误? (FASM)[重复]
【发布时间】:2016-10-09 20:40:19
【问题描述】:

通过一些操作,我将其缩小为ret 操作的问题。我知道call 将返回地址推入堆栈;弹出再推回去违法吗?

format ELF64 executable 3

entry start

segment readable executable

start:
    pop rcx         ; argc
    mov [argc],cl       ; int -> ASCII
    add [argc],'0'
    push 1 argc 1
    call sys_write

    mov rdi,0
    mov rax,60
    syscall

sys_write: ; (fd,*buf,count)
    pop r11
    pop rdx rsi rdi
    mov rax,1
    syscall
    push r11
    ret

segment readable writable

argc rb 1

输出是:

$ ./prog
1Segmentation fault
$ _

【问题讨论】:

  • SYSCALL 破坏 r11。您几乎可以选择任何其他寄存器。但是在寄存器中传递函数参数(就像 ABI 标准调用约定那样)或者使用mov ..., [rsp+8] 读取堆栈要容易得多。 FASM 的pop rdx rsi rdi 语法只是语法糖,它仍然组装成 3 条指令。这效率不高。
  • 如果您使用了调试器,您可以检查寄存器值。
  • 你在开玩笑吧。好吧,r12 工作了。只是我的运气。非常感谢。
  • @PeterCordes 另外,我知道它效率不高,但我想在编写宏之前为我正在编写的另一个更大的程序编写简洁的系统调用。不过感谢rsp 的建议。我从来没有想过。

标签: linux assembly return x86-64 fasm


【解决方案1】:

syscall 指令用RFLAGS 寄存器破坏R11 的内容,这意味着在创建syscall 后,您存储在R11 中的值将被覆盖。

一种解决方案可能是简单地选择一个不会被系统调用修改的适当寄存器。根据 Intel 的指令参考手册(http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf,第 4-668 页第 2B 页)syscall 覆盖 RCXRIPR11RFLAGS 作为其操作的一部分,但操作系统是当然能够恢复 RIP 和 RFLAGS。

这留下了很多其他选择。一个不错的选择是在标准用户空间调用约定中允许函数调用破坏的寄存器,但 Linux 系统调用将保持不变。 R8 符合要求。由于您没有使用标准的 x86-64 System V function-calling conventionRBXRBP 将是更好的选择(更小的机器代码大小,因为它们不需要 REX 前缀)。

【讨论】:

  • syscall 指令似乎使用RCX 来存储系统调用的返回地址,因此它似乎也不可用。
  • /facepalm,当然可以。我的错。我认为 3 操作数系统调用没有任何免费的调用破坏低 8 寄存器。 (RBX 和 RBP 保留调用)。最好的选择当然是一开始就不弹出返回地址。
  • 等一下,R8 没有被调用者保存在 x86-64 SystemV ABI 中。不,您永远不需要保存/恢复 RSP 或 RFLAGS。保存 FLAGS 是 SYSCALL 使用 R11 的目的(因此无论操作系统配置如何,它都可以被屏蔽以在禁用或不禁用中断的情况下进入内核)。 RCX 和 R11 的原始值被破坏,但其他所有内容都在某个地方并在内核的SYSRET instruction 之前或由内核的SYSRET instruction 恢复。
  • 当然Linux系统调用用返回值覆盖RAX,与实际SYSCALL/SYSRET机制的操作分开。
  • 你说得对,我完全不了解 R8。正在恢复的 RSP 看起来取决于操作系统系统调用处理程序,因为 syscall 不会保存它,sysret 不会自行修改它。
猜你喜欢
  • 1970-01-01
  • 2013-02-11
  • 1970-01-01
  • 2014-07-22
  • 1970-01-01
  • 2018-01-07
  • 1970-01-01
  • 2015-05-09
相关资源
最近更新 更多