我使用裸函数在程序运行时修补部分程序。我可以在 Windows 的 VC++ 中轻松地做到这一点。我正在尝试在 Linux 中执行此操作,但 gcc 似乎不支持裸函数。用裸函数编译代码给我这个:警告:‘naked’属性指令被忽略。在 CentOS 5.5 i386 下编译。
根据 docs:
仅在某些平台(ARM、AVR、MCORE、RX 和 SPU)上 GCC 支持裸属性: 在 ARM、AVR、MCORE、RX 和 SPU 端口上使用此属性来 表明指定的函数不需要序言/结语 编译器生成的序列。这取决于程序员 提供这些序列。唯一可以安全的语句 包含在裸函数中的是没有 操作数。所有其他声明,包括本地声明 应避免使用变量、if 语句等。裸 应该使用函数来实现程序集的主体 函数,同时允许编译器构造必要的 汇编程序的函数声明。naked
我不知道为什么。
===更新===
截至 2023 年,他们开始工作:
__attribute__((naked))
void my_write(int fd, char const* str, int size) {
asm
(
"write: \n\t"
" pusha \n\t"
" movl $4, %eax \n\t"
" movl 36(%esp), %ebx \n\t"
" movl 40(%esp), %ecx \n\t"
" movl 44(%esp), %edx \n\t"
" int $0x80 \n\t"
" popa \n\t"
" ret \n\t"
);
}
void _start() {
my_write(1, "hi\n", 3);
my_write(1, "bye\n", 4);
}
使用
gcc -m32 -nostdlib my_write.c
与
gcc version 10.2.1 20210110 (Debian 10.2.1-6)
编译
===旧答案===
在 x86 上,您可以通过在全局范围内使用 asm 来解决问题:
void my_write(int fd, const void *buf, int count);
asm
(
".global my_write \n\t"
"write: \n\t"
" pusha \n\t"
" movl $4, %eax \n\t"
" movl 36(%esp), %ebx \n\t"
" movl 40(%esp), %ecx \n\t"
" movl 44(%esp), %edx \n\t"
" int $0x80 \n\t"
" popa \n\t"
" ret \n\t"
);
void _start()
{
my_write(1, "hi\n", 3);
my_write(1, "bye\n", 4);
}
另外
naked
列在x86函数属性中,所以我想它适用于较新的gcc。
这是一个丑陋的解决方案。链接到目标架构的 .asm 文件。
GCC 仅支持 ARM 和其他嵌入式平台上的裸函数。 http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
另外,你所做的本质上是不安全的,因为你不能保证你正在修补的代码在程序运行时不会执行。