作为二进制数组的GCC内联程序集
GCC中是否有任何方法将内联作为二进制数组的GCC内联程序集,c,gcc,inline-assembly,C,Gcc,Inline Assembly,GCC中是否有任何方法将内联\uuuu asm\uuuu表示为char[]数组?我想要一些像: void my_func(); char my_code[] = { __asm__("callq %0" :: "r" (my_func)) }; 稍后的my_code将用作运行时修补程序,即 void another_function(); mprotect(another_function, getpagesize(), PROT_WRITE | PROT_READ | PROT_E
\uuuu asm\uuuu
表示为char[]
数组?我想要一些像:
void my_func();
char my_code[] = {
__asm__("callq %0" :: "r" (my_func))
};
稍后的my_code
将用作运行时修补程序,即
void another_function();
mprotect(another_function, getpagesize(), PROT_WRITE | PROT_READ | PROT_EXEC);
memcpy(another_function + offset, my_code, sizeof(my_code));
有什么想法吗?你可以定义一个函数,编译它,然后得到它的源代码
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
void my_func(void) {}
extern void my_code(void);
extern void my_code_end(void);
__attribute__((__used__)) static void _my_code(void) {
asm volatile(
".globl my_code\n"
"my_code:\n"
" callq *%0\n"
" nop\n"
" ret\n"
".globl my_code_end\n"
"my_code_end:\n"
:: "r" (my_func)
);
}
int main() {
size_t my_code_len = (uintptr_t)my_code_end - (uintptr_t)my_code;
const unsigned char *arr = (const char*)my_code;
printf("my_code[%zu]=", my_code_len);
for (size_t i = 0; i < my_code_len; ++i) {
printf("%02x", arr[i]);
}
printf("\n");
return 0;
}
我们可以从组件输出中检查它是否正常:
$ objdump -D ./a.out
...
0000000000000727 <my_code>:
727: ff d0 callq *%rax
729: 90 nop
72a: c3 retq
...
$objdump-D./a.out
...
0000000000000727 :
727:ff d0 callq*%rax
729:90不
72a:c3 retq
...
你可以定义一个函数,编译它,然后得到它的源代码
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
void my_func(void) {}
extern void my_code(void);
extern void my_code_end(void);
__attribute__((__used__)) static void _my_code(void) {
asm volatile(
".globl my_code\n"
"my_code:\n"
" callq *%0\n"
" nop\n"
" ret\n"
".globl my_code_end\n"
"my_code_end:\n"
:: "r" (my_func)
);
}
int main() {
size_t my_code_len = (uintptr_t)my_code_end - (uintptr_t)my_code;
const unsigned char *arr = (const char*)my_code;
printf("my_code[%zu]=", my_code_len);
for (size_t i = 0; i < my_code_len; ++i) {
printf("%02x", arr[i]);
}
printf("\n");
return 0;
}
我们可以从组件输出中检查它是否正常:
$ objdump -D ./a.out
...
0000000000000727 <my_code>:
727: ff d0 callq *%rax
729: 90 nop
72a: c3 retq
...
$objdump-D./a.out
...
0000000000000727 :
727:ff d0 callq*%rax
729:90不
72a:c3 retq
...
如果\u my\u code
包含GCC添加的序言,该怎么办?我在\u my\u code
中声明my\u code
,因此如果它确实包含任何序言,它将位于my\u code
之前。可能应该重构一点,这样它更具可读性。@ivaigult和Kamil:因为您在内联asm中使用了.globl my_code
等,所以请将它放在全局范围内,而不是放在另一个名称类似的函数中。实际上调用该函数是不安全的(因为它会在不通知编译器的情况下关闭红色区域)。哦,等等,您确实需要从\u my\u code
复制到my\u code\u end
,以获取将my\u func
放入asm选择的寄存器的指令。如果它使用RIP相对LEA(PIE或共享库)而不是绝对的mov eax,imm32
(非PIE可执行),那么将指令复制到同一个程序中的其他地方会改变地址。如果\u my_code
包含GCC添加的序言怎么办?我在\u my_code
中声明my_code
,因此,如果它确实包含任何序言,那么它将在my_code
之前。可能应该重构一点,这样它更具可读性。@ivaigult和Kamil:因为您在内联asm中使用了.globl my_code
等,所以请将它放在全局范围内,而不是放在另一个名称类似的函数中。实际上调用该函数是不安全的(因为它会在不通知编译器的情况下关闭红色区域)。哦,等等,您确实需要从\u my\u code
复制到my\u code\u end
,以获取将my\u func
放入asm选择的寄存器的指令。如果它使用RIP相对LEA(PIE或共享库)而不是绝对mov eax、imm32
(非PIE可执行文件)来执行此操作,则将指令复制到同一程序中的其他位置将更改地址。