gcc - 更改 gcc/g++ abi 中的调用约定
问题描述
我怎么能强制 gcc/g++ 不使用寄存器,而只使用 x86_64 中的堆栈来将参数传递给函数,就像它在 32 位版本中一样(并且可能以这种方式获取函数结果)。我知道它破坏了官方 ABI 并且调用方和被调用方都必须以这种方式编译才能正常工作。我不在乎是否使用 push/pop 或 mov/sub 方式。我希望编译器应该有一个可以强制执行它的标志,但我找不到它。
解决方案
看来你不能不破解 GCC 的源代码。
没有使用低效堆栈参数的标准 x86-64 调用约定。
GCC 只知道如何使用标准调用约定,在本例中为 x86-64 SysV 和 MS Windows fastcall 和 vectorcall。(例如__attribute__((ms_abi))
或vectorcall
)。通常没有人想要这个;MS 的调用约定对于包装器或可变参数函数已经足够友好了。__attribute__
即使在为 Linux、MacOS、*BSD 等编译时,您也可以将它用于某些功能(由 控制),如果有帮助的话。很难想象纯堆栈参数的用例。
GCC 允许您将寄存器指定为固定(GCC 从未触及,如-ffixed-rdi
)、调用破坏或调用保留。 但是使用带有参数传递寄存器的那些只会创建错误的代码,而不是你想要的。
例如
int foo(int a, int b, int c);
void caller(int x) {
foo(1,2,3);
//foo(4,x,6);
}
caller:
push rdi
mov edx, 3
mov esi, 2
pop rdi
jmp foo
它保存/恢复 RDI,但1
在调用foo
.
并且它不会将 RDI 排除在 arg 传递序列之外并在以后碰撞其他 args。(我在想你也许可以发明一个调用约定,其中所有传递参数的寄存器都是,fixed
或者call-saved
,也许让 GCC 回退到堆栈参数。但不是。)
推荐阅读
- vim - nvim 中的 set mouse = a for 是什么?
- javascript - mailchimp 在 Status:404 发送响应
- hibernate - 是否可以在另一个实体的 @NamedEntityGraph 中引用 @NamedEntityGraph?
- javascript - 您可以在 SVG 的“文本”标签中添加“缩写”标签吗?
- c# - AddMicrosoftIdentityWebApp 与 AddAzureADBearer
- c# - Blazor 服务器端如何获取单击元素的值
- elixir - 如何在 Elixir 测试中使用 Finch 旁路?
- postgresql - PostgreSQL:创建新表时如何自动设置表所有者
- javascript - jQuery AJAX 调用在点击处理程序中被多次触发
- linux - “未知广告数据包类型、无效广告数据、已纠正广告长度”Linux、Raspberry Pi、iOS、Homepod 的问题