此问题已在此处有答案:
Why is there no "sub rsp" instruction in this function prologue and why are function parameters stored at negative rbp offsets?(2个答案)
Compiler using local variables without adjusting RSP(1个答案)
How system V ABI's red zone is implemented(1个答案)
上个月关门了。
以下是关于我的系统的一些信息:
- 运行在Intel x86_64上的Ubuntu 22.04.3;
- ggc版本11.4.0;
我注意到,在叶函数中,rsp寄存器不像在非叶函数中那样递减。
例如,考虑文件test. c中的以下C程序:
int fx(){
int x = 30;
int y = 34;
int z = 45;
return 30;
}
int main(){
int a = 10;
int b = 20;
int c = fx();
}
在使用“gcc test.c -fno-stack-protector -o test”编译它之后,我运行“objdump -dw -M suffix test”,我得到:
0000000000001129 <fx>:
1129: f3 0f 1e fa endbr64
112d: 55 pushq %rbp
112e: 48 89 e5 movq %rsp,%rbp
1131: c7 45 fc 1e 00 00 00 movl $0x1e,-0x4(%rbp)
1138: c7 45 f8 22 00 00 00 movl $0x22,-0x8(%rbp)
113f: c7 45 f4 2d 00 00 00 movl $0x2d,-0xc(%rbp)
1146: b8 1e 00 00 00 movl $0x1e,%eax
114b: 5d popq %rbp
114c: c3 retq
000000000000114d <main>:
114d: f3 0f 1e fa endbr64
1151: 55 pushq %rbp
1152: 48 89 e5 movq %rsp,%rbp
1155: 48 83 ec 10 subq $0x10,%rsp
1159: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
1160: c7 45 f8 14 00 00 00 movl $0x14,-0x8(%rbp)
1167: b8 00 00 00 00 movl $0x0,%eax
116c: e8 b8 ff ff ff callq 1129 <fx>
1171: 89 45 f4 movl %eax,-0xc(%rbp)
1174: b8 00 00 00 00 movl $0x0,%eax
1179: c9 leaveq
117a: c3 retq
正如你所看到的,在main中我们有subq $0x10,%rsp
,但在fx
中这不会发生。
我的问题:
1.它是否与gcc遵循的System V ABI有关,或者它只是编译器执行的优化?
1.是什么原因导致了这种行为?
1.有没有一种方法可以告诉编译器我不希望在叶函数中出现这种行为?
1条答案
按热度按时间unguejic1#
因为你没有通过寄存器传递任何参数,也没有调用任何其他函数,所以保留堆栈空间是没有意义的。
https://godbolt.org/z/7qE4nbdcn
是否可以在Ubuntu x86_64系统中编译带有“-mno-red-zone”标志的C程序,如“gcc file. c-fno-stack-protector -mno-red-zone -o file”?这个选项是否会破坏某些东西或导致一些不兼容性,或者它只是一个优化?
它是安全的。基本上,它在用户空间代码中是毫无意义的。这是一种优化吗?- 是的,差不多保留空间是毫无意义的,除非你的堆栈大于红色区域。
它将保留堆栈减去红色区域的大小。
https://godbolt.org/z/8qb191x9E
我读到过System V ABI“命令”红色区域。这是否意味着即使我们使用-mno-red-zone选项,这个红色区域也确实存在?我的意思是,如果我们使用这个选项,我们不使用红色区域,但它仍然存在?
这与你的代码无关。信号和中断处理程序会将堆栈指针从您的指针上移开。要更改它,您需要重新编译内核并修改它的一些代码。