我正在尝试构建一个基本的JIT
引擎来理解目的。
尝试做一些我读到的基本概念,这是一个例子:
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
void * fptr;
int (*_printf)(const char*,...);
int test1(void)
{
int arr[100] = {0x0};
_printf("In %s\n", __FUNCTION__); << Segfault due to this printf call
return 5;
}
int main()
{
fptr = mmap(NULL, 4096, PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
memset((unsigned char *)fptr, 0x90, 4096);
printf("Address of printf = %p\n", &printf);
_printf = printf;
int (* testptr)(void);
memcpy(fptr, (unsigned char *)&test1, 67);
testptr = fptr;
int i = test1();
printf("ret = %d\n", i);
i = 0x0;
i = testptr();
printf("ret = %d\n", i);
return 0;
}
此示例将函数test1()复制到另一块可执行内存并尝试执行它(我复制67个字节,这是粗略的,但在此示例中无关紧要)。
如果我不从共享库中调用任何外部符号(在本例中为printf),我可以执行复制的函数,但是当从test1()调用printf()时程序面向SIGSEGV。
我认为这是由于使用相对地址而发生的,即如果从原始位置执行,test1()将起作用,否则所有相对地址都将变坏。
这是gdb所说的,
info registers
r15 0x0 0
rip 0x7ffff7ff7025 0x7ffff7ff7025
eflags 0x10202 [ IF RF ]
cs 0x33 51
(gdb) x/10bx $rip
0x7ffff7ff7022: 0xf3 0x48 0xab 0x48 0x8b 0x15 0x08 0x0a
0x7ffff7ff702a: 0x20 0x00
(gdb)
gdb) x/67bx fptr
0x7ffff7ff7000: 0x55 0x48 0x89 0xe5 0x48 0x81 0xec 0x90
0x7ffff7ff7008: 0x01 0x00 0x00 0xcc 0x8d 0xb5 0x70 0xfe
0x7ffff7ff7010: 0xff 0xff 0xb8 0x00 0x00 0x00 0x00 0xba
0x7ffff7ff7018: 0x32 0x00 0x00 0x00 0x48 0x89 0xf7 0x48
0x7ffff7ff7020: 0x89 0xd1 0xf3 0x48 0xab 0x48 0x8b 0x15
0x7ffff7ff7028: 0x08 0x0a 0x20 0x00 0xbe 0x1d 0x08 0x40
0x7ffff7ff7030: 0x00 0xbf 0xf4 0x07 0x40 0x00 0xb8 0x00
0x7ffff7ff7038: 0x00 0x00 0x00 0xff 0xd2 0xb8 0x05 0x00
0x7ffff7ff7040: 0x00 0x00 0xc9
(gdb)
And here is the test1() function, code is compiled with -O0
(gdb) disassemble/r test1
Dump of assembler code for function test1:
0x000000000040062c <+0>: 55 push %rbp
0x000000000040062d <+1>: 48 89 e5 mov %rsp,%rbp
0x0000000000400630 <+4>: 48 81 ec 90 01 00 00 sub $0x190,%rsp
0x0000000000400637 <+11>: 48 8d b5 70 fe ff ff lea -0x190(%rbp),%rsi
0x000000000040063e <+18>: b8 00 00 00 00 mov $0x0,%eax
0x0000000000400643 <+23>: ba 32 00 00 00 mov $0x32,%edx
0x0000000000400648 <+28>: 48 89 f7 mov %rsi,%rdi
0x000000000040064b <+31>: 48 89 d1 mov %rdx,%rcx
0x000000000040064e <+34>: f3 48 ab rep stos %rax,%es:(%rdi)
0x0000000000400651 <+37>: 48 8b 15 08 0a 20 00 mov 0x200a08(%rip),%rdx # 0x601060 <_printf>
0x0000000000400658 <+44>: be 1d 08 40 00 mov $0x40081d,%esi
0x000000000040065d <+49>: bf f4 07 40 00 mov $0x4007f4,%edi
0x0000000000400662 <+54>: b8 00 00 00 00 mov $0x0,%eax
0x0000000000400667 <+59>: ff d2 callq *%rdx
0x0000000000400669 <+61>: b8 05 00 00 00 mov $0x5,%eax
0x000000000040066e <+66>: c9 leaveq
0x000000000040066f <+67>: c3 retq
End of assembler dump.
有关如何解决此问题的任何想法?
使用-fPIC -pie
编译代码无济于事。