更改 gcc/g++ abi 中的调用约定
Changing calling convention in 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 的调用约定对于包装器或可变函数已经足够友好了。即使在为 Linux、MacOS、*BSD 等编译时,您也可以将其用于某些功能(由 __attribute__
控制),如果有帮助的话。很难想象纯堆栈参数的用例。
GCC 允许您将寄存器指定为固定(GCC 从未触及,如 -ffixed-rdi
)、调用破坏或调用保留。 但是使用带有参数传递寄存器的那些只会产生错误的代码,而不是你想要的。
例如
int foo(int a, int b, int c);
void caller(int x) {
foo(1,2,3);
//foo(4,x,6);
}
compiled by gcc9.2 -O3 -fcall-saved-rdi
caller:
push rdi
mov edx, 3
mov esi, 2
pop rdi
jmp foo
它 saves/restores RDI 但在调用 foo
.
之前没有在其中放入 1
并且它不会将 RDI 排除在 arg 传递序列之外并在以后碰撞其他 args。 (我在想你可以发明一个调用约定,其中所有的 arg 传递寄存器都是 fixed
或 call-saved
,也许让 GCC 回退到堆栈 args。但是不行。)
我如何强制 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 的调用约定对于包装器或可变函数已经足够友好了。即使在为 Linux、MacOS、*BSD 等编译时,您也可以将其用于某些功能(由 __attribute__
控制),如果有帮助的话。很难想象纯堆栈参数的用例。
GCC 允许您将寄存器指定为固定(GCC 从未触及,如 -ffixed-rdi
)、调用破坏或调用保留。 但是使用带有参数传递寄存器的那些只会产生错误的代码,而不是你想要的。
例如
int foo(int a, int b, int c);
void caller(int x) {
foo(1,2,3);
//foo(4,x,6);
}
compiled by gcc9.2 -O3 -fcall-saved-rdi
caller:
push rdi
mov edx, 3
mov esi, 2
pop rdi
jmp foo
它 saves/restores RDI 但在调用 foo
.
1
并且它不会将 RDI 排除在 arg 传递序列之外并在以后碰撞其他 args。 (我在想你可以发明一个调用约定,其中所有的 arg 传递寄存器都是 fixed
或 call-saved
,也许让 GCC 回退到堆栈 args。但是不行。)