- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
作为 Rust 操作系统的一部分,我有以下系统调用入口点:
#[no_mangle]
#[naked]
#[inline(never)]
unsafe extern "C" fn syscall_handler() {
// switch to the kernel stack dedicated for syscall handling, and save the user task's details
asm!("swapgs; \
mov gs:[0x8], rsp; \
mov gs:[0x10], rcx; \
mov gs:[0x18], r11; \
mov rsp, gs:[0x0];"
: : : "memory" : "intel", "volatile");
let (rax, rdi, rsi, rdx, r10, r8, r9): (u64, u64, u64, u64, u64, u64, u64);
asm!("" : "={rax}"(rax), "={rdi}"(rdi), "={rsi}"(rsi), "={rdx}"(rdx), "={r10}"(r10), "={r8}"(r8), "={r9}"(r9) : : "memory" : "intel", "volatile");
// do stuff with rax, rdi, rsi...
这在 Debug模式和 Release模式(启用调试信息)下工作正常,因为它生成存储本地堆栈变量的汇编代码,如 rdi
、rsi
、等在基指针 rbp
的负偏移处。例如,这是生成的代码:
<syscall_handler>:
swapgs
mov %rsp,%gs:0x8
mov %rcx,%gs:0x10
mov %r11,%gs:0x18
mov %gs:0x0,%rsp
mov %rax,-0x1f0(%rbp)
mov %rdi,-0x1e8(%rbp)
mov %rsi,-0x1e0(%rbp)
mov %rdx,-0x1d8(%rbp)
mov %r10,-0x1d0(%rbp)
mov %r8,-0x1c8(%rbp)
mov %r9,-0x1c0(%rbp)
movb $0x4,-0x1b1(%rbp)
该代码运行良好,因为我的系统调用处理程序使用指向当前内核堆栈顶部的堆栈指针运行(像往常一样),这意味着可以使用堆栈指针/基指针(基指针)的负偏移量rbp
在此之前根据堆栈指针值设置)。
当我在没有调试信息的 Release模式下构建时,它生成的代码使用堆栈指针本身的正偏移量(rsp
,而不是基指针)作为本地堆栈变量的位置。这真的很奇怪并且会导致问题,因为当前堆栈指针 rsp
之上的内存超出了范围。
这是在没有调试信息的纯 Release模式下生成的代码:
<syscall_handler>:
swapgs
mov %rsp,%gs:0x8
mov %rcx,%gs:0x10
mov %r11,%gs:0x18
mov %gs:0x0,%rsp
mov %rax,0x1c0(%rsp)
mov %rdi,0x1c8(%rsp)
mov %rsi,0x1d0(%rsp)
mov %rdx,0x1d8(%rsp)
mov %r10,0x1e0(%rsp)
mov %r8,0x1e8(%rsp)
mov %r9,0x1f0(%rsp)
为什么会生成这段代码,使用堆栈指针的正偏移量的代码?这让我觉得很奇怪。
有什么方法可以避免这种情况或以某种方式更改代码生成?
最佳答案
堆栈向下增长。 RSP 的正偏移量是可以避免中断异步修改的部分,即“保留”部分。
RSP 的负偏移量为 the red zone, which you can't have on the kernel stack .
使用 sub rsp, 0x100
或其他任何方式为裸函数的局部变量保留足够的空间。 或者更好的是,将整个入口点写在 asm 中而不是乱用编译器为此生成的代码。
或者更好的是,您自己使用 push
,它更紧凑(代码大小)并且同样高效。 push
非常适合在堆栈上保存寄存器; Linux 的系统调用入口点使用它。 (例如,the entry point into an x86-64 kernel from syscall
in 64-bit user-space 使用 push
保存所有寄存器,从 Linux 4.12 开始(在 Spectre/Meltdown 缓解/变通补丁使入口点变得更加复杂之前)。
奇怪/令人困惑的原因是您要求一个naked
函数(因此没有函数序言来保留堆栈空间),但是无论如何您都在其中使用了局部变量。否则,编译器将 sub rsp, 0x...
自行为局部变量保留足够的空间,然后再访问它们。
我认为在某些支持裸函数的 C/C++ 编译器中,这是不支持的;只允许内联 asm 作为整个函数体。但是就内联 asm 和编译器之间奇怪的探戈而言,IDK 官方支持 Rust 所说的。就像我说的,如果您用纯 asm 编写入口点,就不会有这些问题。
您的 Debug模式版本似乎已损坏;您正在相对于 RBP 进行存储,但 RBP 尚未设置。您需要一个naked
函数,因此您需要自己mov rbp, rsp
(从gs:0
加载RSP 之后),并且然后 sub rsp, 0x20
或任何在堆栈帧中为那些负偏移量保留足够空间的东西。
我认为你的 Debug模式版本是相对于用户空间的 RBP 存储的,如果用户空间使用 RBP 指向任何不应该被破坏的地方进行系统调用,这将严重破坏,如果 RBP 保持不变则更可怕一个非指针值。
(如果您刚刚使用 mov rbp, rsp
或其他东西,根据您的评论,您将这部分排除在外,那么您使用的是 RSP 下面的空间,如果没有红区。)
关于assembly - 发布与 Debug模式下局部堆栈变量的代码生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49125151/
对此感到疯狂,真的缺少一些东西。 我有webpack 4.6.0,webpack-cli ^ 2.1.2,所以是最新的。 在文档(https://webpack.js.org/concepts/mod
object Host "os.google.com" { import "windows" address = "linux.google.com" groups = ["linux"] } obj
每当我安装我的应用程序时,我都可以将数据库从 Assets 文件夹复制到 /data/data/packagename/databases/ .到此为止,应用程序工作得很好。 但 10 或 15 秒后
我在 cc 模式缓冲区中使用 hideshow.el 来折叠我不查看的文件部分。 如果能够在 XML 文档中做到这一点就好了。我使用 emacs 22.2.1 和内置的 sgml-mode 进行 xm
已结束。此问题不符合 Stack Overflow guidelines .它目前不接受答案。 我们不允许提出有关书籍、工具、软件库等方面的建议的问题。您可以编辑问题,以便用事实和引用来回答它。 关闭
根据java: public Scanner useDelimiter(String pattern) Sets this scanner's delimiting pattern to a patt
我读过一些关于 PRG 模式以及它如何防止用户重新提交表单的文章。比如this post有一张不错的图: 我能理解为什么在收到 2xx 后用户刷新页面时不会发生表单提交。但我仍然想知道: (1) 如果
看看下面的图片,您可能会清楚地看到这一点。 那么如何在带有其他一些 View 的简单屏幕中实现没有任何弹出/对话框/模式的微调器日期选择器? 我在整个网络上进行了谷歌搜索,但没有找到与之相关的任何合适
我不知道该怎么做,我一直遇到问题。 以下是代码: rows = int(input()) for i in range(1,rows): for j in range(1,i+1):
我想为重写创建一个正则表达式。 将所有请求重写为 index.php(不需要匹配),它不是以/api 开头,或者不是以('.html',或'.js'或'.css'或'.png'结束) 我的例子还是这样
MVC模式代表 Model-View-Controller(模型-视图-控制器) 模式 MVC模式用于应用程序的分层开发 Model(模型) - 模型代表一个存取数据的对象或 JAVA PO
我想为组织模式创建一个 RDF 模式世界。您可能知道,组织模式文档基于层次结构大纲,其中标题是主要的分组实体。 * March auxiliary :PROPERTIES: :HLEVEL: 1 :E
我正在编写一个可以从文件中读取 JSON 数据的软件。该文件包含“person”——一个值为对象数组的对象。我打算使用 JSON 模式验证库来验证内容,而不是自己编写代码。符合代表以下数据的 JSON
假设我有 4 张 table 人 公司 团体 和 账单 现在bills/persons和bills/companys和bills/groups之间是多对多的关系。 我看到了 4 种可能的 sql 模式
假设您有这样的文档: doc1: id:1 text: ... references: Journal1, 2013, pag 123 references: Journal2, 2014,
我有这个架构。它检查评论,目前工作正常。 var schema = { id: '', type: 'object', additionalProperties: false, pro
这可能很简单,但有人可以解释为什么以下模式匹配不明智吗?它说其他规则,例如1, 0, _ 永远不会匹配。 let matchTest(n : int) = let ran = new Rand
我有以下选择序列作为 XML 模式的一部分。理想情况下,我想要一个序列: 来自 my:namespace 的元素必须严格解析。 来自任何其他命名空间的元素,不包括 ##targetNamespace和
我希望编写一个 json 模式来涵盖这个(简化的)示例 { "errorMessage": "", "nbRunningQueries": 0, "isError": Fals
首先,我是 f# 的新手,所以也许答案很明显,但我没有看到。所以我有一些带有 id 和值的元组。我知道我正在寻找的 id,我想从我传入的三个元组中选择正确的元组。我打算用两个 match 语句来做到这
我是一名优秀的程序员,十分优秀!